Skip to content

Commit 127cac7

Browse files
committed
Merge branch 'gawk-gsed-user-subshell'
* Branch commit log: jj-fzf: require 'gawk' as GNU awk binary jj-fzf: support 'gsed' as GNU sed binary jj-fzf: Ctrl-Z: use user's $SHELL to execute a subshell Signed-off-by: Tim Janik <timj@gnu.org>
2 parents 5bdb7c3 + cfd9b75 commit 127cac7

File tree

2 files changed

+39
-38
lines changed

2 files changed

+39
-38
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ The available hotkeys are displayed onscreen for simple discoverability.
2121
The commands and key bindings can also be displayed with `jj-fzf --help` and are documented in the wiki: [jj-fzf-help](https://github.com/tim-janik/jj-fzf/wiki/jj-fzf-help)
2222

2323
The `jj-fzf` script is implemented in bash-5.1, using fzf-0.29 and jj-0.23.0.
24-
Command line tools like sed, grep are assumed to provide GNU tool semantics.
24+
Command line tools like sed, grep, gawk are assumed to provide GNU tool semantics.
2525

2626
<!-- USAGE -->
2727
## Usage

jj-fzf

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
set -Eeuo pipefail #-x
44
SCRIPTNAME=`basename $0` && function die { [ -n "$*" ] && echo "$SCRIPTNAME: **ERROR**: ${*:-aborting}" >&2; exit 127 ; }
55
SELF="$0"
6-
# for function exports to work sub-shell must be bash too
7-
export SHELL=bash
86

97
# == PREVIEW fast path ==
108
export REVPAT='^[^a-z()0-9]*([k-xyz]{7,})([?]*)\ ' # line start, ignore --graph, parse revision letters, catch '??'-postfix
@@ -52,10 +50,12 @@ fi
5250

5351
# == Check Deps ==
5452
VERSION=0.23.0
55-
jj --version --ignore-working-copy | grep -Eq 'jj 0\.2[3-9]\.' || die 'jj-0.23 is required'
56-
fzf --help | grep -Fq ' --header-first' || die 'fzf-0.29 is required'
57-
sed --version | grep -Fq 'GNU sed' || die 'GNU sed is required'
58-
awk --version | grep -Fq 'GNU Awk' || die 'GNU Awk is required'
53+
jj --version --ignore-working-copy | grep -Eq 'jj 0\.2[3-9]\.' || die "failed to find 'jj' version 0.23 in \$PATH"
54+
fzf --help | grep -Fq ' --header-first' || die "failed to find 'fzf' version 0.29 in \$PATH"
55+
sed --version | grep -Fq 'GNU sed' &&
56+
gsed() { sed "$@"; } && export -f gsed ||
57+
gsed --version | grep -Fq 'GNU sed' || die "failed to find 'gsed' in \$PATH (GNU sed)"
58+
gawk --version | grep -Fq 'GNU Awk' || die "failed to find 'gawk' in \$PATH (GNU Awk)"
5959
TRACK=--track && FZFHELP="$(fzf --help 2>&1)" && [[ "$FZFHELP" =~ "--track" ]] || TRACK=
6060

6161
# == Early Options ==
@@ -77,8 +77,7 @@ JJROOT=$(jj --ignore-working-copy root) || die "$PWD: not a JJ repository"
7777
JJFZFSHOW="jj --no-pager --ignore-working-copy ${JJFZF_ATOP:+--at-op $JJFZF_ATOP} show --tool true"
7878
JJFZFONELINE="jj --no-pager --ignore-working-copy log --color=always --no-graph -T builtin_log_oneline"
7979
JJFZFPAGER="less -Rc"
80-
JJFZF_SHELL="${JJFZF_SHELL:-/usr/bin/env bash -i}"
81-
JJSUBSHELL='T=$(tty 2>/dev/null||tty <&1 2>/dev/null||tty <&2 2>/dev/null)&&test -n "$T"&&echo -e "\n#\n# Type \"exit\" to leave subshell\n#" && unset JJ_CONFIG && exec '"$JJFZF_SHELL"' <$T 1>$T 2>$T'
80+
JJSUBSHELL='T=$(tty 2>/dev/null||tty <&1 2>/dev/null||tty <&2 2>/dev/null)&&test -n "$T"&&echo -e "\n#\n# Type \"exit\" to leave subshell\n#" && unset JJ_CONFIG && exec /usr/bin/env '"$SHELL"' <$T 1>$T 2>$T'
8281
INFO_BINDING=" fzf </dev/null >/dev/tty 2>&1 --prompt ' ' --disabled --layout=reverse --height 1 --margin 4 --padding 4 --border=block --no-info --no-scrollbar --no-clear --bind=enter:print-query "
8382
FZFSETTINGS=(
8483
--ansi --no-mouse -x -e
@@ -97,6 +96,8 @@ FZFSETTINGS=(
9796
FZFPOPUP=(fzf "${FZFSETTINGS[@]}" --margin 0,3%,5%,3% --border)
9897
JJLOGCMD=( $SELF fzflog )
9998
TEMPD=
99+
# for function exports to work sub-shell must be bash too
100+
export SHELL=bash
100101

101102
# == JJ_CONFIG ==
102103
# parsable version of builtin_log_oneline; https://github.com/martinvonz/jj/blob/main/cli/src/config/templates.toml
@@ -301,7 +302,7 @@ echo_signoff()
301302
if test "${JJFZF_SIGNOFF:-true}" == true ; then
302303
echo # separating newline before signoff section
303304
$JJFZFSHOW -T 'format_detailed_signature(author) ++ "\n"' -r @ |
304-
sed -e 's/>.*/>/ ; s/^/Signed-off-by: /'
305+
gsed -e 's/>.*/>/ ; s/^/Signed-off-by: /'
305306
fi
306307
)
307308
# Echo current or default message
@@ -317,7 +318,7 @@ echo_commit_msg()
317318
# start with file name prefixes
318319
cd "$JJROOT" # create root relative file names
319320
FILES=()
320-
readarray -t FILES < <(jj --ignore-working-copy log --no-graph -r "$R" -T '' -s | sed 's/^\w //')
321+
readarray -t FILES < <(jj --ignore-working-copy log --no-graph -r "$R" -T '' -s | gsed 's/^\w //')
321322
test ${#FILES[@]} -gt 0 &&
322323
printf "%s: \n" "${FILES[@]}" ||
323324
echo ""
@@ -569,7 +570,7 @@ file-editor()
569570
# cd root; otherwise revision file paths will mismatch
570571
cd "$JJROOT"
571572
# read files edited by revision
572-
readarray -t FILES < <(jj --ignore-working-copy log --no-graph -r "$R" -T '' -s | sed 's/^\w //')
573+
readarray -t FILES < <(jj --ignore-working-copy log --no-graph -r "$R" -T '' -s | gsed 's/^\w //')
573574
# make sure to edit revision
574575
test "$W" == "$R" || (
575576
IMMU=$($JJFZFSHOW -r "$R" -T 'if(immutable, "true")')
@@ -595,7 +596,7 @@ help()
595596
JJCMDS=:
596597
for w in $( LANG=C
597598
jj --help |
598-
sed -r '1,/^Commands:/d; /^\w/{x;q}; s/^ *(\w+)\b.*/\1/' ) ; do
599+
gsed -r '1,/^Commands:/d; /^\w/{x;q}; s/^ *(\w+)\b.*/\1/' ) ; do
599600
[[ $w == help ]] && continue
600601
JJCMDS="$JJCMDS$w:"
601602
done
@@ -623,7 +624,7 @@ split-interactive()
623624
set -Eeuo pipefail #-x
624625
TRUNCATE=y
625626
test $TRUNCATE == y && echo -n > "$1" || :
626-
sed 's/TRUNCATE=./TRUNCATE=n/' -i "$0"
627+
gsed 's/TRUNCATE=./TRUNCATE=n/' -i "$0"
627628
__EOF__
628629
chmod +x $TEMPD/trunc1st.sh
629630
export EDITOR=$TEMPD/trunc1st.sh
@@ -671,7 +672,7 @@ if [[ $# == 2 ]] && [[ "${1:0:1}" == + ]] ; then
671672
grep -s -n '' "$file" /dev/null |
672673
"${FZFPOPUP[@]}" \
673674
--border-label '-[ LINE HISTORY (EXPERIMENTAL) ]-' --color=border:yellow,label:yellow \
674-
--preview " git log --graph --no-patch -M -C --find-copies-harder --pretty='%C(blue)%h %C(yellow)%aL %C(reset)%s%n%b' -L{2}:{1} --color $C | sed 's/Signed-off-by:.*//; /^ *$/d' " \
675+
--preview " git log --graph --no-patch -M -C --find-copies-harder --pretty='%C(blue)%h %C(yellow)%aL %C(reset)%s%n%b' -L{2}:{1} --color $C | gsed 's/Signed-off-by:.*//; /^ *$/d' " \
675676
--bind "enter:execute( git log -M -C --find-copies-harder -L{2},+7:{1} --color $C | $JJFZFPAGER)" \
676677
--header "File Line History" \
677678
--no-tac --no-sort +m -d: \
@@ -736,7 +737,7 @@ merging()
736737
--border-label '-[ MERGING ]-' --color=border:bright-blue,label:bright-blue \
737738
--prompt "Merge +> " \
738739
--header "$H" --header-first \
739-
--bind "alt-u:execute-silent( sed 's/0/2/;s/1/0/;s/2/1/' -i $TEMPD/upstream.toggle )+refresh-preview" \
740+
--bind "alt-u:execute-silent( gsed 's/0/2/;s/1/0/;s/2/1/' -i $TEMPD/upstream.toggle )+refresh-preview" \
740741
-m --color=pointer:grey \
741742
--no-tac --no-sort > $TEMPD/selections.txt &&
742743
mapfile -t selections < $TEMPD/selections.txt &&
@@ -764,8 +765,8 @@ merging()
764765
echo -e "\n* Branch '`rev_bookmark1 $c`' commit log:" ||
765766
echo -e "\n* Branch commit log:" # "$c ^$MERGE_BASE"
766767
git log --pretty=$'\f%s%+b' $c ^$MERGE_BASE |
767-
sed '/^\(Signed-off-by\|Acked-by\|Tested-by\|Cc\):/d' |
768-
sed '/^$/d ; s/^/\t/ ; s/^\t\f$/ (no description)/ ; s/^\t\f/ /'
768+
gsed '/^\(Signed-off-by\|Acked-by\|Tested-by\|Cc\):/d' |
769+
gsed '/^$/d ; s/^/\t/ ; s/^\t\f$/ (no description)/ ; s/^\t\f/ /'
769770
done
770771
echo_signoff
771772
)
@@ -839,7 +840,7 @@ undone_log()
839840
# list all oplog descriptions, find description with "undo operation 123abc"
840841
T='coalesce( self.description().first_line(), " ") ++ "\n"'
841842
jj --no-pager --ignore-working-copy op log --no-graph --color=never -T "$T" |
842-
sed -nr '
843+
gsed -nr '
843844
# turn "undo operation 123abc" into an exact id with 16 characters
844845
/^undo operation [a-f0-9]{16}/s/^undo operation ([a-f0-9]{16}).*/\1/
845846
T; # goto EOS unless the previous s/// matched
@@ -865,12 +866,12 @@ label(if(current_operation, "current_operation"),
865866
oplog_oneline()
866867
(
867868
temp_dir
868-
# turn each undone and undo operation on "123abc" into a new sed commands that replaces this operations graph character
869+
# turn each undone and undo operation on "123abc" into a new gsed commands that replaces this operations graph character
869870
undone_log |
870-
sed -r 's/([a-f0-9]+)/ s|○(.*\1)|-\\1| /' > $TEMPD/undone.sed
871+
gsed -r 's/([a-f0-9]+)/ s|○(.*\1)|-\\1| /' > $TEMPD/undone.sed
871872
# show operation log, filtered through the above sed script to alter markers for undone ops
872873
jj --no-pager --ignore-working-copy op log --color=always -T "$JJ_FZF_OPLOG_ONELINE" |
873-
sed -rf $TEMPD/undone.sed # beware, script needs to ignore ANSI color escape sequences
874+
gsed -rf $TEMPD/undone.sed # beware, script needs to ignore ANSI color escape sequences
874875
)
875876
FUNCTIONS+=( 'oplog_oneline' )
876877

@@ -894,8 +895,8 @@ op-log()
894895
--border-label '-[ OP-LOG ]-' --color=border:bright-yellow,label:bright-yellow \
895896
--prompt "Operation > " \
896897
--header "$H" --header-first \
897-
--bind "ctrl-d:execute-silent( sed 's/^VIEW=.*/VIEW=diff@oplog/' -i $TEMPD/oplog.env )+refresh-preview" \
898-
--bind "ctrl-l:execute-silent( sed 's/^VIEW=.*/VIEW=log@oplog/' -i $TEMPD/oplog.env )+refresh-preview" \
898+
--bind "ctrl-d:execute-silent( gsed 's/^VIEW=.*/VIEW=diff@oplog/' -i $TEMPD/oplog.env )+refresh-preview" \
899+
--bind "ctrl-l:execute-silent( gsed 's/^VIEW=.*/VIEW=log@oplog/' -i $TEMPD/oplog.env )+refresh-preview" \
899900
--bind "alt-w:execute-silent( $SELF wdrestore@oplog {} )+abort" \
900901
--bind "alt-z:execute-silent( $SELF undo-op@oplog {} )+abort" \
901902
--bind "enter:execute( [[ {} =~ \$OPPAT ]] || exit && export JJFZF_ATOP=\"\${BASH_REMATCH[1]}\" && $SELF logrev @ {q} )" \
@@ -1099,8 +1100,8 @@ reparenting()
10991100
--preview ". $TEMPD/reparenting.env && reparenting_revs {+} && reparenting_cmd" \
11001101
--prompt "Parents > " \
11011102
--header "$H" --header-first \
1102-
--bind "alt-a:execute-silent( sed 's/^OP=.*/OP=\"|\"/' -i $TEMPD/reparenting.env )+refresh-preview" \
1103-
--bind "alt-d:execute-silent( sed 's/^OP=.*/OP=\"~\"/' -i $TEMPD/reparenting.env )+refresh-preview" \
1103+
--bind "alt-a:execute-silent( gsed 's/^OP=.*/OP=\"|\"/' -i $TEMPD/reparenting.env )+refresh-preview" \
1104+
--bind "alt-d:execute-silent( gsed 's/^OP=.*/OP=\"~\"/' -i $TEMPD/reparenting.env )+refresh-preview" \
11041105
-m --color=pointer:grey \
11051106
--no-tac --no-sort > $TEMPD/selections.txt &&
11061107
mapfile -t selections < $TEMPD/selections.txt &&
@@ -1149,13 +1150,13 @@ rebasing()
11491150
--preview "[[ {} =~ $REVPAT ]] || exit; export REV=\"\${BASH_REMATCH[1]}\"; $PREVIEW " \
11501151
--prompt "Rebase > " \
11511152
--header "$H" --header-first \
1152-
--bind "alt-b:execute-silent( sed 's/^FR=.*/FR=--branch/' -i $TEMPD/rebasing.env )+refresh-preview" \
1153-
--bind "alt-s:execute-silent( sed 's/^FR=.*/FR=--source/' -i $TEMPD/rebasing.env )+refresh-preview" \
1154-
--bind "alt-r:execute-silent( sed 's/^FR=.*/FR=--revisions/' -i $TEMPD/rebasing.env )+refresh-preview" \
1155-
--bind "alt-p:execute-silent( sed 's/^SP=false/SP=x/; s/^SP=true/SP=false/; s/^SP=x/SP=true/' -i $TEMPD/rebasing.env )+refresh-preview" \
1156-
--bind "ctrl-d:execute-silent( sed 's/^TO=.*/TO=--destination/' -i $TEMPD/rebasing.env )+refresh-preview" \
1157-
--bind "ctrl-a:execute-silent( sed 's/^TO=.*/TO=--insert-after/' -i $TEMPD/rebasing.env )+refresh-preview" \
1158-
--bind "ctrl-b:execute-silent( sed 's/^TO=.*/TO=--insert-before/' -i $TEMPD/rebasing.env )+refresh-preview" \
1153+
--bind "alt-b:execute-silent( gsed 's/^FR=.*/FR=--branch/' -i $TEMPD/rebasing.env )+refresh-preview" \
1154+
--bind "alt-s:execute-silent( gsed 's/^FR=.*/FR=--source/' -i $TEMPD/rebasing.env )+refresh-preview" \
1155+
--bind "alt-r:execute-silent( gsed 's/^FR=.*/FR=--revisions/' -i $TEMPD/rebasing.env )+refresh-preview" \
1156+
--bind "alt-p:execute-silent( gsed 's/^SP=false/SP=x/; s/^SP=true/SP=false/; s/^SP=x/SP=true/' -i $TEMPD/rebasing.env )+refresh-preview" \
1157+
--bind "ctrl-d:execute-silent( gsed 's/^TO=.*/TO=--destination/' -i $TEMPD/rebasing.env )+refresh-preview" \
1158+
--bind "ctrl-a:execute-silent( gsed 's/^TO=.*/TO=--insert-after/' -i $TEMPD/rebasing.env )+refresh-preview" \
1159+
--bind "ctrl-b:execute-silent( gsed 's/^TO=.*/TO=--insert-before/' -i $TEMPD/rebasing.env )+refresh-preview" \
11591160
--no-tac --no-sort +m ) &&
11601161
[[ "$REV" =~ $REVPAT ]] &&
11611162
REV="${BASH_REMATCH[1]}" ||
@@ -1332,12 +1333,12 @@ DOC['undo']='Use `jj op undo` to undo the last operation performed by `jj` that
13321333
undo()
13331334
(
13341335
temp_dir
1335-
# turn each undone operation "123abc" into an sed delete command
1336+
# turn each undone operation "123abc" into an gsed delete command
13361337
undone_log |
1337-
sed -r 's|([a-f0-9]+)| /\\b\1/d |' > $TEMPD/delops.sed
1338+
gsed -r 's|([a-f0-9]+)| /\\b\1/d |' > $TEMPD/delops.sed
13381339
# list operation IDs, skipping undone ones
13391340
jj --ignore-working-copy op log --no-graph -T 'self.id().short(16) ++ " " ++ self.description().first_line() ++ "\n"' |
1340-
sed -rf $TEMPD/delops.sed > $TEMPD/undoable-ops.lst
1341+
gsed -rf $TEMPD/delops.sed > $TEMPD/undoable-ops.lst
13411342
# fetch first
13421343
read op rest < $TEMPD/undoable-ops.lst
13431344
# read -p "Undo $op? " YN ; [[ "${YN:0:1}" =~ [yY] ]] || exit
@@ -1377,7 +1378,7 @@ if [[ "${1:-}" = --help ]] ; then
13771378
echo "*$k:* **$NAME**"
13781379
D="${DOC[$NAME]:-}"
13791380
test -z "$D" ||
1380-
echo "$D" | fold -s -w78 | sed 's/^/ /'
1381+
echo "$D" | fold -s -w78 | gsed 's/^/ /'
13811382
done
13821383
) | (
13831384
B=$'\e[1m' # Bold
@@ -1400,7 +1401,7 @@ if [[ "${1:-}" = --help ]] ; then
14001401
s,(\bhttps?://[^ ()\r]+),$U\1$Z,g # Link
14011402
"
14021403
tr \\n \\r |
1403-
{ $COLOR && sed -re "$SEDSCRIPT" || cat ; } |
1404+
{ $COLOR && gsed -re "$SEDSCRIPT" || cat ; } |
14041405
tr \\r \\n
14051406
)
14061407
exit 0

0 commit comments

Comments
 (0)