Forcing the order of arguments in function generated for a "alias" - fish

When I create an alias like:
alias "myA" "PREFIX $argv SUFFIX"
fish genarates a function with body equivalent to: "PREFIX SUFFIX $argv.
Is there a trick/hack/legitimate way to force the shell so that the call myA 1234 is executed as PREFIX 1234 SUFFIX?
I know how to do that by writing a function. I generate about 15+ of these, on the fly, and the PREFIX, SUFFIX strings keep changing very frequently. So it is not practical to write a function.
Thanks!
Cheers; 'best,
shankar

You seem to have misunderstood what the alias command does. It does define a function. But it does not do the transformation you imply. It only appears to do so because you double-quoted the alias definition. Which means that $argv is interpolated before the function is created. If, as is likely to be the case, $argv is undefined (or the empty array) then "PREFIX $argv SUFFIX" is equivalent to "PREFIX SUFFIX".
To answer your question: No, there is no way to do what you want using the alias command. Honestly, I think alias should never have been added to fish as it isn't needed and simply confuses people migrating from bash where the concept of an "alias" is very different. It's trivial to replace
alias myA "PREFIX $argv SUFFIX"
with
function myA; PREFIX $argv SUFFIX; end

Related

Uppercasing filename in Makefile using sed

I try to convert a filename such as foo/bar/baz.proto into something like foo/bar/Baz.java in my Makefile. For this purpose, I thought I could use sed. However, it seems that the command does not work as expected:
uppercase_file = $(shell echo "$(1)" | sed 's/\(.*\/\)\(.*\)/\1\u\2/')
# generated Java sources
PROTO_JAVA_TARGETS := ${PROTO_SPECS:$(SRCDIR)/%.proto=$(JAVAGEN)/$(call uppercase_file,%).java}
When I try to run the sed command on the command line it seems to work:
~$ echo "foo/bar/baz" | sed 's/\(.*\/\)\(.*\)/\1\u\2/'
foo/bar/Baz
Any ideas why this does not work inside the Makefile?
UPDATE:
The java files are generated with the following target:
$(JAVAGEN)/%.java: $(SRCDIR)/%.proto
How can I apply the substitution also for targets?
GNU Make does not replace % character in the replacement part of a substitution reference (which is basically a syntactic sugar for patsubst) if it is part of a variable reference. I have not found this behavior described in the documentation, but you can look it implemented in the source code (the relevant function I believe is find_char_unquote).
I suggest moving the call out of the substitution reference, since uppercase_file obviously works properly on any file path:
PROTO_JAVA_TARGETS := $(call uppercase_file,${PROTO_SPECS:$(SRCDIR)/%.proto=$(JAVAGEN)/%.java})
If $(PROTO_SPECS) resolves not to a single element, but rather to a list of elements, you can use foreach to call the function on every elements of a processed list:
PROTO_JAVA_TARGETS := $(foreach JAVA,${PROTO_SPECS:$(SRCDIR)/%.proto=$(JAVAGEN)/%.java},$(call uppercase_file,$(JAVA)))
The java files are generated with the following target: $(JAVAGEN)/%.java: $(SRCDIR)/%.proto
How can I apply the substitution also for targets?
Since Make matches targets first, and there is no way to run sed backwards, what you need here is either define an inverse function, or generate multiple explicit rules. I will show the latter approach.
define java_from_proto
$(call uppercase_file,$(1:$(SRCDIR)/%.proto=$(JAVAGEN)/%.java)): $1
# Whatever recipe you use.
# Use `$$#`, `$$<` and so on instead of `$#` or `$<`.
endef
$(foreach PROTO,$(PROTO_SPECS),$(eval $(call java_from_proto,$(PROTO))))
We basically generate one rule per file in $(PROTO_SPEC) using a multiline variable syntax, and then use eval to install that rule. There is also a very similar example on this documentation page that can be helpful.

variable expansion inside namespace-qualified variable name

