Prevent yargs describe feature from showing auto-generated tags - node.js

When using yargs .describe method to generate usage information, is there some way to prevent yargs from auto-adding information about type, default value, choices etc.?
I.e. the following
.option('foo', {
type: 'string',
choices: ['bar','baz'],
required: true,
default: 'bar',
description: 'The most important option of all'
})
results in this output when doing --help:
--foo The most important option of all [string] [required] [choices: "bar", "baz"] [default: "bar"]
I find that to be ugly, out of line with how help texts are generally formatted in linux, and confusing to read. Also, on longer description texts that include line breaks, it breaks formatting.
I haven't found anything in the docs. Anyone know of a way to do this, without having to completely give up yargs' describe feature?

Related

Argparse: is it possible to combine help texts from multiple parsers?

I'm writing a module with custom logging utilities to be imported in other scripts.
It's based on the standard-library logging module.
One of these utilities looks like this:
import argparse as ap
def parse_log_args() -> dict:
log_arg_parser = ap.ArgumentParser(description='Parses arguments that affect logging')
log_arg_parser.add_argument(
'--level',
dest='level',
help='Sets logging level',
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
)
log_args, _ = log_arg_parser.parse_known_args()
return vars(log_args)
This function looks for arguments that have to do with logging (even though only --level is defined for the time being) and parses those independently of (and before) all others so that the logging can be configured early on and used in the rest of the script.
The goal here is to remain flexible and be able to quickly plug-in support for these arguments, both in scripts that expect no other arguments and in those that do.
From the point of view of simply parsing arguments this works: this function runs first, parses --level and then the script-specific parser comes and handles the rest.
The problem, however, is the help text. When I run a script that calls this function with --help it only displays the help text from this first parser and not from the script-specific one. So something like this:
Parses arguments that affect logging
optional arguments:
-h, --help show this help message and exit
--level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
Sets logging level
Is there a way to combine the help-texts from all the ArgumentParser instances in a script?
Alternatively: Is there a different way to achieve this in a flexible/plug-in kind of way, that is, without modifying existing ArgumentParsers or having to add them to scripts that don't yet use them?
PS: A similar question has been asked before here: Argparse combine --help directives but the proposed ideas don't really solve the problem:
Define the first parser with add_help=False: This would hide the option from the user which I would prefer not to do.
Use subcommands somehow: doesn't seem to be applicable here.
I think this might fit the bill:
import argparse
part1 = argparse.ArgumentParser(add_help=False)
#... some parsing takes place ...
part2 = argparse.ArgumentParser(add_help=True, parents=[part1])
part1 parser must be fully initialized for parents to work.
More on the topic:
https://docs.python.org/3/library/argparse.html#parents

Arbitrary lookaheads in PLY

I am trying to parse a config, which would translate to a structured form. This new form requires that comments within the original config be preserved. The parsing tool is PLY. I am running into an issue with my current approach which I will describe in detail below, with links to code as well. The config file is going to look contain multiple config blocks, each of which is going to be of the following format
<optional comments>
start_of_line request_stmts(one or more)
indent reply_stmts (zero or more)
include_stmts (type 3)(zero or more)
An example config file looks like this.
While I am able to partially parse the config file with the grammar below, I fail to accomodate comments which would exist within the block.
For example, a block like this raises syntax errors, and any comments in a block of config fail to parse.
<optional comments>
start_of_line request_stmts(type 1)(one or more)
indent reply_stmts (type 2)(one or more)
<comments>
include_stmts (type 3)(one or more)(optional)
The parser.out mentions one shift/reduce conflict which I think arises because once the reply_stmts are parsed, a comments section which follows could mark start of a new block or comments within the subblock. Current grammar parsing result for the example file
[['# test comment ', '# more of this', '# does this make sense'], 'DEFAULT', [['x', '=',
'y']], [['y', '=', '1']], ['# Transmode', '# maybe something else', '# comment'],
'/random/location/test.user']
As you might notice, the second config block complete misses the username, request_stmt, reply_stmt sections.
What I have tried
I have tried moving the comments section around in the grammar, by specifying it before specific blocks or in the statement grammar. In the code link pasted above, the comments section has been specified in the overall statement grammar. Both of these approaches fail to parse comments within a config block.
username : comments username
| username
include_stmt : comments includes
| includes
I have two main questions:
Is there a mistake I am making in the implementation/understanding of LR parsing, solving which I could achieve what I want to ?
Is there a better way to achieve the same goal than my current approach ? (PLY-fu, different parser, different grammar)
P.S Wasn't able to include the actual code in the question, mentioned in the comments
You are correct that the problem is that when the parser sees a comment, it cannot know whether the comment belongs to the same section or whether the previous section is finished. In the former case, the parser needs to shift the comment, while in the latter case it needs to reduce the configuration section.
Since there could be any number of comments, the necessary lookahead could be arbitrarily large, in which case LR parsing wouldn't be possible. But a simple trick can reduce the lookahead to two tokens: just combine consecutive comments into a single token.
Any LR(k) grammar has an equivalent LR(1) grammar. In effect, the LR(1) grammars works by delaying all decisions for k-1 tokens, accumulating these tokens into the parser state. That's a massive increase in grammar size, but it's usually possible to achieve the same effect in other ways, and that's certainly the case here.
The basic idea is that any comment is (temporarily) accumulated into a list of comments. When a non-comment token is encountered, this temporary list is attached to that token.
This can be done either in the lexical scanner or in the parser actions, depending on your inclinations.
Before attempting all that, you should make sure that retaining comments is really useful to your application. Comments are normally not relevant to the semantics of a program (or configuration file), and it would certainly be much simpler for the lexer to just drop comments into the bit-bucket. If your application will end up reformatting the input, then it will have to retain comments. But if it only needs to extract information from the configuration, putting a lot of effort into handling comments is hard to justify.

