2 New tmux solution
source | link

Building uponI combined ideas Sato Katsura's answerand Stéphane Chazelas's answers into a script, thiswhich is aliased to sr (for "Select Result"). It can be called after a command that outputs paths line by line to stdout. For example

$ locate genomics
/home/user/articles/macaulay_voet_2014_plos_genetics.pdf
/home/user/articles/shmulevich_et_al_2003_comparative_functional_genomics.pdf

$ sr zh
1) /home/user/articles/macaulay_voet_2014_plos_genetics.pdf
2) /home/user/articles/shmulevich_et_al_2003_comparative_functional_genomics.pdf
#? 

The script then waits for me to type a number and press enter, after which it opens that item in the program specified as the first argument (in this case zathura, for which I have defined the shorthand zh in the script). I am currentlyhave yet to test this extensively, but it is doing everything I want at the moment.

My current solution requires tmux, since it can access the output of the last command without rerunning it (by copying from the terminal). Similar solutions exist for screen as shown in Stéphane Chazelas' answer. If using neither of these, one could simply get the last command from history and then evaluate it again in the select statement. Below is the full script.

#!/usr/bin/env bash 

# Enumerate stdout from the previous search command line by line.
# Enable opening a file by passing the desired opening program as an
# argument and then select a number from the output.
# Defaults to using `xdg-open` when no argument is passed.
# Does only work for stdout that list the full path to a file or relative 
# the directory this script is being called from.

# Aliases are not expanded within bash scripts.
# Create a few aliases instead of importing entire alias file.
if [[case $1 ==in
 '' ]]; then '' )
        opener='xdg-open'
elif [[ $1 == 'vi' ]]; then  ;;
    'vi' )
        opener='nvim'
elif [[ $1 == 'zh' ]]; then  ;;
    'zh' )
        opener='zathura'
else        ;;
    * )
        opener=$1
fiesac

# The default split delimiter in bash is any whitespace. Change this
# to only split on newline in order to account for filenames with spaces.
old_IFS="$IFS"
IFS=$'\n'

# Retrive the second last command fromUse mytmux historyto filecopy (the last
# command is calling thisparagraph script)above. `cut` removes the numberThis ofspecific thenavigation commandsequence
# Somethingonly likeworks `$(evalif 'fceach -lnprompt -1')`is couldprefaced bewith useda newline, butsuch mightas givefrom unexpectedhaving
# results`precmd() with{ sharedprint history"" }` in zsh`.zshrc`
last_command=$(tailtmux copy-2 ~/.zsh_historymode
tmux |send-keys head2 -1{ |3 cutj -d0 ';'space -f} 2-)enter
# The eval constructResults isare necessarysaved toin runan thearray commandfor withclarity
search_results+=$(tmux itssave-buffer arguments-)
select fname in $(eval $last_command);$search_results; do
    if [ '"$fname"' ]; then
        $opener "$fname"
        break
    fi
done

# Set IFS back to deafultdefault
IFS="$old_IFS"

I have aliased this script to sr (for "Select Result"), and it needs to be called after a command that lists files line by line to stdout. For example

$ locate genomics
/home/user/articles/macaulay_voet_2014_plos_genetics.pdf
/home/user/articles/shmulevich_et_al_2003_comparative_functional_genomics.pdf

$ sr zh
1) /home/user/articles/macaulay_voet_2014_plos_genetics.pdf
2) /home/user/articles/shmulevich_et_al_2003_comparative_functional_genomics.pdf
#? 

The script then waits for me to type a number and press enter, after which it opens that item in the program specified as the first argument (in this case zathura, for which I have defined the shorthand zh in the script). I have still to test this extensively, but it is doing everything I want at the moment.

Building upon Sato Katsura's answer, this is the script I am currently using

#!/bin/bash
# Enumerate stdout from the previous search command line by line.
# Enable opening a file by passing the desired opening program as an
# argument and then select a number from the output.
# Defaults to using `xdg-open` when no argument is passed.
# Does only work for stdout that list the full path to a file or relative 
# the directory this script is being called from.

# Aliases are not expanded within bash scripts.
# Create a few aliases instead of importing entire alias file.
if [[ $1 == '' ]]; then
    opener='xdg-open'
elif [[ $1 == 'vi' ]]; then
    opener='nvim'
elif [[ $1 == 'zh' ]]; then
    opener='zathura'
else
    opener=$1
fi

# The default split delimiter in bash is any whitespace. Change this
# to only split on newline in order to account for filenames with spaces.
old_IFS="$IFS"
IFS=$'\n'

# Retrive the second last command from my history file (the last
# command is calling this script). `cut` removes the number of the command
# Something like `$(eval 'fc -ln -1')` could be used, but might give unexpected
# results with shared history in zsh.
last_command=$(tail -2 ~/.zsh_history | head -1 | cut -d ';' -f 2-)
# The eval construct is necessary to run the command with its arguments
select fname in $(eval $last_command); do
    if [ '"$fname"' ]; then
        $opener "$fname"
        break
    fi
done

# Set IFS back to deafult
IFS="$old_IFS"