Problem
I want to perform parametric variable evaluation. The to-be-evaluated variable name is constructed with a string concatenation - from a namespace part and a name part being defined in a variable. Example: env:$var, where the value of $var is, for instance "OS". However, while using the expression
${env:OS}
gives the expected value Windows_NT, the construct
$var="OS"
${env:$var}
is a null-valued expression.
Motivation
I'm not really intereseted in the value of environment variables (but this was the simplest example, I could find). What I really want, is to refer to the content of a file via the ${c:<filename>} construct. I want to perform several, conditional in-file string substitutions and, I'd like to use a construct similar to this:
<identify files in a foreach>
${c:<filename>} -replace 'this', 'that' > ${c:<new filename>}
To achieve this, I need <filename> to be a value of an iterator variable.
Question
If the value of $var is OS, what shall be at ..., if I expect the value of the following expression to be Windows_NT?
${env:...var...}
Use Get-ChildItem on the env: PSDrive and expand the Value of the result:
(ls env:$var).Value
Edit: As #PetSerAl suggested in the comments using Get-Content is a more elegant approach:
(cat env:$var)

Explain ${var:-val} and ${var+val}

Can any one explain this format?
${name:-$devi}
Example:
"${1+"$#"}" will check for that first variable to be set , if not it will use that
command line argument.
What is the difference between :- and + between those variables?
${var:-val}
is the same as ${var} if var is set and non-null, otherwise it expands to val. This is used to specify a default value for a variable.
${var+val}
expands to nothing if var is unset, otherwise it expands to val. This is used to supply an alternate value for a variable.
"${1+"$#"}"
is a workaround for a bug in old shell versions. If you just wrote "$#", it would expand to "" when no arguments were supplied, instead of expanding to nothing; the script would then act as if a single, empty argument had been supplied. This syntax first checks whether $1 is set -- if there's no first argument, then there are obviously no arguments at all. If $1 is unset, it expands to nothing, otherwise it's safe to use "$#".
Most modern shell versions don't have this bug, so you can just write "$#" without the special check. I'm not sure if there are any other common use cases for the + construct in shell variable expansion.

Tcl set command

Quick question... I'm trying the following:
set changedir "cd $JSDIR/"
eval $changedir
..Where $JSDIR is defined already. Running this script gives the error: "set: Variable name must begin with a letter."
What's the fix?
Thanks.
That's not an error message generated by Tcl, because Tcl's variables most definitely do not need to begin with a letter. OK, it tends to be convenient to keep them alphanumeric because the $var shorthand syntax is more restrictive than the general space of variable names, but the set var form can handle virtually anything.
I'm guessing that script is being evaluated by something that isn't Tcl, perhaps bash?
Try to set changedir cd ${JSDIR/} instead
This message can appear when in fact the variable name is entirely correct, and the real problem is that the variable value needs to be quoted. Try instead of: set changedir "cd $JSDIR//"

What does the period '.' operator do in powershell?

