[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Useful elisp I wrote, send-region-to-shell-mode

From: Ian Kelling
Subject: Useful elisp I wrote, send-region-to-shell-mode
Date: Thu, 13 Mar 2014 20:18:52 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20131103 Icedove/17.0.10

I just switched over to shell-mode and definitely recommend it over a normal
terminal in general. This elisp seems to fill in an obviously missing piece of
integration with emacs. It's currently too hackish to recommend for going into
emacs, but I figured I would share and see if anyone had feedback or found it
useful. I'll post this it on the emacs wiki as well.

(defun send-region-to-shell-mode ()
  "Send region as input to shell in a shell-mode buffer.
Temporarily hide shell prompts for multi-line input.
Create & show shell buffer in a new window if needed.

Main use = enhance workflow when editing shell a script.

Minimal setup needed:
1. Adjust the arguments within this function
depending on how you set and unset the prompt in your shell.
2. Make a keybind to this function."
  (send-region-comint "*shell*"
                      "unset PROMPT_COMMAND; unset PS1"

;; supporting functions

(defun send-region-comint (buffer-name &optional before after init)
  "Input the region to BUFFER-NAME, assuming it is a comint-derived buffer.
        Show BUFFER-NAME if it is not show.
        Call INIT if BUFFER-NAME does not exist.
        Invisibly execute BEFORE & AFTER by comint process."
  (let ((input (buffer-substring-no-properties (mark) (point)))
        (buffer (get-buffer buffer-name)))
    (unless buffer
      ;; save-excursion etc. don't work for (shell), so I do this instead
      (if init (let ((original-buffer (current-buffer)))
                 (funcall init)
                 (switch-to-buffer original-buffer))
        (error "No existing buffer found and no init function argument. ")))
    (setq buffer (get-buffer buffer-name))
    (buffer-window-show buffer)
    (with-current-buffer buffer
      (let ((proc (get-buffer-process buffer)))
        (if before (send-invisible-string proc before))
        (goto-char (process-mark proc))
        (insert input)
        (if after (send-invisible-string proc after))))))

(defun send-invisible-string (proc string)
  "Like send-invisible, but non-interactive"
  (funcall comint-input-sender proc string))

;; modified version of temp-buffer-window-show,
;; only removed a few initial lines which set buffer read only etc.
;; I tried to find an existing function, but no dice
(defun buffer-window-show (&optional buffer action)
  "Like temp-buffer-window-show, but without any modifications to the buffer,
      like read only etc."
  (let (window frame)
    (with-current-buffer buffer
      (when (let ((window-combination-limit
                   ;; When `window-combination-limit' equals
                   ;; `temp-buffer' or `temp-buffer-resize' and
                   ;; `temp-buffer-resize-mode' is enabled in this
                   ;; buffer bind it to t so resizing steals space
                   ;; preferably from the window that was split.
                   (if (or (eq window-combination-limit 'temp-buffer)
                           (and (eq window-combination-limit
              (setq window (display-buffer buffer action)))
        (setq frame (window-frame window))
        (unless (eq frame (selected-frame))
          (raise-frame frame))
        (setq minibuffer-scroll-window window)
        (set-window-hscroll window 0)
        (with-selected-window window
          (run-hooks 'temp-buffer-window-show-hook)
          (when temp-buffer-resize-mode
            (resize-temp-buffer-window window)))
        ;; Return the window.

- Ian Kelling

reply via email to

[Prev in Thread] Current Thread [Next in Thread]