How to add all tab completitions to my current command? - zsh

So I've typed a command (pacman -S perl-) and I hit tab and see that there are a whole bunch of completions (about 40), and I realize that I want to run every single completion (so I don't accidentally install from CPAN what is already a builtin).
How do I run all completions of a command?
BONUS: How do I run more than one and less than all of the commands (without typing them in individually)?
Example situation (the actual situation):
XXXXXXXXXXXXXXXXX ❯❯❯ pacman -S perl-<Tab> ⏎
-- packages --
perl perl-IPC-Run3
perl-ack perl-libwww
perl-Archive-Zip perl-Locale-Gettext
perl-Authen-SASL perl-LWP-MediaTypes
perl-Benchmark-Timer perl-LWP-Protocol-https
perl-Capture-Tiny perl-MailTools
perl-common-sense perl-MIME-tools
perl-Compress-Bzip2 perl-Mozilla-CA
perl-Convert-BinHex perl-Net-DNS
perl-Crypt-SSLeay perl-Net-HTTP
perl-DBI perl-Net-IP
perl-Digest-HMAC perl-Net-SMTP-SSL
perl-Encode-Locale perl-Net-SSLeay
perl-Error perl-Path-Class
perl-Exporter-Lite perl-Probe-Perl
perl-ExtUtils-Depends perl-Regexp-Common
perl-ExtUtils-PkgConfig perl-Socket6
perl-File-Copy-Recursive perl-Sys-CPU
perl-File-Listing perl-TermReadKey
perl-File-Next perl-Test-Pod
perl-File-Which perl-Test-Script
perl-Getopt-Tabular perl-TimeDate
perl-HTML-Parser perl-Try-Tiny
perl-HTML-Tagset perl-URI
perl-HTTP-Cookies perl-WWW-RobotRules
perl-HTTP-Daemon perl-XML-LibXML
perl-HTTP-Date perl-XML-NamespaceSupport
perl-HTTP-Message perl-XML-Parser
perl-HTTP-Negotiate perl-XML-SAX
perl-IO-HTML perl-XML-SAX-Base
perl-IO-Socket-INET6 perl-XML-Simple
perl-IO-Socket-SSL perl-YAML
perl-IO-stringy perl-YAML-Syck

