142 lines
5.5 KiB
EmacsLisp
142 lines
5.5 KiB
EmacsLisp
(defun ambrevar/helm-ff--shell-interactive-buffer-p (buffer)
|
|
(with-current-buffer buffer
|
|
(and (eq major-mode 'shell-mode)
|
|
(save-excursion
|
|
(goto-char (point-min))
|
|
(comint-next-prompt 1)
|
|
(null (eql (point) (point-min)))))))
|
|
|
|
(defun ambrevar/helm-ff-switch-to-shell (_candidate)
|
|
"Like `helm-ff-switch-to-eshell' but for `M-x shell'.
|
|
|
|
With a numeric prefix arg switch to numbered shell buffer, if no
|
|
prefix arg provided and more than one shell buffer exists, provide
|
|
completions on those buffers. If only one shell buffer exists,
|
|
switch to this one, if no shell buffer exists or if the numeric
|
|
prefix arg shell buffer doesn't exists, create it and switch to it."
|
|
(let ((cd-shell
|
|
(lambda ()
|
|
(goto-char (point-max))
|
|
(comint-delete-input)
|
|
(insert (format "cd %s"
|
|
(shell-quote-argument
|
|
(if (tramp-tramp-file-p helm-ff-default-directory)
|
|
(tramp-file-name-localname
|
|
(tramp-dissect-file-name helm-ff-default-directory))
|
|
helm-ff-default-directory))))
|
|
(comint-send-input)))
|
|
(bufs (cl-loop for b in (mapcar 'buffer-name (buffer-list))
|
|
when (ambrevar/helm-ff--shell-interactive-buffer-p b)
|
|
collect b)))
|
|
(helm-aif (and (null helm-current-prefix-arg)
|
|
(if (cdr bufs)
|
|
(helm-comp-read "Switch to shell buffer: " bufs
|
|
:must-match t)
|
|
(car bufs)))
|
|
(switch-to-buffer it)
|
|
(shell))
|
|
(funcall cd-shell)))
|
|
|
|
(advice-add 'helm-ff-switch-to-eshell :override 'ambrevar/helm-ff-switch-to-shell)
|
|
;; TODO: Above code can be removed with Helm 3.6.3.
|
|
|
|
(defun ambrevar/shell-setup ()
|
|
(set (make-variable-buffer-local 'comint-input-history-ignore)
|
|
(regexp-opt '("^#" "^ " "^cd ")))
|
|
;; Only ending with '#' or '$' but seems slower:
|
|
;; (setq comint-prompt-regexp "^[^#$]*
|
|
;; [^#$]*[#$>] +")
|
|
(setq comint-prompt-regexp "^[^#$%>]*
|
|
[^#$%>]*[#$%>] +"))
|
|
|
|
(add-hook 'shell-mode-hook 'ambrevar/shell-setup)
|
|
|
|
(defun ambrevar/shell-prompt-begin-position ()
|
|
;; We need this convoluted function because `looking-at-p' does not work on
|
|
;; multiline regexps _and_ `re-search-backward' skips the current line.
|
|
(save-excursion
|
|
(let ((old-point (point)))
|
|
(max
|
|
(save-excursion
|
|
;; Right result if not on prompt.
|
|
(call-interactively #'comint-previous-prompt)
|
|
(re-search-backward comint-prompt-regexp)
|
|
(point))
|
|
(save-excursion
|
|
;; Right result if on first char after prompt.
|
|
(re-search-backward comint-prompt-regexp)
|
|
(point))
|
|
(save-excursion
|
|
;; Right result if on prompt.
|
|
(call-interactively #'comint-next-prompt)
|
|
(re-search-backward comint-prompt-regexp)
|
|
(if (<= (point) old-point)
|
|
(point)
|
|
(point-min)))))))
|
|
|
|
(defun ambrevar/shell-prompt-end-position ()
|
|
(save-excursion
|
|
(goto-char (ambrevar/shell-prompt-begin-position))
|
|
(call-interactively #'comint-next-prompt)
|
|
(point)))
|
|
|
|
(defun ambrevar/shell-prompt ()
|
|
(buffer-substring-no-properties
|
|
(ambrevar/shell-prompt-begin-position)
|
|
(ambrevar/shell-prompt-end-position)))
|
|
|
|
(defun ambrevar/shell-propertize-prompt () ; Inspired by `shx--propertize-prompt'.
|
|
"Add a mouseover timestamp to the last prompt."
|
|
(let ((inhibit-read-only t)
|
|
(inhibit-field-text-motion t))
|
|
(add-text-properties
|
|
(save-excursion
|
|
(re-search-backward comint-prompt-regexp nil :noerror)
|
|
(point))
|
|
(process-mark (get-buffer-process (current-buffer)))
|
|
`(help-echo ,(format-time-string "%F %T")))))
|
|
|
|
(defun ambrevar/shell-send-input ()
|
|
"Send or parse the input currently written at the prompt.
|
|
In normal circumstances this input is additionally filtered by
|
|
`shx-filter-input' via `comint-mode'."
|
|
(interactive)
|
|
(ambrevar/shell-propertize-prompt)
|
|
(comint-send-input))
|
|
(define-key shell-mode-map (kbd "<return>") 'ambrevar/shell-send-input)
|
|
|
|
(defun ambrevar/shell-command-duration ()
|
|
"Return duration of command at point in a `shell' buffer."
|
|
(interactive)
|
|
(let ((begin (ignore-errors (parse-time-string (get-text-property
|
|
(ambrevar/shell-prompt-begin-position)
|
|
'help-echo))))
|
|
(end (parse-time-string (save-excursion
|
|
(goto-char (ambrevar/shell-prompt-end-position))
|
|
(call-interactively #'comint-next-prompt)
|
|
(ambrevar/shell-prompt)))))
|
|
(if begin
|
|
(message "Command took %.0f seconds."
|
|
(- (float-time (apply 'encode-time end))
|
|
(float-time (apply 'encode-time begin))))
|
|
(message "No timestamp."))))
|
|
|
|
(defun ambrevar/shell-narrow-to-prompt ()
|
|
"Narrow buffer to prompt at point."
|
|
(interactive)
|
|
(let ((begin (ambrevar/shell-prompt-begin-position)))
|
|
(narrow-to-region
|
|
begin
|
|
(save-excursion
|
|
(goto-char (ambrevar/shell-prompt-end-position))
|
|
(call-interactively #'comint-next-prompt)
|
|
(if (= begin
|
|
(ambrevar/shell-prompt-begin-position))
|
|
(point-max)
|
|
(ambrevar/shell-prompt-begin-position))))))
|
|
(define-key shell-mode-map (kbd "C-x n d") 'ambrevar/shell-narrow-to-prompt)
|
|
|
|
(define-key shell-mode-map (kbd "C-x M-O") 'comint-truncate-buffer)
|
|
|
|
(provide 'init-shell)
|