Sometimes it may happen that we would like to open the current buffer in another text editor (notepad, gedit, texmaker, ....). What are the best ways to do it?
-
Are you talking about sending the current buffer text as well?– Sean AllredJan 10, 2015 at 3:32
-
2"But why would you want to?" :(– lilyJan 10, 2015 at 6:25
-
@IstvanChung It may happen! For example you are editing an HTML file and you would like to open it in a web browser, also for the case where your language is not supported by the spell-checking engines of Emacs. And many other examples.– NameJan 10, 2015 at 9:37
-
@SeanAllred yes.– NameJan 10, 2015 at 9:40
3 Answers
You could use something such as the following
(defun open-external (&optional editor)
(interactive "sEditor to use: ")
(let ((file (buffer-file-name (current-buffer))))
(if (executable-find editor)
(if file
(shell-command (format "%s %s"
(executable-find editor)
file))
(user-error "Current buffer has no associated file."))
(user-error "Editor (%s) not found on path" editor))))
This uses buffer-file-name
rather than buffer-name
to ensure you get the associated file from the filesystem. It also validates that both the file and the editor selected are found on path (or explicitly pointed to).
-
-
I think you can simplify this by dropping the
let
call. You can access thebuffer-file-name
directly as a variable, you don't need to call it and store the value.– robruJan 11, 2015 at 18:53 -
The
let
is more personal preference. Have to accessfile
twice so rather use a temporary variable than type it out fully both times. Jan 21, 2015 at 14:37 -
A few remarks (only the first has some importance) (i) I suggest using
call-process
instead ofshell-command
, otherwise you'd have to quote the filename for the shell. (ii) as was pointed out,buffer-file-name
is also a variable name, which you can use directly (as for the function,(current-buffer)
is used by default) (iii) you could define a temporary variable for(executable-find editor)
too (I don't know how costly that function call is, but I guess this is more than a call to the functionbuffer-file-name
!) May 13, 2015 at 8:49
This version opens the buffer in an external program (use a prefix to change the default). If the buffer is not visiting a file, open it up in a temporary file:
(defvar alternate-editor "gedit"
"Editor to use when visiting a buffer outside of emacs.")
(defun open-in-alternate-editor (&optional arg)
"Open buffer in alternative editor. If buffer is unsaved,
bring it up in a temporary file. With prefix argument, ask for
the editor to use."
(interactive "P")
(let ((edit (executable-find (if arg
(read-from-minibuffer
"Enter editor to use: "
alternate-editor)
alternate-editor)))
(file (or (buffer-file-name)
(make-temp-file "unsaved-emacs-buffer-")))
(buff (unless (buffer-file-name)
(save-restriction (widen) (buffer-string)))))
(when (null edit)
(error "Can't find alternate editor"))
(unless (buffer-file-name)
(with-temp-file file
(insert buff)))
(start-process "Alternate Editor" nil edit file)))
Note that the defvar
might be overkill -- you could just replace it with whatever string you like within the defun
.
M-! (shell-command)
You could for example define your own command for edit that takes the current buffer name as input
(defun ppop-open-in-gedit ()
(interactive "")
(shell-command (format "gedit %s" (buffer-file-name))))
(global-set-key (kbd "<f10>") 'ppop-open-in-gedit)
I would check if the buffer has a corresponding file, but you get the idea.
-
2
(buffer-file-name)
is better than(buffer-name (current-buffer))
here. They both default to the current buffer, so you don't need to specify it explicitly.– TylerJan 9, 2015 at 20:55