Here is my own solution to deal with,
To apply matching for completion results.
To insert all the completion matches into the command line.
To activate menu selection and select the completion more than one.
To apply matching for completion results, it could be done with the _match.
Here is an example ~/.zshrc:
# below is same as the zsh default effect
# zstyle ':completion:*::::' completer _complete _ignored
zstyle ':completion:*::::' completer _complete _match _ignored
# I don't like expand-or-complete to <Tab>, so I moved it to <C-x><Tab>
bindkey '^I' complete-word
bindkey '^X^I' expand-or-complete
Now, it could be ok to use *s to get the effects like this:
% ls m*e* ;# I have some local files that matches the glob.
main.epro mem.c mem.pro modentry.c module.o modules.stamp
makepro.awk mem.epro mem.syms module.c module.pro
math.epro mem.o mkmakemod.sh module.epro module.syms
% git m*e*<Tab>
;# This prompts completions rather than expands the local files
;# like this:
% git merge
merge -- join two or more development histories together
merge-base -- find as good a common ancestor as possible for a merge
merge-file -- run a three-way file merge
merge-index -- run merge for files needing merging
merge-one-file -- standard helper-program to use with git merge-index
merge-tree -- show three-way merge without touching index
mergetool -- run merge conflict resolution tools to resolve merge conflicts
mktree -- build tree-object from git ls-tree formatted text
m*e*
To insert all the compliteon matches into the command line, it cloud be done with the all-matches. If you have the below snippets in your ~/.zshrc:
zle -C all-matches complete-word _my_generic
zstyle ':completion:all-matches::::' completer _all_matches
zstyle ':completion:all-matches:*' old-matches only
_my_generic () {
local ZSH_TRACE_GENERIC_WIDGET= # works with "setopt nounset"
_generic "$#"
}
bindkey '^X^a' all-matches
typing Tab then Control-x,Control-a inserts the completion matches to the command line.
For example:
% vim string.<Tab>
string.c string.epro string.syms
;# then hit <C-x><C-a>
% vim string.c string.epro string.syms
To activate menu selection and select the completion more than one, it could be done by customizing menuselect keymap.
(From zhmodules(1) 22.7.3 Menu selection)
zstyle ':completion:*' menu select=0
zmodload zsh/complist
bindkey -M menuselect "^[a" accept-and-hold
bindkey -M menuselect '^[^[' vi-insert
This activete menu selection for the completion results. During the menu selection is active, typing M-a (or Esc-a) inserts the selected entry and advances the "menu cursor" to next entry.
For example session:
% ls sig*
sigcount.h signals.h signals.syms signames.o signames1.awk
signals.c signals.o signames.c signames.pro signames2.awk
signals.epro signals.pro signames.epro signames.syms
% vim sig<Tab> ;# this lists the matches
sigcount.h signals.epro signals.syms signames.epro signames1.awk
signals.c signals.h signames.c signames.syms signames2.awk
;# hitting <Tab> second time, the "menu cursor" appears and
;# the first entry will be activated
;# Note: "[[]]" denotes the "menu cursor" here
% vim sigcount.h
[[sigcount.h]] signals.epro signals.syms signames.epro signames1.awk
signals.c signals.h signames.c signames.syms signames2.awk
;# then hit <M-a>(Esc a)
;# "sigcount.h" is now in the command line and
;# the "menu cursor" points "signals.c" now.
% vim sigcout.h signals.c
sigcount.h signals.epro signals.syms signames.epro signames1.awk
[[signals.c]] signals.h signames.c signames.syms signames2.awk
;# then <Tab><Tab>
% vim sigcount.h signals.h
sigcount.h signals.epro signals.syms signames.epro signames1.awk
signals.c [[signals.h]] signames.c signames.syms signames2.awk
So, you could select multiple entries in the completion results to hit M-a(or Esc-a) as you like.
Below paragraph is not bad to know.
In this expample configration, hitting EscEsc (we did bindkey -M menuselect '^[^[' vi-insert in the above snippets) while the menu selection is active, it allows us to interactively limit the completion result based on input patterns.
;# activate "menu selection" and hit <Esc><Esc>,
;# the "interacitve:" mode will be shown at this point.
% vim sig*
interactive: sig[]
[[sigcount.h]] signals.epro signals.syms signames.epro signames1.awk
signals.c signals.h signames.c signames.syms signames2.awk
;# hitting "*awk" while interactive is activetad,
;# it colud limit the completion to "sig*awk"
% vim sig*awk
interactive: sig[]
[[signames1.awk]]signames2.awk
sig*awk
I'm not sure I describe correctly, so here is the portion of the zsh doc for the menu selection's "interactive mode".
vi-insert
this toggles between normal and interactive mode; in interactive mode the keys bound to self-insert and self-insert-unmeta insert into the command line as in normal editing mode but without leaving menu selection; after each character completion is tried again and the list changes to contain only the new matches; the completion widgets make the longest unambiguous string be inserted in the command line and undo and backward-delete-char go back to the previous set of matches
-- zhmodules(1) 22.7.3 Menu selection
It could be fine to see also edit-command-line for dealing with quite big command line buffers.
Now on my debian system, I can get the below effect:
# apt-get install perl-*<Tab><C-x><C-a><C-w>
;# ⇓
# apt-get install perl-base perl-byacc perl-cross-debian perl-debug perl-depends perl-doc perl-doc-html perl-modules perl-stacktrace perl-tk

