From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Ian Kelling Newsgroups: gmane.emacs.help Subject: Re: Useful elisp I wrote, send-region-to-shell-mode Date: Sat, 15 Mar 2014 00:58:30 -0700 Message-ID: <53240826.7030501@gmail.com> References: <5322751C.3020108@gmail.com> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Trace: ger.gmane.org 1394870360 2240 80.91.229.3 (15 Mar 2014 07:59:20 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sat, 15 Mar 2014 07:59:20 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Sat Mar 15 08:59:27 2014 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1WOjV8-0006sB-Up for geh-help-gnu-emacs@m.gmane.org; Sat, 15 Mar 2014 08:59:27 +0100 Original-Received: from localhost ([::1]:49108 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WOjV8-0003Jh-Je for geh-help-gnu-emacs@m.gmane.org; Sat, 15 Mar 2014 03:59:26 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:37043) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WOjUr-0003JI-A0 for help-gnu-emacs@gnu.org; Sat, 15 Mar 2014 03:59:15 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WOjUk-0003W1-7d for help-gnu-emacs@gnu.org; Sat, 15 Mar 2014 03:59:09 -0400 Original-Received: from out1-smtp.messagingengine.com ([66.111.4.25]:38421) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WOjUk-0003Ur-3S for help-gnu-emacs@gnu.org; Sat, 15 Mar 2014 03:59:02 -0400 Original-Received: from compute2.internal (compute2.nyi.mail.srv.osa [10.202.2.42]) by gateway1.nyi.mail.srv.osa (Postfix) with ESMTP id 6DC9720840; Sat, 15 Mar 2014 03:59:01 -0400 (EDT) Original-Received: from frontend2 ([10.202.2.161]) by compute2.internal (MEProxy); Sat, 15 Mar 2014 03:59:01 -0400 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d= messagingengine.com; h=message-id:date:from:mime-version:to :subject:references:in-reply-to:content-type :content-transfer-encoding; s=smtpout; bh=HUXGkTNzJMREWNpFS3/B2O F8w5I=; b=XFamQGcstXsNJ6zjvXQuVYFy3Y1sYkfUrG3rl4eRCsqo1iTmAiKDUe fopbjdZv/qoNul14jezEBHOYYLwfsqEZIHnUhvq7E0IcZtoe2pgyRZ717FLnNV0l VLWo0eMwlPKR107caLx5p3++vc9KF9PxS9Gxlc5vIo4GrCxg5lX6U= X-Sasl-enc: m2F++ICZ/3GhFo/pvjl0NzR+pTmoqWnY25NY9jKwhhk3 1394870341 Original-Received: from [192.168.1.2] (unknown [67.160.118.141]) by mail.messagingengine.com (Postfix) with ESMTPA id 15400680156 for ; Sat, 15 Mar 2014 03:59:00 -0400 (EDT) User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20131103 Icedove/17.0.10 In-Reply-To: <5322751C.3020108@gmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 66.111.4.25 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:96517 Archived-At: I've been sitting at the computer too long, hopefully this isn't a double post. On 03/14/2014 03:59 AM, Alan Schmitt wrote:> Hello Ian, > > Ian Kelling writes: > >> I just switched over to shell-mode and definitely recommend it over >> a normal terminal in general. > > I'm curious about this. I tried several times to use a shell in emacs > instead of a terminal, and I have always gone back. The main two reasons > I could not keep using them are some incompatibilities with some shells > (I use fish, for instance, which can only run in ansi-term, and even > there it's not perfect), and window management (having a quick access > to a shell window). You get emacs window management, it is what it is. I'm happy with it. I can put shell-mode's in their own frames. > This is very nice, thanks for sharing. I often use org-mode when > developing scripts, but this could be a useful alternative. I'm using org-babel in conjunction with this. Related: going to send a patch to org-mode which sends std-err to babel results. > Do you have tips for using a shell in emacs? In > particular, what shell do you run? I use bash, which luckily is very compatible. You lose the bash keybinds and replace them with emacs ones, which are generally the same or better. The only notable thing you lose is compatibility with interactive shell programs that do anything more interactive than prompting for input. If you use those enough, shell-mode is a no go. term/ansi-term mode is one avenue to try, but I wouldn't bother. Tips, yes. A bit of reading in ctrl-h m in shell-mode covers almost everything. I use the bash-completion elisp package via melpa. It enables the smart command argument completions of http://bash-completion.alioth.debian.org/, which come standard in most gnu/linux distros. ;; don't store successive duplicates in comint command history (setq comint-input-ignoredups t) I also bound 'comint-previous-input / 'comint-next-input to the up/down keys I'm used to in a shell. After sending off my first email, I realized some more functionality I wanted in my function; Send the current line if region isn't active. Also, when in shell mode, send lines BACK to the previous window. The new version: ;; example keybind (global-set-key (kbd "") 'send-shell) ;; optional variables used by send-shell (setq shell-unset-prompt "unset PROMPT_COMMAND; unset PS1") (setq shell-set-prompt "PROMPT_COMMAND=prompt_command") (setq shell-send-yank-key (kbd "C-v")) (defun send-shell () "Send current line or region (if active) to shell-mode buffer. When in shell-mode, copy the current line, paste it in the most recently visited visible window. Optional variables: `shell-unset-prompt/shell-set-prompt': shell commands invisibly sent to temporarily hide shell prompts for multi-line input. `send-shell-buffer-name': Use this instead of default *shell* `shell-send-yank-key' key to use instead of yank to paste into recent window. This allows compatibility with modes like org-mode which have their own yank function. Creates & shows shell-mode buffer in a new window if needed." (interactive) (if (string-equal mode-name "Shell") (progn (call-interactively 'copy-line) (select-window (previous-window nil nil 'visible)) (if (and (boundp 'shell-send-yank-key) shell-send-yank-key) (call-interactively (global-key-binding shell-send-yank-key)) (yank)) (select-window (next-window nil nil 'visible))) (let (start end) (if mark-active (setq start (mark) end (point)) (setq start (save-excursion (beginning-of-line) (point)) end (save-excursion (end-of-line) (point))) (next-line)) (send-comint-input (or (and (boundp 'send-shell-buffer-name) send-shell-buffer-name) "*shell*") start end 'shell)))) ;; supporting functions (defun copy-line (arg) "Copy lines (as many as prefix argument) in the kill ring. Pretend the last line of the buffer has a trailing newline to avoid insanity." (interactive "p") (kill-ring-save (line-beginning-position) (line-end-position arg)) (kill-append "\n" nil) (if (and arg (not (= 1 arg))) (message "%d lines copied" arg))) (defun send-comint-input (buffer-name start end &optional 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." (interactive) (let ((input (filter-buffer-substring start end)) (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 (and (boundp 'send-shell-buffer-name) send-shell-buffer-name)) (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 (boundp 'shell-unset-prompt) (send-invisible-string proc shell-unset-prompt)) (goto-char (process-mark proc)) (insert input) (comint-send-input) (if (boundp 'shell-set-prompt) (send-invisible-string proc shell-set-prompt)))))) (defun send-invisible-string (proc string) "Like send-invisible, but non-interactive" (comint-snapshot-last-prompt) (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 'temp-buffer-resize) temp-buffer-resize-mode)) t 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. window))))