次の提案された解決策は、ユーザーがコマンドプロンプトに続くバッファにeshell
コマンドを挿入するのではなく、内部でプログラムによって入力を送信できるようにすることを目的としていeshell
ます。@lawlistは、Emacs開発チームが検討する機能リクエストを提出しました:http ://debbugs.gnu.org/cgi/bugreport.cgi?bug=25270
サンプルの使用法: (eshell-send-input nil nil nil "ls -la /")
(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 'quit nil))
(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)))))