This documents my first experience with programming in elisp. In restrospect, I was really bad at it. This post then shows that you can still make something with elisp even if you are bad at it.
A slightly better example of making something with elisp is on my package clipboard2org, a tiny package to paste html or picture. See clipboard2org
PDF files drag-drop
I wanted to be able to drag and drop pdf files, as well as drag and drop pdf URLs to emacs. The result of dragging should be to download the file to a directory under the same directory as the org file you are editing and then create a link to the file. It also allows for drag and drop of image files.
The code was based on org download. If it is not a pdf, or if it is but the download fails, it fails back to the original drag and drop code.
Easy templates cannot run arbitrary code. They are handled by org-cycle, which is a function that handles every action that TAB performs in org mode.
So, I created a function and added an advice to org-cycle, This detects strings of the type ">[a-zA-Z]+", i.e. > followed by letters and then runs a function.
In order to create other templates, add another block similar to
((string= key "t")(insert-todays-date)t)
under it.
This particular template inserts today's date when someone writes >t and presses tab.
(defuninsert-todays-date()(interactive)(insert (format-time-string"<%Y-%m-%d>")))(defunorg-try-my-template-function(&optional arg)"Try to complete a structure template before point.
This looks for strings like \"<e\" on an otherwise empty line and
expands them."(interactive)(let((l (buffer-substring (point-at-bol)(point)))
a)(if(and(looking-at "[ \t]*$")(string-match "^[ \t]*>\\([a-zA-Z]+\\)$" l))(let*((key (match-string1 l))(start (point-at-bol))(end (point)))(when(cond((string= key "t")(insert-todays-date)t))(delete-region start end)t)))))(require 'org)(with-eval-after-load 'org
(advice-add #'org-cycle :before-until#' org-try-my-template-function))
The problem is that xclip causes emacs to hang, because it forks a child that keeps stdout open. So instead, one can use the emacs backed for getting the xselection from the clipboard.
This code requests a text/html selection and checks if it exists. If it exists, it first decodes it using whatever encoding was being used, and then uses pandoc to convert the html to org mode.
(defunhtml2org-clipboard()"Convert clipboard contents from HTML to Org and then paste (yank)."(interactive)(let*((text_html (gui-backend-get-selection 'PRIMARY 'text/html))(text_raw (gui-get-selection))(text_html (when text_html
(decode-coding-string text_html 'unix)))(text_html (when text_html
(shell-command-to-string(concat "echo "(shell-quote-argument text_html)"|timeout 2 pandoc -f html-native_divs-native_spans -t org"))))(text (or text_html
text_raw)))(progn(kill-new text)(yank))))(with-eval-after-load 'org
(define-key org-mode-map(kbd "C-y ") 'html2org-clipboard)(define-key org-mode-map(kbd "C-<tab>") '(lambda()(interactive)(save-excursion (org-back-to-heading)(org-cycle)))))