I've found a solution to my problem, and it gets the job done, but it's not the kind of solution that I want.
I selected the completion text on my screen (I'm using mintty) and copied it into my editor. I then reformatted it like so:
perl perl-IPC-Run3 \
perl-ack perl-libwww \
perl-Archive-Zip perl-Locale-Gettext \
perl-Authen-SASL perl-LWP-MediaTypes \
perl-Benchmark-Timer perl-LWP-Protocol-https \
perl-Capture-Tiny perl-MailTools \
perl-common-sense perl-MIME-tools \
perl-Compress-Bzip2 perl-Mozilla-CA \
perl-Convert-BinHex perl-Net-DNS \
perl-Crypt-SSLeay perl-Net-HTTP \
perl-DBI perl-Net-IP \
perl-Digest-HMAC perl-Net-SMTP-SSL \
perl-Encode-Locale perl-Net-SSLeay \
perl-Error perl-Path-Class \
perl-Exporter-Lite perl-Probe-Perl \
perl-ExtUtils-Depends perl-Regexp-Common \
perl-ExtUtils-PkgConfig perl-Socket6 \
perl-File-Copy-Recursive perl-Sys-CPU \
perl-File-Listing perl-TermReadKey \
perl-File-Next perl-Test-Pod \
perl-File-Which perl-Test-Script \
perl-Getopt-Tabular perl-TimeDate \
perl-HTML-Parser perl-Try-Tiny \
perl-HTML-Tagset perl-URI \
perl-HTTP-Cookies perl-WWW-RobotRules \
perl-HTTP-Daemon perl-XML-LibXML \
perl-HTTP-Date perl-XML-NamespaceSupport \
perl-HTTP-Message perl-XML-Parser \
perl-HTTP-Negotiate perl-XML-SAX \
perl-IO-HTML perl-XML-SAX-Base \
perl-IO-Socket-INET6 perl-XML-Simple \
perl-IO-Socket-SSL perl-YAML \
perl-IO-stringy perl-YAML-Syck
And pasted it back into my terminal after pacman -S.
I've said that this isn't the kind of solution that I want, and so I should mention the sort of solution I'm looking for.
I'm looking for something like pacman -S perl-* which looks like it might glob up all of the completions or something (It doesn't).

Related

reverse search history with fzf requires an extra enter to be printed on the prompt

I'm trying to write a zsh bindkey in order to reverse-search into the history with fzf:
This is an excerpt of my loaded .zshrc:
function _reverse_search() {
local selected_command=$(fc -rl 1 | awk '{$1=""; print substr($0,2)}' | sort --unique | fzf --height=10 )
print -z -- "${selected_command}"
}
zle -N _reverse_search
bindkey '^r' _reverse_search
when pressed ^r this is what happens: a second enter after the selection must be pressed in order to come back to the prompt and see the selecred command:
how could I avoid the extra enter?

Is any way serah match value from root node by xmlstarlet and return XPATH

