Here is an example:
extern crate clap;
use clap::{Arg, App};
fn main() {
let args = App::new("test")
.arg(Arg::with_name("scoring_method")
.short("s")
.long("scoring-method")
.help("Very very very very very very long long long long long help help help help help message message message message message message message"))
.get_matches();
}
Leads to the help text formatting like this:
(pasting in code mode causes Stack Overflow to fix the formatting issue)
The exact string produced is:
'USAGE:\n play [FLAGS]\n\nFLAGS:\n -h, --help Prints help information\n -s, --scoring-method Very very very very very very long long long long long help help help help help message\n message message message message message message\n -V, --version Prints version information'
Clap has a max_term_width that it uses to wrap the text that it outputs. As mentioned in that documentation, it defaults to 120 characters, which is why you see the text split eventually, but not where you'd hoped.
If you have a certain width that you'd like to set, you can use set_term_width with a specific value. Alternatively, you can use a crate like terminal_size to get the size of the current terminal, and use that to set the width for clap to use.
As a full example:
extern crate clap;
extern crate terminal_size;
use clap::{App, Arg};
use terminal_size::{terminal_size, Width};
fn main() {
let args = App::new("test")
.set_term_width(if let Some((Width(w), _)) = terminal_size() { w as usize } else { 120 })
.arg(Arg::with_name("scoring_method")
.short("s")
.long("scoring-method")
.help("Very very very very very very long long long long long help help help help help message message message message message message message"))
.get_matches();
}
Today (Clap v4.0.26) you can enable the wrap_help feature. This takes a dependency on terminal_size internally.
Related
I've finished my CLI but it exits too quickly for people to use it, Anyone know how would I go towards implementing code in my main.rs without breaking the compiler lol.
I was thinking of maybe a for loop that prints , read and execute and then start again. Or maybe a read line function so it stays up long enough to output the display.
Where would you guys implement that ? Thanks!
use structopt::StructOpt;
mod cli;
mod task;
use cli::{Action::*, CommandLineArgs};
use task::Task;
fn main() {
// Get the command-line arguments.
let CommandLineArgs {
action,
todo_file,
} = CommandLineArgs::from_args();
// Unpack the todo file.
let todo_file = todo_file.expect("Failed to find todo file");
// Perform the action.
match action {
Add { text } => task::add_task(todo_file,
Task::new(text)),
List => task::list_tasks(todo_file),
Done { position } =>
task::complete_task(todo_file, position),
}
.expect("Failed to perform action")
}
From the example, it seems you're getting the arguments from the command line. If you instead wanted the program to wait for a user to enter some text, interpret that text as a command and run it, and then wait for input again, until the user exits the program, then you'll probably want https://doc.rust-lang.org/std/io/struct.Stdin.html or possibly a higher level crate such as https://docs.rs/rustyline/8.0.0/rustyline/
If you were using stdin directly, you can call io::stdin().read_line() which will wait until the user has entered a line of text and pressed enter before the function will return. You can then parse that string to get the action to perform. The input/parsing/action code can be surrounded in a loop {} and one of the actions can be an exit command that will exit the loop.
I would like to include --help and --version long options without the -h and -V short options. Is this possible?
I'm using clap with yaml. The closest I've been able to come up with is to use hidden (unused) args that mask the short options.
# main.rs
use clap::{load_yaml, App};
fn main() {
let y = load_yaml!("cli.yaml");
let m = App::from_yaml(y).get_matches();
println!("_help {}", m.is_present("_help"));
println!("_version {}", m.is_present("_version"));
}
# Cargo.toml
[package]
name = "app"
version = "0.0.1"
edition = "2018"
[dependencies]
clap = {version = "~2.33.0", features = ["yaml"]}
# cli.yaml
name: app
version: 0.0.1
args:
- opt: { short: "o", long: "opt" }
- _help: { short: "h", hidden: true }
- _version: { short: "V", hidden: true }
$ cargo -q run -- --help
app 0.0.1
USAGE:
app [FLAGS]
FLAGS:
--help Prints help information
-o, --opt
--version Prints version information
$ cargo -q run -- -h
_help true
_version false
$ cargo -q run -- -o
_help false
_version false
$ cargo -q run -- -V
_help false
_version true
$ cargo -q run -- -x
error: Found argument '-x' which wasn't expected, or isn't valid in this context
USAGE:
app [FLAGS]
For more information try --help
This doesn't feel like a very clean approach. Is there another/better way?
Clap is designed more towards creating an args parser. So there aren't really that much functionality for getting and removing existing arguments.
If you simply want to rename "-h" to e.g. "-?", then you can do that with help_short("-?") (see also version_short().)
However, there are ways to work around it.
Assuming you're using e.g. clap = "2.33". Then similarly to what you're already doing, you can override/replace the help and version args, and in that way "remove" the short versions. (For brevity, I'll only include examples for help.)
You can of course keep it in cli.yaml if you want, but I'll add it to main.rs. In short, you want to add a new "help" arg and only give it a long version. It's important that you include help("Prints help information") as this is replacing the existing help arg, so if you don't it won't have the default help message for --help.
The downside to overring "help" is that you'd need to handle print_help() yourself.
use clap::{load_yaml, App, Arg};
fn main() {
let y = load_yaml!("cli.yaml");
let mut app = App::from_yaml(y)
.arg(
Arg::with_name("help")
.long("help")
.help("Prints help information"),
);
let m = app.clone().get_matches();
if m.is_present("help") {
app.print_help().unwrap();
// std::process::exit(0);
// or just
return;
}
}
However, if you're using clap = "3.0.0-beta.2" then that simplifies things, with the introduction of mut_arg(). Because that allows us to mutate the argument. Thereby, we no longer need to call print_help() ourselves.
use clap::{load_yaml, App, Arg};
fn main() {
let y = load_yaml!("cli.yaml");
let m = App::from(y)
.mut_arg("help", |h| {
Arg::new("help")
.long("help")
.about("Prints help information")
})
.get_matches();
}
Note that App::from_yaml() is now App::from(), while Arg::with_name() has become Arg::new(), and help() is now about().
I am using Nodejs c++ addon in my nodejs project. JS calls a method defined in c++ with a string as the parameter. I couldn't get the string in c++. Below is my code in c++:
NAN_METHOD(DBNode::Test){
printf("Hello\n");
printf("%s\n", info[0]->ToString());
printf("%d\n", info[1]->ToNumber());
}
Below is my js code:
const test = require('./build/Release/test.node');
test.test('ssss', 99);
Below is the output:
$ node demo.js
Hello
?ڄ?C
-272643000
You can see from the above output that the string and integer values are not correctly printed. Is there anything wrong with my code?
Let start from numbers. ToNumber returns value of type Local<Number>. It differs from regular C-like value what printf can digest.
First of all you need unwrap Local. It is v8 pointer-like utility class.
You can do it with overrided * operator. So *(info[1]->ToNumber()) gives us v8 Number child of Value. But this is not the end of story. Now we can pull good-old int from it (*(info[1]->ToNumber())).Int32Value(). Or you can use the fact Handle ancestors override -> operator too and write like info[1]->ToNumber()->Int32Value().
String case is harder. V8 uses utf8 strings and you can use String::Utf8Value utility class to get buffer of char from it. *(String::Utf8Value(info[0]->ToString()))
Usually you do not need it in v8 addons and I suggest you work with v8 objects(like Local, String, Number, etc) in your native code.
below is the solution :--
NAN_METHOD(updateSignalValue) {
Nan::Utf8String lSignal(info[0]);
int len = lSignal.length();
if (len <= 0) {
return Nan::ThrowTypeError("arg must be a non-empty string");
}
std::cout << "\n hello lSignal value is :"<
Regards, Rakesh Kumar Jha
I was browsing the docs, and I found StaticString. It states:
An simple string designed to represent text that is "knowable at compile-time".
I originally thought that String has the same behaviour as NSString, which is known at compile time, but it looks like that I was wrong. So my question is when should we use StaticString instead of a String, and is the only difference is that StaticString is known at compile-time?
One thing I found is
var a: String = "asdf" //"asdf"
var b: StaticString = "adsf" //{(Opaque Value), (Opaque Value), (Opaque Value)}
sizeofValue(a) //24
sizeofValue(b) //17
So it looks like StaticString has a little bit less memory footprint.
It appears that StaticString can hold string literals. You can't assign a variable of type String to it, and it can't be mutated (with +=, for example).
"Knowable at compile time" doesn't mean that the value held by the variable will be determined at compile time, just that any value assigned to it is known at compile time.
Consider this example which does work:
var str: StaticString
for _ in 1...10 {
switch arc4random_uniform(3) {
case 0: str = "zero"
case 1: str = "one"
case 2: str = "two"
default: str = "default"
}
print(str)
}
Any time you can give Swift more information about how a variable is to be used, it can optimize the code using it. By restricting a variable to StaticString, Swift knows the variable won't be mutated so it might be able to store it more efficiently, or access the individual characters more efficiently.
In fact, StaticString could be implemented with just an address pointer and a length. The address it points to is just the place in the static code where the string is defined. A StaticString doesn't need to be reference counted since it doesn't (need to) exist in the heap. It is neither allocated nor deallocated, so no reference count is needed.
"Knowable at compile time" is pretty strict. Even this doesn't work:
let str: StaticString = "hello " + "world"
which fails with error:
error: 'String' is not convertible to 'StaticString'
StaticString is knowable at compile time. This can lead to optimizations. Example:
EDIT: This part doesn't work, see edit below
Suppose you have a function that calculates an Int for some String values for some constants that you define at compile time.
let someString = "Test"
let otherString = "Hello there"
func numberForString(string: String) -> Int {
return string.stringValue.unicodeScalars.reduce(0) { $0 * 1 << 8 + Int($1.value) }
}
let some = numberForString(someString)
let other = numberForString(otherString)
Like this, the function would be executed with "Test" and "Hello there" when it really gets called in the program, when the app starts for example. Definitely at runtime. However if you change your function to take a StaticString
func numberForString(string: StaticString) -> Int {
return string.stringValue.unicodeScalars.reduce(0) { $0 * 1 << 8 + Int($1.value) }
}
the compiler knows that the passed in StaticString is knowable at compile time, so guess what it does? It runs the function right at compile time (How awesome is that!). I once read an article about that, the author inspected the generated assembly and he actually found the already computed numbers.
As you can see this can be useful in some cases like the one mentioned, to not decrease runtime performance for stuff that can be done at compile time.
EDIT: Dániel Nagy and me had a conversation. The above example of mine doesn't work because the function stringValue of StaticString can't be known at compile time (because it returns a String). Here is a better example:
func countStatic(string: StaticString) -> Int {
return string.byteSize // Breakpoint here
}
func count(string: String) -> Int {
return string.characters.count // Breakpoint here
}
let staticString : StaticString = "static string"
let string : String = "string"
print(countStatic(staticString))
print(count(string))
In a release build only the second breakpoint gets triggered whereas if you change the first function to
func countStatic(string: StaticString) -> Int {
return string.stringValue.characters.count // Breakpoint here
}
both breakpoints get triggered.
Apparently there are some methods which can be done at compile time while other can't. I wonder how the compiler figures this out actually.
I'm running into a disconnect between the online documentation and the behavior I see in my programs accessing C structs within GO code. go version says I am using:
go version go1.4.2 linux/amd64
According to the GO CGO documentation:
Within the Go file, C's struct field names that are keywords in Go can be
accessed by prefixing them with an underscore: if x points at a C struct with
a field named "type", x._type accesses the field. C struct fields that cannot
be expressed in Go, such as bit fields or misaligned data, are omitted in the
Go struct, replaced by appropriate padding to reach the next field or the end
of the struct.
I had troubles with this, so made a quick sample program to test it out:
package main
// struct rec
// {
// int i;
// double d;
// char* s;
// };
import "C"
import "fmt"
func main() {
s := "hello world"
r := C.struct_rec{}
r.i = 9
r.d = 9.876
r.s = C.CString(s)
fmt.Printf("\n\tr.i: %d\n\tr.d: %f\n\tr.s: %s\n",
r.i,
r.d,
C.GoString(r.s))
}
When I use underscores as the docs indicate (eg, substitute r._i for r.i above) I get the following compile error:
r._i undefined (type C.struct_rec has no field or method _i)
When I don't use underscores it works fine. I tried this with both pointers and non-pointers. The only other idea I can think of is that maybe it's because I allocated the instances in GO rather than C, is that the case??
Thanks for any help!
The answer is in the very quote you have in your question:
Within the Go file, C's struct field names that are keywords in Go can be accessed by prefixing them with an underscore(…)
i, d, and s are not keywords in Go.