This is a weird one. Normally when I execute an external command from powershell I use the & operator like this:
& somecommand.exe -p somearguments
However, today I came across the . operator used like this:
.$env:systemdrive\chocolatey\chocolateyinstall\chocolatey.cmd install notepadplusplus
What purpose does the period serve in this scenario? I don't get it.
The "." dot sourcing operator will send AND receive variables from other scripts you have called. The "&" call operator will ONLY send variables.
For instance, considering the following:
Script 1 (call-operator.ps1):
clear
$funny = "laughing"
$scriptpath = split-path -parent $MyInvocation.MyCommand.Definition
$filename = "laughing.ps1"
"Example 1:" # Call another script. Variables are passed only forward.
& $scriptpath\$filename
"Example 2:" # Call another script. Variables are passed backwards and forwards.
. $scriptpath\$filename
$variableDefinedInOtherScript
Script 2 (laughing.ps1):
# This is to test the passing of variables from call-operator.ps1
"I am $funny so hard. Passing variables is so hilarious."
$variableDefinedInOtherScript = "Hello World!"
Create both scripts and ONLY run the first one. You'll see that the "." dot sourcing operator sends and receives variables.
Both have their uses, so be creative. For instance, the "&" call operator would be useful if you wanted to modify the value(s) of variables in another script while preserving the original value(s) in the your current script. Kinda a safeguard. ;)
The Short:
It is a Special Operator used to achieve what regular operators cannot achieve. This particular operator . actually has two distinctively different Special Operator use cases.
The Long:
As with any other language, scripting or otherwise, PowerShell script also supports many different types of Operators to help manipulate values. These regular operators include:
Arithmetic
Assignment
Comparison
Logical
Redirection
List item
Split and Join
Type
Unary
However, PowerShell also supports whats known as Special Operators which are used to perform tasks that cannot be performed by the other types of operators.
These Special Operators Include:
#() Array subexpression operator
& Call operator
[ ] Cast operator
, Comma operator
. Dot sourcing operator
-f Format operator
[ ] Index operator
| Pipeline operator
. Property dereference operator
.. Range operator
:: Static member operator
$( ) Subexpression operator
. Dot sourcing operator: is used in this context to allow a script to run in the current scope essentially allowing any functions, aliases, and variables which has been created by the script to be added to the current script.
Example:
. c:\scripts.sample.ps1
NoteThat this application of the . Special Operator is followed by a space to distinguish it from the (.) symbol that represents the current directory
Example:
. .\sample.ps1
. Property dereference operator: Allows access to the properties and methods of of an object which follows the . by indicating that the expression on the left side of the . character is an object and the expression on the right side of the is an object member (a property or method).
Example:
$myProcess.peakWorkingSet
(get-process PowerShell).kill()
Disclaimer & Sources:
I had the same question while looking at a PowerShell script that I was trying to expand on its feature sets and landed here when doing my research for the answer. However I managed to find my answer using this magnificent write up on the Microsoft Development Network supplemented with this further expansion of the same ideas from IT Pro.
Cheers.
The dot is a call operator:
$a = "Get-ChildItem"
. $a # (executes Get-ChildItem in the current scope)
In your case, however, I don't see what it does.
.Period or .full stop for an objects properties; like
$CompSys.TotalPhysicalMemory
See here: http://www.computerperformance.co.uk/powershell/powershell_syntax.htm#Operators_
This answer is to expand slightly upon those already provided by David Brabant and his commenters. While those remarks are all true and pertinent, there is something that has been missed.
The OPs use of & when invoking external commands is unnecessary. Omitting the & would have no effect (on the example of his usage). The purpose of & is to allow the invocation of commands whose names are the values of a (string) expression. By using the & above, powershell then (essentially) treats the subsequent arguments as strings, the first of which is the command name that & duly invokes. If the & were omitted, powershell would take the first item on the line as the command to execute.
However, the . in the second example is necessary (although, as noted by others, & would work just as well in this case). Without it, the command line would begin with a variable access ($env:systemdrive) and so powershell would be expecting an expression of some form. However, immediately following the variable reference is a bare file path which is not a valid expression and will generate an error. By using the . (or &) at the beginning of the line, it is now treated as a command (because the beginning doesn't look like a valid expression) and the arguments are processed as expandable strings (" "). Thus, the command line is treated as
. "$env:systemdrive\chocolatey\chocolateyinstall\chocolatey.cmd" "install" "notepadplusplus"
The first argument has $env:systemdrive substituted into it and then . invokes the program thus named.
Note: the full description of how powershell processes command line arguments is way more complicated than that given here. This version was cut down to just the essential bits needed to answer the question. Take a look at about_Parsing for a comprehensive description. It is not complete but should cover most normal usage. There are other posts on stackoverflow and github (where powershell now resides) that cover some of the seemingly quirky behaviour not listed in the official documentation. Another useful resource is about_Operators though again this isn't quite complete. An example being the equivalence of . and & when invoking something other than a powershell script/cmdlet getting no mention at all.