Skip to content
This repository has been archived by the owner on Apr 17, 2019. It is now read-only.

Cache CLI input values #1496

Merged

Conversation

uatuko
Copy link
Contributor

@uatuko uatuko commented Jun 22, 2018

Description of the Change

Cache CLI input values to make it more convenient (#827).

There are two use cases.

  1. Make is possible to use default values provided during creation of a iroha_cli::interactive::ParamsMap - If a default value is provided (e.g. default host/port), that will be used when the user input is empty.
  2. Cache any user inputs - When an input is captured for a parameter, that value is cached and displayed on the input prompt for that parameter. If the user input is empty, cache value will be used.

Benefits

Get rid of annoying repeated host/port entries when attempting to send requests to Iroha (among other inputs) and make the CLI less frustrating to use.

Possible Drawbacks

There's no option to remove a cached value other than replacing it with a new value. However, the CLI doesn't allow empty inputs so this shouldn't be a problem.

Usage Examples or Tests

Scenario 1 - Using default values

There's no user input for Peer port (50051), default is used (prompt displays the default values).

$ ../build/bin/iroha-cli -account_name admin@test
Welcome to Iroha-Cli. 
Choose what to do:
1. New transaction (tx)
2. New query (qry)
3. New transaction status request (st)
> : 2
Choose query: 
1. Get Account Information (get_acc)
2. Get Account's Asset Transactions (get_acc_ast_tx)
3. Get Account's Signatories (get_acc_sign)
4. Get Account's Assets (get_acc_ast)
5. Get all current roles in the system (get_roles)
6. Get information about asset (get_ast_info)
7. Get Account's Transactions (get_acc_tx)
8. Get Transactions by transactions' hashes (get_tx)
9. Get all permissions related to role (get_role_perm)
0. Back (b)
> : 7
Requested account Id: admin@test
Query is formed. Choose what to do:
1. Send to Iroha peer (send)
2. Save as json file (save)
0. Back (b)
> : 1
Peer address (0.0.0.0): localhost
Peer port (50051):
[2018-06-22 22:42:44.265421000][th:5963568][info] QueryResponseHandler [Transaction]
[2018-06-22 22:42:44.265988000][th:5963568][info] QueryResponseHandler -Hash- ed98fb922acad35d9262d56115daba6b092722f60523a9e3e03e642cc2364fd3
[2018-06-22 22:42:44.266060000][th:5963568][info] QueryResponseHandler -Creator Id- admin@test
[2018-06-22 22:42:44.266081000][th:5963568][info] QueryResponseHandler -Created Time- 1529697208667
[2018-06-22 22:42:44.266162000][th:5963568][info] QueryResponseHandler -Commands- 3
[2018-06-22 22:42:44.267579000][th:5963568][info] QueryResponseHandler  CreateAsset: [asset_name=coolcoin, domain_id=test, precision=2, ] 
[2018-06-22 22:42:44.267692000][th:5963568][info] QueryResponseHandler  AddAssetQuantity: [account_id=admin@test, asset_id=coolcoin#test, amount=Amount: [intValue=50050, precision=2, ], ] 
[2018-06-22 22:42:44.267753000][th:5963568][info] QueryResponseHandler  TransferAsset: [src_account_id=admin@test, dest_account_id=test@test, asset_id=coolcoin#test, description=, amount=Amount: [intValue=10050, precision=2, ], ] 
--------------------

Scenario 2 - Using cached values

There aren't any user inputs for Requested account Id (admin@test), Peer address (localhost) and Peer port (50051) , cached valued are used. Note the prompt displays the cached values.

Choose what to do:
1. New transaction (tx)
2. New query (qry)
3. New transaction status request (st)
> : 2
Choose query: 
1. Get Account Information (get_acc)
2. Get Account's Asset Transactions (get_acc_ast_tx)
3. Get Account's Signatories (get_acc_sign)
4. Get Account's Assets (get_acc_ast)
5. Get all current roles in the system (get_roles)
6. Get information about asset (get_ast_info)
7. Get Account's Transactions (get_acc_tx)
8. Get Transactions by transactions' hashes (get_tx)
9. Get all permissions related to role (get_role_perm)
0. Back (b)
> : 7
Requested account Id (admin@test): 
Query is formed. Choose what to do:
1. Send to Iroha peer (send)
2. Save as json file (save)
0. Back (b)
> : 1
Peer address (localhost): 
Peer port (50051): 
[2018-06-22 22:42:51.678041000][th:5963568][info] QueryResponseHandler [Transaction]
[2018-06-22 22:42:51.678202000][th:5963568][info] QueryResponseHandler -Hash- ed98fb922acad35d9262d56115daba6b092722f60523a9e3e03e642cc2364fd3
[2018-06-22 22:42:51.678225000][th:5963568][info] QueryResponseHandler -Creator Id- admin@test
[2018-06-22 22:42:51.678237000][th:5963568][info] QueryResponseHandler -Created Time- 1529697208667
[2018-06-22 22:42:51.678266000][th:5963568][info] QueryResponseHandler -Commands- 3
[2018-06-22 22:42:51.678312000][th:5963568][info] QueryResponseHandler  CreateAsset: [asset_name=coolcoin, domain_id=test, precision=2, ] 
[2018-06-22 22:42:51.678363000][th:5963568][info] QueryResponseHandler  AddAssetQuantity: [account_id=admin@test, asset_id=coolcoin#test, amount=Amount: [intValue=50050, precision=2, ], ] 
[2018-06-22 22:42:51.678408000][th:5963568][info] QueryResponseHandler  TransferAsset: [src_account_id=admin@test, dest_account_id=test@test, asset_id=coolcoin#test, description=, amount=Amount: [intValue=10050, precision=2, ], ] 
--------------------
Choose what to do:
1. New transaction (tx)
2. New query (qry)
3. New transaction status request (st)
> : 

Signed-off-by: Uditha Atukorala <ua@nuked.zone>
Signed-off-by: Uditha Atukorala <ua@nuked.zone>
Signed-off-by: Uditha Atukorala <ua@nuked.zone>
Signed-off-by: Uditha Atukorala <ua@nuked.zone>
@l4l l4l added needs-review pr awaits review from maintainers cli command line interface new-feature labels Jun 24, 2018
@l4l l4l requested review from l4l and grimadas June 24, 2018 13:16
Copy link
Contributor

@l4l l4l left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use clang-format please

@@ -73,6 +77,8 @@ namespace iroha_cli {
ParamsMap getCommonParamsMap(const std::string &default_ip,
int default_port);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to add doc comment

// Description of parameters
using ParamsDescription = std::vector<std::string>;
using ParamsDescription = std::vector<std::shared_ptr<ParamData>>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why shared_ptr?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I can use and update the cache. I tried passing ParamData by refs instead of a pointer but doesn't seem to work with boost::optional (or I couldn't get it to work). I can give it another go to avoid using a pointer if that's preferred.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean why not just std::vector<ParamData>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it gets copied and I lose the reference to the initial objection when trying to update the cache (interactive_common_cli.cpp:148).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, it looks useless. Parameter in function is auto, not auto &, so modification of param bring nothing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll give another go at using std::vector<ParamData>. IIRC I couldn't get it to compile when tried to return a reference in findInHandlerMap.

// commonParamsMap
};
}

ParamsDescription makeParamsDescription(std::vector<std::string> params) {
ParamsDescription data;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using:

return std::accumulate(
    params.begin(),
    params.end(),
    ParamsDescription{},
    [](auto &&acc, auto &el) {
      acc.push_back(std::make_shared<ParamData>(std::make_pair(el, "")));
      return std::forward<decltype(acc)>(acc);
    });

@@ -62,11 +72,11 @@ namespace iroha_cli {
}

void printCommandParameters(std::string &command,
std::vector<std::string> parameters) {
ParamsDescription parameters) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be const ParamsDescription&

@@ -87,12 +97,20 @@ namespace iroha_cli {
return line;
}

boost::optional<std::string> promptString(ParamData param) {
std::string message = std::get<0>(param);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider adding a new structure, because std::get say nothing about the semantic

@@ -87,12 +97,20 @@ namespace iroha_cli {
return line;
}

boost::optional<std::string> promptString(ParamData param) {
std::string message = std::get<0>(param);
if (not std::get<1>(param).empty()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::accumulate is also applicable here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think it is appropriate to use std::accumulate here. param is just a std::pair (and changing to a struct).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, indeed. I though there was a loop, nvm then

auto val = promptString(param);
if (val and not val.value().empty()) {
params.push_back(val.value());
auto val = promptString(*param);
Copy link
Contributor

@l4l l4l Jun 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer using monadic bind operator

promptString(*param) | [&](auto &val) {
  if (not val.empty()) {
  ...
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how to use this feature, I get a compile error 😟.

../iroha-cli/interactive/impl/interactive_common_cli.cpp:151:28: error: invalid operands to binary expression ('boost::optional<std::string>' (aka 'optional<basic_string<char, char_traits<char>, allocator<char> > >') and '(lambda at ../iroha-cli/interactive/impl/interactive_common_cli.cpp:151:30)')
      promptString(*param) | [&](auto &val) {
      ~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~

Help please?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Do not forget to include "common/types.hpp"
  2. The operator itself is in the namespace, so you may use using namespace iroha; inside the function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was missing using namespace iroha;. Thanks.

{GET_ROLES, makeParamsDescription({})},
{GET_AST_INFO, makeParamsDescription({ast_id})},
{GET_ROLE_PERM, makeParamsDescription({role_id})}
// query_params_map_
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think it can be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please clarify, not sure what you meant here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean the line with a comment. But you don't really have to remove it since the PR is about different things

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this comment is needed for better formatting

@@ -46,8 +47,11 @@ namespace iroha_cli {
RESULT
};


// Parameter prompt and default/cache value pair
using ParamData = std::pair<std::string, std::string>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider declaring struct ParamData instead

// commonParamsMap
};
}

ParamsDescription makeParamsDescription(std::vector<std::string> params) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const std::vector<std::string> &

@uatuko
Copy link
Contributor Author

uatuko commented Jun 24, 2018

@l4l, if I use clang-format (e.g. clang-format -i -style=Google interactive_common_cli.hpp) the entire file seem to get reformatted. Should I do it anyway or am I using clan-format incorrectly?

@l4l
Copy link
Contributor

l4l commented Jun 24, 2018

@uditha-atukorala we have minor differences with google code style (in terms of clang-format) actually. They are listed in config, so prefer using -style=file (or smth like that)

Signed-off-by: Uditha Atukorala <ua@nuked.zone>
Signed-off-by: Uditha Atukorala <ua@nuked.zone>
// Description of parameters
using ParamsDescription = std::vector<std::string>;
using ParamsDescription = std::vector<std::shared_ptr<ParamData>>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a continuation of the previous discussion
boost::optional can handle lvalue refs. Try this diff out: curl http://termbin.com/kzb6 | git apply

Signed-off-by: Uditha Atukorala <ua@nuked.zone>
Signed-off-by: Uditha Atukorala <ua@nuked.zone>
Signed-off-by: Uditha Atukorala <ua@nuked.zone>
Copy link
Contributor

@l4l l4l left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

[](auto &&acc, auto &el) {
acc.push_back(ParamData({el, {}}));
return std::forward<decltype(acc)>(acc);
;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove that ; plz

// Parameter prompt and default/cache
/**
* Data structure for parameter data
*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redundant line

Signed-off-by: Uditha Atukorala <ua@nuked.zone>
@sorabot
Copy link

sorabot commented Jun 25, 2018

SonarQube analysis reported 2 issues

  1. MINOR interactive_common_cli.cpp#L43: Return value of function to_string() is not used. rule
  2. MINOR interactive_transaction_cli.hpp#L145: Unused private function: 'InteractiveTransactionCli::parseRevokePermission' rule

Copy link
Contributor

@grimadas grimadas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job, thanks for your contribution

std::string line, std::string command_name, ParamsMap params_map) {
auto params_description =
findInHandlerMap(command_name, std::move(params_map));
std::string line, std::string command_name, ParamsMap &params_map) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it should be const ParamsMap &

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually not, it is intentional it to be not const ParamsMap & since it gets updated with user input values.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Missed that

@@ -136,7 +170,7 @@ namespace iroha_cli {
* @return vector with needed parameters
*/
boost::optional<std::vector<std::string>> parseParams(
std::string line, std::string command_name, ParamsMap params_map);
std::string line, std::string command_name, ParamsMap &params_map);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also const ParamsMap &

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, params_map gets updated.

boost::optional<V> findInHandlerMap(K command_name,
std::unordered_map<K, V> params_map) {
boost::optional<V &> findInHandlerMap(
K command_name, std::unordered_map<K, V> &params_map) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, params_map gets updated.

@@ -211,7 +245,7 @@ namespace iroha_cli {
C class_pointer,
std::string &line,
std::unordered_map<std::string, V> &parsers_map,
ParamsMap params_map) {
ParamsMap &params_map) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const ParamsMap &

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, params_map gets updated.

@l4l l4l removed the needs-review pr awaits review from maintainers label Jun 26, 2018
@l4l l4l merged commit 04c3bea into hyperledger-archives:develop Jun 26, 2018
@uatuko uatuko deleted the feature/cache-cli-input-params branch June 26, 2018 10:10
l4l pushed a commit that referenced this pull request Jul 25, 2018
Signed-off-by: Uditha Atukorala <ua@nuked.zone>
l4l pushed a commit that referenced this pull request Jul 25, 2018
Signed-off-by: Uditha Atukorala <uditha-atukorala@users.noreply.github.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cli command line interface
Development

Successfully merging this pull request may close these issues.

None yet

4 participants