Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: "Pull just the text of a single command" (was Re: .zsh_history)

On 2023-04-15 12:47, Bart Schaefer wrote:
I'm not sure which past discussion you're referencing, but it's

This goes back to when I first started with Linux.  It was one of my first issues here.  You weighed in on the topic but 'noglob' was the best we did at the time.  Quite possible I was not communicating very well.

So if you want the unaltered text as you work
with it, ZLE is where you get it.

That's what I want.  I only refer to history because:

$ print -rS "$@"

... as I have it now, does write the command with its tail unexpanded, and, combined with 'noglob' I get pretty much what I want.  But it's a huge labor to do something that should be very simple.

The best place to grab it after
hitting enter is probably in the zle-line-finish hook, but that won't
always give you full multi-line events (e.g., when the PS2 prompt is
active, you get it a line at a time).
Sounds worth trying.

Finally, the preexec function (and hook) gives access to the full
event with only history expansions already done (in $1), before it is
entered into the "fc"-able history, along with the event with all the
other expansions done (in $3).

That sounds exactly right.  Come to that, an expansion of a call to history -- the ! stuff -- would be the one and only thing I would want pre-expanded.  It's sorta the obvious exception because it's a meta command -- a command to call a command.  Nuts, I'm trying to remember if I ever tried something like that.  If you're recommending it now, you would have recommended it then, and I'd have tried it then ... but I can't remember.  But I know I didn't try anything with zle.

There's nowhere other than ZLE that
can give you the raw ! references, and preexec can't give you $1 in a
shell script where history isn't available at all.

What you can't do is defer expansions (other than globbing, via
noglob) until "inside" the execution of the command (e.g., your shell
function).  I have a vague recollection that this may relate to you
being accustomed to DOS/Windows where expansion of the arguments is
done by calling a library after the fact, as opposed to the shell
doing all of it first.
Yeah.  We did conclude that what I was trying to do was a fundamental violation of basic Unix/Linux philosophy.

Anyway, everything you asked about is there, you just need to adjust
your thinking about the sequence of events to find the right place to
accomplish what you want.

I'm not fussy.  Just so long as I can access the tail from within a function, I don't care how that tail gets stored.   It's hard to explain why this matters but most of my wrapper functions are ever more complex massaging of the output of some basic command -- and lots of color.  If I need a modification, rather than edit my own code, what I do is first edit the 'real' command to make the change I want, then when I know what I want, I edit my own code so as to achieve that result.  For example 'l' wraps 'ls':

$ l

LISTING of "*": All file types, INsensitive. Sorting upside down by: Mod. Time:

 18432 [2022-10-09--16:43] 2021-08-12-backup/
  1024 [2022-11-12--09:43] Boneyard/
  4096 [2022-11-20--10:38] 2022-11-20-backup/
 18432 [2022-11-20--14:12] Empty/
  4096 [2022-11-28--06:55] Znt/


  8649 [2023-03-22--19:54] miscfunctions,8,local files only with changed
  8649 [2023-03-22--19:54] miscfunctions
 19831 [2023-03-22--20:28] l,4,BUG  x colorized in l X
 19831 [2023-03-22--20:28] l

Items found: 169
Total bytes in directory "/aWorking/Zsh/Source/Wk": 1.7M
Total including subdirs: 25M

... a listing the way I like it to look.  What 'l' actually executes is:

$ ls --time-style='+[%F--%H:%M]' --group-directories-first -AFrGgdt --color=always (#i)* 2> /dev/null | sed -r "s/^(.{10} {1,3}[[:digit:]]{1,3} )/ /" | egrep -v '^total' | sed '/;34m\.\x1b\[0m\/$/d' | perl -pe "s|\] (.*?)()|\] \1^[[31;1m\2^[[0m|i"

So, using my convoluted method:

$ l ,H

... writes the above command to history and then up-arrow retrieves it for editing.  Once I've made whatever change I want to the 'real' command, then I edit my own code so as to implement the modification.  Basically I can edit in two stages.  And the thing is that the '*' and various other expandable things must *not* expand, otherwise the command written to history can become almost infinitely long.  Clear as mud?  Anyway it works marvelously but is convoluted ... unless I can grab the tail, unexpanded, with less trouble.  That way, instead of storing it via history, I can access it some other way.  IOW the only reason I use history is because it shows unexpanded commands. Show me how to do this with zle or preexec and I'll be in heaven.

Messages sorted by: Reverse Date, Date, Thread, Author