passing exclamation, brackets as part of executable arguments in powershell - powershell

In git, if we want to exclude a file from diff output (on bash) we do something like follows:
git diff -- !(file.txt)
But this is disallowed in powershell. Hence is there a way to achieve this in the powershell prompt?

Simply single-quote your argument:
git diff -- '!(file.txt)'
Single-quoting makes PowerShell treat the string literally and prevents it from interpreting chars. such as ( as its own metacharacters.
Before invoking the target program, PowerShell re-quotes arguments if and as needed, behind the scenes; that is:
It encloses an argument in "..." if it contains whitespace, and also in certain, less common scenarios (see link below).
It passes it without quotes otherwise.
Note: There are pitfalls associated with this invisible re-quoting - see this answer.

Related

Is there a way to add a command to neovim that can be called as `:command`?

What I would like to archieve is to be able to use :< shell command and add the output to the shell command to the cursor's position in neovim.
It seems I could use :redir to archieve this functionality and wrap it in to a function.
Is there a way to associate a [neo]vim function to :command?
A command can't return value. Hence a command is not an expression. And in particular, commands never can be "nested" one into another, like function calls. Cf. Shell scripting, for example.
In principle, there are some tricks, like a builtin function that accepts command name, runs it, and returns output as string value. But this is rather "convenient redir", not "syntax breaker".
To add external tool output into cursor position use, for example,
put=system('blah blah')
This is legal, as (some of) commands may accept expressions, including function calls.
Make sure to escape "bars" and "double quotes" though, as (sometimes) they are special in VimScript.

Conventions for command line verb arguments -a vs --arg

I've just noticed a pattern (in git and the CommandLineParser lib for .NET) for verb-style command arguments, and wondering if someone can confirm:
myprog dothis -a "someArg"
-a
--arg
What's the difference between the single-dash-prefix and the double-dash-prefix? Is the single dash prefix always for a single-letter argument specifier, where a double dash prefix always for a "long name" of the argument?
Is there a formal convention somewhere that drives this, or is it a generally accepted informal practice? (or am I just making something of nothing?)
Just curious... the I had never noticed the pattern in git and the CommandLineParser docs are pretty thin and some blog post or another implicated the convention.
(for that matter... what's this style of verb/args even called? I can't seem to find much of anything on it)
From the wikipedia: https://en.wikipedia.org/wiki/Command-line_interface
Option conventions in Unix-like systems
In Unix-like systems, the ASCII hyphen-minus begins options; the new
(and GNU) convention is to use two hyphens then a word (e.g. --create)
to identify the option's use while the old convention (and still
available as an option for frequently-used options) is to use one
hyphen then one letter (e.g. -c); if one hyphen is followed by two or
more letters it may mean two options are being specified, or it may
mean the second and subsequent letters are a parameter (such as
filename or date) for the first option.
Two hyphen-minus characters without following letters (--) may
indicate that the remaining arguments should not be treated as
options, which is useful for example if a file name itself begins with
a hyphen, or if further arguments are meant for an inner command (e.g.
sudo). Double hyphen-minuses are also sometimes used to prefix "long
options" where more descriptive option names are used. This is a
common feature of GNU software. The getopt function and program, and
the getopts command are usually used for parsing command-line options.
There is posix convention and getopt
But it's not always the case, e.g. java and find.
See also:
https://golang.org/pkg/flag/
http://docs.oracle.com/javase/8/javafx/api/javafx/application/Application.Parameters.html

How do I ignore escape characters in command line arguments?

Consider a simple F# console application that echoes the command line arguments passed to it, one command per line:
[<EntryPoint>]
let main argv =
argv |> Array.iter (printfn "%s")
0
If I pass this program a directory path with a trailing slash, it treats the slash as an escape character producing unexpected results:
> app.exe "c:\some path\" "c:\another path"
c:\some path" c:\another
path
How can I retrieve the command line arguments without interpreting a slash as an escape character?
System.Environment.CommandLine gives you access to the complete unescaped command line, and you are free to process that however you like.
But unless you plan to implement a full-blown parser in your app, this is not going to be a reliable approach, and it's unlikely you will be able to reliably handle all of the byzantine escaping rules implemented by all of the various shells your app might have been invoked in. e.g. cmd.exe escapes things differently from powershell.exe, which is in turn different from Cygwin, etc etc.
A better choice is to simply take argv as-is, validate it as you see fit (e.g. File.Exists(argv.[0]) or whatever), and bail out with a helpful error message if the user messed something up.

How To Format Command Line Argument Key Value Pairs

A typical format for command line arguments is:
myApp --myArg=myValue
What if I want to pass in a set of key value pairs through the command line? Something like:
myApp --myList={arg1=val1;arg2=val2;arg3=val3...}
Since there seems to be no standard for this sort of thing, can anyone provide examples from well-used utilities that have this sort of command line argument input? I poked around some man pages but didn't find any.
Edit: I'm wondering both how the input should be formatted and what the help text might look like.
I think it largely depends on how you parse the arguments in your program.
Here are some examples that the programs accept multiple key-value pair values.
man php:
--define foo[=bar]
-d foo[=bar] Define INI entry foo with value bar
man git:
-c <name>=<value>
Pass a configuration parameter to the command. The value given will
override values from configuration files. The <name> is expected in
the same format as listed by git config (subkeys separated by
dots).
For both, one can pass multiple -d or -c arguments to the programs which gives you the ability to supply a list of key-value pairs to the programs.
IMO, it's not a big problem having your own style of accepting lists of key-value pairs for your program as long as it works and is well-documented. :)
P.S.: I think this question would be more appropriate be placed on Programmers Stack Exchange rather than on SO. See here and here.
If the app needs so many arguments, I would use a config file instead of passing them in command line:
myApp --config=file.cnf
This approach has the following advantages:
flexibility - you can have a bunch of configs prepared for different invocations, and just use them,
no problems with quoting - it's always painful if command line arguments have spaces, double quotes, <, >, or other special characters,
simplicity - you control the config file format, it can be for example INI, JSON, XML etc. It's easy to create it and as easy to parse as parsing command line -- if not easier,
security - if any argument may be sensitive, it's not visible from tools displaying command line arguments.

Separating interpreter command line arguments from script arguments

Suppose you have an interpreter that takes command line arguments including the filenames for a script to be run, and optionally further arguments to be passed to the script. The interpreter then needs to figure out which of the given arguments were intended for its own use and which were intended to be passed to the script.
Is there a widely used convention for separating the former from the latter?
With Bash
-- A -- signals the end of options and disables further option
processing. Any arguments after the -- are treated as file-
names and arguments. An argument of - is equivalent to --.
With CMD :: is often used as a dummy argument to indicate recusrsion for instance. Prefixed on a line, it can be used to turn the line into a comment, giving a handy "programmed-skip" facility