Is the final comma in Rust struct definitions necessary?

Consider the following code:
struct User {
user: String,
email: String,
}
The compiler doesn't complain about it. The trailing comma after the email field struck me as odd, so I tried this:
struct User {
user: String,
email: String // no comma
}
The compiler still doesn't complain. Is there a difference or are the two scenarios completely equivalent?
The last comma is purely optional in struct definitions. This is pure convenience; it allows you to leave that trailing comma in, so you do not have to go back and modify a line if you add an additional field, delete a field or change their order.
It also, coincidentally, makes code generation from macros easier, as your codegen macro no longer has to care about keeping track of whether you are on the last generated field.
The one time when you'll see a trailing comma being mandatory is in macros like the diesel table! macro, and the reason is down to the macro invocation structure chosen by the diesel developers.
Have to say that you are an acute observer. They are equivalent according to rust reference:
StructFields :
StructField (, StructField)* ,?
It is that way for convenience reason: be able to add or remove lines without touching previous ones.
Here's a counter-example. In languages that don't have such convenience, people may choose to format the code in unusual ways to achieve virtually the same, such as:
data Person = Person
{ firstName :: String
, lastName :: String
, age :: Int
}
I like an optional trailing comma more.

Structure output of 'systemctl -h' command into a list and/or dictionary

Before I spend hours trying to code this I thought I'd ask the experts to see if anyone has already accomplished this. I've tried to do some searching but to be honest I'm not sure how to search for what I'm looking for. So, I'll do my best to describe it here and maybe one of you can either explain a way to search for a solution to my problem or possibly even provide a solution!
I wish to gather the output of 'systemctl -h' and parse it into a Python3 list of dictionaries; with each list entry being a dictionary of the possible options listed in the Help output.
What is interesting/hard about this desired output is that there are a lot of caveats that need considered:
Some lines in the Help output aren't options (like the first line and blank lines).
Some lines are "headings" for a group of commands. <-- Using this as the 'section' keyword would be a "nice to have".
Some of the options have short-key values "-h" in addition to "--help". While other commands don't follow that format at all.
Separation of the option's values is done using spacing/newline. Sometimes it is a single space, sometimes multiple spaces, sometimes it is a newline along with more spaces.
I think the resulting Python list of dictionaries should have something like this as its structure:
help_output = [
{'section': '<section name>',
'options': {
'shortcode': '<-h>',
'longcode': '<--help or list-unit-files>',
'description': '<blah>'
}
},
]
Alas, I lack the scripting foo to deal with all these caveats in a "clean" way. So, instead of me hacking together some non-Pythonic garbage I would like to get some input from you all.
Thanks for your time and I hope you find my question/challenge worthy of answering. :-)

Cannot configure Resharper to allow abbreviations as a parameter name

I am trying to get resharper to accept "ID" as an allowable abbreviation when used in an parameter list, yet it seems to ignore the abbreviation and complain about inconsistent naming with the message...
"Name 'ID' does not match rule 'Parameters'. Suggested name is 'id'."
... for a method signature like
GetThisSpecificEntity(int? ID, string uniqueEntityName);
... but does not generate a message for signatures like this...
GetThisSpecificEntity(int? entityID, string uniqueEntityName);
Trying to change the abbreviations list to include "ID" does not stop this from popping up, and changing parameter naming options to allow "ID" as prefix or suffix seems to causes other conflicts and weirdness with the default 'Parameters' rule elsewhere in code.
I'm not looking to debate usage of "ID" (Identity) vs "Id" (Ego) as part of this, as it seems to be a problem for any parameter that is added into the abbreviations list. I have about a dozen domain-specific abbreviations - "AII", "SAP", "PLC", etc - that I've added to reduce the noise generated by legacy code, and I simply want to have this abbreviation honored in parameter lists. Is there a way to make this work the way I need it to?

Resources