* append to history entry?
@ 2016-12-26 23:16 Ray Andrews
2016-12-27 1:28 ` Ray Andrews
[not found] ` <5288b537-f06a-d18a-60ea-1f962856c80c__41345.3811700039$1482803962$gmane$org@eastlink.ca>
0 siblings, 2 replies; 21+ messages in thread
From: Ray Andrews @ 2016-12-26 23:16 UTC (permalink / raw)
To: Zsh Users
Can I arrange for a function to append something to it's own entry into
history when it is run? My function 'rap' is a wrapper around all the
various 'apt' 'dpkg' and sundry Debian package managers and I might:
$ rap ,I libapt-pkg.so.4.12
... which installs that package. But, I tend to install things in backup
clones of my install so that if the package screws things up royally,
which happens far too often, I can just back out of the clone and
restore it to a previous condition and no harm has been done. But,
there can be situations where I've installed something I want to keep to
one of these clones, and I can forget what has been installed where. For
example here's just a few days mucking things up:
18270 rap ,F libapt-pkg.so.4.12
18272 rap ,F libapt-pkg.so
18290 rap ,N regex*
18291 rap ,I regexxer
18296 rap ,N draftsight
18369 rap ,I xdg-utils
18370 rap ,I libaudio2
18386 rap ,N epiphany
18388 rap ,I epiphany-browser
18390 rap ,N dosemu
18391 rap ,I dosemu
18462 rap ,I librecad
18472 rap ,F libicuuc
18473 rap ,I libicu57
18474 rap ,R libreoffice
18475 rap ,I libreoffice
18482 rap ,N pptview
... now, 'draftsight' made a shambles of the clone, but stuff before and
after that might have gone to different clones so if it were possible to
have the above lines (as retrieved from history) somehow stored with
'$HOST' appended to them automatically (my $HOST always being the name
of the clone I'm running) it would look something like this:
18296 rap ,N draftsight HP-b6--9-Debian2
... which would let me know that I installed draftsight to clone #2 on
partition 6 of disk 'b' on machine 'HP'.
So I'm asking for the variable '$HOST' to be added to the command before
it is appended to history. Doable?
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-26 23:16 append to history entry? Ray Andrews
@ 2016-12-27 1:28 ` Ray Andrews
2016-12-27 4:47 ` Bart Schaefer
[not found] ` <5288b537-f06a-d18a-60ea-1f962856c80c__41345.3811700039$1482803962$gmane$org@eastlink.ca>
1 sibling, 1 reply; 21+ messages in thread
From: Ray Andrews @ 2016-12-27 1:28 UTC (permalink / raw)
To: zsh-users
On 26/12/16 03:16 PM, Ray Andrews wrote:
> Can I arrange for a function to append something to it's own entry
> into history when it is run? My function 'rap' is a wrapper around all
> the various 'apt' 'dpkg' and sundry Debian package managers and I might:
>
>
> $ rap ,I libapt-pkg.so.4.12
This seems to work:
alias rap=' noglob _rap'
function _rap ()
{
print -S "rap $* ; echo $HOST"
...
...
Leading space keeps the command out of history as usual, then I just
replace it with the massaged version. On recall:
$ rap ,N libreoffice ; echo HP-b6--9-Debian2
... so the $HOST information is harmless on re-execution but I have my
reminder as to which clone I was running at the time.
Sound?
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-27 1:28 ` Ray Andrews
@ 2016-12-27 4:47 ` Bart Schaefer
0 siblings, 0 replies; 21+ messages in thread
From: Bart Schaefer @ 2016-12-27 4:47 UTC (permalink / raw)
To: zsh-users
On Dec 26, 5:28pm, Ray Andrews wrote:
} Subject: Re: append to history entry?
}
} On 26/12/16 03:16 PM, Ray Andrews wrote:
} > Can I arrange for a function to append something to it's own entry
} > into history when it is run?
You might also want to look at the zshaddhistory hook function.
} This seems to work:
} ...
} Leading space keeps the command out of history as usual, then I just
} replace it with the massaged version.
This looks fine. My only suggestion would be to use the ":" command
instead of "echo".
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
[not found] ` <5288b537-f06a-d18a-60ea-1f962856c80c__41345.3811700039$1482803962$gmane$org@eastlink.ca>
@ 2016-12-27 12:55 ` Daniel Shahaf
2016-12-27 16:00 ` Bart Schaefer
0 siblings, 1 reply; 21+ messages in thread
From: Daniel Shahaf @ 2016-12-27 12:55 UTC (permalink / raw)
To: Ray Andrews; +Cc: zsh-users
Ray Andrews wrote on Mon, Dec 26, 2016 at 17:28:05 -0800:
> print -S "rap $* ; echo $HOST"
This will not reproduce arguments with literal whitespace or backslashes
correctly. Two changes are required to support them:
1) Pass -r to print.
2) When interpolating a variable into a command, it should be
(q)-esacped.
Putting all that and Bart's suggestion together gives:
print -rS -- "rap ${(q)@} ; : ${(q)HOST}"
[just in case somebody puts a backslash in their hostnames ;)]
Cheers,
Daniel
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-27 12:55 ` Daniel Shahaf
@ 2016-12-27 16:00 ` Bart Schaefer
2016-12-27 18:23 ` Ray Andrews
0 siblings, 1 reply; 21+ messages in thread
From: Bart Schaefer @ 2016-12-27 16:00 UTC (permalink / raw)
To: zsh-users
On Dec 27, 12:55pm, Daniel Shahaf wrote:
}
} print -rS -- "rap ${(q)@} ; : ${(q)HOST}"
Well, if we're being really pedantic, that's not right either, because
print -S requires a single string argument, but ${(q)@} in double quotes
results in multiple strings quoted individually, whereas ${(q)*} results
in backslashing the spaces between the arguments.
An extra level of nested expansion fixes that, and for readability it'd
be better to use (q+) on the arguments and (q-) on the host name:
print -rS -- "rap ${${(q+)@}} ; : ${(q-)HOST}"
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-27 16:00 ` Bart Schaefer
@ 2016-12-27 18:23 ` Ray Andrews
2016-12-27 19:09 ` Bart Schaefer
0 siblings, 1 reply; 21+ messages in thread
From: Ray Andrews @ 2016-12-27 18:23 UTC (permalink / raw)
To: zsh-users
On 27/12/16 08:00 AM, Bart Schaefer wrote:
> On Dec 27, 12:55pm, Daniel Shahaf wrote:
> }
> } print -rS -- "rap ${(q)@} ; : ${(q)HOST}"
>
> Well, if we're being really pedantic, that's not right either, because
> print -S requires a single string argument, but ${(q)@} in double quotes
> results in multiple strings quoted individually, whereas ${(q)*} results
> in backslashing the spaces between the arguments.
>
> An extra level of nested expansion fixes that, and for readability it'd
> be better to use (q+) on the arguments and (q-) on the host name:
>
> print -rS -- "rap ${${(q+)@}} ; : ${(q-)HOST}"
>
Jesus! I'm goin' back, to where ah' come from. ;-)
Seriously, I wish I knew if stuff like that really is part of the best
of all possible worlds or if it is a case of fundamental errors in
design of the first shells gradually accumulating more and more
band-aids as time went on until we have exceptions to the exceptions to
the exceptions and funny little gotchas within funny little gotchas.
Can't we have "print --Just-Do-It" ? Anyway I'll take the above on faith.
One thing tho Bart, it seems it should be 'echo' because when the
command line is recalled and executed, the colon throws an error whereas
the 'echo' just dumbly prints the host name which is harmless. Anyway
I'm intrigued by the idea of sending little messages to history like
this. As it is, I just 'echo' messages to myself which are of course
there in history to remind me what I was doing at the time. But maybe
this whole thing is a bit smart-assy. Thanks gentlemen.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-27 18:23 ` Ray Andrews
@ 2016-12-27 19:09 ` Bart Schaefer
2016-12-27 23:16 ` Ray Andrews
0 siblings, 1 reply; 21+ messages in thread
From: Bart Schaefer @ 2016-12-27 19:09 UTC (permalink / raw)
To: Ray Andrews, zsh-users
On Dec 27, 10:23am, Ray Andrews wrote:
}
} Seriously, I wish I knew if stuff like that really is part of the best
} of all possible worlds or if it is a case of fundamental errors in
} design of the first shells
Neither, really. It's a case of gradually accumulating requirements
on what shells do, rather than any flaw in the original design. In
the original design you'd have relied on external programs for all
of this stuff.
} Can't we have "print --Just-Do-It" ?
That's what the -r option is, but print doesn't control how its
arguments are processed as part of the command line parse, which is
necessary for what you asked about.
Seriously, you can't ask for a way to muck with something that is
normally handled transparently by the shell internals and then gripe
about having to replicate some of that hidden processing. Well, you
can, but it doesn't really help. :-)
Daniel is rather dogmatic about handling edge cases that I tend to
ignore for the sake of not throwing out all the details that make you
"take it on faith" (a phrase that makes ME grind my teeth whenever you
write it).
} One thing tho Bart, it seems it should be 'echo' because when the
} command line is recalled and executed, the colon throws an error
It shouldn't. There's no difference between "echo" and ":" except
that ":" discards its arguments without printing them. If you're
getting an error on ":" you've done something else to cause it.
What error?
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-27 19:09 ` Bart Schaefer
@ 2016-12-27 23:16 ` Ray Andrews
2016-12-27 23:55 ` Bart Schaefer
0 siblings, 1 reply; 21+ messages in thread
From: Ray Andrews @ 2016-12-27 23:16 UTC (permalink / raw)
To: zsh-users
On 27/12/16 11:09 AM, Bart Schaefer wrote:
> Neither, really. It's a case of gradually accumulating requirements
> on what shells do, rather than any flaw in the original design.
Well, the flaw is just that the additional stuff wasn't anticipated.
Mind, foretelling the future
can be difficult.
> Seriously, you can't ask for a way to muck with something that is
> normally handled transparently by the shell internals and then gripe
> about having to replicate some of that hidden processing. Well, you
> can, but it doesn't really help. :-)
Yeah, the chaffing is just because however useful some of that is in
most situations,
it would be nice to be able to occasionally have a string be just a
string be just a string
in a C sort of way. Plain vanilla a literal. Like my old gripe about a
command not being
able to know the literal keystrokes that called it *except* that it's
perfectly literal in history
*except* that if commands are chained with semicolons one can't just
grab it back from
history for the obvious reason that any given command doesn't know where
it is in a string
of chained commands -- one would think that one should be able to
intercept the string
before all the expansions. So I hafta do all this 'noglob'. Most of my
irritations with zsh
are in trying to *stop* it from doing things on occasion.
>
> Daniel is rather dogmatic about handling edge cases that I tend to
> ignore for the sake of not throwing out all the details that make you
> "take it on faith" (a phrase that makes ME grind my teeth whenever you
> write it).
Well, I trust you guys and until I see the logic, I'm just going to take
your words for it.
There is so much to know.
>
> } One thing tho Bart, it seems it should be 'echo' because when the
> } command line is recalled and executed, the colon throws an error
>
> It shouldn't. There's no difference between "echo" and ":" except
> that ":" discards its arguments without printing them. If you're
> getting an error on ":" you've done something else to cause it.
>
> What error?
>
Ah ... seems there must be a space after the colon:
print -rS -- "rap ${${(q+)@}}; : ${(q-)HOST}"
... that works fine, and doesn't bother with the echo, so it seems to be
exactly the sort of
thing I'm looking for as to writing to history. So much to love,
frustrations or no.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-27 23:16 ` Ray Andrews
@ 2016-12-27 23:55 ` Bart Schaefer
2016-12-28 0:57 ` Ray Andrews
[not found] ` <f87d7f79-3529-d832-eed5-83d4130ea128__16005.139592062$1482888562$gmane$org@eastlink.ca>
0 siblings, 2 replies; 21+ messages in thread
From: Bart Schaefer @ 2016-12-27 23:55 UTC (permalink / raw)
To: Ray Andrews, zsh-users
On Dec 27, 3:16pm, Ray Andrews wrote:
}
} it would be nice to be able to occasionally have a string be just a
} string be just a string in a C sort of way.
That's what $'...' does, but you can't ask for a C string and for
variable interpolation at the same time. Well, you can, but it
doesn't really help. ;-)
Maybe this would be easier (in the "should have thought of this before"
category):
print -s -f '%s' rap "$@" ";" ":" "$HOST"
(Note this doesn't work with -S, which currently is silently ignored if
the -f option is given, but as you already have all the words separated
here there's no reason to re-parse them.)
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-27 23:55 ` Bart Schaefer
@ 2016-12-28 0:57 ` Ray Andrews
2016-12-28 6:04 ` Bart Schaefer
[not found] ` <f87d7f79-3529-d832-eed5-83d4130ea128__16005.139592062$1482888562$gmane$org@eastlink.ca>
1 sibling, 1 reply; 21+ messages in thread
From: Ray Andrews @ 2016-12-28 0:57 UTC (permalink / raw)
To: zsh-users
On 27/12/16 03:55 PM, Bart Schaefer wrote:
> That's what $'...' does, but you can't ask for a C string and for
> variable interpolation at the same time. Well, you can, but it
> doesn't really help. ;-)
Indeed. Be careful what you ask for ... I am expecting the variables to
expand.
It's all this backslash and 'is it one string or several strings'
stuff. Dunno ...
is that really different? It just seems that the expansion of the
variables is 'visible'
for lack of a better word -- you expect it, it's not a gotcha the way
the rest is.
For me, the task is to see the 'naturalness' for lack of a better word
of the way
that zsh does this:
print -rS -- "rap ${${(q+)@}}; : ${(q-)HOST}"
... it seems that the backslashes need protecting and reprotecting and
yet more
protecting and each stage of the protection is different from the last.
Couldn't we just:
setopt protect-backslashes-thanks
print -S "rap $@; : $HOST"
... it's not that the backslashes are presumed special, it's that I'd
say we should only have to
press one button once to literalise them. Is it impossible that this
could be simple and intuitive?
No ordinary mortal would know to do what you guys showed me, one must be
shown and even
Bart and Daniel didn't get it exactly right the first time. What hope
do I have?
>
> Maybe this would be easier (in the "should have thought of this before"
> category):
>
> print -s -f '%s' rap "$@" ";" ":" "$HOST"
>
> (Note this doesn't work with -S, which currently is silently ignored if
> the -f option is given, but as you already have all the words separated
> here there's no reason to re-parse them.)
>
I'll chew on that.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
[not found] ` <f87d7f79-3529-d832-eed5-83d4130ea128__16005.139592062$1482888562$gmane$org@eastlink.ca>
@ 2016-12-28 5:28 ` Daniel Shahaf
2016-12-28 6:31 ` Bart Schaefer
2016-12-28 16:33 ` Ray Andrews
0 siblings, 2 replies; 21+ messages in thread
From: Daniel Shahaf @ 2016-12-28 5:28 UTC (permalink / raw)
To: Ray Andrews; +Cc: zsh-users
Ray Andrews wrote on Tue, Dec 27, 2016 at 16:57:48 -0800:
> On 27/12/16 03:55 PM, Bart Schaefer wrote:
> >That's what $'...' does, but you can't ask for a C string and for
> >variable interpolation at the same time. Well, you can, but it
> >doesn't really help. ;-)
> Indeed. Be careful what you ask for ... I am expecting the variables
> to expand. It's all this backslash and 'is it one string or several
> strings' stuff. Dunno ... is that really different? It just seems
> that the expansion of the variables is 'visible' for lack of a better
> word -- you expect it, it's not a gotcha the way the rest is. For me,
> the task is to see the 'naturalness' for lack of a better word of the
> way that zsh does this:
>
> print -rS -- "rap ${${(q+)@}}; : ${(q-)HOST}"
>
> ... it seems that the backslashes need protecting and reprotecting and
> yet more protecting and each stage of the protection is different from
> the last. Couldn't we just:
Actually, there's just one escaping: instead of using «${foo}»,
use «${(q)foo}» if $foo is a scalar and «${${(q)foo}}» if it is an
array. The - and + are cosmetic.
> setopt protect-backslashes-thanks
> print -S "rap $@; : $HOST"
>
> ... it's not that the backslashes are presumed special, it's that I'd
> say we should only have to press one button once to literalise them.
Most programming languages don't work this way.
When zsh parses the line «print -S -r -- "rap $@; : $HOST"», it does not
yet know that 'print' denotes the shell builtin and that 'print -S'
re-parses its argument according to shell syntax; and even if it did, it
_still_ wouldn't necessarily be correct for zsh to automatically escape
every variable that's interpolated into the string argument at the end,
because people sometimes use variable interpolations that _must not_ be
${(q)}-escaped.
The selling point of this strategy is that the parsing of string
literals is consistent: the string literal «"rap $@; : $HOST"» always
means the same thing, regardless of what command it is an argument to;
the string literal «"foo $*"» always means '"foo" followed by the
positional arguments joined by spaces without any escaping'. Then, if
a particular command needs quoting, it is up to the programmer to supply
the appropriate quoting.
The strategy you're describing amounts to a macro expansion language;
such languages are generally a lot more hairy than zsh.
> Is it impossible that this could be simple and intuitive? No ordinary
> mortal would know to do what you guys showed me, one must be shown and
> even Bart and Daniel didn't get it exactly right the first time. What
> hope do I have?
I didn't get it right, but Bart was right all along. Anyway, the rules
are simple:
1) When using the 'print' builtin, always pass '-r --'.
2) When interpolating a variable into a string that will be parsed as
zsh code, escape that variable using ${${(q)}}.
But yes, you have to do (2) yourself.
I hope this helped...
Cheers,
Daniel
>
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-28 0:57 ` Ray Andrews
@ 2016-12-28 6:04 ` Bart Schaefer
2016-12-28 17:39 ` Ray Andrews
0 siblings, 1 reply; 21+ messages in thread
From: Bart Schaefer @ 2016-12-28 6:04 UTC (permalink / raw)
To: zsh-users
On Dec 27, 4:57pm, Ray Andrews wrote:
} Subject: Re: append to history entry?
}
} It's all this backslash and 'is it one string or several strings'
} stuff.
The "one or several" distinction of course has to do with the way
arguments are processed. You definitely want to be able to preserve
inside the function whatever argument division was supplied to it
at the call, so you need a way to indicate that; you just have to
be sure you're only making that indication when you mean it.
} ... it seems that the backslashes need protecting and reprotecting and
} yet more protecting and each stage of the protection is different from
} the last.
The backslash stuff is borrowed conceptually from C (\t for tab, etc.).
Having that same paradigm applied at multiple levels of processing stems
from the language being interpreted rather than compiled.
} For me, the task is to see the 'naturalness' for lack of a better word
} of the way that zsh does this:
}
} print -rS -- "rap ${${(q+)@}}; : ${(q-)HOST}"
The point is that this isn't "natural," because what you asked for isn't
natural. Think through what you said you want:
1. Take a command line and parse it.
2. When the parsed arguments are received by the command ...
a. reconstitute the original command line
b. append another command that includes the host name
3. Put all of that into the history, formatted such that
a. it shows what you want when you recall the history, and
b. it executes again without errors
Which step of that after the first one is "natural" for the shell?
Of course you can fudge any one of those steps. The host name most
probably doesn't have any special characters, so ${(q-)HOST} is
likely going overboard and all you really need is $HOST; but for the
sake of everyone else who's going to see this and copy-paste, it
may be worth forestopping any future problems.
Similarly you may never have any quoted spaces or backslashes or
anything like that in the arguments of "rap" and therefore ${(q+)@}
might also be unnecessary, but someone might try to use this same
recipe for some other command that does have those things. I tend
to want those people to make their own mistakes and come back with
more questions; Daniel tries to cover all corner cases up front.
} Couldn't we just:
}
} setopt protect-backslashes-thanks
} print -S "rap $@; : $HOST"
That still wouldn't work because $@ is the way you preserve argument
divisions. You can't get away from thinking about what you mean.
} Bart and Daniel didn't get it exactly right the first time. What hope
} do I have?
Stop worrying about getting it exactly right. What you had in the
first place was going to work in 90%+ of cases, and when you found
a case that didn't, then someone could have explained why not.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-28 5:28 ` Daniel Shahaf
@ 2016-12-28 6:31 ` Bart Schaefer
2016-12-28 16:33 ` Ray Andrews
1 sibling, 0 replies; 21+ messages in thread
From: Bart Schaefer @ 2016-12-28 6:31 UTC (permalink / raw)
To: zsh-users
On Dec 28, 5:28am, Daniel Shahaf wrote:
}
} Actually, there's just one escaping: instead of using «${foo}»,
} use «${(q)foo}» if $foo is a scalar and $«{${(q)foo}}» if it is an
} array.
Unfortunately that's not quite right: you mean «${${(q)foo[@]}}» or
«${${(@q)foo}}» -- if it's just "an array" then it'll be joined
before (q)-ting.
} I didn't get it right, but Bart was right all along. Anyway, the rules
} are simple:
}
} 1) When using the 'print' builtin, always pass '-r --'.
I'd avoid this kind of blanket statement, because it leads to the question,
"if you should ALWAYS do that, why doesn't print just do that without being
told?"
} 2) When interpolating a variable into a string that will be parsed as
} zsh code, escape that variable using ${${(q)}}.
... and put that (@) or [@] in there so the (q) applies to each array
element separately ... unless that's not what you mean.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-28 5:28 ` Daniel Shahaf
2016-12-28 6:31 ` Bart Schaefer
@ 2016-12-28 16:33 ` Ray Andrews
1 sibling, 0 replies; 21+ messages in thread
From: Ray Andrews @ 2016-12-28 16:33 UTC (permalink / raw)
To: zsh-users
On 27/12/16 09:28 PM, Daniel Shahaf wrote:
...
> 2) When interpolating a variable into a string that will be parsed as
> zsh code, escape that variable using ${${(q)}}.
>
> But yes, you have to do (2) yourself.
>
> I hope this helped...
>
> Cheers,
>
> Daniel
Yes, it helps a great deal. I can't say I get it yet, but I see where
you are coming from. Indeed, consistency must trump everything. "
${${(q)}} " seems byzantine but if it really is unavoidable -- it could
not have been made simpler -- then that's the way it is. I don't care
about the 'extra' keystrokes, I care that code helps you to do what you
want to do, instead of fighting against you. And that it does what you
might reasonably expect it to do. Transparency should be a virtue.
When I see the necessity, I'll stop chafing. Anyway, I tax everyone's
patience, so enough of this for now.
>
>>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-28 6:04 ` Bart Schaefer
@ 2016-12-28 17:39 ` Ray Andrews
2016-12-28 18:22 ` Bart Schaefer
0 siblings, 1 reply; 21+ messages in thread
From: Ray Andrews @ 2016-12-28 17:39 UTC (permalink / raw)
To: zsh-users
On 27/12/16 10:04 PM, Bart Schaefer wrote:
> The backslash stuff is borrowed conceptually from C (\t for tab, etc.).
> Having that same paradigm applied at multiple levels of processing stems
> from the language being interpreted rather than compiled.
I think what I'm not really getting is the multiple level thing. When I
get that, maybe difficulties
will melt away. Of course the backslash is special, hasta be.
> The point is that this isn't "natural," because what you asked for isn't
> natural.
No? It seems simple enough and the ' : ' command seems tailor made for it.
> but for the
> sake of everyone else who's going to see this and copy-paste, it
> may be worth forestopping any future problems.
Of course! It's the gotchas that drive me crazy. Un-robust code is
alpha code.
I guess that's one of these cultural things -- for me the idea that
something
more or less works most of the time, but never on Thursday, just doesn't
cut it.
No, I'll never have a backslash in my $HOST but that's irrelevant because
it hasta be proof against that possibility. I agree with you
absolutely. $HOST
is an unformated literal string and should be seen that way every time.
>
> You can't get away from thinking about what you mean.
Indeed not. The difficulty is that what I mean and what zsh thinks I
mean ain't the same.
I keep lusting after 'history'. Sheesh, what I want is already there,
zsh already knows how
to preserve the literal keystrokes that you typed into history, I just
can't get at it.
If I could just intercept the command as it goes into history -- but
with each command
knowing what belongs to itself when there are semicolons -- I'd have
everything I want:
$ com1 "\'"{(g+)}()\(\t | @$%^>> /dev/the-void < ; com2 "\t"; echo
"don't try this at home"
... now hit the up arrow and what I get back is exactly what I typed.
So why can't we have:
function com1 ()
{
echo "Here's exactly what you typed, absolutely unmolested, when you
invoked this command:\n
$MY-LITERAL-ARGUMENTS-AS-HISTORY-WILL-RECORD-THEM"
}
$ com1 "\'"{(g+)}()\(\t | @$%^>> /dev/the-void <
Here's exactly what you typed, absolutely unmolested, when you
invoked this command:
com1 "\'"{(g+)}()\(\t | @$%^>> /dev/the-void <
$
Somewhere, in the deepest bowels of the parser, the literal string
exists just before it is sent to history. If I could just grab it
somehow ...
Don't let me bother you too much Bart, we've been over this, and it
seems it can't be done. In practical terms what you've shown me works
perfectly.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-28 17:39 ` Ray Andrews
@ 2016-12-28 18:22 ` Bart Schaefer
2016-12-28 19:20 ` Ray Andrews
0 siblings, 1 reply; 21+ messages in thread
From: Bart Schaefer @ 2016-12-28 18:22 UTC (permalink / raw)
To: Ray Andrews, zsh-users
On Dec 28, 9:39am, Ray Andrews wrote:
} Subject: Re: append to history entry?
}
} On 27/12/16 10:04 PM, Bart Schaefer wrote:
} > You can't get away from thinking about what you mean.
}
} Indeed not. The difficulty is that what I mean and what zsh thinks I
} mean ain't the same.
As it has ever been in pretty much all programming languages.
} If I could just intercept the command as it goes into history --
} but with each command knowing what belongs to itself when there are
} semicolons
That's where your confusion is. History is *NOT* command history.
It's *command line input* history. History does NOT know what text
belongs to what command, and it's not processed at the same level as
the parser that figures that out. It's involved with the lexer,
which decides how to break things into tokens but does not decide
what those tokens mean. History is thus connected more closely to
the line editor than to the command execution engine.
} Somewhere, in the deepest bowels of the parser, the literal string
} exists just before it is sent to history.
No, that's completely wrong. The literal string is long gone by the
time you get that far down in the parser. When your "com1" function
is called, all the expansions and substitutions have long since been
done and the original text discarded; "setopt xtrace" and look at the
output -- THAT is what exists at the point "com1" runs.
In fact by that point the literal command input is *already in* the
history, unless you've stopped it somehow e.g. histignorespace.
Read up on the "trap" command with the DEBUG pseudo-signal, and the
ZSH_DEBUG_CMD variable, which is the closest thing there is to what
you are imagining.
The zshaddhistory hook is where you get at the literal input string.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-28 18:22 ` Bart Schaefer
@ 2016-12-28 19:20 ` Ray Andrews
2016-12-28 21:24 ` Ray Andrews
[not found] ` <3b8fe027-d7fb-25fb-bc05-9ecd3a91b08f__38422.8622112007$1482960347$gmane$org@eastlink.ca>
0 siblings, 2 replies; 21+ messages in thread
From: Ray Andrews @ 2016-12-28 19:20 UTC (permalink / raw)
To: zsh-users
On 28/12/16 10:22 AM, Bart Schaefer wrote:
> what those tokens mean. History is thus connected more closely to
> the line editor than to the command execution engine.
Whatever, I can't comment on the stage, I only say that at some point the
string is literal.
>
> Read up on the "trap" command with the DEBUG pseudo-signal, and the
> ZSH_DEBUG_CMD variable, which is the closest thing there is to what
> you are imagining.
>
> The zshaddhistory hook is where you get at the literal input string.
>
Ok, I'll see what I can figure out.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-28 19:20 ` Ray Andrews
@ 2016-12-28 21:24 ` Ray Andrews
[not found] ` <3b8fe027-d7fb-25fb-bc05-9ecd3a91b08f__38422.8622112007$1482960347$gmane$org@eastlink.ca>
1 sibling, 0 replies; 21+ messages in thread
From: Ray Andrews @ 2016-12-28 21:24 UTC (permalink / raw)
To: zsh-users
On 28/12/16 11:20 AM, Ray Andrews wrote:
> Ok, I'll see what I can figure out.
>
>
Needless to say this is exploratory:
function zshaddhistory ()
{
LITERAL=( "${(@s/;/)1}" )
#print -rl $LITERAL
LITERAL[1]=${LITERAL[1]/ #/}
LITERAL[2]=${LITERAL[2]/ #/}
LITERAL[3]=${LITERAL[3]/ #/}
LITERAL[4]=${LITERAL[4]/ #/}
LITERAL[5]=${LITERAL[5]/ #/}
#print -r $LITERAL[1]
#print -r $LITERAL[2]
#print -r $LITERAL[3]
#print -r $LITERAL[4]
#print -r $LITERAL[5]
}
function test ()
{
print -r "you typed: $LITERAL[1]"
}
$ test \r * \n""''
you typed: test \r * \n""''
$ test $HOST
you typed: test $HOST
... but it seems to do exactly what I want the only thing lacking is to
associate each
member of the array to the appropriate command, if there are several on
the same line.
I can think of a few hacks that might do it, but is there a robust way?
Would precmd()
be able to keep count? Something of that nature? This is going to come
out right.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
[not found] ` <3b8fe027-d7fb-25fb-bc05-9ecd3a91b08f__38422.8622112007$1482960347$gmane$org@eastlink.ca>
@ 2016-12-28 23:34 ` Daniel Shahaf
2016-12-29 0:51 ` Bart Schaefer
2016-12-29 3:27 ` Ray Andrews
0 siblings, 2 replies; 21+ messages in thread
From: Daniel Shahaf @ 2016-12-28 23:34 UTC (permalink / raw)
To: Ray Andrews; +Cc: zsh-users
Ray Andrews wrote on Wed, Dec 28, 2016 at 13:24:25 -0800:
> On 28/12/16 11:20 AM, Ray Andrews wrote:
> >Ok, I'll see what I can figure out.
>
> Needless to say this is exploratory:
>
>
> function zshaddhistory ()
> {
> LITERAL=( "${(@s/;/)1}" )
⋮:
> ... but it seems to do exactly what I want the only thing lacking is
> to associate each member of the array to the appropriate command, if
> there are several on the same line. I can think of a few hacks that
> might do it, but is there a robust way? Would precmd() be able to
> keep count? Something of that nature? This is going to come out
> right.
You can easily convert the string "$1" to a token stream, however, there
is no fully robust way to translate that token stream into a list of
commands without reimplementing the parser.
Just consider the following cases (there are more, but you should get
the gist):
# quoted semicolon
echo lorem\;ipsum
# non-top-level semicolon
(foo; bar); baz
() { foo; bar } baz
for 1 in foo bar; baz $1
# non-semicolon
foo& bar&
case foo in (bar) : ;; esac
# INTERACTIVE_COMMENTS
echo foo # bar ;
What are you trying to do now? This is no longer your original
question about recording the hostname in history.
Is this about 'rap' being called in the middle of a command line…?
Cheers,
Daniel
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-28 23:34 ` Daniel Shahaf
@ 2016-12-29 0:51 ` Bart Schaefer
2016-12-29 3:27 ` Ray Andrews
1 sibling, 0 replies; 21+ messages in thread
From: Bart Schaefer @ 2016-12-29 0:51 UTC (permalink / raw)
To: zsh-users
On Dec 28, 11:34pm, Daniel Shahaf wrote:
}
} You can easily convert the string "$1" to a token stream
Which is in fact what ${(z)...} is for.
} however, there
} is no fully robust way to translate that token stream into a list of
} commands without reimplementing the parser.
Compare for example the state machine in zsh-syntax-highlighting's
main-highlighter.zsh ...
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: append to history entry?
2016-12-28 23:34 ` Daniel Shahaf
2016-12-29 0:51 ` Bart Schaefer
@ 2016-12-29 3:27 ` Ray Andrews
1 sibling, 0 replies; 21+ messages in thread
From: Ray Andrews @ 2016-12-29 3:27 UTC (permalink / raw)
To: zsh-users
On 28/12/16 03:34 PM, Daniel Shahaf wrote:
>
> Just consider the following cases (there are more, but you should get
> the gist):
Sure, no surprise there, of course only the parser knows one semicolon
from the next
but as Bart says, the history string is saved way before the parser gets
to it, so it sounds
like I can have my strings, but not robustly check for separation of
commands.
> What are you trying to do now? This is no longer your original
> question about recording the hostname in history.
>
> Is this about 'rap' being called in the middle of a command line…?
It's mostly for my command wrappers. The thing is to make it possible
to see the
'real' command being run by the wrapper. I have it mostly satisfactory
but the
method is belaboured. For example 'l' wraps 'ls'. If I do:
/boot $ l ,R *amd64 ( 'R' meaning sort and tabulate
from the right)
in my /boot directory I get:
|
| || |1 4153384 2016-12-17/09:56:35 vmlinuz-4.8.0-2-amd64||
|| 1 3161213 2016-12-17/09:56:35 System.map-4.8.0-2-amd64||
|| 1 17655948 2016-12-27/15:59:03 initrd.img-4.8.0-2-amd64||
|| 1 183632 2016-12-17/09:56:35 config-4.8.0-2-amd64||
||
|but, what did the wrapper do to get that? It did this:
$ ls -AGFrgt --time-style=+%F/%T --group-directories-first *amd64 |
egrep -v '^total' | rev | sort -r | column -t | rev | cut
--delimiter=' ' --fields=3-
How it works is that I start the function thusly:
alias l='noglob _l'
function _l ()
{
.... process various switches, cobbling together the real command ending
up with:
_execute $command-string
}
... and '_execute' essentially does this:
|
||_execute ()||
||{ ||
||||print -rS "$*"||
|| echo "\nEXECUTING: ${@//'\'/\\\\}\n"||( more protecting
backslashes :( )
|| eval "$@"||
||}||
|
... 'eval' of course expands and executes BUT the command has been
pushed to history without glob expansion (which would obviously be
impractical in many situations) so that I can recall the 'real' command
as I choose.
That's useful for debugging the wrapper -- if the wrapper screws up, I
just recall the real command and find out where the issue is. Also, I
might want to modify the real command in some way and re-execute it
since the wrappers themselves only handle routine usage. As it is now,
variables are expanded which is no huge problem but if there was some
way of grabbing the arguments to the command unexpanded I could just
chew on those so that the command pushed to history was totally
unexpanded as tho I had typed the real command in by hand. And of
course 'eval' would take care of everything as far as execution anyway.
The only time it gets unworkable is if some variable contains something
huge, but 99% of the time, what I have now is functional, but on
principal I'd still like to be able to have my entire command string
unaltered , push the constructed real command to history with wildcards
and variables as typed, and just have 'eval' expand everything as
needed. I know it's sorta the opposite of what zsh is for, but having
the real command available for recall can be hugely useful.
Here's another example:
/boot $ f ,Hd zsh* /
EXECUTING: find -H -O3 / -warn -xdev -iname "zsh*" -type d | grep -i
--color=always zsh
/etc/zsh-virgin
/usr/share/zsh
... up arrow brings the real command right back in case I want to play
with it some how or just see what the wrapper actually did.
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2016-12-29 3:27 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-26 23:16 append to history entry? Ray Andrews
2016-12-27 1:28 ` Ray Andrews
2016-12-27 4:47 ` Bart Schaefer
[not found] ` <5288b537-f06a-d18a-60ea-1f962856c80c__41345.3811700039$1482803962$gmane$org@eastlink.ca>
2016-12-27 12:55 ` Daniel Shahaf
2016-12-27 16:00 ` Bart Schaefer
2016-12-27 18:23 ` Ray Andrews
2016-12-27 19:09 ` Bart Schaefer
2016-12-27 23:16 ` Ray Andrews
2016-12-27 23:55 ` Bart Schaefer
2016-12-28 0:57 ` Ray Andrews
2016-12-28 6:04 ` Bart Schaefer
2016-12-28 17:39 ` Ray Andrews
2016-12-28 18:22 ` Bart Schaefer
2016-12-28 19:20 ` Ray Andrews
2016-12-28 21:24 ` Ray Andrews
[not found] ` <3b8fe027-d7fb-25fb-bc05-9ecd3a91b08f__38422.8622112007$1482960347$gmane$org@eastlink.ca>
2016-12-28 23:34 ` Daniel Shahaf
2016-12-29 0:51 ` Bart Schaefer
2016-12-29 3:27 ` Ray Andrews
[not found] ` <f87d7f79-3529-d832-eed5-83d4130ea128__16005.139592062$1482888562$gmane$org@eastlink.ca>
2016-12-28 5:28 ` Daniel Shahaf
2016-12-28 6:31 ` Bart Schaefer
2016-12-28 16:33 ` Ray Andrews
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).