4

I want this to work (it needs extendedglob and histsubstpattern):

alias ri='^(#b)E(?)^E${(l:2::0:)$((match[1]+1))}' 

But it doesn't:

$ alias sss='^(#b)E(?)^E${(l:2::0:)$((match[1]+1))}' $ echo /Users/evar/Downloads/Video/Teenage_Mutant_Ninja_Turtles_2003_S02E01_DVDRip_30NAMA.mkv /Users/evar/Downloads/Video/Teenage_Mutant_Ninja_Turtles_2003_S02E01_DVDRip_30NAMA.mkv $ sss zsh: command not found: Pocket 

I wouldn't mind using a function instead of an alias, but the result was the same.

I even tried export ss='^(#b)E(?)^E${(l:2::0:)$((match[1]+1))}' and then doing $ss, but that failed with zsh: command not found: ^(#b)E(?)^E${(l:2::0:)$((match[1]+1))}.

Using eval '^(#b)E(?)^E${(l:2::0:)$((match[1]+1))}' also fails with zsh: command not found: Pocket.

Update: Related (possibly duplicate) questions found:

Alternative of bash's `history -p` in zsh?

https://stackoverflow.com/questions/27494753/how-to-get-last-command-run-without-using

https://stackoverflow.com/questions/48696876/using-history-expansion-in-a-bash-alias-or-function

1 Answer 1

3

You can't, history expansion happens before alias or parameter expansion.

I personally hate history expansion and is the first thing I disable.

Here, instead of aliasing a history expansion, I'd suggest creating a widget that increments a E<n> number left of the cursor:

increment-episode() { emulate -L zsh setopt extendedglob LBUFFER=${LBUFFER/(#b)(*E)(<->)/$match[1]${(l:${#match[2]}::0:)$((match[2]+1))}} } zle -N increment-episode bindkey '\e+' increment-episode 

And then, you just press Up and then Alt++ and you have a visual feedback of what's going on at every stage and can undo/redo/adapt at will, and not work blindly like with csh history expansion (a feature from the 70s that IMO made sense then but not so much now that we have faster and more capable terminals and line-editors).

But if you really wanted to blindly evaluate the code in the previous command in the history with the number after E incremented, you could do:

rerun-with-next-episode() { emulate -L zsh setopt extendedglob local new new=${${history:0:1}/(#b)E(<->)/E${(l:${#match[1]}::0:)$((match[1]+1))}} # display it print -ru2 -- $new # put it on the history print -rs -- $new # evaluate it eval -- $new } 
6
  • Is the setopt extendedglob locally scoped? If not, can it not be locally scoped? And why does the history expansion bother you enough to warrant disabling? Any specific cons? Commented Sep 3, 2018 at 11:08
  • 1
    @HappyFace, my main concern is unwanted expansions of !s. emulate -L resets the options to a sane default and makes options (including ones set later on) locally scoped. If you want extendedglob set globally (which I'd recommend for interactive use), just add setopt extendedglob to your ~/.zshrc. Commented Sep 3, 2018 at 11:10
  • BTW, I don't understand why eval '^(#b)E(?)^E${(l:2::0:)$((match[1]+1))}' is failing. Shouldn't evaling a command be just like typing it? and thank you, things finally worked out. :D Commented Sep 3, 2018 at 13:43
  • 1
    @HappyFace, history expansion is only done upon input lines coming from zle. Think of the history number for instance. It wouldn't make sense in eval Commented Sep 3, 2018 at 13:49
  • 1
    @HappyFace, see also the edit for possible improvements to your approach. Commented Sep 3, 2018 at 14:00

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.