I am trying to write a helm command to select email addresses from three sources: an aliases variable, org-contacts, and the contacts from mu4e. The command works fine, showing me candidates from all three sources. But, I need one function to act on the selections from the aliases, another to act on the org-contacts, and a third to act on the mu contacts, with the final result being a comma-separated list of email addresses that is inserted.
I can select multiple entries, but the function that gets called when I press enter is the default action for the source I am in, and it does not seem to get the the selected entries as an argument, and helm-marked-candidates doesn't seem to have all the selected entries in it. Here is a minimal example that allows multiple selections across sources, but where the multiple selections do not get passed to the respective functions. Any ideas on how to do that? Or if it is possible?
(setq helm-source1
'((name . "source 1")
(candidates . (1 2 3 4))
(action . (lambda (x) (message-box "%s" (helm-marked-candidates))))))
(setq helm-source2
'((name . "source 2")
(candidates . ("a" "b" "c" "d"))
(action . (lambda (x) (message-box "%s" (helm-marked-candidates))))))
(defun j-insert-emails ()
"Helm interface to email addresses"
(interactive)
(helm :sources '(helm-source1
helm-source2)))
Related
So i try to create a list of string in the form
"a" "b" "c"
This is a list of files which i want to pass to org-agenda-files
As for now this looks like this
(setq org-agenda-files "~/.tasks.org")
Now i need to add some files coming from a directory. i can get those with directory-files-recursively "~/orgroam/daily" "\\[^.].*\.org\'". this will return lets say ("~/b" "~/c")`.
The problem comes when i try to concatenate the "a". What i have tied so far is
(list "~/.tasks.org" (mapconcat #'identity (directory-files-recursively "~/orgroam/daily" "\\`[^.].*\\.org\\'") " "))
and
(concat "~/.tasks.org " (mapconcat #'identity (directory-files-recursively "~/orgroam/daily" "\\`[^.].*\\.org\\'") " "))
but this returns "a" "b c" and "a b c"
Another thing i tried out is to add the result of directory-files-recursively after the (setq org-agenda-files '("~/.tasks.org")) using add-to-list. in this case i get Wrong type argument: stringp, ("~/orgroam/daily/2022-01-19.org" "~/orgroam/daily/2022-01-28.org"....)
Does anyone have a suggestion to achieve the desired output for org-agenda-files?
If you want to include all org files from another directory, you can:
(setq org-agenda-files '("~/.tasks.org"
"~/orgroam/daily/"))
If you still want to append files, you can:
(setq org-agenda-files (append
'("~/.tasks.org")
(directory-files-recursively "~/Documents/Org/notes/" "\\`[^.].*\\.org\\'")))
As a friendly reminder, numerous Org files may cause Agenda to be very slow, you can refer to this blog.
I use helm for Emacs with several sources and wonder how I can extract the list of all entries that the user has marked with Ctrl+Space. As an example, execute the following in your *scratch* buffer
(require 'helm)
(defun helm-test-action (candidate)
"Test."
(interactive)
(message (concat "candidate = " (prin1-to-string candidate)
"\n, helm-marked-candidates = " (prin1-to-string (helm-marked-candidates)))))
(defun helm-test-case ()
"Test."
(interactive)
(helm :sources (list (helm-build-sync-source "First Source"
:candidates '("one" "two" "three")
:action #'helm-test-action)
(helm-build-sync-source "Second Source"
:candidates '("four" "five")
:action #'helm-test-action))))
and then M-x helm-test-case.
When you mark, say, "one" and "four" with Ctrl+Space and press Enter, how do I retrieve the two marked entries from my action? It seems candidate is always the line on which the cursor has been placed and (helm-marked-candidates) yields the list of marked entries of the current source. How do I get the list of marked entries across all sources?
Thanks for your help,
HPF
The answer is to use (helm-marked-candidates :all-sources t). This returns a list of all marked entries or, if none has been marked, the entry under the cursor when you hit enter.
It makes sense, of course, only if all your sources contain candidates of the same form and if the default action is the same for all sources. It seems this requirement isn't enforced though.
Regards,
HPF
The org-cdlatex-mode helps to insert math latex symbols/tempelates in org-mode.
I would like to add some extra symbols/accents to it. I realized that the math accents are stored in the variable cdlatex-math-modify-alist-comb and if I add to that list in the scrach buffer, I will get the extra short key for the new symbol, for example running:
(add-to-list 'cdlatex-math-modify-alist-comb '(?o "\\operatorname" nil t t nil))
works as expected. However if I add the same line in the init file, the new key won't be added to the list and emacs complains with warning that the list variable is free!
I probably need to add to the list after it has been loaded, however I couldn't find any source of how to do it.
The variable that needs to be set in your case is cdlatex-math-modify-alist. The documentation of that variable says: Any entries in this variable will be added to the default.
The workaround I did is to create a function that adds them every time I call my math minor mode
(define-minor-mode org-math-mode
"Some config to write math on `org-mode'."
:lighter "org-math-mode"
(org-fragtog-mode 1)
(org-cdlatex-mode 1)
(lauremacs-cdlatex-add-math-symbols))
(defun lauremacs-cdlatex-add-math-symbols ()
(add-multiple-into-list
'cdlatex-math-symbol-alist-comb
'(
(?. "\\cdot" "\\dots")
(?\; "\\;")
(?C "" "\\mathbb{C}" "\\arccos")
(?N "\\nabla" "\\mathbb{N}" "\\exp")
(?Q "\\Theta" "\\mathbb{Q}")
(?R "\\Re" "\\mathbb{R}")
(?Z "" "\\mathbb{Z}")
)))
where add to multiple is just a helper function that uses add-to-list
(defun add-multiple-into-list (lst items)
"Add each item from ITEMS into LST."
(throw-unless (symbolp lst) "List should be a symbol.")
(dolist (item items)
(add-to-list lst item)))
This might lead to a very big 'cdlatex-math-symbol-alist-comb but it didn't bothered me yet, a solution to this is adding to list if element is not there or something like this
Just edit cdlatex.el and compile it. For example, I add sum with this piece of code:
("sum" "Insert \\sum_{i=1}{n}"
"\\sum_{i=1}{n}?" cdlatex-position-cursor nil nil t)
and it works.
While opening a file in emacs using tab completion, emacs brings up the Completions buffer with a list of the possible completions. The list is ordered alphabetically. How would I configure emacs so that the default behavior is to sort the possible file completions based on time showing the newest or oldest file / directory at the top of the list? Could I further change the sorting criteria dynamically while looking at the completions buffer?
If you use Icicles then you can easily control sorting.
And you can easily change sort orders on the fly.
And for file-name completion the default sort orders include the order you are requesting. You can choose it to be your default sort order for file-name completion. Or you can choose it during file-name completion, by either cycling or completing its name.
And you can easily define your own sort orders.
If you use only vanilla Emacs then you can fiddle with completion metadata for file-name completion. See metadata categories display-sort-function and cycle-sort-function.
For example, you can define your own completion command that acts similar to read-file-name but that uses a different sort function.
This is what vanilla library tmm.el does, for example:
(minibuffer-with-setup-hook
#'tmm-add-prompt
(completing-read
(concat gl-str " (up/down to change, PgUp to menu): ")
(tmm--completion-table tmm-km-list) nil t nil
(cons 'tmm--history (- (* 2 history-len) index-of-default))))
(defun tmm--completion-table (items)
(lambda (string pred action)
(if (eq action 'metadata)
'(metadata (display-sort-function . identity))
(complete-with-action action items string pred))))
An additional approach can be to define advice for completion--insert-strings. For instance, I wanted to
Sort symbols with -- last.
Hide * buffers, unless explicitly filtering for them.
and came up with the following solution:
(advice-add #'completion--insert-strings :around #'my-cmplt-insstr)
(defun my-cmplt-insstr (oldfun strings &rest r)
"Hook into `completion--insert-strings' that applies some postprocessing."
;; Symbols: Sort `--' after anything else.
(when (cl-every #'intern-soft strings)
(mylog "my-cmplt-insstr: -- comes last")
(setq strings
(cl-sort strings #'<
:key (lambda (it) (s-count-matches "--" it))))
(setq strings
(cl-loop with last-had-ddash = nil
for string in strings
for has-ddash = (string-match-p "--" string)
if (and has-ddash (not last-had-ddash))
collect ""
collect string
do (setq last-had-ddash has-ddash))))
;; Buffers: * hidden by default.
(when (cl-member "*Messages*" strings :test #'string=)
(unless (cl-every (lambda (it) (string-prefix-p "*" it)) strings)
(setq strings
(cl-remove-if (lambda (it) (string-prefix-p "*" it)) strings))))
(apply oldfun strings r))
This solution uses rough heuristics to guess what is being completed, but it could be used as an alternate starting point, e.g. with specific read-* functions being advised to set flags for determining which rules are applied.
How can I let the user select multiple items from a list instead of just one? Like in the C-x b menu in helm.
Currently I can only select a single item instead of getting a complete list:
(defun test-main ()
(interactive)
(let ((choice (completing-read "Select: " '("item1 item2 item3"))))
(message choice)))
You can do that with completing-read-multiple:
(defun test-main ()
(interactive)
(let ((choice (completing-read-multiple "Select: " '("item1" "item2" "item3"))))
(message "%S" choice)))
It returns the selected items as a list, so if you type item2,item3 at the prompt, it returns ("item2" "item3").
Because that's what vanilla completing-read does. It reads and returns a single choice, providing completion to help you choose.
You can do what you are asking for with Icicles. It redefines function completing-read when Icicle mode is on.
Many Icicles commands are multi-commands, which means that you can make multiple input choices in a single command execution: a multiple-choice command. You can define your own multi-commands, using any actions.
And for any completion (not just for a multi-command), you can manipulate, save, and restore sets of completion candidates.
(You can also enter multiple inputs in the minibuffer. This is useful even for commands that read input without completion.)