bash readline bind with dynamic prefix argument? - bash

Is there a way to make a bash keybinding that moves the cursor N characters forward, where N is variable? I was hoping I could do
bind '"\e\C-i": "\e$(echo "$N")\C-f"'
but of course the $() isn't expanded beforehand.
Note that I don't want to have to specify the prefix manually – I want a function to give it (or if it's read from an env-var or a file as a workaround).

Related

How to provide arguments to Readline functions via inputrc

I'm trying to use the insert-comment function provided by readline to uncomment a line.
According to the documentation:
If a numeric argument is supplied, this command acts as a toggle: if the characters at the beginning of the line do not match the value of comment-begin, the value is inserted, otherwise the characters in comment-begin are deleted from the beginning of the line
I have following line in my .inputrc for it:
"\eW": insert-comment 1
Which maps insert-comment to Alt-W (just for testing. I intend to remap Alt-# when it works)
On reloading .inputrc, entering some text on the terminal (like #123) and then pressing Alt-W, # gets prepended to whatever I type (like ##123), the same behaviour as Alt-#.
How do I use insert-comment function as a toggle mapped to a custom key sequence?
As far as I know, Readline doesn't support adding an argument in a binding like this. You can define a macro, though. For example, suppose you left insert-comment bound to Alt-W. Then you could define Alt-# as
"\e#": "\e1\eW"
The \e1 sets the argument to 1, followed by \eW to invoke insert-comment with the current argument.

How to pass infomation to POV-Ray from a shell script

How do I pass a variable from a shell script to POV-Ray? My desire would the ability to pass a variable as a command-line argument and then use that value in the .ini file or .pov file
Something like
POV-Ray +pass var=$imageNumber file.pov
And then being able to use var in POV-Ray
I realize that I could edit the .ini and .pov files in the script or use modulus to use the single frame variable as two variables, but both those solutions seem awkward.
I want to generate 1000s of extremely similar scenes. Each scene is exactly the same except that a heightmap uses a different image file as its source. Normally, I would use the animation tools in POV-Ray to generate multiple frames. However, I am already using the animation tools to cycle over a different property in each scene.
For *nix systems, use POV-Ray's file handling system to open the standard-in file in your .pov file
#fopen STDIN "/dev/stdin" read
#read (STDIN, var1, var2)
This will read from the standard-in for a comma separated list of POV literals. However, POV-Ray doesn't handle reading from a pipe; Thus, use herestrings (or heredocuments if you must use only sh compatible syntax) to fill stdin for POV-Ray.
For example, if run in the shell (works for bash):
povray "example.pov" <<<'"hello","world"'
Will fill the variables var1 and var2 from above with the values "hello" and "world" respectively. Note that quotes must be included around each string value in the list. This is because POV wants POV literals in the 'file' we are passing.
If you want to use an .ini file instead, just call the .ini file in place of the .pov file and everything will work as expected.
If you want more or less variable to be passed to the POV file, add or remove variable names from the #read directive and extend or trim the number you are passing to the same length.'
You can also pass shell variables like this. If foo contains "hello" including the quotes, and "example.pov" is expecting one string in the herestring, then
povray "example.pov" <<<$foo
will pass hello to the variable in the #read directive.
Additionally, you can other POV literals than stings, in that case use the relevant POV syntax the that literal type. However, you can't put POV expressions into the herestring. See the wiki page for more information.
As of POV-Ray 3.7 you can now declare constants in the INI file, and therefore the command line, with Declare=MyValue=24. This would be the same as a #declare MyValue=24; in a scene file. The value on the right-hand side must be a constant float value.
see the relevant manual entry
As long as you don't pass fractional values (or use extremely large sequence numbers), you should be able to use this as a component in the file name.

dynamically allocate variables in bash

I've encountered a problem in my bash script.
I need to assign new variables according to files in my folder and assign them a number according to the amount of arguments the script gets (whether it's a script or not).
I'm trying to get a script written like this:
n_${array[*]}=`arg_count ${array[*]}`
while arg_count checks how many parameters a script gets.
for further use, I'm going to change those variables if there's a function with different arguments needed.
Thanks in advance!
In general, you can use the declare builtin to accomplish this, because it is a command whose argument is a string that resembles an assignment.
declare "n_${array[*]}=$(arg_count ${array[*]})"
However, note that unless you set IFS appropriately and the array contents are amenable, the expansion of ${array[*]} isn't going to be a string that forms part of a valid identifier.
You probably want to either use an associative array,
declare -A n
n[${array[*]}]=$(arg_count ${array[*]})
or write your code in a programming language that properly supports data structures.

How to parse a word in shell script

I want to parse the following word in shell script
VERSION=METER1.2.1
Here i want to split it as two words as
WORD1=METER
WORD2=1.2.1
Let me help how to parse it?
Far more efficient than using external tools such is sed is bash's built-in parameter expansion support. For instance, if you want the name variable to contain everything until the first number, and the numbers variable to contain everything after the last alpha character:
version=METER1.2.1
name=${version%%[0-9]*}
numbers=${version##*[[:alpha:]]}
To understand this, see the BashFAQ entry on string manipulation in general, or the BashFAQ entry on parameter expansion in particular.

Bash variable concatenation

Which form is most efficient?
1)
v=''
v+='a'
v+='b'
v+='c'
2)
v2='a'` `'b'` `'c'
Assuming readability were exactly the same to you, and that's a stretch, would 1) mean creating and throwing away a few string immutables (like in Python) or act as a Java "StringBuffer" with periodical expansion of the buffer capacity? How are string concatenations handled internally in Bash?
If 2) were just as readable to you as 1), would the backticks spawn subshells and would that be more costly, even as a potential 'no-op' than what is done in 1) ?
Well, the simplest and most efficient mechanism would be option 0:
v="abc"
The first mechanism involves four assignments.
The second mechanism is bizarre (and is definitely not readable). It (nominally) runs an empty command in two sub-shells (the two ` ` parts) and concatenates the outputs (an empty string) with the three constants. If the shell simply executes the back-tick commands without noting that they're empty (and it's not unreasonable that it won't notice; it is a weird thing to try — I don't recall seeing it done in my previous 30 years of shell scripting), this is definitely vastly slower.
So, given only options (1) and (2), use option (1), but in general, use option (0) shown above.
Why would you be building up the string piecemeal like that? What's missing from your example that makes the original code sensible but the reduced code shown less sensible.
v=""
x=$(...)
v="$v$x"
y=$(...)
v="$v$y"
z=$(...)
v="$v$z"
This would make more sense, especially if you use each of $x, $y and $z later, and/or use intermediate values of $v (perhaps in the commands represented by triple dots). The concatenation notation used will work with any Bourne-shell derivative; the alternative += shell will work with fewer shells, but is probably slightly more efficient (with the emphasis on 'slightly').
The portable and straight forward method would be to use double quotes and curly brackets for variables:
VARA="beginning text ${VARB} middle text ${VARC}..."
you can even set default values for empty variables this way
VARA="${VARB:-default text} substring manipulation 1st 3 characters ${VARC:0:3}"
using the curly brackets prevents situations where there is a $VARa and you want to write ${VAR}a but end up getting the contents of ${VARa}

Resources