Customized org-capture-template for Org Capture Extension - emacs

I am using the great Org Capture Extension Firefox addon to directly capture my web links into my Emacs documents.
A minimal org capture template is:
(setq org-capture-templates `(
("L" "Protocol Link" entry (file+headline "~/web.org" "Links")
"* [[%:link][%:description]]\n")
;; ... your other templates
))
I use this to bookmark articles, in peculiar a lot of them are on
arxiv.org. The problem is that arxiv title pages contain [] characters, for instance:
[1606.04838] Optimization Methods for Large-Scale Machine Learning
This does not mix well with the [[%:link][%:description]] used in the template to create the org mode link. For instance a capture returns:
** [[https://arxiv.org/abs/1606.04838][[1606.04838] Optimization Methods for Large-Scale Machine Learning]]
and the Org-Mode link is broken because of the brackets in the "[1606.04838]" string.
How to solve this?

The cure is to transform the link [%:description] description into a string that does not contain squared brackets []. For this we can define a function that transforms the [, ] chars into (, ) ones.
(defun transform-square-brackets-to-round-ones(string-to-transform)
"Transforms [ into ( and ] into ), other chars left unchanged."
(concat
(mapcar #'(lambda (c) (if (equal c ?[) ?\( (if (equal c ?]) ?\) c))) string-to-transform))
)
Then we can use this function into the org-capture-template. The %(sexp) syntax is used to evaluate the lisp code into the template:
%(sexp) Evaluate Elisp sexp and replace with the result.
For convenience, %:keyword (see below) placeholders
within the expression will be expanded prior to this.
The sexp must return a string.
The modified org-capture-template is:
(setq org-capture-templates '(
("L" "Protocol Link" entry (file+headline "~/web.org" "Links")
"* [[%:link][%(transform-square-brackets-to-round-ones \"%:description\")]]\n")
;; ... your other templates
))
Then when you click on the Firefox Org-Capture button the template is correctly expended to
** (1606.04838) Optimization Methods for Large-Scale Machine Learning
with a well formed Org-Mode link (note that the [1606.04838] was turned into (1606.04838))

Related

Can Emacs' org-mode recognize tags within (instead of just at the endof ) a headline

I am learning how to use Emacs and org-mode, and am wondering whether Emacs can support tags within rather than just at the end of headlines (whether natively or through a package or configuration in ~/.emacs).
Put differently, Emacs natively supports tags in this form:
* This is a headline. :tag1:tag2:
Is there a way to get Emacs to recognize tags in the format below in addition?
* This is a headline with :tag1: and :tag2:.
I've been searching for answers for several hours, and haven't found this question anywhere else; I'd be grateful for any advice!
The real answer to this question is in #lawlist's comment above, that (to quote #lawlist) it "is not possible [to get org-mode to recognize tags within a line of text instead of at the end of the line] without substantially modifying several aspects of org-mode yourself."
For this reason, if #lawlist writes the comment up as an answer, I'll accept it. I'm also writing up this additional answer, though, for anyone like me who comes along and, learning this, wants a way to take some text and automatically generate org-mode tags for it. Following the discussion in the comments above, I've written a function in elisp below, which allows a user to highlight some text and automatically find any tags within the text (here, in the form {{tag}}) and concatenate them in org-mode tag format at the end of the first line.
(defvar tag-regexp-for-generating-org-mode-tag-list-from-text "{{\\(.*?\\)}}"
"A regular expression, in double-quotes, used for finding 'tags' within lines of text (these can then be translated into org-mode syntax tags.
For example, in the string \"This text contains the 'tags' {{tag1}} and {{tag2}}\", the default regular expression
\"{{\\(.*?\\)}}\"
would find \"tag1\" and \"tag2\", which could then be transformed into org-mode syntax tags, \":tag1:tag2:\"")
;; Following https://emacs.stackexchange.com/a/12335, use just the selected region.
(defun generate-org-mode-tag-list-from-selected-text (beginning-of-selected-region end-of-selected-region)
"Take a highlighted section of text, find all strings within that text that match the search parameters defined in the variable tag-regexp-for-generating-org-mode-tag-list-from-text (by default, strings of the form {{tag1}} {{tag2}}), and concatenate them into a set of org-mode tags (:tag1:tag2:)
When text is highlighted, the argumentes beginning-of-selected-region and end-of-selected-region will be automatically populated.
"
(interactive "r") ;; 'r' mode will auto-populate 'beginning-of-selected-region' and 'end-of-selected-region' above with the values of region-beginning and region-end.
(if (use-region-p) ;; If a region is actively highlighted
(progn ;; Start a multi-line sequence of commands
;; Following https://learnxinyminutes.com/docs/elisp/, go to the beginning-of-selected-region (here, of the selected region), and do a find-and-replace.
(setq list-of-tag-strings (list)) ;; Create a blank list, which we'll fill in below.
(goto-char beginning-of-selected-region) ;; Go to the beginning of the selected region (we'll then search forward from there.
;; A regex of "{{\\(.*?\\)}}" below looks for tags in {{this}} form. You can specify any other regex here instead.
(while (re-search-forward tag-regexp-for-generating-org-mode-tag-list-from-text end-of-selected-region 't) ;; Search forward, but only up to the end-point of the selected region (otherwise, end-of-selected-region could be replaced with nil here).
(add-to-list 'list-of-tag-strings ;; Add to the list called list-of-tag-strings
(replace-regexp-in-string "[[:space:]|:|-]+" "_" (match-string 1)) ;; Since org-mode tags cannot have spaces or colons (or dashes?) within them, replace any of those in the first capture group from the regular expression above ('match-string 1' returns whatever was in the parentheses in the regular expression above) with an underscore.
t) ;; Append (first checking for duplicate items) the first capture group from the regular expression above (i.e., what's inside the parentheses in the regular expression) to a list. The t tells the function to append (rather than prepend) to the list.
) ;; End of while statement
;; Go to the end of the first line of the selected region.
(goto-char beginning-of-selected-region)
(end-of-line)
(if (> (length list-of-tag-strings) 0) ;; If the length of the list of found tags is greater than 0:
(insert " " ":" (mapconcat 'identity list-of-tag-strings ":") ":")) ;; Insert two spaces, a ':', the items from the list each separated by a ':', and a final ':'.
(message "Tags gathered from the selected region (which comprises character markers %d to %d) and printed on the first line of the region." beginning-of-selected-region end-of-selected-region))
;; 'Else' part of the statement:
(message "No region is selected for gathering tags. To run the function, you need to highlight a region first.")
))
You can then highlight text like this, and run the function with M-x generate-tag-list-from-selected-text:
This is a test {{with}} some {{tags}} in it.
This is another test with an {{additional tag}} and {{one:more}}.
This text will then become
This is a test {{with}} some {{tags}} in it. :with:tags:additional_tag:one_more:
This is another test with an {{additional tag}} and {{one:more}}.
Since this is the first function I've written in elisp, I used two sources for understanding the basics of elisp syntax, specifically regarding a) using just a selected area of text and b) running find-and-replace operations on that text. Given that the function uses the generic structure of the code vs. its specific content, I'm thinking that I'm within my rights to open up the function with a CC0 dedication (I do this because of StackOverflow's ongoing discussion about licensing of code on this site).

My Emacs mode does not highlight keywords

I am trying to write an Emacs major mode but it is not working; specifically, my keywords are not being displayed in keyword font face. I have tried to follow the tutorials but I must be doing something wrong. I know a little Lisp but I do not know Emacs scripting.
My Emacs mode script:
;; emacs mode for OldRope
;; does no work for some reason
(setq oldrope-directive-keywords-regexp (regexp-opt '("page" "link" "goto" "act" "end" "div" "span" "include")))
(defvar oldrope-font-lock-defaults '((
(oldrope-directive-keywords-regexp . font-lock-keyword-face))))
(define-derived-mode oldrope-mode fundamental-mode
"oldrope mode"
"Major mode for editing OldRope games"
(setq comment-start "/*")
(setq comment-end "*/")
(setq font-lock-defaults oldrope-font-lock-defaults))
(provide 'oldrope-mode)
Test file:
$[page start]$ Hello $[link]$ Click me $[act]$ That is right. $[end]$
(For context, this is part of https://github.com/martinellison/oldrope but that is not really relevant to the question).
You need this - the rest is OK:
(defvar oldrope-font-lock-defaults
`(((,oldrope-directive-keywords-regexp . font-lock-keyword-face))))
By simply quoting the list you were not evaluating oldrope-directive-keywords-regexp - your quoted list just had that symbol as its car.
Using either backquote (`) plus comma (,) or (list (list (cons oldrope-directive-keywords-regexp 'font-lock-keyword-face))) you evaluate that variable and use its value in the resulting list.

Secret structure in org-mode?

I'm wondering I if there's any functionality in org-mode that can make me able to operate with secret structure, that is: structure that I can see when I'm editing but that is treated as if it wasn't there when exporting. It's mainly importing when I export to ascii.
Example:
I would like this in the .org file:
* Normal heading
** Secret heading 1
Some text 1
** Secret heading 2
Some text 2
** Secret heading 3
Some text 3
To be exported to this:
Normal heading
--------------
Some text 1
Some text 2
Some text 3
What makes the headings secret can be anything like a tag, a property or something else but the secret headings should be foldable.
Edit:
Found this solution (from here) (I'm using org-mode 7.9.3 f. It doesn't work. Headlines with the :ignoreheading: tag are still displayed:
;; backend aware export preprocess hook
(defun sa-org-export-preprocess-hook ()
"My backend aware export preprocess hook."
(save-excursion
(when (eq org-export-current-backend 'latex)
;; ignoreheading tag for bibliographies and appendices
(let* ((tag "ignoreheading"))
(org-map-entries (lambda ()
(delete-region (point-at-bol) (point-at-eol)))
(concat ":" tag ":"))))))
(add-hook 'org-export-preprocess-hook 'sa-org-export-preprocess-hook)
You can use the EXCLUDE_TAGS property and tag certain sections, then export with org-export-exclude-tags. E.g:
#+EXCLUDE_TAGS: noexport
* Public Section
* Secret Section :noexport:
Documentation here.
What you want is addressed here -- and here's the answer (repeated):
Add the following to your .emacs file:
(require 'ox-extra)
(ox-extras-activate '(ignore-headlines))
Use the ignore tag on headlines you'd like to have ignored (while not ignoring their content)
I upgraded to org-mode 8.2.5h and with that this works:
(defun sa-ignore-headline (contents backend info)
"Ignore headlines with tag `ignoreheading'."
(when (and (org-export-derived-backend-p backend 'latex 'html 'ascii)
(string-match "\\`.*ignoreheading.*\n"
(downcase contents)))
(replace-match "" nil nil contents)))
(add-to-list 'org-export-filter-headline-functions 'sa-ignore-headline)
But only if you don't have the options: #+OPTIONS: tags:nil. Guess it's sort of obvious that tags shouldn't be filtered away before a filtering that relies on a certain tag is invoked - but that bugged me for quite some time.
Note: when exporting to ascii the headline underlining will remain without the headline, so you need this setting too:
(setq org-ascii-underline (quote ((ascii) (latin1) (utf-8))))
... to remove headlines all together.
In the linked question about the ignoreheading tag I posted a working, simpler org-export-before-parsing-hook solution for Org 8.2.10 in Emacs 24.1.1.
It is based on the documentation of the org-map-entries function which also states that it wraps it in save-recursion automatically. It is simpler than using concat because the second argument to org-map-entries is an agenda-style match string.
While trying to solve the same problem I found this thread describing how to extend ox-extra.el using a notignore tag. This method does not export any headings unless explicitly tagged notignore. Content of the heading are exported normally.
For most of my documents the notignore approach is more useful than the 'ignore' approach because the majority of headings are 'secret structure' not intended for export.
Presently I have notignore-headlines activated in my init.el file. Can anyone suggest a way to activate this on a per document basis.

Close HTML tags as soon as one opens them

I'd like the corresponding, closing HTML tag to be automatically inserted whenever I open one.
So if I type
<div>
I should get
<div></div>
Without having to call to sgml-close-tag myself.
How to achieve this?
Rather than calling a hook function after every single key-stroke, it makes sense to only call it after a > was typed. This can be achieved by rebinding the > character in the keymap that sgml-mode uses.
In addition, sgml-close-tag shouldn't get called if the tag is already closed. Therefore, the following code adds a simple regexp check for that:
(defun my-sgml-insert-gt ()
"Inserts a `>' character and calls
`my-sgml-close-tag-if-necessary', leaving point where it is."
(interactive)
(insert ">")
(save-excursion (my-sgml-close-tag-if-necessary)))
(defun my-sgml-close-tag-if-necessary ()
"Calls sgml-close-tag if the tag immediately before point is
an opening tag that is not followed by a matching closing tag."
(when (looking-back "<\\s-*\\([^</> \t\r\n]+\\)[^</>]*>")
(let ((tag (match-string 1)))
(unless (and (not (sgml-unclosed-tag-p tag))
(looking-at (concat "\\s-*<\\s-*/\\s-*" tag "\\s-*>")))
(sgml-close-tag)))))
(eval-after-load "sgml-mode"
'(define-key sgml-mode-map ">" 'my-sgml-insert-gt))
If you like paredit (and if you're an emacs user, chances are you do), you may be interested in tagedit, an emacs package written by Magnar Sveen that provides paredit-like features for editing html.
The library is here: https://github.com/magnars/tagedit, and can be installed through Melpa/Marmalade (package-install tagedit).
If you enable the experimental features (tagedit-add-experimental-features), then it will automatically close tags for you and keep the corresponding closing tag text matching the opening tag text. That's on top of being able to splice, slurp, barf and all the other crazy things that paredit lets you do when working with balanced expressions...I think it's great!
I'm using yasnippet for this purpose.
To type shortcuts this answer, like <kbd>C-o</kbd>, I have the following snippet:
# -*- mode: snippet -*-
# name: kbd
# key: kbd
# --
<kbd>$0</kbd>
So I type kbdC-o and it get's expanded to <kbd></kbd> with cursor
right in the middle. You can have the same behavior for div.
You may eval this on your sgml-buffer or add ii to your sgml-hook:
(add-hook 'post-self-insert-hook
(lambda () (and (eq (char-before) ?>) (sgml-close-tag))) nil t)
Whenever you insert a ">", the function sgml-close-tag will be run for you

org-mode capture with sexp

I'm trying to get create a capture template that converts an URL to an org-mode link with the <title> as the link name.
My conversion function looks like this:
(defun get-page-title (url)
"Get title of web page, whose url can be found in the current line"
;; Get title of web page, with the help of functions in url.el
(with-current-buffer (url-retrieve-synchronously url)
;; find title by grep the html code
(goto-char 0)
(re-search-forward "<title>\\([^<]*\\)</title>" nil t 1)
(setq web_title_str (match-string 1))
;; find charset by grep the html code
(goto-char 0)
;; find the charset, assume utf-8 otherwise
(if (re-search-forward "charset=\\([-0-9a-zA-Z]*\\)" nil t 1)
(setq coding_charset (downcase (match-string 1)))
(setq coding_charset "utf-8")
;; decode the string of title.
(setq web_title_str (decode-coding-string web_title_str (intern
coding_charset)))
)
(concat "[[" url "][" web_title_str "]]")
))
When called from normal emacs lisp code it returns the correct result. But when used in this org-capture-template it only returns bad url.
setq org-capture-templates
(quote
(("l" "Link" entry (file+headline "" "Links")
"* \"%c\" %(get-page-title \"%c\")"))))
Is the order of expansion different? Do I need to escape the string differently? Magic?
The first %c is only their to debug the string and indeed is getting printed as "url".
Please don't even bother pointing out that parsing XML with regexp is the wrong approach. Cthulhu is already haunting me and this isn't going to make it worse.
The problem is the order of expansion of template parameters. The simple % templates are expanded after the sexp has been evaluated. The original error message still contains a template and thus is expanded into the contents of the clipboard and thus the error message contains not the string that was originally passed to get-page-title.
The solution is to access the kill ring from within the sexp:
%(get-page-title (current-kill 0))
EDIT This behavior is now documented in org-mode.
Wouldn't the solution be to use org-protocol.el?
http://orgmode.org/worg/org-contrib/org-protocol.html
I just tested it with the following template (adding a sub-heading for your desired title as headline).
Template:
("t"
"Testing Template"
entry
(file+headline "~/org/capture.org" "Testing")
"* %^{Title}\n** %:description\n\n Source: %u, %c\n\n%i"
:empty-lines 1)
Then using a browser-based keybind (in my case with Opera, although examples for Firefox, Uzbl, Acrobat and Conkeror are provided as well) I was able to capture the following:
** Testing for StackExchange
*** org-protocol.el - Intercept calls from emacsclient to trigger custom actions
Source: [2011-08-05 Fri], [[http://orgmode.org/worg/org-contrib/org-protocol.html]
[org-protocol.el - Intercept calls from emacsclient to trigger custom actions]]
org-protocol intercepts calls from emacsclient to trigger custom actions
without external dependencies.
(I broke the org-link simply to keep the scrolling to a minimum, it was not on two lines originally)
#aboabo shared an undocumented variable in https://stackoverflow.com/a/21080770/255961 that provides a more general solution to the question's topic of how to use sexp with keyword values in a template (beyond kill ring). The variable org-store-link-plist stores all the information being passed to the capture. So you can access its values directly from a function like this:
(defun url()
(plist-get org-store-link-plist :url))
("w" "capture" entry (file "~/refile.org")
"* [[%:link][%:description]] :NOTE:\n%(url)%U\n"
:immediate-finish t)
PS, According to the manual page (quote below) it sounds to me like your approach in teh question should work also. But I agree what you describe is what seems to be actually happening - it seems like a bug relative to the manual.
%(sexp) Evaluate Elisp sexp and replace with the result. For convenience,
%:keyword (see below) placeholders within the expression will be
expanded prior to this.