516516 ! (( mis))
517517}
518518
519+ randline () {
520+ read -r -d ' ' use << EOF
521+ randline [OPTIONS]
522+ Select a line at random from input and print it.
523+ EOF
524+ # no options just help
525+ local opt OPTIND OPTARG
526+ while getopts " :h" opt; do
527+ case " $opt " in
528+ * )
529+ printf " %s\\ n" " $use " >&2
530+ return 1
531+ ;;
532+ esac
533+ done
534+ # read all lines then print one random line
535+ local lines=()
536+ mapfile -t lines
537+ local pick=$(( RANDOM % ${# lines[@]} ))
538+ printf " %s\\ n" " ${lines[$pick]} " ;
539+ }
540+
519541rleval () {
520542 read -r -d ' ' use << EOF
521543rleval [OPTIONS] COMMAND [ARGS ...]
661683
662684cz () {
663685 # version
664- local ver=" 0.8.5 "
686+ local ver=" 0.8.6 "
665687 # usage
666688 local hows=" " use=" "
667689 read -r -d ' ' use << EOF
@@ -696,7 +718,8 @@ OPTIONS
696718 -0 : Read null terminated lines from input.
697719 -i IN-FILE : Set file from which to read selections instead of stdin.
698720
699- These options control which line selection utility is used:
721+ These options control how lines are selected:
722+ -w : Pick a line at random.
700723 -x : Use a graphical line selection tool.
701724 -y : Use a terminal line selection tool.
702725 -z TOOL : Use the given line selection tool.
@@ -743,16 +766,17 @@ Pick from lines on stdin.:$ printf "%s\\n" foo bar qux | cz
743766Accept null delimited input lines.:$ find . -name '*.yml' -print0 | cz -0
744767Extract useful fields from selected line.:$ cz -q -f 0,5 -d : < /etc/passwd
745768Safely handle input strings containing shell characters.:$ cz -e 'echo -- {0:}' -i <(printf "%s\\ n" '\$ USER' '; false' '\$ (fortune)' '-e')
769+ Pick a line randomly instead of using interactive selecting.:# printf "%s\\ n" {A..Z} | cz -w
746770Add selection to common commands.:$ cz -r -e 'dig {0} AAAA +short' compgen hostname
747- Easily define plugins as bash functions.:$ cz_whois() { cz -e 'whois {0}' -f 0 compgen hostname; }; cz whois
771+ Extend plugins with bash functions.:$ cz_whois() { cz -e 'whois {0}' -f 0 compgen hostname; }; cz whois
748772Select a password and put it on an xclip clipboard.:$ cz pass | cz xclip in
749773Jump to any descendant directory.:$ cd \$ (cz descendant)
750774Jump to any ancestor directory.:$ cd \$ (cz ancestor)
751775Grab a URL from a paste buffer and open it in a browser.:$ cz xclip out | cz -e 'firefox {0}' uri
752776Compose plugins to get the contents of any element from any JSON file.:$ cz -e 'cz jq {0}' locate *.json
753777Compose plugins to get any file under an apparix bookmarked directory.:$ cz -e 'cz find file {1}' apparix
754778Find a file then open it for editing:$ find . -type f -print0 | cz -0 -r -e 'vim {0}'
755- Consult the I Ching.:cz -z shuf -uf0,2 unicode character 'Yijing Hexagram Symbols' | sed 's/HEXAGRAM FOR//'
779+ Consult the I Ching.:cz -u -f0,2 -w unicode character 'Yijing Hexagram Symbols' | sed 's/HEXAGRAM FOR//'
756780EOF
757781 # supported tools
758782 read -r -d ' ' exes << EOF
@@ -784,21 +808,21 @@ EOF
784808 IFS=: read -r gfx app _ <<< " ${CZ_GUI:-2}"
785809 if [ -z " $DISPLAY " ]; then gfx=0; fi
786810 # set options from the environment
787- local tpl=" ${_CZ_TEMPLATE} " # string | command template
788- local fld=" ${_CZ_FIELDS} " # string | field selection
789- local mode=" ${_CZ_MODE} " # string | indicator for program mode
790- local help=" ${_CZ_HELP} " # string | indicator for help requested
791- local dlm=" ${_CZ_DELIM:- $IFS } " # string | delimeter to split selected line
792- local dbg=" ${_CZ_DEBUG} " # boolean | whether or not write debug info
811+ local tpl=" ${_CZ_TEMPLATE} " # string | command template
812+ local fld=" ${_CZ_FIELDS} " # string | field selection
813+ local mode=" ${_CZ_MODE} " # string | indicator for program mode
814+ local help=" ${_CZ_HELP} " # string | indicator for help requested
815+ local dlm=" ${_CZ_DELIM:- $IFS } " # string | delimeter to split selected line
816+ local dbg=" ${CZ_DEBUG :- $ _CZ_DEBUG } " # boolean | whether or not write debug info
793817 # set option defaults
794- local inp=" /dev/stdin" # string | file from which to select a line
795- local buf=0 # boolean | require buffered stdin for command
796- local run=" " # string | program mode implied by another option
797- local nul=0 # boolean | whether to read null separated lines
798- local clr=0 # boolean | whether to refresh cached input lines
818+ local inp=" /dev/stdin" # string | file from which to select a line
819+ local buf=0 # boolean | require buffered stdin for command
820+ local run=" " # string | program mode implied by another option
821+ local nul=0 # boolean | whether to read null separated lines
822+ local clr=0 # boolean | whether to refresh cached input lines
799823 # accept options
800824 local opt OPTIND OPTARG
801- while getopts " :cd:e:f:ghHi:klmopqrstuvxyz :0" opt; do
825+ while getopts " :cd:e:f:ghHi:klmopqrstuvwxyz :0" opt; do
802826 case " $opt " in
803827 c) # clear hold caches
804828 clr=1
859883 q) # print rendered template from '-f' with variables shell-quoted
860884 mode=1
861885 ;;
862- r) # execute rendered template from '-e'
886+ r) # run rendered command template from '-e'
863887 mode=2
864888 ;;
865889 s) # print string from '-e' as command
@@ -871,13 +895,13 @@ EOF
871895 u) # print rendered template from '-f' with variables inserted directly
872896 mode=5
873897 ;;
874- 0) # handle null separated input
875- nul=1
876- ;;
877898 v) # write version
878899 printf " cz %s\\ n" " $ver "
879900 return 0
880901 ;;
902+ w) # select a random line instead of using an external tool
903+ app=" randline"
904+ ;;
881905 x) # try to use a graphical tool for line selection
882906 gfx=1
883907 ;;
891915 return 2
892916 fi
893917 ;;
918+ 0) # handle null separated input
919+ nul=1
920+ ;;
894921 \? ) # invalid option?
895922 printf " Bad option: -%s\\ n%s\\ n" " $OPTARG " " $use " >&2
896923 return 2
967994 fi
968995 # read the selection file
969996 local items=() lines=()
997+ if (( dbg)) ; then printf " READ %(%H:%M:%S)T\\ n" -1 >&2 ; fi
970998 if (( nul)) ; then
971999 mapfile -d ' ' -t lines < " $inp "
9721000 mapfile -t items < <( printf " %q\\ n" " ${lines[@]} " )
9811009 fi
9821010 # buffer stdin if reading selection input from another file
9831011 # this is needed to pass pipe input to plugin commands
984- declare -a stdin
1012+ local stdin=()
9851013 if [[ " $inp " != " /dev/stdin" ]] && ! [ -t 0 ]; then
1014+ if (( dbg)) ; then printf " IBUF %(%H:%M:%S)T\\ n" -1 >&2 ; fi
9861015 mapfile -t stdin
9871016 # optionally require actual input lines
9881017 if (( buf)) && ! (( ${# stdin} )) ; then return 4; fi
9931022 return 0
9941023 fi
9951024 # choose a line using a known program
996- local out
1025+ local out=" "
1026+ if (( dbg)) ; then printf " PICK %(%H:%M:%S)T\\ n" -1 >&2 ; fi
9971027 out=$( case " $app " in
9981028 choose)
9991029 choose -n 20
@@ -1016,6 +1046,9 @@ EOF
10161046 pick)
10171047 pick
10181048 ;;
1049+ randline)
1050+ randline
1051+ ;;
10191052 rofi)
10201053 local theme=" ${CZ_ROFI_THEME:- Paper} "
10211054 rofi -theme " $theme " -i -dmenu -p " "
@@ -1125,7 +1158,7 @@ EOF
11251158 return 4
11261159 fi
11271160 if (( dbg)) ; then
1128- printf " # %s ==> %s\\ n" " $fld " " $out " >&2
1161+ printf " # %s ==> %s\\ n" " $fld " " $cmd " >&2
11291162 fi
11301163 printf " %s\\ n" " $cmd "
11311164 ;;
@@ -1135,7 +1168,7 @@ EOF
11351168 return 4
11361169 fi
11371170 if (( dbg)) ; then
1138- printf " # %s ==> %s\\ n" " $fld " " $out " >&2
1171+ printf " # %s ==> %s\\ n" " $fld " " $cmd " >&2
11391172 fi
11401173 printf " %s\\ n" " $cmd "
11411174 ;;
@@ -1152,7 +1185,7 @@ function _cz() {
11521185 # cz has some options
11531186 local opt=" " opts
11541187 declare -A opts
1155- for opt in -{d,e,f,h,i,l,k,m,o,p,q,r,s,t,u,v,x,y,z,0}; do opts[" $opt " ]=0; done
1188+ for opt in -{d,e,f,h,i,l,k,m,o,p,q,r,s,t,u,v,w, x,y,z,0}; do opts[" $opt " ]=0; done
11561189 # scan all previous words
11571190 local base=" " last=" " word=" " i=0
11581191 for (( i= 1 ; i < "$COMP_CWORD "; i++ )) ; do
@@ -1212,7 +1245,7 @@ function _cz() {
12121245 COMPREPLY=(" ${reply[@]} " )
12131246 return
12141247 fi
1215- # TODO maybe complete something specific for a plugin
1248+ # TODO maybe complete something specific for plugins
12161249 case " $base " in
12171250 * ) return ;;
12181251 esac
@@ -2599,7 +2632,7 @@ EOF
25992632 printf " Either grep or rg is required!\\ n" >&2
26002633 return 5
26012634 fi
2602- cz -d ' :' -f 0 -e " $EDITOR +{1} -- {0}" \
2635+ cz -d ' :' -f " 0,1 " -e " $EDITOR +{1} -- {0}" \
26032636 -i <( printf " %s\\ n" " $matches " )
26042637}
26052638
@@ -3079,7 +3112,7 @@ EOF
30793112 | jq -r ' .data[] | [.released_at, .code, .name ] | @tsv' ) ; then
30803113 return 2
30813114 fi
3082- cz -d $' \t ' -f 1 -i <( sort -u <<< " ${sets[@]}" )
3115+ cz -d $' \t ' -e ' xdg-open https://scryfall.com/sets/{1} ' - f 1 -i <( sort -u <<< " ${sets[@]}" )
30833116}
30843117
30853118cz_mtg_card () {
@@ -3089,16 +3122,16 @@ Select an MTG card by name using data from scryfall.com.
30893122EOF
30903123 req curl sort || return 5
30913124 local url=" "
3092- if ! url=$( hold -pe -n scryfallbulk -t 86400 -- curl -sS https://api.scryfall.com/bulk-data \
3125+ if ! url=$( hold -pe -n scryfallbulk -t 604800 -- curl -sS https://api.scryfall.com/bulk-data \
30933126 | jq -r ' .data[] | select(.type == "oracle_cards") | .download_uri' ) ; then
30943127 return 2
30953128 fi
30963129 local data=" " menu=" "
3097- if ! data=$( hold -e -n scryfalldata -t $(( 86400 * 7 )) curl -sS " $url " ) ; then
3130+ if ! data=$( hold -e -n scryfalldata -t 604800 -- curl -sS " $url " ) ; then
30983131 return 2
30993132 fi
31003133 local filter=' .[] | [.set, (.scryfall_uri | split("?"))[0], .name] | @tsv'
3101- if ! menu=$( hold -g -t 43200 || hold -f <( jq -r " $filter " " $data " | sort -u) ) ; then
3134+ if ! menu=$( hold -g -t 3600 || hold -f <( jq -r " $filter " " $data " | sort -u) ) ; then
31023135 return 2
31033136 fi
31043137 cz -d $' \t ' -e ' xdg-open {1}' -f 2 -i " $menu "
@@ -3453,7 +3486,6 @@ EOF
34533486done
34543487unset t c
34553488
3456-
34573489cz_systemd_file () {
34583490 { hep " $_CZ_HELP " && return ; } << EOF
34593491cz systemd file [user|system] [TYPE]
@@ -3672,7 +3704,7 @@ EOF
36723704use strict;
36733705use warnings;
36743706use open ":std", ":encoding(UTF-8)";
3675- use Unicode::UCD qw/charinfo charscript charscripts charblock charblocks/;
3707+ use Unicode::UCD qw/charinfo charscript charscripts charblock charblocks/;
36763708my (\$ blocks,\$ scripts) = (charblocks(),charscripts());
36773709for (@ARGV) {
36783710 my \$ section = \$ blocks->{\$ _} || \$ scripts->{\$ _};
0 commit comments