Elisp - Avoid prompt in interactive function - emacs

I'm trying to call the following org-mode function to insert the current timestamp in the buffer. The function is called by a script.
(org-time-stamp-inactive)
This, as expected, brings up a prompt asking for the date to use for the timestamp. But I want to skip the prompt and insert the timestamp directly. Is that possible at all? Haven't found anything that could help me.

This should insert the current inactive time stamp:
(org-insert-time-stamp nil nil t)

org-time-stamp unconditionally¹ calls org-read-date to prompt the user for a date. You can't pass a date. But you can locally bind org-read-date to a function that returns the date that you want to use.
(require 'cl)
(flet ((org-read-date (org-with-time &rest args)
(format-time-string (if org-with-time "%Y-%m-%d %H:%M" "%Y-%m-%d")
(current-time))))
(org-time-stamp-inactive with-time))
¹ Except sometimes when there is already a time stamp, but that's no help.

I ended up creating the timestamp from scratch with the following call:
(insert (format-time-string "[%Y-%m-%d %a]"))

You can find the answer in documentation for similar function (org-time-stamp)
[...] With two universal prefix arguments, insert an active timestamp
with the current time without prompting the user. [...]
So.. all you need to do is press C-u C-u before you invoke the function (for example C-u C-u M-x org-time-stamp-inactive RET)

Related

How to insert date only in org-mode

I can insert an inactive timestamp interactively with org-time-stamp-inactive (C-c C-!), then pressing Enter when presented with the calendar. This inserts a value like [2021-12-10 Fri].
I would like to know if this can be achieved programmatically with org-time-stamp-inactive. I tried org-time-stamp-inactive '(16) but this also inserts a time which I do not want. I can do insert (format-time-string "[%Y-%m-%d %a]") but this uses a different approach, and I would like to know if what I want can be achieved with org-time-stamp-inactive.
EDIT (in response to comment): No, it is not possible, but you got to look at the code to make sure. org-time-stamp-inactive is a thin wrapper around org-time-stamp. That in turn calls org-insert-time-stamp, which takes a time and a with-hm argument (among others - see the doc string of the function with C-h f org-insert-time-stamp for the details). If with-hm is nil, then no time is printed. But org-time-stamp (and therefore org-time-stamp-inactive) always calls org-insert-time-stamp with a non-nil with-hm, so the time is always inserted in that case. The best you can do is call the underlying function org-insert-time-stamp like so: (org-insert-time-stamp (current-time) nil 'inactive).
I still think your simple suggested solution (elaborated a bit in the original answer below) is the best way to go about the problem.
[ORIGINAL ANSWER]
Org mode is plain text: things may appear differently, but all that is smoke and mirrors: you can cat an Org mode file in the terminal and see precisely what it contains. In particular, inactive time data are just strings of the form [2021-12-11]. So there is no penalty if you do it manually, instead of going through some Org mode interfaces: the end result is the same, so your manually inserted date is just as good as the one inserted by org-time-stamp-inactive.
So assuming that the simple solution you suggested is acceptable, here's filling in the details:
(defun my/org-insert-current-time-as-inactive-time-stamp ()
(interactive)
(insert (format-time-string "[%Y-%m-%d]")))
(define-key org-mode-map (kbd "C-c _") #'my/org-insert-current-time-as-inactive-time-stamp)
C-c _ was undefined in the Org mode keymap in my case, but YMMV: choose something that is not used.

How to use elisp to let user pick a date from calendar?

Just learn to write an interactive function in elisp:
If called with prefix, open calendar and get the date which is picked by user.
I try to do something like this:
(calendar)
(org-get-date-from-calendar)
It return today straight away instead of let user to pick a date.
I tried
(org-read-date)
And that worked for me
As you've seen, the problem is that after invoking (calendar) your code simply continues and doesn't wait around for any interactions in the calendar window. You need to prevent the emacs command loop from continuing until the user has selected a date.
Setting up your own keys is one way to do this. For example, if you look at the org-read-date-minibuffer-local-map variable in the org-mode source code, you can see that org-mode essentially takes over keys in calendar mode to allow the user to navigate the calendar while org-mode waits for the result. Studying this keymap and the org-eval-in-calendar function might give you some ideas on how to achieve what you want.
Another way to wait for the result is via recursive-edit. The code below enters the calendar and, by calling (recursive-edit), waits for the user to exit the calendar via the q key, which normally invokes calendar-exit. The code temporarily applies advice to that function to have it set a local variable to the date selected in the calendar before calling calendar-exit (via the funcall) and then exiting the recursive edit:
(let* (date
(adv '(lambda (fn &rest args)
(setq date (calendar-cursor-to-date))
(funcall fn args)
(exit-recursive-edit))))
(advice-add 'calendar-exit :around adv)
(calendar)
(message "Select the desired date, then type `q' to exit.")
(recursive-edit)
(advice-remove 'calendar-exit adv)
date)
Using advice can be a brittle approach, though. It potentially changes function semantics in unexpected ways — and see this page for other potential problems — plus there are probably other issues lurking with this approach with respect to abnormal exits. You're better off using keymap approaches like those used in org-mode.

How to insert current time in the emacs org-mode

Is there a simple way to insert the current time (like TIME: [2012-07-02 Mon 16:44]) in the org-mode? In the manual there is a lot of stuff (clocks, deadlines, schedules), but most of them require entering the time manually.
C-u C-c . will insert a timestamp at point, though Org will still prompt you for a time (with the default being the current time).
More: "Creating timestamps" in the Org Mode manual.
In my installation, which is org-mode version 9, the following enters the current date and time without prompting anything
C-u C-u C-c .
C-u C-c !
inserts an inactive timestamp with the current time such as:
[2018-05-08 Tue 00:30]
In emacs-lisp, you could use
(org-insert-time-stamp (current-time) t)
With default settings, it will generate a time stamp on the format
<2021-06-20 Sun 10:33>
If you want to access it from any emacs session, put
(defun insert-now-timestamp()
"Insert org mode timestamp at point with current date and time."
(interactive)
(org-insert-time-stamp (current-time) t))
in your .emacs file. You may then call the function with M-x insert-now-timestamp.
Emacs 27.2, org mode 9.4.4.
Edit: I now realise this does the same thing as #anachronic's solution. I however leave it here for reference.
On my installation
C-u C-c .
inserts a date-with-time stamp
Just give you some other options:
If you are using windows system, you can use AutoHotKey to achieve this.
If you can install YASnippet for emacs, it also have the shortcut to insert current date and time.
These two options are very powerful tools, not for just insert date and time.

How can I insert text to a buffer without the trailing "nil"

I've got a function to insert the current date into my file
(defun insert-date ()
(interactive)
(insert
(format-time-string "%m-%d-%Y")))
This works for inserting the date into my current buffer, however the output is 01-24-2011nil
How can I remove the nil from the input.
As noted above, insert returns nil and inserts the arguments as a side effect. Since you've declared your function interactive, you can call it using M-x. Even if you don't declare it interactive, you can say M-: (insert-date).
It's the C-j that is inserting nil. The function itself as you've defined it is OK. C-j in the scratch buffer is useful for debugging Lisp that you have written, but you have to remember that it will insert the return value. If you don't want that, try C-x C-e instead.

Usage of current-buffer in emacs?

I'm using emacs and I have written a script which uses "current-buffer". However the emacs system doesn't recognise "current-buffer". When I try "M - x current-buffer" i get the response:
no match
: Any idea what I'm doing wrong?
current-buffer is not an interactive function. That is, can't be invoked interactively via M-x as you've tried to do. You can execute non-interactive lisp-code directly by using eval-expression as follows:
M-: (current-buffer) RET
Notice that you have to enter a proper lisp expression. If you want to capture the value in a variable, something like this
M-: (setq xyzzy (current-buffer)) RET
will store the current buffer into the variable xyzzy.
Do I interpret you correct that you have created a function named current-buffer that you want to be available with M-x current-buffer?
To enable functions to be called by M-x function-name the function needs to be marked as interactive.
A sample from the emacs manual:
(defun multiply-by-seven (number) ; Interactive version.
"Multiply NUMBER by seven."
(interactive "p")
(message "The result is %d" (* 7 number)))
The (interactive "p") part makes the function callable from the minibuffer (through M-x).
I sounds like you would (also) like to know how to get the name of the current buffer interactively. Use M-: (buffer-name).