When working in Emacs org-mode, how do I make a word part italic? I want this:
wordx
but when I try word/x/ it produces
word/x/
and word{/x/} produces
word{x}
You can do this by creating a custom link.
Simple method:
(org-add-link-type "emph" nil 'org-export-emph)
(defun org-export-emph (path desc format)
(let ((text (or desc path)))
(cond
((eql format 'html)
(format "<em>%s</em>" text))
((eql format 'latex)
(format "\\emph{%s}" text))
(t
text))))
This then allows you to write par[[emph:ti]]ally em[[emph:ph][ph]]asized words.
Better (?) method:
You only define the link type by
(org-add-link-type "emph")
and handle that link type via a generic trancoder in your exporter backend.
Related
I have a list of org files under a directory:
> org-file1.org
> org-file2.org
> org-file3.org
> ...
> org-fileN.org
I want to extract their titles (using #+title tag) as links as follows:
[[file:org-file1.org][title for org file 1]]
[[file:org-file2.org][title for org file 2]]
[[file:org-file3.org][title for org file 3]]
...
[[file:org-fileN.org][title for org file N]]
How can I extract these as a list using Emacs Lisp?
You could use the org-element-api for this, but in this case it is probably easier/faster to simply search by regexp using looking-at-p. To get all files in a directory, there is directory-files(-recursively). Then finally you could achieve it using the following function:
(defun extract-org-directory-titles-as-list (&optional dir)
(interactive "D")
(print
(delete nil
(let ((case-fold-search t))
(mapcar (lambda (f)
(when (string-match "org$" f)
(with-temp-buffer
(insert-file-contents-literally
(concat (file-name-as-directory dir) f))
(while (and (not (looking-at-p "#\\+TITLE:"))
(not (eobp)))
(forward-line))
(when (not (eobp))
(cons f (substring (thing-at-point 'line) 9 -1))))))
(directory-files dir))))))
(defun insert-directory-org-file-titles (&optional dir)
(interactive "D")
(let ((files-titles (extract-org-directory-titles-as-list dir)))
(dolist (ft files-titles)
(insert (concat "[[file:" (car ft)"][" (cdr ft) "]]\n")))))
If you prefer to just have it as a (a)list, like you asked, then just use extract-org-directory-titles-as-list.
Here's some code that can be used on a single file to get the title. It's part of an org mode file that can be used for testing. Save it as an Org mode file, visit it in Emacs and type C-c C-c on the code block. Change the title and evaluate the code block again.
#+OPTIONS: toc:nil
#+TITLE: This is a very nice title, don't you think?
#+AUTHOR: A.U. Thor
* foo
bar
* Code
#+begin_src elisp :results drawer
(save-excursion
(goto-char (point-min))
(let ((case-fold-search t))
(search-forward-regexp "^#\\+TITLE:")
(org-element-property :value (org-element-context (org-element-at-point)))))
#+end_src
#+RESULTS:
:results:
This is a very nice title, don't you think?
:end:
The code block goes to the beginning of the buffer, searches forward for the string #+TITLE: at the beginning of a line (the search is case-insensitive) and then uses some functions from the org-element library to parse the buffer at point, get the context and get the :value property out of it.
In order to make it into a complete solution, you have to:
make it more robust: check that this is a title keyword not just some random junk that happened to satisfy the match, although that's unlikely; but better safe than sorry.
wrap it in a loop that does a find-file on every file in the directory and gets the title for each file and returns a list of tuples: (filename title) that you can easily use to create your links.
My problem is to export this org-block
#+BEGIN_NOTE
some text here
#+END_NOTE
to this Latex code
\begin{bclogo}[logo=\bcattention, noborder=true, barre=none]{some text here}
\end{bclogo}
Is there a way to customize how to export in Latex this block of text?
You can keep the NOTE environment and replace it with bclogo through a latex-specific filter (I modified John's code):
(defun my/latex-process-NOTE-blocks (text backend info)
"Filter special blocks from latex export."
(when (eq backend 'latex)
(let ((text (replace-regexp-in-string "\\\\begin{NOTE}" "\\\\begin{bclogo}[logo=\\\\bcattention, noborder=true, barre=none]{" text)))
(replace-regexp-in-string "\\\\end{NOTE}" "}\\\\end{bclogo}" text))))
(eval-after-load 'ox '(add-to-list
'org-export-filter-special-block-functions
'my/latex-process-NOTE-blocks))
If you want to do this with all latex-derived backends, you can replace (eq backend 'latex) with (org-export-derived-backend-p backend 'latex).
If you want to make sure the block starts with \begin{NOTE}:
(defun string/starts-with (string prefix)
"Return t if STRING starts with prefix."
(and (string-match (rx-to-string `(: bos ,prefix) t) string) t))
(defun my/latex-process-NOTE-blocks (text backend info)
"Filter special blocks from latex export."
(when (eq backend 'latex)
(if (string/starts-with text "\\begin{NOTE}")
(let ((text (replace-regexp-in-string "\\\\begin{NOTE}" "\\\\begin{bclogo}[logo=\\\\bcattention, noborder=true, barre=none]{" text)))
(replace-regexp-in-string "\\\\end{NOTE}" "}\\\\end{bclogo}" text)))))
(eval-after-load 'ox '(add-to-list
'org-export-filter-special-block-functions
'my/latex-process-NOTE-blocks))
May I suggest to use instead something like:
#+LaTeX_HEADER: \usepackage[tikz]{bclogo}
...
#+ATTR_LATEX: :options [logo=\bcattention, noborder=true, barre=none]{some title here}
#+BEGIN_bclogo
some text here
#+END_bclogo
Using a LaTeX special block is well suited here, unless you really want to use notes.
You can do it like this with a custom block in org-mode:
+begin_bclogo
some text here
+end_bclogo
Then, use a filter to modify the export like this:
(defun ox-mrkup-filter-special-block (text back-end info)
(let ((text (replace-regexp-in-string "\\\\begin{bclogo}" "\\\\begin{bclogo}[logo=\\\\bcattention, noborder=true, barre=none]{" text)))
(replace-regexp-in-string "\\\\end{bclogo}" "}\\\\end{bclogo}" text)))
(let ((org-export-filter-special-block-functions '(ox-mrkup-filter-special-block)))
(find-file (org-export-to-file 'latex "custom.tex")))
That exports to:
\begin{bclogo}[logo=\bcattention, noborder=true, barre=none]{
some text here
}\end{bclogo}
This seems to get close to what you want. I am not sure how you could get a body in the environment. I think you would need to use an attribute to set the text in {} and then use the text as the body. That is probably not easy to implement in a filter, and would be better implemented in a custom export.
I've got some org files with content as below:
* HOLD Some todo heading :project:
#+BEGIN_SRC shell
grunt watch
#+END_SRC
* TODO Some other heading :test:
#+BEGIN_SRC emacs-lisp
(message "TEST")
#+END_SRC
I want to switch from HOLD to INPROGRESS state on clock-in. This is easy and I got it.
Then on org-after-todo-state-change-hook I want to execute code included in entry but only on specific TAGS.
So, I got:
(defun tester/after-change-hook()
"Test function on hook."
(when (string= org-state "INPROGRESS")
;; DO SOMETHING on entry with 'project' tag
;; DO SOMETHING on entry with 'test' tag
;; MAYBE TRY TO EXECUTE CODE ON entry with 'project' tag
;; MAYBE TRY TO EXECUTE CODE ON entry with 'test' tag
)
)
(add-hook 'org-after-todo-state-change-hook 'tester/after-change-hook)
Unfortunately, I don't know how to write a function to execute code on specific tag or execute inline code on specific tag.
I've been trying with org-scan-tags function or org-element-map.
I can see that other people can make use of them.
But unfortunately all this Lisp stuff is like a black magic for me.
I don't know how to write function that will test tags on currently clocked task.
Could someone help me with this lisp syntax?
In theory I know which functions are required to do what I want.
In real life I don't know how to write this in lisp.
One way to match a member in a list of tags would be to use something like (member "test" tags) -- see example below where the presence of tag named test will yield a congratulations message, or a go-fish message if the tag named test is not present. You can also use a regexp to match whole words or parts of words, but that is beyond the scope of this example.
Here is a 4-step approach to test the example below. [The example was tested by #lawlist using Org version 8.2.5c.]
(1) Copy and paste my entire code into your .emacs file; save the file; and, restart Emacs.
(2) Open a new buffer and type:
* This is a task. :test:lawlist:
(3) M-x org-mode
(4) Place the cursor anywhere on the line you just typed and: M-x example
Once you get the example up and running (without making any modifications), then you can slowly make your own modifications -- keep testing your new code at various stages along the way, so that any wrong turns in your coding will not get too far out of hand (which would make debugging that much more difficult).
(require 'org)
(require 'org-element)
(defun example ()
(interactive)
(save-excursion
(org-back-to-heading t)
(let* (
(element (org-element-at-point))
(title (org-element-property :title element))
(tags (org-element-property :tags element)))
(cond
((and
(equal title "")
(not (equal tags nil)))
(error "The `title` cannot be blank."))
((and
(equal tags nil)
(not (equal title "")))
(error "The `tags` cannot be blank."))
((and
(equal title "")
(equal tags nil))
(error "The `title` and `tags` cannot be blank."))
((and
(not (equal tags nil))
(not (equal title "")))
(message "TITLE: %s | TAG(S): %s" title tags)
(if (member "test" tags)
(message "Congratulations: You found a match.")
(message "Uh-oh -- no match -- go fish!"))) ))))
I would like to save all attachments to an email at once. I therefore set gnus-summary-save-parts-default-mime to ".* /.*". However, when using "X m", I not only get all attachments, but also a file named "nnimap+my.name#googlemail.com/INBOX.2393.1" (referring to the account I'm reading emails from) which contains the signature of the email I received. How can I exclude files of this "type" from being saved on "X m"? In other words: How can I specify the correct regexp for gnus-summary-save-parts-default-mime to prevent this file from being saved, too?
This defadvice will do what you want for the moment by excluding any parts that do not have filenames (in this case that is true of the article itself):
(defadvice gnus-summary-save-parts-1 (around gnus-summary-save-parts-exclude-self activate)
(let ((handle (ad-get-arg 2)))
(unless (and (not (stringp (car handle)))
(not (mm-handle-filename handle)))
ad-do-it)))
I am using Gnus v5.13; if you're also using the same or similar version, let me know if this modified version of gnus-summary-save-parts-1 works for you; you will want to set gnus-summary-save-parts-exclude-article to t. If it works for you, I will submit a patch for it to the Gnus projects.
Note, either use the above defadvice OR use the code below, but do not use both together. The defadvice is an easy quick fix that you can use for the moment. The code below I will submit as a patch to the Gnus project and I only included this here for you to test to see if it works on your system if you are also using Gnus v5.13. If they accept this patch and make it part of a future release then you will not need the defadvice above; instead you'll just be able to customize the gnus-summary-save-parts-exclude-article variable.
(require 'gnus)
(require 'gnus-sum)
(defcustom gnus-summary-save-parts-exclude-article nil
"If non-nil don't save article along with attachments."
:group 'gnus-article-mime
:type 'boolean)
(defun gnus-summary-save-parts-1 (type dir handle reverse)
(if (stringp (car handle))
(mapcar (lambda (h) (gnus-summary-save-parts-1 type dir h reverse))
(cdr handle))
(when (if reverse
(not (string-match type (mm-handle-media-type handle)))
(string-match type (mm-handle-media-type handle)))
(let* ((name (or
(mm-handle-filename handle)
(unless gnus-summary-save-parts-exclude-article
(format "%s.%d.%d" gnus-newsgroup-name
(cdr gnus-article-current)
gnus-summary-save-parts-counter))))
(file (when name
(expand-file-name
(gnus-map-function
mm-file-name-rewrite-functions
(file-name-nondirectory
name))
dir))))
(when file
(incf gnus-summary-save-parts-counter)
(unless (file-exists-p file)
(mm-save-part-to-file handle file)))))))
I'm looking for some help developing what I think should be an easy program.
I want something similar to Emacs tags-search command, but I want to collect all search results into a buffer. (I want to see all results of M-,)
I'm thinking this python style pseudo code should work, but I have no idea how to do this in emacs lisp? Any help would be greatly appreciated.
def myTagsGrep(searchValue):
for aFile in the tag list:
result = grep aFile seachValue
if len(result) > 0:
print aFile # to the buffer
print result # to the buffer
I would like to be able to browse through the buffer with the same features tags-apropos does.
Note that a similar question has been asked before:
Is there a way to get emacs tag-search command to output all results to a buffer?
Since I'm such a fan of igrep, I'd use it as the building block. From there it's two simple routines and you're done. With that library and these two functions, all you have to do is:
M-x igrep-tags ^SomeRegexp.*Here RET
Here's the code:
(require 'igrep)
(defun igrep-tags (regex)
(interactive "sTAGS Regexp: ")
(igrep igrep-program regex (tags-file-names)))
(defun tags-file-names ()
(save-excursion
(visit-tags-table-buffer)
(mapcar (lambda (f) (file-truename f))
(tags-table-files))))
And, because the list of files can get really long, and you likely don't care what that list is, you can add these two pieces of code which will make the filenames invisible after the grep has finished:
(add-hook 'compilation-finish-functions 'igrep-tags-hide-filenames)
(defun igrep-tags-hide-filenames (buffer stat)
"hide the filenames b/c they can get long"
(save-excursion
(set-buffer buffer)
(save-match-data
(goto-char (point-min))
(if (search-forward (combine-and-quote-strings (tags-file-names))
nil
(save-excursion (forward-line 10) (point)))
(let ((display-string "..<files from TAGS>.."))
(put-text-property (match-beginning 0) (match-end 0) 'invisible t)
(put-text-property (match-beginning 0) (match-end 0) 'display display-string))))))
To avoid the really long command line, you can use the following code (which creates a temporary file containing all the names of files from TAGS file and uses that instead):
(defun igrep-tags (regex)
(interactive "sTAGS Regexp: ")
(let ((igrep-find t)
(igrep-use-file-as-containing-files t))
(igrep igrep-program regex nil)))
(defvar igrep-use-file-as-containing-files nil)
(defadvice igrep-format-find-command (around igrep-format-find-command-use-filename-instead activate)
"use the second argument as a file containing filenames"
(if igrep-use-file-as-containing-files
(progn (with-temp-file
(setq igrep-use-file-as-containing-files (make-temp-file "tags-files"))
(insert (combine-and-quote-strings (tags-file-names))))
(setq ad-return-value (format "cat %s | xargs -e %s"
igrep-use-file-as-containing-files
(ad-get-arg 0))))
ad-do-it))
And, for those using Emacs 22 or earlier, you'll need the routine that's shipped with Emacs 23 (from subr.el)
(defun combine-and-quote-strings (strings &optional separator)
"Concatenate the STRINGS, adding the SEPARATOR (default \" \").
This tries to quote the strings to avoid ambiguity such that
(split-string-and-unquote (combine-and-quote-strings strs)) == strs
Only some SEPARATORs will work properly."
(let* ((sep (or separator " "))
(re (concat "[\\\"]" "\\|" (regexp-quote sep))))
(mapconcat
(lambda (str)
(if (string-match re str)
(concat "\"" (replace-regexp-in-string "[\\\"]" "\\\\\\&" str) "\"")
str))
strings sep)))
Here is the code I use to create a tag system for my personal notes. It uses bookmarks and treats each word in a bookmark as a single tag. Its not quite what you're looking for but it might get you started.
The first couple of functions are probably already implemented in emacs, but I wrote my own for reasons that I no longer recall.
;; FILTER keeps only elements of li for which pred returns true
(defun filter (pred li)
(let (acc)
(dolist (elem li)
(if (funcall pred elem)
(setq acc (cons elem acc))))
(reverse acc)))
(defun string-match-all-p (str li)
(if li
(if (string-match-p (car li) str)
(string-match-all-p str (cdr li))
nil)
t))
;;bookmarks as tags
(defun lookup-bookmark-tags (tagstring)
(interactive "s")
(let ((taglist (split-string tagstring " ")))
(let ((bookmark-alist (filter
(lambda (elem)
(string-match-all-p (car elem) taglist))
bookmark-alist)))
(call-interactively 'list-bookmarks))))
I then bind the 'tagging' behavior to a key (F11) and the 'lookup' behavior to another (F12).
(global-set-key [f11] 'bookmark-set)
(global-set-key [f12] 'lookup-bookmark-tags))
Hope that is useful to you.
This is what you want:
http://www.emacswiki.org/emacs/Icicles_-_Emacs_Tags_Enhancements#icicle-tags-search
This is the doc string for icicle-tags-search:
Search all source files listed in tags tables for matches for REGEXP.
You are prompted for the REGEXP to match. Enter REGEXP with `RET'.
You do not need `M-,' - you see all matches as search hits to visit.
All tags in a tags file are used, including duplicate tags from the
same or different source files.
By default, all tags files are used, but if you provide a prefix
argument then only the current tag table is used.
If your TAGS file references source files that no longer exist, those
files are listed. In that case, you might want to update your TAGS
file.
You can alternatively choose to search, not the search contexts as
defined by the context regexp you provide, but the non-contexts, that
is, the text in the files that does not match the regexp. To do this,
use `C-M-~' during completion. (This is a toggle, and it affects only
future search commands, not the current one.)
See also this page for more explanation about Icicles search:
http://www.emacswiki.org/emacs/Icicles_-_Search_Commands%2c_Overview