Emacs function to create new terminal - emacs

Each time I open a new terminal in Emacs "M-x term" I get the currently open one, to get around this I need to rename the buffer where the terminal is running upon and then start a new one through M-x term.
I would like to write a function which holds a global counter and uses it to start a new terminal using it to generate the buffer name; once done I could map this function to a key binding of my preference.
I am having issues in running the terminal in a new created buffer, I am not an experienced ELisp programmer and this code might look quite naive to some, nonetheless this where I am at the moment :
(defvar counter 0)
(defun mine/open-terminal ()
"Open a new terminal and rename the buffer"
(setq counter (+ counter 1))
(setq title (concat "Terminal-" (number-to-string counter)))
(setq terminal (get-buffer-create title))
That function creates a new buffer with the correct name - although it does not show up it immediately as I would like it to do, the rub is that if I add at the end of the function the line:
(term "/bin/bash")
A new buffer called terminal is created, I have the feeling I am missing a bit here, is there a way to start a new terminal giving to it a buffer name ?
Thanks a lot.

The easiest way to do it I have found so far was it to literally copy the source code of the original term function from :
term.el source
And modify it into:
;; My terminal stuff
(defvar counter 0)
(defun my/open-terminal ()
"Open a new terminal and rename the buffer"
(interactive)
(setq counter (+ counter 1))
(setq title (concat "Terminal-" (number-to-string counter)))
(setq buf-title (concat "*" title "*"))
(message buf-title)
(set-buffer (make-term title "/bin/bash"))
(term-mode)
(term-char-mode)
(switch-to-buffer buf-title)
)

Maybe you can have a look at sane-term package. It has sane-term-create (create new term) and sane-term (loop through terms or create one if none.)

Here is an alternative approach that does not use a counter attached to a global or buffer-local variable -- i.e., the counter is only let-bound for the duration of the function.
(require 'term)
(defun my-term (program)
"Start a terminal-emulator in a new buffer.
The buffer is in Term mode; see `term-mode' for the
commands to use in that buffer.
\\<term-raw-map>Type \\[switch-to-buffer] to switch to another buffer."
(interactive (list (read-from-minibuffer "Run program: "
(or explicit-shell-file-name
(getenv "ESHELL")
(getenv "SHELL")
"/bin/sh"))))
(let* ((n 0))
(catch 'done
(while t
(let* (
bufname
buffer
(basename "term"))
(setq basename (concat basename (if (= n 0) "" (int-to-string n))))
(setq bufname (concat "*" basename "*"))
(setq n (1+ n))
(when (not (get-buffer bufname))
(setq buffer (set-buffer (make-term basename program)))
(term-mode)
(term-char-mode)
(throw 'done (switch-to-buffer buffer))) )))))

Related

How to save the state of Agenda buffer in Emacs?

What I mean:
Each of us has his own commands set in org-agenda-custom-commands variable.
But how can I detect what commands were used to create the current state of Agenda buffer (looking only at this buffer, maybe any local varibales?).
I want to save it and recreate later without dependence on current .emacs configuration
(defun wg-get-org-agenda-view-commands ()
"Get commands by which the current state of Agenda buffer can
be restored using \"(eval commands)\"."
(interactive)
(if (get-buffer org-agenda-buffer-name)
(with-current-buffer org-agenda-buffer-name
(let* ((p (or (and (looking-at "\\'") (1- (point))) (point)))
(series-redo-cmd (get-text-property p 'org-series-redo-cmd)))
(if series-redo-cmd
(get-text-property p 'org-series-redo-cmd)
(get-text-property p 'org-redo-cmd))))))
(defun wg-run-agenda-cmd (f)
"Run commands \"f\" in Agenda buffer. You can get these
commands using \"wg-get-org-agenda-view-commands\"."
(if (get-buffer org-agenda-buffer-name)
(save-window-excursion
(with-current-buffer org-agenda-buffer-name
(let* ((line (org-current-line)))
(if f (eval f))
(org-goto-line line))))))
Just read doc strings for both functions.
Thanks to fellas on org-mode mailing list. They gave me a hint.
Now I continue "workgroups" extension - workgroups2 which can save and restore org-agenda buffer.

Emacs Lisp buffer not running font lock mode until opened by user

My problem is I am opening a buffer using (set-buffer (find-tag-noselect (current-word))) and then I try to copy some text out of that buffer. The text that I get back has only the properties (fontified nil). find-tag-noselect automatically opens the buffer found in the TAGS file but it seems it does not run the font lock mode over it. When I manually switch to this buffer after it has been opened and then run the function again when it copies the text it has all the correct text properties attached. So what do I need to do to have this buffer completely initialized so that the correct syntax highlighting will be copied in?
(defvar newline-string "
")
(defun get-initial-indent-regexp-python()
"Gets the initial amount of spaces for the function we are looking at, does not account for tabs"
(concat "^" (get-current-indent-string) (concat "[^ #" newline-string "]")))
(defun get-end-of-function-python(spaces-regex)
"Gets the point at the end of a python block"
(save-excursion
(forward-line 1)
(while (and (not (looking-at spaces-regex)) (equal (forward-line 1) 0)))
(point)))
(defun get-point-at-end-of-function ()
"This might be better served checking the major mode."
(setq extension (file-name-extension (buffer-file-name)))
(if (equal extension "py")
(get-end-of-function-python (get-initial-indent-regexp-python))))
(defun inline-function ()
"Must change to overlays, be able to toggle visibility"
(interactive)
(let (text indent-string)
; clean all overlays without attached buffer
(save-excursion
(set-buffer (find-tag-noselect (current-word)))
(setq text (buffer-substring (point) (get-point-at-end-of-function))))
(setq text (concat newline-string text))
(save-excursion
(move-end-of-line nil)
(let (overlay)
(setq overlay (make-overlay (point) (+ (point) 1) (current-buffer)))
(overlay-put overlay 'display text)
(setq inline-func-overlays (cons overlay inline-func-overlays))))))
What's happening is that font-lock is done on-the-fly, so only the displayed parts of the buffer get "fontified". If you want/need to overrule this optimization, you need different functions depending on the circumstance (depending on how font-lock happens to be configured). We should add a new font-lock-ensure-fontified function for that, but in the mean time, you can take ps-print-.el as an example:
(defun ps-print-ensure-fontified (start end)
(cond ((and (boundp 'jit-lock-mode) (symbol-value 'jit-lock-mode))
(jit-lock-fontify-now start end))
((and (boundp 'lazy-lock-mode) (symbol-value 'lazy-lock-mode))
(lazy-lock-fontify-region start end))))
I'm not exactly sure what you're trying to do, but set-buffer does not display the buffer, so its effect ends when the current command terminates. It's generally useful only for temporary buffer switches inside a function and I guess this is the reason it doesn't run font-lock on the buffer. When you manually go to the buffer you're probably using a different function - switch-to-buffer.
Try explicitly calling 'font-lock-fontify-buffer'.

File path to clipboard in Emacs

What is the most simple way to send current full file name with file path to clipboard?
What I am using now is messages buffer: I copy file name that appears there after saving a file. But, I suppose, there should be much more simple way.
Why no one tell the simple solution.
Just go to your dired buffer then press 0 w or C-u 0 w.
This will call dired-copy-filename-as-kill which gives you full path of a file. If you want current dir, just delete the file at the end of it or you can use the function below, then bind it to any key you like.
(defun my/dired-copy-dirname-as-kill ()
"Copy the current directory into the kill ring."
(interactive)
(kill-new default-directory))
PS: personally I go to current directory from file buffer using dired-jump
I use this:
(defun my-put-file-name-on-clipboard ()
"Put the current file name on the clipboard"
(interactive)
(let ((filename (if (equal major-mode 'dired-mode)
default-directory
(buffer-file-name))))
(when filename
(with-temp-buffer
(insert filename)
(clipboard-kill-region (point-min) (point-max)))
(message filename))))
In Emacs Prelude I use:
(defun prelude-copy-file-name-to-clipboard ()
"Copy the current buffer file name to the clipboard."
(interactive)
(let ((filename (if (equal major-mode 'dired-mode)
default-directory
(buffer-file-name))))
(when filename
(kill-new filename)
(message "Copied buffer file name '%s' to the clipboard." filename))))
If you want to write the name/path of the current buffer you can type C-u M-: and then either (buffer-file-name) - for the full path - or (buffer-name) for the buffer name.
That is:
M-: + ellisp expression evaluates an ellisp expression in the mini-buffer
C-u write the output to the current buffer
Does not exactly answer to the question but could be useful if someone use this or other function sporadically, and prefers to not initialize the function at every startup.
In the Spacemacs distribution, you can press Spacefyy to display the buffer name in the minibuffer and copy it to the kill ring.
The function spacemacs/show-and-copy-buffer-filename seems to originate from this blog post: Emacs: Show Buffer File Name.
(defun camdez/show-buffer-file-name ()
"Show the full path to the current file in the minibuffer."
(interactive)
(let ((file-name (buffer-file-name)))
(if file-name
(progn
(message file-name)
(kill-new file-name))
(error "Buffer not visiting a file"))))
There's a buffer-extension - and it has copy-buffer-file-name-as-kill function. It even asks You what to copy: name, full name or a directory name.
Edit:
I use modified version of copy-buffer-file-name-as-kill from buffer-extension.el:
(defun copy-buffer-file-name-as-kill (choice)
"Copyies the buffer {name/mode}, file {name/full path/directory} to the kill-ring."
(interactive "cCopy (b) buffer name, (m) buffer major mode, (f) full buffer-file path, (d) buffer-file directory, (n) buffer-file basename")
(let ((new-kill-string)
(name (if (eq major-mode 'dired-mode)
(dired-get-filename)
(or (buffer-file-name) ""))))
(cond ((eq choice ?f)
(setq new-kill-string name))
((eq choice ?d)
(setq new-kill-string (file-name-directory name)))
((eq choice ?n)
(setq new-kill-string (file-name-nondirectory name)))
((eq choice ?b)
(setq new-kill-string (buffer-name)))
((eq choice ?m)
(setq new-kill-string (format "%s" major-mode)))
(t (message "Quit")))
(when new-kill-string
(message "%s copied" new-kill-string)
(kill-new new-kill-string))))
If you use Doom Emacs, it can be done with SPC f y.
To paste the current file path in the buffer, the most simple way I see is to do: C-u M-! pwd (this might not work on Windows systems though).
Alternatively, you can use C-x C-b to show the file paths of all opened buffers.
This is what has worked for me on MacOS 10.15.7, GNU Emacs 27.1
(defun copy-current-buffer-file-name ()
(interactive)
(shell-command (concat "echo " (buffer-file-name) " | pbcopy")))
set keybinding to "C-x M-f":
(global-set-key (kbd "C-x M-f") 'copy-current-buffer-file-name)
FYI: For a real beginner reading this, you need to add those lines to your init.el file.
Lots of good answers here, though I think for the "most simple way", as described in the question, there's room for improvement. Here's what I came up with (with thanks to other answers for the bits and pieces):
M-: (kill-new (buffer-file-name)) RET
This does precisely what you asked for -- takes the filename of the current buffer, and puts it in the "kill ring" and, depending on your settings, also the system clipboard. (See emacswiki/CopyAndPaste for more details on that part.)
If you want to do this regularly, then setting up a function like listed in the other answers, and binding it to an available key sequence, would make it easier to do frequently. But the above works with no prior setup, which I'm interpreting to be more "simple".

Emacs - Can't get buffer-offer-save working

I would like to have Emacs ask me whether I want to save a modified buffer, when that buffer is not associated with a file. To open a new buffer (not visiting a file) I have the following function in my .emacs file:
;; Creates a new empty buffer
(defun new-empty-buffer ()
"Opens a new empty buffer."
(interactive)
(let ((buf (generate-new-buffer "untitled")))
(switch-to-buffer buf)
(funcall (and default-major-mode))
(setq buffer-offer-save t)))
I thought setting "buffer-offer-save" to something not nil would made the trick. But whenever I kill the buffer with "kill-this-buffer", it gets instantly killed without asking anything.
This happens on GNU Emacs 23.1.1
Any ideas?
Thanks,
W
Edited to add use of buffers-offer-save. Note: the variable buffer-offer-save is only used upon exiting Emacs.
You can start with this code and customize it to what you want:
(add-to-list 'kill-buffer-query-functions 'ask-me-first)
(defun ask-me-first ()
"prompt when killing a buffer"
(if (or buffer-offer-save
(eq this-command 'kill-this-buffer)
(and (buffer-modified-p) (not (buffer-file-name))))
(y-or-n-p (format "Do you want to kill %s without saving? " (buffer-name)))
t))
Upon further reflection, that is a bit heavy-handed because you get prompted for all buffers that get killed, and there are often lots of temporary buffers that Emacs uses. If you just want to be prompted when you try to interactively kill a buffer (that isn't associated with a file).
You can use this advice which only prompts you when you're interactively trying to kill a buffer:
(defadvice kill-buffer (around kill-buffer-ask-first activate)
"if called interactively, prompt before killing"
(if (and (or buffer-offer-save (interactive-p))
(buffer-modified-p)
(not (buffer-file-name)))
(let ((answ (completing-read
(format "Buffer '%s' modified and not associated with a file, what do you want to do? (k)ill (s)ave (a)bort? " (buffer-name))
'("k" "s" "a")
nil
t)))
(when (cond ((string-match answ "k")
;; kill
t)
((string-match answ "s")
;; write then kill
(call-interactively 'write-file)
t)
(nil))
ad-do-it)
t)
;; not prompting, just do it
ad-do-it))
Modifying 'new-empty-buffer seems to make it work as I intended with Trey's defadvice.
;; Creates a new empty buffer
(defun new-empty-buffer ()
"Opens a new empty buffer."
(interactive)
(let ((buf (generate-new-buffer "untitled")))
(switch-to-buffer buf)
(funcall (and default-major-mode))
(put 'buffer-offer-save 'permanent-local t)
(setq buffer-offer-save t)))
This makes buffer-offer-save permanent local in our new buffer, so it won't get killed with the rest of the local variables when switching major modes.
buffer-offer-save asking on exiting Emacs but not on closing a buffer manually doesn't make sense, so why not “enlarge” its responsibilities?
(defadvice kill-buffer (around kill-buffer-ask activate)
"If `buffer-offer-save' is non-nil and a buffer is modified,
prompt before closing."
(if (and buffer-offer-save (buffer-modified-p))
(when (yes-or-no-p "The document isn't saved. Quit? ")
ad-do-it)
ad-do-it))
It will not prompt if untitled buffer is newly created. It will not prompt if you use kill-buffer from Elisp. It will not prompt on Emacs system buffers like *Messages*. But it will prompt if you created an empty buffer and wrote something in it.
See also my answer on creating an empty buffer.

Re-open *scratch* buffer in Emacs?

If I accidentally closed the scratch buffer in Emacs, how do I create a new scratch buffer?
GNU Emacs default bindings:
C-xb *scratch* RET
or, more verbosely
M-x switch-to-buffer *scratch* RET
The *scratch* buffer is the buffer selected upon startup, and has the major mode Lisp Interaction. Note: the mode for the *scratch* buffer is controlled by the variable initial-major-mode.
In general you can create as many "scratch" buffers as you want, and name them however you choose.
C-xb NAME RET
switches to a buffer NAME, creating it if it doesn't exist. A new buffer is not associated with a file on disk until you use C-xC-w (or M-x write-file RET) to choose a file where it should be saved.
M-x text-mode RET
changes the current buffer's major mode to Text mode. To find all the modes available (that is, without requiring any new packages), you can get a list by typing:
M-x apropos-command -mode$ RET
I add following in my .emacs:
;; bury *scratch* buffer instead of kill it
(defadvice kill-buffer (around kill-buffer-around-advice activate)
(let ((buffer-to-kill (ad-get-arg 0)))
(if (equal buffer-to-kill "*scratch*")
(bury-buffer)
ad-do-it)))
If I don't want to see scratch buffer I press C-x C-k , but it doesn't kill it, just place in the end of buffer list, so then I need it next time I don't have to create new one.
There are a whole bunch of tips on this EmacsWiki page.
Here's the first one:
A very simple function to recreate the scratch buffer:
(defun create-scratch-buffer nil
"create a scratch buffer"
(interactive)
(switch-to-buffer (get-buffer-create "*scratch*"))
(lisp-interaction-mode))
C-x b *scratch* RET y RET with iswitchb-mode enabled.
Just C-x b *scratch* RET otherwise.
I found this years ago when I first started using emacs; I have no idea where now but it has always had a home in my personal .el files. It does pop up in google searches.
;;; Prevent killing the *scratch* buffer -- source forgotten
;;;----------------------------------------------------------------------
;;; Make the *scratch* buffer behave like "The thing your aunt gave you,
;;; which you don't know what is."
(save-excursion
(set-buffer (get-buffer-create "*scratch*"))
(make-local-variable 'kill-buffer-query-functions)
(add-hook 'kill-buffer-query-functions 'kill-scratch-buffer))
(defun kill-scratch-buffer ()
;; The next line is just in case someone calls this manually
(set-buffer (get-buffer-create "*scratch*"))
;; Kill the current (*scratch*) buffer
(remove-hook 'kill-buffer-query-functions 'kill-scratch-buffer)
(kill-buffer (current-buffer))
;; Make a brand new *scratch* buffer
(set-buffer (get-buffer-create "*scratch*"))
(lisp-interaction-mode)
(make-local-variable 'kill-buffer-query-functions)
(add-hook 'kill-buffer-query-functions 'kill-scratch-buffer)
;; Since we killed it, don't let caller do that.
nil)
;;;----------------------------------------------------------------------
Like the docstring says, this function will:
Switch to the scratch buffer. If the buffer doesn't exist create it and write the initial message into it."
This will bring a new scratch buffer up which looks like the initial scratch buffer.
(defun switch-buffer-scratch ()
"Switch to the scratch buffer. If the buffer doesn't exist,
create it and write the initial message into it."
(interactive)
(let* ((scratch-buffer-name "*scratch*")
(scratch-buffer (get-buffer scratch-buffer-name)))
(unless scratch-buffer
(setq scratch-buffer (get-buffer-create scratch-buffer-name))
(with-current-buffer scratch-buffer
(lisp-interaction-mode)
(insert initial-scratch-message)))
(switch-to-buffer scratch-buffer)))
(global-set-key "\C-cbs" 'switch-buffer-scratch)
I used to use dwj's solution, and I was quite happy about it, until the day I realized that it failed when you actually rename the scratch buffer (for example by saving it).
Then I adopted this, which works well for me :
(run-with-idle-timer 1 t
'(lambda () (get-buffer-create "*scratch*")))
I have scratch as an interactive command for opening a new scratch buffer (I like to have several):
(defun scratch ()
"create a new scratch buffer to work in. (could be *scratch* - *scratchX*)"
(interactive)
(let ((n 0)
bufname)
(while (progn
(setq bufname (concat "*scratch"
(if (= n 0) "" (int-to-string n))
"*"))
(setq n (1+ n))
(get-buffer bufname)))
(switch-to-buffer (get-buffer-create bufname))
(if (= n 1) initial-major-mode))) ; 1, because n was incremented
adopted from: http://everything2.com/index.pl?node_id=1038451
(global-set-key (kbd "C-x M-z")
'(lambda ()
(interactive)
(switch-to-buffer "*scratch*")))
This will not only quickly switch to *scratch* buffer(since I do this frequently), but recreate a *scratch* buffer and enable lisp-interaction-mode automatically if you kill it accidentally. Change the binding as you like.
Just to note emacs package unkillable-scratch in MELPA will do this. There is also scratch-persist that will automatically save and restore the buffer between sessions.
This is what I use - I have this bound to a convenient keystroke. It sends you to the *scratch* buffer, regardless of whether or not it already exists, and sets it to be in lisp-interaction-mode
(defun eme-goto-scratch ()
"this sends you to the scratch buffer"
(interactive)
(let ((eme-scratch-buffer (get-buffer-create "*scratch*")))
(switch-to-buffer eme-scratch-buffer)
(lisp-interaction-mode)))
I prefer to have my scratch buffer be an actual file that is automatically saved, and reopening it is as simple as opening a file. On startup, I kill the default and find my own like this.
(add-hook 'emacs-startup-hook
(lambda ()
(kill-buffer "*scratch*")
(find-file "/Users/HOME/Desktop/.scratch")))
I have a custom kill-buffer function that does essentially the same thing -- reopens my personal scratch saved file and kills the default scratch if I killed the last visible buffer.
I customized a few of the desktop.el functions to load after (kill-buffer "*scratch*") and (find-file "/Users/HOME/Desktop/.scratch") so that the file last visible on exiting Emacs doesn't get buried by the default scratch or buried by my custom scratch when launching Emacs.
I enjoy using auto-save-buffers-enhanced, which automatically saves any file extension that is not specifically excluded:
https://github.com/kentaro/auto-save-buffers-enhanced/blob/master/auto-save-buffers-enhanced.el
(require 'auto-save-buffers-enhanced)
(auto-save-buffers-enhanced t)
(setq auto-save-buffers-enhanced-save-scratch-buffer-to-file-p 1)
(setq auto-save-buffers-enhanced-exclude-regexps '("\\.txt" "\\.el" "\\.tex"))
I use a slight variation of the function by #paprika when I want to create a no-file visiting buffer:
(defun lawlist-new-buffer ()
"Create a new buffer -- \*lawlist\*"
(interactive)
(let* (
(n 0)
bufname)
(catch 'done
(while t
(setq bufname (concat "*lawlist"
(if (= n 0) "" (int-to-string n))
"*"))
(setq n (1+ n))
(if (not (get-buffer bufname))
(throw 'done nil)) ))
(switch-to-buffer (get-buffer-create bufname))
(text-mode) ))
I have combined the solutions posted so far into one function:
(defun --scratch-buffer(&optional reset)
"Get the *scratch* buffer object.
Make new scratch buffer unless it exists.
If RESET is non-nil arrange it that it can't be killed."
(let ((R (get-buffer "*scratch*")))
(unless R
(message "Creating new *scratch* buffer")
(setq R (get-buffer-create "*scratch*") reset t))
(when reset
(save-excursion
(set-buffer R)
(lisp-interaction-mode)
(make-local-variable 'kill-buffer-query-functions)
(add-hook 'kill-buffer-query-functions '(lambda()(bury-buffer) nil)
)))
R))
To apply this function in your .emacs use:
(--scratch-buffer t)
(run-with-idle-timer 3 t '--scratch-buffer)
This will make the scratch buffer indestructible in the first place, and if saved it will be recreated. Additionally we can use a shortcut function scratch to bring up the buffer quickly:
(defun scratch()
"Switch to *scratch*. With prefix-arg delete its contents."
(interactive)
(switch-to-buffer (--scratch-buffer))
(if current-prefix-arg
(delete-region (point-min) (point-max))
(goto-char (point-max))))
In the past it has proven useful to know the original startup-directory from which Emacs was started. This is either the value of desktop-dirname or the default-directory local variable of the scratch-buffer:
(defvar --scratch-directory
(save-excursion (set-buffer "*scratch*") default-directory)
"The `default-directory' local variable of the *scratch* buffer.")
(defconst --no-desktop (member "--no-desktop" command-line-args)
"True when no desktop file is loaded (--no-desktop command-line switch set).")
(defun --startup-directory ()
"Return directory from which Emacs was started: `desktop-dirname' or the `--scratch-directory'.
Note also `default-minibuffer-frame'."
(if (and (not --no-desktop) desktop-dirname)
desktop-dirname
--scratch-directory))
So --startup-directory will always return the base directory of your makefile, TODO-file etc. In case there is no desktop (--no-desktop commandline-switch or no desktop-file) the --scratch-directory variable will hold directory Emacs was once started under.
find answer in EmacsWiki: http://www.emacswiki.org/emacs/RecreateScratchBuffer
(defun create-scratch-buffer nil
"create a scratch buffer"
(interactive)
(switch-to-buffer (get-buffer-create "*scratch*"))
(lisp-interaction-mode))
To add to the accepted answer, if you have ILO mode on (and it is autocompleting after C-x b, thus not letting you write *scratch*), then try:
C-xb C-b*scratch* RET
C-x b C-b *scratch* RET
C-xb and then type *scratch* ↩︎
to create a new buffer which is in lisp interaction mode also.