Define initial input for zsh read builtin - zsh

Bash's builtin read command has a -i option, which specifies an initial input, which the user can accept as it is or edit or add to. I cannot find anything similar for Zsh's read command.
None of the options listed in the zshbuiltins man page seem relevant:
read [ -rszpqAclneE ] [ -t [ num ] ] [ -k [ num ] ] [ -d delim ]
[ -u n ] [ name[?prompt] ] [ name ... ]
Read one line and break it into fields using the characters in $IFS as separators, except as noted below. The first field is assigned to the first name, the second field to
the second name, etc., with leftover fields assigned to the last name. If name is omitted then REPLY is used for scalars and reply for arrays.
-r Raw mode: a `\' at the end of a line does not signify line continuation and backslashes in the line don't quote the following character and are not removed.
-s Don't echo back characters if reading from the terminal.
-q Read only one character from the terminal and set name to `y' if this character was `y' or `Y' and to `n' otherwise. With this flag set the return status is zero only
if the character was `y' or `Y'. This option may be used with a timeout (see -t); if the read times out, or encounters end of file, status 2 is returned. Input is
read from the terminal unless one of -u or -p is present. This option may also be used within zle widgets.
-k [ num ]
Read only one (or num) characters. All are assigned to the first name, without word splitting. This flag is ignored when -q is present. Input is read from the ter-
minal unless one of -u or -p is present. This option may also be used within zle widgets.
Note that despite the mnemonic `key' this option does read full characters, which may consist of multiple bytes if the option MULTIBYTE is set.
-z Read one entry from the editor buffer stack and assign it to the first name, without word splitting. Text is pushed onto the stack with `print -z' or with push-line
from the line editor (see zshzle(1)). This flag is ignored when the -k or -q flags are present.
-e
-E The input read is printed (echoed) to the standard output. If the -e flag is used, no input is assigned to the parameters.
-A The first name is taken as the name of an array and all words are assigned to it.
-c
-l These flags are allowed only if called inside a function used for completion (specified with the -K flag to compctl). If the -c flag is given, the words of the cur-
rent command are read. If the -l flag is given, the whole line is assigned as a scalar. If both flags are present, -l is used and -c is ignored.
-n Together with -c, the number of the word the cursor is on is read. With -l, the index of the character the cursor is on is read. Note that the command name is word
number 1, not word 0, and that when the cursor is at the end of the line, its character index is the length of the line plus one.
-u n Input is read from file descriptor n.
-p Input is read from the coprocess.
-d delim
Input is terminated by the first character of delim instead of by newline.
-t [ num ]
Test if input is available before attempting to read. If num is present, it must begin with a digit and will be evaluated to give a number of seconds, which may be a
floating point number; in this case the read times out if input is not available within this time. If num is not present, it is taken to be zero, so that read returns
immediately if no input is available. If no input is available, return status 1 and do not set any variables.
This option is not available when reading from the editor buffer with -z, when called from within completion with -c or -l, with -q which clears the input queue before
reading, or within zle where other mechanisms should be used to test for input.
Note that read does not attempt to alter the input processing mode. The default mode is canonical input, in which an entire line is read at a time, so usually `read
-t' will not read anything until an entire line has been typed. However, when reading from the terminal with -k input is processed one key at a time; in this case,
only availability of the first character is tested, so that e.g. `read -t -k 2' can still block on the second character. Use two instances of `read -t -k' if this is
not what is wanted.
If the first argument contains a `?', the remainder of this word is used as a prompt on standard error when the shell is interactive.
The value (exit status) of read is 1 when an end-of-file is encountered, or when -c or -l is present and the command is not called from a compctl function, or as described
for -q. Otherwise the value is 0.
The behavior of some combinations of the -k, -p, -q, -u and -z flags is undefined. Presently -q cancels all the others, -p cancels -u, -k cancels -z, and otherwise -z can-
cels both -p and -u.
The -c or -l flags cancel any and all of -kpquz.
How can I achieve the same goal in Zsh?

In zsh you could manually set the variable and use vared instead of read:
name=iconoclast
vared -p "Enter your name: " name
This is the equivalent of the following in bash:
read -p "Enter your name: " -e -i iconoclast name

Related

ZSH completion matching control : fuzzy match on one part of input

I'm writing a zsh completion for some program, and parts of it involves completing resource routes (/they/look/like/this).
I have a command mycmd that I can use to generate some completion candidates of resource routes, and provide completions for my program, using:
_multi_parts '/' "($(mycmd /some/resource/id))"
Now, I would like to implement a specific behavior to match resources that contain the last identifier in my query, not only those that start with it.
For example, $(mycmd "/resource/identifier/bc") gives completions like :
/resource/identifier/abc456/
/resource/identifier/123abcXYZ/
We get resource names whose identifier contains bc, which is the intended behavior.
Now here is the problem: zsh completion prevents these completions from showing up, because none of them matches "/resource/identifier/bc*", the default pattern for zsh.
I read the documentation for ZSH _multi_parts , compadd. It appears that using -M <pattern> described in compadd doc and available for _multi_parts could do the trick, by specifying a custom pattern for completion as described in ZSH Matching Control documentation. However this doc is lacking useful examples and is overall very obscure to me.
I spent hours of trials and errors to find the right pattern argument for _multi_parts -M <pattern> to achieve what I want with no success. Any hint on this would be much appreciated.
EDIT: actually, simply ignoring the last resource identifier bc would also work. I did not manage to do this either using -M.
Finally found out how to do this. The correct specification is:
_multi_parts -M 'l:|=*' '/' $completions
The pattern l:|=* allows to recognize matches which contain extra character after the string on the command line.
Looking at zsh completion log below (C-x ?), we find that it also uses patterns r:|/=* r:|=*.
In my understanding, using both r:|=* and l:|=* allows recognizing any completion candidate -- which is fine in my case, since filtering relevant suggestions is done with $mycmd.
Extract from ZSH completion log:
+_multi_parts:94> compadd -O tmp1 -M 'r:|/=* r:|=* l:|=*' - ENSG00000170615_SLC26A5_NT
+_multi_parts:96> [[ 1 -eq 0 ]]
+_multi_parts:99> [[ 1 -eq 1 ]]
+_multi_parts:106> [[ SLC = */* ]]
+_multi_parts:109> matches=( ENSG00000170615_SLC26A5_NT/ )
+_multi_parts:111> PREFIX=/run/echolocation_example/SLC
+_multi_parts:112> SUFFIX=''
+_multi_parts:114> [[ 0 -ne 0 ]]
+_multi_parts:115> zstyle -t :completion::complete:pelican:argument-2: expand suffix
+_multi_parts:119> (( 1 ))
+_multi_parts:120> compadd -p /run/echolocation_example/ -r / -S / -M 'r:|/=* r:|=* l:|=*' - ENSG00000170615_SLC26A5_NT

Passing variables to grep command in Tcl Script

I'm facing a problem while trying to pass a variable value to a grep command.
In essence, I want to grep out the lines which match my pattern and the pattern is stored in a variable. I take in the input from the user, and parse through myfile and see if the pattern exists(no problem here).
If it exists I want to display the lines which have the pattern i.e grep it out.
My code:
if {$a==1} {
puts "serial number exists"
exec grep $sn myfile } else {
puts "serial number does not exist"}
My input: SN02
My result when I run grep in Shell terminal( grep "SN02" myfile):
serial number exists
SN02 xyz rtw 345
SN02 gfs rew 786
My result when I try to execute grep in Tcl script:
serial number exists
The lines which match the pattern are not displayed.
Your (horrible IMO) indentation is not actually the problem. The problem is that exec does not automatically print the output of the exec'ed command*.
You want puts [exec grep $sn myfile]
This is because the exec command is designed to allow the output to be captured in a variable (like set output [exec some command])
* in an interactive tclsh session, as a convenience, the result of commands is printed. Not so in a non-interactive script.
To follow up on the "horrible" comment, your original code has no visual cues about where the "true" block ends and where the "else" block begins. Due to Tcl's word-oriented nature, it pretty well mandates the one true brace style indentation style.

zsh `history n` displays the first n entries instead of the last n entries

I read the doc for history and it says:
history [n]
history -c
history -d offset
history -anrw [filename]
history -p arg [arg ...]
history -s arg [arg ...]
With no options, display the command history list with line
numbers. Lines listed with a * have been modified. An
argument of n lists only the last n lines.
But in my zsh, it always displays the first n lines. I need to use history | tail -n to show the last few lines.
Is there any option set wrongly? How to correct it?
Moreover, how to print history without line number and time stamp so that I can convert a portion of the history to a script
The documentation for zsh history, in zshbuiltins(1), is:
history
Same as fc -l.
where fc -l is:
fc -l [ -LI ] [ -nrdfEiD ] [ -t timefmt ] [ -m match ] [ old=new ... ] [ first [ last ] ]
If first is not specified, it will be set to -1 (the most recent event), or to -16 if the -l flag is given. If last is not specified, it will be set to first, or to -1 if the -l flag is given. However, if the current event has added entries to the history with print -s or fc -R, then the default last for -l includes all new history entries since the current event began.
When the -l flag is given, the resulting events are listed on standard output.
so run:
history -<n>
with a hyphen-minus, as in history -16, to see the last n lines of history in zsh.

grep -l and grep -ln

according to the manual for grep,
-l, --files-with-matches
Suppress normal output; instead print the name of each input
file from which output would normally have been printed. The
scanning will stop on the first match.
grep -l, this seems fine in that when a match is found, the file name containing the match is echoed.
However when i do a grep -ln, grep echoes every line of the occurrence.
Does grep -l really mean to stop when the first occurrence of the match is found and stop scanning, while grep -ln will ignore the -l flag?
Those options are incompatible. Use grep -Hnm 1 if you want to display the line number of the first match (and only the first match) in each file.
-H, --with-filename
Print the filename for each match.
-n, --line-number
Prefix each line of output with the line number within its input file.
-m NUM, --max-count=NUM
Stop reading a file after NUM matching lines.

Unix strace command

I found the following bash script in order to monitor cp progress.
#!/bin/sh
cp_p()
{
strace -q -ewrite cp -- "${1}" "${2}" 2>&1 \
| awk '{
count += $NF
if (count % 10 == 0) {
percent = count / total_size * 100
printf "%3d%% [", percent
for (i=0;i<=percent;i++)
printf "="
printf ">"
for (i=percent;i<100;i++)
printf " "
printf "]\r"
}
}
END { print "" }' total_size=$(stat -c '%s' "${1}") count=0
}
I don't understand the "-ewrite" option for the strace command. The closest thing I've found is the man page for strace which is
-e write=set Perform a full hexadecimal and ASCII dump of all the
data written to file descriptors
listed in the specified set. For
example, to see all output activity on
file descriptors 3 and 5 use -e
write=3,5. Note that this is
independent from the normal tracing of
the write(2) system call which is
controlled by the option -e
trace=write.
However I don't understand what the -ewrite option does.
-ewrite means that only the "write" system call will be traced.
-e expr A qualifying expression which modifies which events
to trace or how to trace them. The format of the
expression is:
[qualifier=][!]value1[,value2]...
where qualifier is one of trace, abbrev, verbose,
raw, signal, read, or write and value is a quali-
fier-dependent symbol or number. The default qual-
ifier is trace. Using an exclamation mark negates
the set of values. For example, -eopen means lit-
erally -e trace=open which in turn means trace only
the open system call. By contrast, -etrace=!open
means to trace every system call except open. In
addition, the special values all and none have the
obvious meanings.
Note that some shells use the exclamation point for
history expansion even inside quoted arguments. If
so, you must escape the exclamation point with a
backslash.

Resources