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

Re: first adventures

On Oct 28, 10:48am, Ray Andrews wrote:
} At the bottom of zleentry():
}      ///
}      printf("FILE: %s LINE: %d\n", __FILE__, __LINE__);
}      puts(ret);
}          return ret;
}    }
} I get:
}      FILE: init.c LINE: 1535
}      !4562; ls zsh.*                      << exactly exactly as typed :)
}      (output)
} ... so, I finally have my gloriously, deliciously unexpanded, plain 
} vanilla command, exactly as I

Well, you think so, but really it just happens that nothing you typed
needed to be metafied.  If you were to step through with a debugger,
you'd find that what's ultimately been called is zleread(), which is
prefixed with this comment:

/* Read a line.  It is returned metafied. */

} typed it. (BTW, 'cmd = -1' and this doesn't seem to be handled by 
} 'ZLE_CMD_READ' but nevermind.)

There are two switch statements in zleentry().  The first one calls
zle_entry_ptr(cmd) and then assigns cmd = -1 to cause the second
switch to be skipped.

} However, as Bart has explained, I really do want to be able to capture 
} the bangchar/history thing expanded
} Where can I capture that output?

That's a complicated question.  Input is actually read by the lexer,
which is called repeatedly by the parser until an entire runnable
shell command has been consumed.  (This is referred to as an "event"
in much of the internals, because that's how it's recorded in the
history when interactive, but the same applies to a script file.)

So if you actually want to try to look at it line by line, your best
bet is to look at the str argument passed to input.c:inputsetline(),
though that has the same caveats about metafication as above.  This
is still before history expansion, though.

History is expanded by the lexer as each word is consumed, because as
I mentioned in private email, the expansion has to be re-analyzed to
correctly tokenize it.  So the previously-discussed point in input.c
where VERBOSE is handled, is the line with history expanded.

The parser itself is driven by Src/init.c:loop().  At around line 160
through 180 is where the preexec function is called after a complete
input event has been read (which may be many lines).  The argument
list of that shell function has the strings that you're looking for:

     Executed just after a command has been read and is about to be
     executed.  If the history mechanism is active (and the line was not
     discarded from the history buffer), the string that the user typed
     is passed as the first argument, otherwise it is an empty string.
     The actual command that will be executed (including expanded
     aliases) is passed in two different forms: the second argument is
     a single-line, size-limited version of the command (with things
     like function bodies elided); the third argument contains the full
     text that is being executed.

(The doc is actually somewhat inaccurate there -- the first argument is
the string after history expansion, not exactly as typed.)

} Finally, if we have several commands on one line, at some point the line 
} must be chopped up
} at the semicolons for execution, since each individual command only 
} 'gets' that part of the
} line that applies to it.  How can that be done?

It's done by the parser.  In loop() you'll find the line:

        if (!(prog = parse_event())) {  /* if we couldn't parse a list */

When prog is non-NULL (the else branch of that if), it contains the
compiled form of the input code, which is already broken up into the
set of commands that will be executed.  There is no human-readable
decomposed form of the individual commands that make up a finished
input event; getpermtext(prog) returns the readable form of the entire
thing, which is the closest you get.

} (I was speculating that 
} if each command
} could somehow know that it was (say) command #3 on that line, then one 
} might very inelegantly
} parse the .histfile line, counting semicolons, and chop it up that way, 
} but how ugly is that.)

If you're examining the history file from the shell, you can use the (z)
and (Z:...:) parameter expansion flags to simulate parsing.

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