3

I have written this function to insert an org-style link to a file:

(defun jay/insert-file-link (fname)
  "Insert link to file (called by Midnight Commander)."
  (interactive "s")
  (insert "[[")
  (insert fname)
  (insert "][")
  (insert fname)
  (insert "]]"))

When I am in a buffer with the cursor after this:

(jay/insert-file-link "foobar")

and hit C-x C-e it correctly inserts and I see

(jay/insert-file-link "foobar")[[foobar][foobar]]

However when I try it from the command line,

emacsclient -e "(jay/insert-file-link \"/tmp/foo\")"

it doesn't do anything in the buffer (it prints nil on the command line as expected)

Any clues as to what I'm dong wrong? Thanks.

  • Can't you use org-insert-link directly? – Jaseem Oct 8 '14 at 8:02
8

Nothing in your function tells Emacs where to insert the text, you need to tell it where to go.

If you’d like Emacs to place this link in a buffer named BUFFER-NAME (which you know will be open), you can use with-current-buffer. The following code inserts the link wherever point happens to currently be in a window displaying that buffer. If no window displays that buffer, it defaults to point-max.

(defun jay/insert-file-link (fname)
  "Insert link to file (called by Midnight Commander)."
  (interactive "s")
  (let* ((target-buffer (get-buffer "BUFFER-NAME"))
         (window (get-buffer-window target-buffer t))
         (p (when window (window-point window))))
    (with-current-buffer target-buffer
      (goto-char (or p (point-max)))
      (insert "[[" fname "][" fname "]]"))))

If you’d like Emacs to place this link in a file named FILE-PATH (which may or may not be opened), you can use find-file.

(defun jay/insert-file-link (fname)
  "Insert link to file (called by Midnight Commander)."
  (interactive "s")
  (find-file "FILE-PATH")
  (insert "[[" fname "][" fname "]]")
  (save-buffer))
  • Thanks for your answer, it's nice to learn about this. But what if I want to insert into the current buffer at the current point without having to name it? I may want to insert into various files. – jtgd Oct 8 '14 at 15:48
  • @jtgd Updated to do what you asked, let me know if it works. – Malabarba Oct 8 '14 at 16:32
  • I updated to the first block of code you provided. It not gives an error on the command line: $ emacsclient -e "(jay/insert-file-link \"/tmp/foo\")" ERROR: Wrong type argument: stringp, nil (dang, I can't do formatting in the comments) – jtgd Oct 9 '14 at 5:56
  • @jtgd I'll try it out in a moment, but are you sure the buffer in question (BUFFER-NAME) is open and visible in a window? – Malabarba Oct 9 '14 at 7:11
  • I assume that I was to supply the name of an actual buffer in its place? I expect to be inserting links in various files so that's not quite what I'm looking for. (see solution below) – jtgd Oct 10 '14 at 0:10
2

Your code is working, as far as Emacs is concerned. But (as Malabarba correctly identified) it's inserting text into the buffer that's current while running code received by the server. That's a buffer called  *server*, not the buffer which you're currently editing.

You need to switch to the desired buffer before inserting the text. Your desired buffer is the one that's shown in the currently selected window.

emacsclient -e '(set-buffer (window-buffer (selected-window)))' -e "(jay/insert-file-link \"/tmp/foo\")"
  • Using Malabarba's change I also tried your command line. It also gave the same error with an additional line: <p> $ emacsclient -e '(set-buffer (window-buffer (selected-window)))' -e "(jay/insert-file-link \"/tmp/foo\")" <p>#<buffer init.el> <p>*ERROR*: Wrong type argument: stringp, nil – jtgd Oct 9 '14 at 6:01
  • @jtgd with his solution, don't use my change, just use your own code from the question. – Malabarba Oct 9 '14 at 7:09
1

Thanks to everyone for their help and thanks to @Jaseem for a key piece. Indeed org-insert-link works better than my hand-rolled version. What I ended up doing was this. The function:

(defun jay/insert-file-link (fname)
  "Insert link to file (called by Midnight Commander)."
  (interactive "s")
  (set-buffer (window-buffer (selected-window)))
  (org-insert-link nil (concat "file://" fname) fname))

and this is the line from Midnight Commander menu file:

l       Insert Link to this file in Emacs
        emacsclient -e '(jay/insert-file-link "%f")' &

Everything works as I wanted it to (with a minor annoyance of MC waiting for me to hit enter). In MC I just hit F2,l and a link to the highlighted file gets inserted wherever the cursor is in emacs.

(I'll edit the title to make it easier for others to find.)

  • Here at stack exchange you don't need to add [SOLVED] to the title, all you need to do is accept the answer that has your solution (clicking the checkmark to the left). Feel free to accept your own answer, since that's what you used in the end. – Malabarba Oct 10 '14 at 0:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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