1

I want to write a function to check if a buffer is an Org buffer. Here is my attempt.

(defun org_bufferp (buffer)
  (if (bufferp buffer)
      ((setq buffer_name (buffer-file-name buffer))
             (if (stringp buffer_name)
                 (if (string-match ".*\.org$" buffer_name) t "nil1")
               "nil2"))
      "nil3"))

However, the result surprised me.

(org_bufferp '(current-buffer)) ;; => nil, but should be t!
(org_bufferp  (current-buffer)) ;; ===> ERROR! Why?

Questions

  1. Why does (org_bufferp '(current-buffer)) return nil? I don't even assign any nil to possible returned values.
  2. Why does (org_bufferp (current-buffer)) return an error?
  3. I'm new to Elisp, and find it hard to deal with the endless parentheses. What would you suggest in order to make the code cleaner?
3
  • 1
    Please don't use tag elisp for questions about using Elisp. It's for questions about the nature of the language itself, e.g. compared to other Lisp dialects. Thx. – Drew Apr 20 '20 at 21:33
  • Your code was syntactically invalid. Added a missing progn. – Drew Apr 20 '20 at 21:38
  • Thank you @Drew. Your answer is valid, but I delete progn from your edit since that's exactly what I missed. I hope future user can be benefited by this post. – Student Apr 21 '20 at 1:03
2

The main ingredient you missed is progn. This could happen to Elisp beginners, who do not yet understand the syntax of if.

Here is the correct code. Notice that progn evaluates its arguments, and returns the last value.

[..]
(progn (setq buffer_name (buffer-file-name buffer))
       (if (stringp buffer_name)
         (if (string-match ".*\.org$" buffer_name) t "nil1")
       "nil2"))
[..]

Your original code is invalid. The car of that list is evaluated to return a string or nil. Then Emacs tries to invoke that as a function and apply it to the rest of the elements in that list. Error. Again, using progn can resolve it.


With the edited code, (org_bufferp '(current-buffer)) returns nil3, and (org_bufferp (current-buffer)) returns nil2 or nil1 if it's not visiting a *.org file (nil2 if not a file-visiting buffer), and t if visiting if visiting a *.org file.

For (org_bufferp '(current-buffer)), the arg is a list, (current-buffer), which clearly doesn't satisfy bufferp.

For (org_bufferp (current-buffer)), buffer_name is either the buffer name, if visiting a file, or nil, otherwise.


You might really want to check the major-mode of the buffer, instead of getting buffer-file-name and then checking the file-name extension. Just do this to your variable buffer, once you've determined that its value is a buffer:

(with-current-buffer buffer (derived-mode-p '(org-mode)))

To make code clearer, and help get over the paren-shock of an Elisp newbie, indent the code using C-M-q with point at the left paren of (defun....

2
  • Thank you @Drew. I would like to hear more about (derived-mode-p). As far as I know, it does not tell if a given buffer is in a certain mode. However, going through the elisp manual did not help me. – Student Apr 21 '20 at 1:39
  • 1
    BTW, it's usually better to test the mode using derived-mode-p than by exact comparison. That way, if you're in a mode that's derived from Org mode it still works. – Drew Apr 21 '20 at 3:59

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.