Currently I am using the function workbench. The function workbench-named introduces a name, which I want to include in buffer and file-name.

Currently only workbench-prefix in being included with the command

(buffer (or name (concat "*" workbench-prefix "*")))

For instance

  1. I want the buffer name to be "*Arktika-<name>*", where name is
    supplied by the user when calling workbench-named.
  2. When saving the buffer to a file, I construct a path followed by the time, then appending "-Arktika-" if name was supplied
  3. When using prefix with C-u M-x workbench, I am asked to supply a major-mode.

Here is the implementation

    (defvar workbench-prefix "Arktika")
    (defvar workbench-dtrek "~/wb/")
    (defvar workbench-histr nil)
    (defvar workbench-modes
      '( ("emacs-lisp-mode" . "el")
         ("lisp-mode" . "lisp")
         ("org-mode" . "org") ))
    (defun workbench (&optional prefix name mode)
      "Generate new temporary buffer."
      (interactive "p")
      (let* ( (buffer (or name (concat "*" workbench-prefix "*")))
                 (concat workbench-dtrek
                         (format-time-string "%Y-%m-%d-T%H:%M:%S--")
                         workbench-prefix "-" name ".org")) )
      (switch-to-buffer (generate-new-buffer buffer))
        (setq buffer-file-name file-name)

    (if current-prefix-arg
        (let* ( (mode (completing-read " Mode: "
                        (map-keys workbench-modes) nil t nil
                        'workbench-histr)) )
          ;; with prefix-arg, use user defined mode
          (funcall (intern mode)))
      ;; otherwise use org-mode
      (funcall (intern (or mode "org-mode"))))

    (defun workbench-named ()
      "Generate new temporary buffer by asking for buffer name."
      (workbench (read-from-minibuffer " Workbench Name: ")))
  • 2
    Please be more specific. This shows a bunch of code and asks a vague question that amounts to "How can I code what I want (which isn't specified)?" And you didn't even check that the code is syntactically correct (missing " at end of doc string).
    – Drew
    Commented Jun 29, 2022 at 14:00
  • I cannot see where I am missing ".
    – Dilna
    Commented Jun 29, 2022 at 14:08
  • You can't see it because I added the missing ". Look at the edit history.
    – Drew
    Commented Jun 29, 2022 at 15:25
  • @dilna What format do you want for the time? What happens to the buffer name if there is no name supplied (the second point indicates this is possible)? Does it matter if we visit a non-existent file first and then rename the buffer (which is considerably simpler to do) ? Please edit the question with this information.
    – Trevoke
    Commented Jul 25, 2023 at 17:13

2 Answers 2


Where are you expecting optional parameter name to be provided?

If you invoke the command interactively then name is nil, because your interactive spec doesn't give it a non-nil value.

Since name is nil, your binding for buffer gets the second value passed to or, which is (concat "*" workbench-prefix "*"). That's why you're seeing only the value of workbench-prefix, wrapped in *.

And in your question you don't specify any interactive behavior you might want for name. Maybe you want something like this?

(interactive "p\ns")

Beyond that, you pass the numeric prefix arg (which is 1 by default) as parameter prefix, and you never even use prefix in your code!

Maybe you want to remove parameter prefix and use only name? Maybe you want to use s and not p in the interactive spec?

It's impossible to guess what you're really wanting to do, so it's unlikely to be able to guess what answer might help you. (Please try to pose clearer questions.)

  • I only put it so I can use (if current-prefix-arg. Prefix is used to activate completing-read so that I can select a major-mode for the buffer. It would help on simplifying the implementation.
    – Dilna
    Commented Jun 29, 2022 at 16:10
  • No idea what you're saying. You don't use current-prefix-arg in your code. And as I said, arg prefix is unused (and is 1, the numeric prefix value). And arg name is useless in your code: it's always nil and that's ignored by concat.
    – Drew
    Commented Jun 29, 2022 at 20:27
  • I added tho part that uses current-prefix-arg. You see a better way to set the mode? Cannot see how the arg name in not used when calling workbench-named.
    – Dilna
    Commented Jun 29, 2022 at 20:40
  • No idea what you're doing, sorry. Your code doesn't ever bind or set argument name, so it's always nil (default for an optional arg). And your code doesn't make use of function workbench-named.
    – Drew
    Commented Jun 29, 2022 at 21:35
  • Am just making named buffer using a major mode. Which I can save with a filename that includes the date.
    – Dilna
    Commented Jun 29, 2022 at 21:52

I made a few adjustments; here's the core logic. Whatever is not right should just be a tiny detail that can be adjusted independently of the answer itself. For instance, dilna-workbench is no longer an interactive function because it doesn't make sense for it to be interactive; obviously the dilna-named-workbench is the user entry point.

As such, dilna-named-workbench now takes the optional prefix argument. Called without a prefix argument, it'll prompt the user for a name for the buffer. Called with the prefix, it'll ask for a name and a major mode.

The function dilna-workbench generates a string version of the timestamp, finds the appropriate path and filename based on the workbench prefix and workbench path, visits that file, then renames the buffer as specified in the question.

Note the helper function dilna-path-join which I stole from the f library: https://github.com/rejeep/f.el . Necessary because we must handle both relative and absolute paths.

(defvar dilna-workbench-prefix "Arktika")
(defvar dilna-workbench-path "/tmp")

(defun dilna-path-join (&rest args)
  "Join ARGS to a single path.
Stolen and inlined from the `f' library, highly recommended."
  (let (path (relative (not (file-name-absolute-p (car args)))))
     (lambda (arg) (setq path (expand-file-name arg path)))
    (if relative (file-relative-name path) path)))

(defun dilna-workbench (name &optional mode)
  "Creates and visits a new workbench file and gives the buffer a custom NAME.
Optionally set majode mode to MODE, provided as a string."
  (let* ((time (format-time-string "%F-%T"))
         (filename (string-join `(,time ,dilna-workbench-prefix ,name) "-"))
         (path (dilna-path-join dilna-workbench-path filename)))
    (find-file path)
    (rename-buffer (format "*%s-%s*" dilna-workbench-prefix name))
    (when mode (funcall (intern mode)))))

(defun dilna-named-workbench (&optional prefix)
  "Ask user for a name and create a new workbench file from that name.
If PREFIX is non-nil, ask the user for a major-mode and set new buffer to
that mode."
  (interactive "P")
  (let ((name (read-from-minibuffer "Workbench name: "))
        (mode (when prefix (read-from-minibuffer "Major mode: "))))
    (dilna-workbench name mode)))
  • @dilna if this answer solved your problem, please mark it as accepted.
    – Trevoke
    Commented Jul 26, 2023 at 15:58

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.