As title
I am resarch xmlstartle, but seems no way to serach value from root node then return XPATH
Is any idea?
ThanksPeter
Perhaps you can make use of this example which handles elements and
attributes but not other node types. Assuming a POSIX shell,
indentation and line continuation characters added for readability.
xmlstarlet select --text -t \
-m '//xsl:*/#test[contains(.,"position")]' \
-m 'ancestor-or-self::*' \
--var pos='1+count(preceding-sibling::*[name() = name(current())])' \
-v 'concat("/",name(),"[",$pos,"]")' \
-b \
--if 'count(. | ../#*) = count(../#*)' \
-v 'concat("/#",name())' \
-b \
-n \
/usr/share/*/xslt/docbook/common/db-common.xsl
Where:
the outer -m (--match) option specifies the target, with optional
search conditions given as
predicates
the inner -m (--match) builds the XPath of elements from root to target,
calculating position by counting siblings
for an attribute node target - which doesn't match ancestor-or-self::* -
the -i (--if) clause adjusts the XPath
a -C (--comp) option before -t lists the generated XSLT code
Output:
/xsl:stylesheet[1]/xsl:template[2]/xsl:for-each[1]/xsl:if[1]/#test
/xsl:stylesheet[1]/xsl:template[3]/xsl:for-each[1]/xsl:if[1]/#test
/xsl:stylesheet[1]/xsl:template[7]/xsl:for-each[1]/xsl:choose[1]/xsl:when[1]/#test
/xsl:stylesheet[1]/xsl:template[7]/xsl:for-each[1]/xsl:choose[1]/xsl:when[3]/#test
Output from outer -m '//xsl:param[string(#select)]':
/xsl:stylesheet[1]/xsl:template[1]/xsl:param[1]
/xsl:stylesheet[1]/xsl:template[4]/xsl:param[1]
/xsl:stylesheet[1]/xsl:template[5]/xsl:param[1]
/xsl:stylesheet[1]/xsl:template[5]/xsl:param[2]
/xsl:stylesheet[1]/xsl:template[6]/xsl:param[1]

zscroll text in the tmux status bar

I am trying to configure my .tmux.conf to display a scrolling string of text. For what it is worth, the scrolling text is an aviation weather observation that is scraped using a really ugly bash script that is defined in .zshrc as follows:
function scrollMetar {
curl -s "https://www.aviationweather.gov/metar/data?ids=kjyo&format=raw&date=&hours=0" | awk '/Data\ starts\ here/{getline; print}' | html2text | zscroll -l 14 -n 0
}
I want to take the scrolling output from the scrollMetar command and have that scroll on the tmux status line.
My current .tmux.conf section looks like this:
set-option -g status-left "\
#[fg=colour7, bg=colour241]#{?client_prefix,#[bg=colour167],} ❐ #S \
#[fg=colour241, bg=colour237] \
#(echo 'TEST TEXT') \
#{?window_zoomed_flag, 🔍,} "
Where the echo 'TEST TEXT' is should be where the scrollMetar would go, but when inserted doesn't output anything.
I am guessing that this maybe a limitation of tmux, but I would be grateful for any advice and I am completely open to alternate implementations.
Okay, so it seems like .tmux.conf did not like calling the function, or could not find it. Putting the function in a executable shell script fixed the problem.

Inserting a newline in a multiline zsh command pulled from history

Sometimes I use multiline commands in zsh:
❯ echo \
> a \
> multiline \
> command
When editing the command after pulling it from a history search, I can change the content of individual lines. However, I can't figure out how to insert another line:
# I want to insert another line after "multiline"...
❯ echo \
> a \
> multiline \ # but hitting <return> here just runs the command, even though there's a backslash at the end of the line
> command
How can I insert a newline in the middle of a multiline command pulled from history?
You can use ESC-Return.
FWIW, I tested it on Debian Jessie, zsh 5.0.7 and it works there.
You can use self-insert-unmeta to bind Alt+Return to insert a literal newline without accepting the command:
bindkey '^[^M' self-insert-unmeta
To use your example: Hitting Alt+Return at the cursor position (#)
% echo \
a \
multiline \#
command
will get you this:
% echo \
a \
multiline \
#
command
This works not only when editing history, but also when typing commands. So you can prepare several commands in a script like fashion and accept them with a single Return.
For example pressing Alt+Return instead of # in this example:
% echo command 1#
echo command 2#
echo command 3
will do the same thing as the command echo command 1; echo command 2; echo command 3 and produce this output:
command 1
command 2
command 3
(A summary of answers from https://unix.stackexchange.com/questions/6620/how-to-edit-command-line-in-full-screen-editor-in-zsh)
zsh comes with a function that can be used to open the current command line in your favorite editor. Add the following lines to your .zshrc:
autoload -z edit-command-line
zle -N edit-command-line
bindkey "^X^E" edit-command-line
The first line loads the function. The second line creates a new widget for the Z shell line editor (zle) from the function of the same name. The third line binds the widget to Control-X Control-E. If you use the vi bindings rather than emacs key bindings, use something like
bindkey -M vicmd v edit-command-line
instead (which binds the widget to v in vicmd mode).
If using bindkey -v mode, you can also use the default o/O commands from vicmd mode to add a newline line and enter insert mode in it, respectively above or below the current line.
Just to note, if you want to comment in a multiline command, you could use:
❯ echo `#first comment` \
a `#second comment` \
multiline \
command
CTRL + Enter (Return) for Windows/WSL
CTRL +X CTRL+E for Mac
Edited as per the comment below
Sounds like an appropriate place to use a shell script file instead no?
#!/bin/zsh
my
commands
here
I can even add a new line at a later time.

How can I send selected text (or a line) in TextMate2 to R running on Terminal

As you know version 2 of TextMate is on the way and the current development version is very promising: https://github.com/textmate/textmate/blob/master/README.md
In my case I am using R in terminal (MacOSX Mountain Lion) and I develop my code with TextMate2. With the previous version of TextMate (1.5.11) I used the following trick to send selected text or lines to my terminal window:
-> See How can I send selected text (or a line) in TextMate to R running on Terminal
This trick worked perfectly for me but I cannot figure out how to get a similar behaviour with TextMate2.
Any idea? I thank you in advance for your precious help.
Actually based on a previous answer (How can I send selected text (or a line) in TextMate to R running on Terminal), I created my own Bundle in TextMate 2 using the following code:
#!/bin/bash
source "$TM_SUPPORT_PATH/lib/bash_init.sh" # might not be necessary
# input is selection or document
rawText="$(cat | sed 's/ / /g;')"
osascript -e 'on run(theCode)' \
-e ' tell application "Terminal"' \
-e ' do script theCode in window 1' \
-e ' end tell' \
-e 'end run' -- "$rawText"
open "txmt://open?line=$(($TM_LINE_NUMBER+1))&column=1000000" &
See the screenchot below.
The only problem is that when you select a chunk of text, the cursor is jumping to the first line of the document, which is a very irritating behaviour. Changing 'Input" from 'Line' to 'Selection' doe not solve the issue.
Any thoughts?
This works for me, and it correctly goes to the end of the selection.
I just added the osascript part in the previous answer, and put it in the code that was in the original R bundle written by Hans-Jörg Bibiko.
Set "scope selector" to "source.r" and "output" to "discard".
Set "Input" to "line" and it does what I need: send the line if nothing is selected, and send the selection otherwise.
edit: it works perfectly with selections, but not with line. When you do not select text it just re-runs everything from the top of the file
edit2: solved, I wrote to Hans-Jörg Bibiko and he pointed me to the "Input" selection.
#!/usr/bin/env bash
# input is selection or document
rawText="$(cat | sed 's/ / /g;')"
curDir=''
if [[ ${#TM_DIRECTORY} -gt 0 ]]; then
curDir="$TM_DIRECTORY"
fi
osascript -e 'on run(theCode)' \
-e ' tell application "Terminal"' \
-e ' do script theCode in window 1' \
-e ' end tell' \
-e 'end run' -- "$rawText"
if [ "$TM_LINE_NUMBER" != "" ]; then
"$TM_MATE" -l "$(($TM_LINE_NUMBER+1)):1000000"
elif [[ $TM_SELECTION =~ [1-9][0-9]*:?[0-9]*-([1-9][0-9]*):?[0-9]* ]]; then
# Regular Selection
"$TM_MATE" -l "$((${BASH_REMATCH[1]}+1)):1000000"
elif [[ $TM_SELECTION =~ [1-9][0-9]*:?[0-9]*x([1-9][0-9]*):?[0-9]* ]]; then
# Block (option) selection
"$TM_MATE" -l "$((${BASH_REMATCH[1]}+1)):1000000"
else
"$TM_MATE"
fi
A bit of an indirect answer : I use the R bundle in Textmate 2 (which also worked in Textmate 1). Just select the lines you want to run and "Send selection to / R App" ( I have it binded to command-R but I'm not sure if it's the original binding)
First time it opens the R app and execute code. Subsequent times it just pastes the code and run it.
It's not exactly "send to terminal" but still works
I got it working with a few changes on bhaibeka's answer. Apparently $TM_LINE_NUMBER is empty and that makes the cursor jump to the first line of the document. By getting rid of the last line, it solves part of the problem.
#!/bin/bash
[[ -f "${TM_SUPPORT_PATH}/lib/bash_init.sh" ]] && . "${TM_SUPPORT_PATH}/lib/bash_init.sh"
rawText="`cat`"
osascript -e 'on run(theCode)' \
-e ' tell application "Terminal"' \
-e ' do script theCode in window 1' \
-e ' end tell' \
-e 'end run' -- "$rawText" > /dev/null
The other problem is how to move the cursor to the end of the selection. I made it work by inserting the 'empty' output at the end of the selection (on the right panel: Output:"Insert After Input" and Format: "Text"). Probably this is not the most elegant way to do it but it works.

Resources