I have aliased this script to sr (for "Select Result"), and it needs to be called after a command that lists files line by line to stdout. For example

$ locate genomics
/home/user/articles/macaulay_voet_2014_plos_genetics.pdf
/home/user/articles/shmulevich_et_al_2003_comparative_functional_genomics.pdf

$ sr zh
1) /home/user/articles/macaulay_voet_2014_plos_genetics.pdf
2) /home/user/articles/shmulevich_et_al_2003_comparative_functional_genomics.pdf
#? 

The script then waits for me to type a number and press enter, after which it opens that item in the program specified as the first argument (in this case zathura, for which I have defined the shorthand zh in the script). I have still to test this extensively, but it is doing everything I want at the moment.

I combined ideas Sato Katsura's and Stéphane Chazelas's answers into a script, which is aliased to sr (for "Select Result"). It can be called after a command that outputs paths line by line to stdout. For example

$ locate genomics
/home/user/articles/macaulay_voet_2014_plos_genetics.pdf
/home/user/articles/shmulevich_et_al_2003_comparative_functional_genomics.pdf

$ sr zh
1) /home/user/articles/macaulay_voet_2014_plos_genetics.pdf
2) /home/user/articles/shmulevich_et_al_2003_comparative_functional_genomics.pdf
#? 

The script then waits for me to type a number and press enter, after which it opens that item in the program specified as the first argument (in this case zathura, for which I have defined the shorthand zh in the script). I have yet to test this extensively, but it is doing everything I want at the moment.

My current solution requires tmux, since it can access the output of the last command without rerunning it (by copying from the terminal). Similar solutions exist for screen as shown in Stéphane Chazelas' answer. If using neither of these, one could simply get the last command from history and then evaluate it again in the select statement. Below is the full script.

#!/usr/bin/env bash 

# Enumerate stdout from the previous search command line by line.
# Enable opening a file by passing the desired opening program as an
# argument and then select a number from the output.
# Defaults to using `xdg-open` when no argument is passed.
# Does only work for stdout that list the full path to a file or relative
# the directory this script is being called from.

# Aliases are not expanded within bash scripts.
# Create a few aliases instead of importing entire alias file.
case $1 in
    '' )
        opener='xdg-open'
        ;;
    'vi' )
        opener='nvim'
        ;;
    'zh' )
        opener='zathura'
        ;;
    * )
        opener=$1
esac

# The default split delimiter in bash is any whitespace. Change this
# to only split on newline in order to account for filenames with spaces.
old_IFS="$IFS"
IFS=$'\n'

# Use tmux to copy the paragraph above. This specific navigation sequence
# only works if each prompt is prefaced with a newline, such as from having
# `precmd() { print "" }` in `.zshrc`
tmux copy-mode
tmux send-keys 2 { 3 j 0 space } enter
# Results are saved in an array for clarity
search_results+=$(tmux save-buffer -)
select fname in $search_results; do
    $opener "$fname"
    break
done

# Set IFS back to default
IFS="$old_IFS"
1
source | link

Building upon Sato Katsura's answer, this is the script I am currently using

#!/bin/bash
# Enumerate stdout from the previous search command line by line.
# Enable opening a file by passing the desired opening program as an
# argument and then select a number from the output.
# Defaults to using `xdg-open` when no argument is passed.
# Does only work for stdout that list the full path to a file or relative 
# the directory this script is being called from.

# Aliases are not expanded within bash scripts.
# Create a few aliases instead of importing entire alias file.
if [[ $1 == '' ]]; then
    opener='xdg-open'
elif [[ $1 == 'vi' ]]; then
    opener='nvim'
elif [[ $1 == 'zh' ]]; then
    opener='zathura'
else
    opener=$1
fi

# The default split delimiter in bash is any whitespace. Change this
# to only split on newline in order to account for filenames with spaces.
old_IFS="$IFS"
IFS=$'\n'

# Retrive the second last command from my history file (the last
# command is calling this script). `cut` removes the number of the command
# Something like `$(eval 'fc -ln -1')` could be used, but might give unexpected
# results with shared history in zsh.
last_command=$(tail -2 ~/.zsh_history | head -1 | cut -d ';' -f 2-)
# The eval construct is necessary to run the command with its arguments
select fname in $(eval $last_command); do
    if [ '"$fname"' ]; then
        $opener "$fname"
        break
    fi
done

# Set IFS back to deafult
IFS="$old_IFS"

I have aliased this script to sr (for "Select Result"), and it needs to be called after a command that lists files line by line to stdout. For example

$ locate genomics
/home/user/articles/macaulay_voet_2014_plos_genetics.pdf
/home/user/articles/shmulevich_et_al_2003_comparative_functional_genomics.pdf

$ sr zh
1) /home/user/articles/macaulay_voet_2014_plos_genetics.pdf
2) /home/user/articles/shmulevich_et_al_2003_comparative_functional_genomics.pdf
#? 

The script then waits for me to type a number and press enter, after which it opens that item in the program specified as the first argument (in this case zathura, for which I have defined the shorthand zh in the script). I have still to test this extensively, but it is doing everything I want at the moment.