8

Brand new emacs user here.

I want to have the ability of opening a terminal with current file path from emacs, like what the open terminal here package does in sublime text 2.

By terminal, I mean a separate external terminal emulator running bash or zsh, like gnome-terminal, not the emulated shells inside emacs, like M-x shell M-x eshell, which I can't appreciate for now.

I googled but had nothing found... It seems that emacs guys really enjoy living in emacs.

6
  • Have you tried M-x ansi-term? It's much better than shell. I use it and it works really well. Or do you mean a new graphical terminal (like opening a gnome-terminal)?
    – PythonNut
    Jan 23, 2015 at 5:37
  • @PythonNut I've just tried it, it even couldn't handle the tab completion... So I still prefer a new terminal window. Ahhh, I've just tried M-! gnome-terminal, it works. I'm wondering why M-! bash couldn't do it.
    – Ply_py
    Jan 23, 2015 at 5:51
  • @Ply_py I think you need to tell terminal emulator and shell. bash is a shell, M-! bash surely won't do what you want. Please find out what terminal emulator you're using first.
    – kuanyui
    Jan 23, 2015 at 6:41
  • @kuanyui Ahh, I just searched these two words... and found the answers here. Clearly I mixed up the notions of shell and terminal(emulator). Thanks, I'll edit the question.
    – Ply_py
    Jan 23, 2015 at 8:10
  • shell and ansi-term definitely do handle tab completion, at least with bash. I use shell every day.
    – wdkrnls
    Jan 23, 2015 at 14:43

7 Answers 7

7

Another try that disowns the process so your terminal will survive even after emacs is killed.

(defun run-gnome-terminal-here ()
  (interactive "@")
  (shell-command (concat "konsole --workdir"
            (file-name-directory (or load-file-name buffer-file-name)) 
              " > /dev/null 2>&1 & disown") nil nil))
4
  • Is there a way to tie the spawned terminal to the lifetime of the emacs process? Aug 12, 2017 at 23:52
  • This doesn't work (emacs freezes until the terminal exits) if your terminal generates any debug messages when loading. To fix, swap the order of 2>&1 and >/dev/null (so that >/dev/null comes first).
    – Mark
    Aug 14, 2017 at 13:06
  • When I try this, Emacs doesn't even let me call the function. After evaluation, the mini buffer says gnome-terminal-here but when entering gnome-terminal-here, it says [No match].
    – UTF-8
    Sep 17, 2017 at 23:14
  • @UTF-8 That's because the function wasn't declared as an interactive command. See my edit. Sep 18, 2017 at 22:26
2

What terminal emulator are you using? Take KDE's Konsole as example, just write a function:

(defun open-konsole ()
  (interactive)
  (call-process "konsole" nil 0 nil "--workdir" default-directory))

The args from 5st place are konsole's argument. See your prefered terminal simulator's man page.

M-x open-konsole will open a new konsole process and use current default-directory (pwd in ELisp) as working directory.

1
  • One can open new tab if konsole is already running with (call-process "konsole" nil 0 nil "--new-tab" "--workdir" default-directory). Also (call-process "wmctrl" nil 0 nil "-a" "\" – Konsole\"") to activate its window.
    – Adobe
    Jan 23, 2015 at 18:36
2

The other answers didn't work for me. This code does:

(defun open-gnome-terminal ()
  (interactive)
  (shell-command "gnome-terminal"))
2

You can use the external package terminal-here. This does only one thing, but does it well; exactly what you requested. And works for me on multiple OS.

1

Building on terminal-here as proposed before, I created a small function that determines depending on the system and desktop environment the program to run. It can be useful if you like changing desktop, or keep your .emacs synchronized between several computers. Note that I didn't tested the windows/darwin/gnome/... shell code, only KDE is tested for now.

;; ##########################################################
;; ### Open terminal
;; ##########################################################

;; Define a function to recognize the desktop environment easily
;; You shouldn't need to touch this function
(defun get-desktop-environment ()
  (interactive)
  (let (
    ;; Create new variable with DE name
    (de_env (getenv "XDG_CURRENT_DESKTOP"))
    ;; Make sure search is case insensitive
    (case-fold-search t))
    (cond ((eq system-type 'darwin)
       "darwin")
      ((memq system-type '(windows-nt ms-dos cygwin))
       "windows")
      ((string-match ".*kde.*" de_env)
       "kde")
      ((string-match ".*gnome.*" de_env)
       "gnome")
      ((string-match ".*unity.*" de_env)
       "unity")
      ((string-match ".*xfce.*" de_env)
       "xfce")
      ((string-match ".*lxde.*" de_env)
       "lxde")
      ((string-match ".*mate.*" de_env)
       "mate")
      ((string-match ".*cinnamon.*" de_env)
       "cinnamon")
      (t "unknown"))))

;; You can edit this function if you want to change the default command for a specific desktop
(defun get-terminal (path)
  (alist-get (get-desktop-environment)
         '(("darwin" . ("open" "-a" "Terminal.app" "."))
           ("windows" . ("cmd.exe" "/C" "start" "cmd.exe"))
           ("kde" . ("konsole" "--workdir" "."))
           ("gnome" . ("gnome-terminal" "--working-directory=."))
           ("xfce" . ("xfce4-terminal" "--working-directory=.")))
         '("x-terminal-emulator") nil 'equal))

(use-package terminal-here
  :ensure t
  :bind (("<f6>" . terminal-here-launch))
  :config
  (setq terminal-here-terminal-command #'get-terminal))
0

Most of the time I use shell-mode. So I heavily use shell-here. But when I need external terminal. I use urxvt-client with tmux using this:

  • Create file named 'term-here' in /usr/local/bin/ containing
urxvtc -e bash -c "tmux -q has-session && exec tmux attach-session -d || exec tmux new-session -n$USER -s$USER@$HOSTNAME"
  • Create new function in emacs
(defun term-here ()
  (interactive)
  (start-process "" nil "term-here"))
  • Bind to your favorite key

This will open urxvt-client (with tmux) in your current directory. I bind it in dired-mode-map.

(use-package dired
  :ensure nil
  :ensure-system-package urxvt
  :bind ((:map dired-mode-map
           ("," . term-here))))

I choose urxvt-client because it is fast and simple. Don't forget to run your urxvt-daemon at startup.

0

This worked perfectly fine for me: (delete-window (async-shell-command "gnome-terminal")). Swap out your terminal command.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.