Wie führe ich programmgesteuert einen Befehl in eshell aus?
8
Ich möchte einfache Befehle ausführen, eshellohne sie explizit in die Eingabeaufforderung einzugeben. Verwenden Sie dazu Folgendes: with-current-bufferWie kann ich das tun?
Können Sie Ihre Frage erweitern? Es ist nicht sehr klar, was Sie fragen.
Kindermädchen
Möchten Sie verwenden comint-send-stringund dann, comint-send-inputsobald die vorherige Zeichenfolge gesendet wurde?
Lawlist
1
eshellnicht verwendet comint, das erschwert es ein wenig.
Wasamasa
Antworten:
11
Meine anfängliche Vermutung war die Suche nach einem offiziellen Befehl, der dies bereits tut, also habe ich gefunden eshell-command. Dies wird jedoch in einem separaten Puffer ausgegeben, sodass dies keine Option ist.
Hier ist ein Beispiel mit lsund einem *eshell*Puffer:
Caisah with-current-bufferin der Frage erwähnt, ist also nicht eshell-commandgenau das, was gewünscht wird? (Obwohl ich es noch einmal lese, sehe ich, dass es nicht klar ist, welcher Puffer aktuell sein soll).
Phils
1
Ich gehe davon aus, dass der Kontext ein bereits vorhandener eshellPuffer ist, in den man bereits Befehle eingeben kann, um sie auszuführen. Es gibt jedoch kein Grundelement, um Dinge in diesem Puffer programmgesteuert auszuführen, als ob man sie geschrieben hätte. Sie eshell-commandverhalten sich etwas anders, da ihre Ausgabe nicht durch normale Verwendung erhalten werden kann eshell.
Wasamasa
2
Die folgende vorgeschlagene Lösung soll es Benutzern ermöglichen, Eingaben programmgesteuert unter der eshellHaube zu senden , anstatt den Befehl nach der eshellEingabeaufforderung in den Puffer einzufügen. @lawlist hat eine Feature-Anfrage an das Emacs-Entwicklungsteam gesendet, die berücksichtigt werden muss: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=25270
(require'eshell)(defun eshell-send-input (&optional use-region queue-p no-newline input-string-a)"Send the input received to Eshell for parsing and processing.
After `eshell-last-output-end', sends all text from that marker to
point as input. Before that marker, calls `eshell-get-old-input' to
retrieve old input, copies it to the end of the buffer, and sends it.
- If USE-REGION is non-nil, the current region (between point and mark)
will be used as input.
- If QUEUE-P is non-nil, input will be queued until the next prompt,
rather than sent to the currently active process. If no process, the
input is processed immediately.
- If NO-NEWLINE is non-nil, the input is sent without an implied final
newline."(interactive "P");; Note that the input string does not include its terminal newline.(let((proc-running-p
(and (eshell-interactive-process)(not queue-p)))(inhibit-point-motion-hooks t)
after-change-functions)(unless (and proc-running-p
(not (eq(process-status (eshell-interactive-process))'run)))(if(or proc-running-p
(>=(point) eshell-last-output-end))(goto-char (point-max));; This is for a situation when point is before `point-max'.(let((copy (or input-string-a (eshell-get-old-input use-region))))(goto-char eshell-last-output-end)(insert-and-inherit copy)))(unless (or no-newline
(and eshell-send-direct-to-subprocesses
proc-running-p))(insert-before-markers-and-inherit ?\n))(if proc-running-p
(progn(eshell-update-markers eshell-last-output-end)(if(or eshell-send-direct-to-subprocesses
(= eshell-last-input-start eshell-last-input-end))(unless no-newline
(process-send-string (eshell-interactive-process)"\n"))(process-send-region (eshell-interactive-process)
eshell-last-input-start
eshell-last-input-end)))(if(and (null input-string-a)(= eshell-last-output-end (point)));; This next line is for a situation when nothing is there --;; i.e., just make a new command prompt.(run-hooks 'eshell-post-command-hook)(let(input)(eshell-condition-case err
(progn(setq input (or input-string-a
(buffer-substring-no-properties
eshell-last-output-end (1-(point)))))(run-hook-with-args 'eshell-expand-input-functions
eshell-last-output-end (1-(point)))(let((cmd (eshell-parse-command-input
eshell-last-output-end (1-(point))nil input-string-a)))(when cmd
(eshell-update-markers eshell-last-output-end)(setq input (buffer-substring-no-properties
eshell-last-input-start
(1- eshell-last-input-end)))(run-hooks 'eshell-input-filter-functions)(and (catch'eshell-terminal(ignore
(if(eshell-invoke-directly cmd)(eval cmd)(eshell-eval-command cmd input))))(eshell-life-is-too-much)))))(quit
(eshell-reset t)(run-hooks 'eshell-post-command-hook)(signal 'quitnil))(error
(eshell-reset t)(eshell-interactive-print
(concat (error-message-string err)"\n"))(run-hooks 'eshell-post-command-hook)(insert-and-inherit input)))))))))(defun eshell-parse-command-input (beg end &optional args input-string-b)"Parse the command input from BEG to END.
The difference is that `eshell-parse-command' expects a complete
command string (and will error if it doesn't get one), whereas this
function will inform the caller whether more input is required.
- If nil is returned, more input is necessary (probably because a
multi-line input string wasn't terminated properly). Otherwise, it
will return the parsed command."(let(delim command)(if(setq delim (catch'eshell-incomplete(ignore
(setq command
(eshell-parse-command
(cons beg end) args t input-string-b)))))(ignore
(message "Expecting completion of delimiter %c ..."(if(listp delim)(car delim)
delim)))
command)))(defun eshell-parse-command (command &optional args toplevel input-string-c)"Parse the COMMAND, adding ARGS if given.
COMMAND can either be a string, or a cons cell demarcating a buffer
region. TOPLEVEL, if non-nil, means that the outermost command (the
user's input command) is being parsed, and that pre and post command
hooks should be run before and after the command."(let*(
eshell--sep-terms
(terms
(if input-string-c
(eshell-parse-arguments--temp-buffer input-string-c)(append
(if(consp command)(eshell-parse-arguments (car command)(cdr command))(let((here (point))(inhibit-point-motion-hooks t))(with-silent-modifications
;; FIXME: Why not use a temporary buffer and avoid this;; "insert&delete" business? --Stef(insert command)(prog1
(eshell-parse-arguments here (point))(delete-region here (point))))))
args)))(commands
(mapcar
(function
(lambda(cmd)(setq cmd (if(or (not (car eshell--sep-terms))(string= (car eshell--sep-terms)";"))(eshell-parse-pipeline cmd)`(eshell-do-subjob
(list ,(eshell-parse-pipeline cmd)))))(setq eshell--sep-terms (cdr eshell--sep-terms))(if eshell-in-pipeline-p
cmd
`(eshell-trap-errors ,cmd))))(eshell-separate-commands terms "[&;]"nil'eshell--sep-terms))))(let((cmd commands))(while cmd
(if(cdr cmd)(setcar cmd `(eshell-commands ,(car cmd))))(setq cmd (cdr cmd))))(if toplevel
`(eshell-commands (progn(run-hooks 'eshell-pre-command-hook)(catch'top-level(progn,@commands))(run-hooks 'eshell-post-command-hook)))(macroexp-progn commands))))(defun eshell-parse-arguments--temp-buffer (input-string-d)"Parse all of the arguments at point from BEG to END.
Returns the list of arguments in their raw form.
Point is left at the end of the arguments."(with-temp-buffer
(insert input-string-d)(let((inhibit-point-motion-hooks t)(args (list t))
delim)(with-silent-modifications
(remove-text-properties (point-min)(point-max)'(arg-begin nil arg-end nil))(goto-char (point-min))(if(setq
delim
(catch'eshell-incomplete(while (not (eobp))(let*((here (point))(arg (eshell-parse-argument)))(if(=(point) here)(error "Failed to parse argument '%s'"(buffer-substring here (point-max))))(and arg (nconc args (list arg)))))))(throw'eshell-incomplete(if(listp delim)
delim
(list delim (point)(cdr args)))))(cdr args)))))
(defun run-this-in-eshell (cmd)"Runs the command 'cmd' in eshell."(with-current-buffer "*eshell*"(eshell-kill-input)(end-of-buffer)(insert cmd)(eshell-send-input)(end-of-buffer)(yank)))
Es wird zuerst die bereits vorhandene cmdEingabe beenden , ausführen und dann die vorhandene Eingabe zurückziehen.
comint-send-string
und dann,comint-send-input
sobald die vorherige Zeichenfolge gesendet wurde?eshell
nicht verwendetcomint
, das erschwert es ein wenig.Antworten:
Meine anfängliche Vermutung war die Suche nach einem offiziellen Befehl, der dies bereits tut, also habe ich gefunden
eshell-command
. Dies wird jedoch in einem separaten Puffer ausgegeben, sodass dies keine Option ist.Hier ist ein Beispiel mit
ls
und einem*eshell*
Puffer:quelle
with-current-buffer
in der Frage erwähnt, ist also nichteshell-command
genau das, was gewünscht wird? (Obwohl ich es noch einmal lese, sehe ich, dass es nicht klar ist, welcher Puffer aktuell sein soll).eshell
Puffer ist, in den man bereits Befehle eingeben kann, um sie auszuführen. Es gibt jedoch kein Grundelement, um Dinge in diesem Puffer programmgesteuert auszuführen, als ob man sie geschrieben hätte. Sieeshell-command
verhalten sich etwas anders, da ihre Ausgabe nicht durch normale Verwendung erhalten werden kanneshell
.Die folgende vorgeschlagene Lösung soll es Benutzern ermöglichen, Eingaben programmgesteuert unter der
eshell
Haube zu senden , anstatt den Befehl nach dereshell
Eingabeaufforderung in den Puffer einzufügen. @lawlist hat eine Feature-Anfrage an das Emacs-Entwicklungsteam gesendet, die berücksichtigt werden muss: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=25270PROBENVERWENDUNG :
(eshell-send-input nil nil nil "ls -la /")
quelle
Ich habe diese Funktion dafür geschrieben,
Es wird zuerst die bereits vorhandene
cmd
Eingabe beenden , ausführen und dann die vorhandene Eingabe zurückziehen.quelle