0
votes

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.

3
Here is what I use to create successively numbered custom scratch buffers, which you can modify to open a new term: emacs.stackexchange.com/a/16493/2287 - lawlist
I see that the function term is just a few lines long -- so go ahead and find the function, open it up, copy it to your .emacs, and create a new function with a different name incorporating a concept similar to the link in the first comment: M-x find-function RET term RET. When you programmatically loop through or search for existing buffers with a particular name, that obviates the need to store buffer object/name information in a global variable. The latter is possible, but appears to be necessary unless the variable will later be used for other things not specified in the question. - lawlist
@lawist: I can't find the function source .. I get an -> Debugger entered--Lisp error: (error "Can't find library term") - pedr0
(require 'term) in the .emacs or M-x eval-expression RET (require 'term) RET. - lawlist
find-library-name: Can't find library /usr/share/emacs/24.3/lisp/term.el :-( Thanks for the link, even though it looks to me that we are trying to do different things, in your case you create a new buffer and you the mode to it, in my case I kind of need to run a process on it, again, I am far from being an expert. - pedr0

3 Answers

2
votes

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)
)
1
votes

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.)

0
votes

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))) )))))