Emacs eshell - Kill window on exit - emacs

I have the following code in my init.el
;;open eshell
(defun eshell-other-window ()
(interactive)
(let ((buf (eshell)))
(switch-to-buffer (other-buffer buf))
(switch-to-buffer-other-window buf)
)
)
(global-set-key (kbd "C-t") 'eshell-other-window)
This works fine until I exit eshell. When I exit, the window stays open. How do I get the window to close automatically?

The following answer assumes that the user is typing exit at the command prompt in the *Eshell* buffer followed by the return/enter key, and the answer assumes that the function eshell/exit is doing its thing. [The user is still free to customize the variable eshell-kill-on-exit to either burry or kill the *Eshell* buffer when exiting.]
(require 'eshell)
(defun my-custom-func ()
(when (not (one-window-p))
(delete-window)))
(advice-add 'eshell-life-is-too-much :after 'my-custom-func)

Related

Emacs. Shell how clean screen?

Windows 7
Emacs 24.5
1.Open shell, by M-x shell.
2.Do some commands.
As result I get screen:
OK. Now I want to clear screen (in Windows consele this is a command "cls").
I want to get the next screen:
How I can do this in Emacs shell?
Run the emacs function "erase-buffer" to clear the buffer.
You could bind a function key to clear your buffer:
(global-set-key (kbd "<f10>")
(lambda ()
(interactive)
(erase-buffer)
(process-send-string nil "\n")))
This also work:
;; clear content of buffer
(defun clear-buffer-permenantly ()
"Clear whole buffer, contents is not added to the kill ring"
(interactive)
(delete-region (point-min) (point-max))
)
(global-set-key (kbd "<f12>")
(lambda ()
(interactive)
(clear-buffer-permenantly)
(process-send-string nil "\n")))

Kill the *terminal* buffer with C-d

I found a nice post a few
days ago detailing how to kill the shell buffer with the C-d key. Basically,
after killing the process with C-d you can now tap C-d again to also kill
the buffer.
I was trying to implement something similar for term-mode, but I ran into a
problem. After you kill the term process (with the usual C-d) it seems that
the key-map being used by the buffer changes, but I can't find out what it is!
For example, launch the term command (M-x term RET RET) and then just
immediatelly hit C-d. Once the process is dead, the buffer still reports being
in term-mode, but they key-map it's using is neither term-mode-map nor
term-raw-map.
So
I either need to find out what map it is using so I can bind C-d to kill-buffer.
Or I need another way to kill the buffer with C-d in term-mode.
Try this out:
(defun delete-char-or-kill-terminal-buffer (N &optional killflag)
(interactive "p\nP")
(if (string= (buffer-name) "*terminal*")
(kill-buffer (current-buffer))
(delete-char N killflag)))
(global-set-key (kbd "C-d") 'delete-char-or-kill-terminal-buffer)
When the *terminal* process exits, the mode of the buffer switches to fundamental, which is why the C-d doesn't do what you want.
While Trey Jackson's version is absolutely correct, below is another version which doesn't require knowing the buffer name. It is then easier to manage multiple terminal buffers.
(defun term-handle-exit--close-buffer (&rest args)
(when (null (get-buffer-process (current-buffer)))
(insert "Press <C-d> to kill the buffer.")
(use-local-map (let ((map (make-sparse-keymap)))
(define-key map (kbd "C-d")
(lambda ()
(interactive)
(kill-buffer (current-buffer))))
map))))
(advice-add 'term-handle-exit :after #'term-handle-exit--close-buffer)

how to run sml/nj program under emacs

after one day struggle I finally configure Emacs for SML/NJ.
I am new to both emacs and SML, now I am having problem to how to run sml program under emacs.
when I command,
M-x sml-mode
it looks OK, no error report.
and after open(or create file like test.sml), I write simple sml program and I don't know how to compile it. I tried C-c C-c and C-c C-b as showed in some video. but there is no any response.
I am using emacs 24.1, SMLNj and windows vista system.
could some on tell me how compile and run SML program in emacs? I am beginner, so simple and detailed answer .
thank you very much.
Try C-c C-l instead. You're going to have to fiddle about and make sure that whatever sml executable you have is available to Emacs and in your PATH or whatever. I'm not familiar enough with Emacs on Windows to help you there. But here's the relevant section of the sml-mode manual: http://www.smlnj.org/doc/Emacs/sml-mode.html#Interaction-Mode
I use this piece of code to start and restart sml repl. I bind it to M-s M-m.
(defun isml ()
"If sml repl exists, then restart it else create a new repl"
(interactive)
(when (get-buffer "*sml*")
(with-current-buffer "*sml*"
(when (process-live-p "sml")
(comint-send-eof)))
(sleep-for 0.2))
(sml-run "sml" ""))
(global-set-key (kbd "M-s M-m") 'isml)
(defun gcr/sml-eval-buffer ()
"Intelligently evaluate a SML buffer."
(interactive)
(gcr/save-all-file-buffers)
(let ((sml-process (get-process "sml")))
(when sml-process
(quit-process sml-process)))
(sleep-for 0.25)
(let ((sml-buffer (get-buffer "*sml*")))
(when sml-buffer
(kill-buffer sml-buffer)))
(sml-prog-proc-load-file buffer-file-name))
#wenjun.yan 's answer does not work on my Emacs. So I changed that to this:
(defun isml ()
"If sml repl exists, then restart it else create a new repl"
(interactive)
(when (get-buffer "*sml*")
(when (process-live-p
(get-process "sml"))
(with-current-buffer "*sml*"
(comint-send-eof)))
(sleep-for 0.2)
(kill-buffer "*sml*"))
(sml-run "sml" ""))
(global-set-key (kbd "<f7>") 'isml)

Emacs Shell mode: how to send region to shell?

Is there some module or command that'll let me send the current region to shell?
I want to have something like Python-mode's python-send-region which sends the selected region to the currently running Python shell.
Ok, wrote an easy bit. Will probably spend some time to write a complete minor mode.
For time being the following function will send current line (or region if the mark is active). Does quite a good job for me:
(defun sh-send-line-or-region (&optional step)
(interactive ())
(let ((proc (get-process "shell"))
pbuf min max command)
(unless proc
(let ((currbuff (current-buffer)))
(shell)
(switch-to-buffer currbuff)
(setq proc (get-process "shell"))
))
(setq pbuff (process-buffer proc))
(if (use-region-p)
(setq min (region-beginning)
max (region-end))
(setq min (point-at-bol)
max (point-at-eol)))
(setq command (concat (buffer-substring min max) "\n"))
(with-current-buffer pbuff
(goto-char (process-mark proc))
(insert command)
(move-marker (process-mark proc) (point))
) ;;pop-to-buffer does not work with save-current-buffer -- bug?
(process-send-string proc command)
(display-buffer (process-buffer proc) t)
(when step
(goto-char max)
(next-line))
))
(defun sh-send-line-or-region-and-step ()
(interactive)
(sh-send-line-or-region t))
(defun sh-switch-to-process-buffer ()
(interactive)
(pop-to-buffer (process-buffer (get-process "shell")) t))
(define-key sh-mode-map [(control ?j)] 'sh-send-line-or-region-and-step)
(define-key sh-mode-map [(control ?c) (control ?z)] 'sh-switch-to-process-buffer)
Enjoy.
(defun shell-region (start end)
"execute region in an inferior shell"
(interactive "r")
(shell-command (buffer-substring-no-properties start end)))
I wrote a package that sends/pipes lines or regions of code to shell processes, basically something similar that ESS is for R. It also allows for multiple shell processes to exist, and lets you choose which one to send the region to.
Have a look here: http://www.emacswiki.org/emacs/essh
M-x append-to-buffer RET
M-x shell-command-on-region
aka.
M-|
Modifying Jurgens answer above to operate on a specific buffer gives the following function, which will send the region and then switch to the buffer, displaying it in another window, the buffer named PYTHON is used for illustration. The target buffer should already be running a shell.
(defun p-send(start end)
(interactive "r") ;;Make the custom function interactive and operative on a region
(append-to-buffer (get-buffer "*PYTHON*") start end) ;;append to the buffer named *PYTHON*
(switch-to-buffer-other-window (get-buffer "*PYTHON*")) ;;switches to the buffer
(execute-kbd-macro "\C-m")) ;;sends the enter keystroke to the shell
Do you want the command to be executed automatically, or just entered into the command line in preparation?
M-x append-to-buffer RET will enter the selected text into the specified buffer at point, but the command would not be executed by the shell.
A wrapper function for that could automatically choose *shell* for the buffer (or more smartly select/prompt based on current buffers in shell-mode), and then call append-to-buffer.
You could trivially record a keyboard macro to copy the region, switch to *shell*, yank, and enter (if required).
F3M-wC-xb*shell*RETC-yRETF4
C-xC-knmy-execute-region-in-shellRET
M-xinsert-kbd-macroRETmy-execute-region-in-shellRET
(global-set-key (kbd "C-c e") 'my-execute-region-in-shell)
Update
The above (brilliant and useful) answers look a bit incomplete as of mid-2020: sh-mode has a function for sending shell region to non-interactive shell with output in the minibuffer called sh-send-line-or-region-and-step.
Alternatively: click Shell-script in the mode bar at the bottom of the window, then Mouse-1, then Execute region. The output is sent to the minibuffer and #<*Messages*>.
If minibuffer output is not enough, there are referenced techniques to redirect output to other buffers (not only the shell one, see for example "How to redirect message/echo output to a buffer in Emacs?").
You can also execute all the script with C-c C-x. VoilĂ .
Here is another solution from this post.
Just copying it for convenience. The print statement is key here.
(add-hook 'python-mode-hook
'my-python-send-statement)
(defun my-python-send-statement ()
(interactive)
(local-set-key [C-return] 'my-python-send-statement)
(end-of-line)
(set-mark (line-beginning-position))
(call-interactively 'python-shell-send-region)
(python-shell-send-string "; print()"))
I adapted the accepted answer for ansi-term / sane-term.
Changes:
change "shell" to "ansi-term" everywhere
The (with-current-buffer pbuff ...) form doesn't work, because of the way that line and char modes work in terminal mode. It'll give you a read-only buffer error. Wrapping the insert in mode commands to toggle toggle line on before inserting fixes that, but is not needed because...
You can just use the process-send-string form by itself evidently, and the term output and cursor location reflect the change.
(defun ansi-term-send-line-or-region (&optional step)
(interactive ())
(let ((proc (get-process "*ansi-term*"))
pbuf
min
max
command)
(unless proc
(let ((currbuff (current-buffer)))
(sane-term)
(switch-to-buffer currbuff)
(setq proc (get-process "*ansi-term*"))))
(setq pbuff (process-buffer proc))
(if (use-region-p)
(setq min (region-beginning)
max (region-end))
(setq min (point-at-bol)
max (point-at-eol)))
(setq command (concat (buffer-substring min max) "\n"))
(process-send-string proc command)
(display-buffer (process-buffer proc) t)
(when step
(goto-char max)
(next-line))))
(defun sh-send-line-or-region-and-step ()
(interactive)
(sh-send-line-or-region t))
(defun sh-switch-to-process-buffer ()
(interactive)
(pop-to-buffer (process-buffer (get-process "*ansi-term*")) t))
(define-key sh-mode-map [(control ?j)] 'sh-send-line-or-region-and-step)
(define-key sh-mode-map [(control ?c) (control ?z)] 'sh-switch-to-process-buffer)

More than one emacs terminal

I am getting more and more used to doing everything from inside emacs, but it seems that eshell, shell and term will only run one instance each. Is there a way to run multiple terminals (preferably term) inside emacs?
Use the command M-x rename-buffer to give the current shell buffer a new name, then you can start a new shell.
You just have to rename the buffer, here's a function to start zsh and prompt for the buffer name:
(defun zsh (buffer-name)
"Start a terminal and rename buffer."
(interactive "sbuffer name: ")
(term "/bin/zsh")
(rename-buffer buffer-name t))
You can always create a new shell with C-u M-x shell
http://www.emacswiki.org/emacs/MultiTerm
You can rename a term and start a new one. I'm using something like that, took it from someone else .emacs.
(require 'term)
(defun visit-ansi-term ()
"If the current buffer is:
1) a running ansi-term named *ansi-term*, rename it.
2) a stopped ansi-term, kill it and create a new one.
3) a non ansi-term, go to an already running ansi-term
or start a new one while killing a defunt one"
(interactive)
(let ((is-term (string= "term-mode" major-mode))
(is-running (term-check-proc (buffer-name)))
(term-cmd "/bin/bash")
(anon-term (get-buffer "*ansi-term*")))
(if is-term
(if is-running
(if (string= "*ansi-term*" (buffer-name))
(call-interactively 'rename-buffer)
(if anon-term
(switch-to-buffer "*ansi-term*")
(ansi-term term-cmd)))
(kill-buffer (buffer-name))
(ansi-term term-cmd))
(if anon-term
(if (term-check-proc "*ansi-term*")
(switch-to-buffer "*ansi-term*")
(kill-buffer "*ansi-term*")
(ansi-term term-cmd))
(ansi-term term-cmd)))))
Or you can have just one and start a screen session in it.
I personally use a screen-like package I wrote, and there's another version available on the wiki here: elscreen. It provides convenient key bindings to jump to/between the different shells.
I modified the accepted answer by Harpo so that it starts a new shell without prompting, shells will be named in the form *shell-1*,*shell-2*,*shell-3* etc.:
(setq bash-counter 1)
(defun bash ()
"Start a bash shell"
(interactive)
(setq bash-counter (+ bash-counter 1))
(let
((explicit-shell-file-name "/bin/bash"))
(shell (concat "*shell-" (number-to-string bash-counter) "*"))
))
Here's a super lightweight little function that you can call to automatically rename the term you're on, and then start a new term:
(defun new-ansi-term ()
(interactive)
(if (string= "*ansi-term*" (buffer-name))
(rename-uniquely))
(ansi-term "/bin/bash"))
Then to bind that within ansi-term, I found this works:
(defvar ansi-term-after-hook nil)
(add-hook 'ansi-term-after-hook
'(lambda ()
(define-key term-raw-map (kbd "C-t") 'new-ansi-term)))
(defadvice ansi-term (after ansi-term-after-advice (org))
(run-hooks 'ansi-term-after-hook))
(ad-activate 'ansi-term)
If you then also bind new-ansi-term to C-t in the normal way, you'll find that when you're not looking at an ansi-term, C-t will focus the ansi-term buffer, and then if you are looking at an ansi-term, C-t will rename it to some unique name, and then open a new ansi-term for you. This works really well in combination with tabbar, which will show you all your opened ansi-terms just above the first line of the buffer. Easy to switch between them ;-)