Org-mode: org-agenda-files defvar directory "evaluation"? - lisp

I have the following setup in my .emacs ...
(defvar org-dir "/home/mash/read/org/")
And use it around such as ...
(setq org-directory org-dir)
(setq org-default-notes-file (concat org-dir "mash.org"))
Now I understand that you can specify a directory such as ...
(setq org-agenda-files '("/home/mash/read/org/"))
But how would I do this with the variable?
(setq org-agenda-files '(org-dir))
(setq org-agenda-files '(,(org-dir))
Any ideas as I would like to use it in my capture templates too ...
(setq org-capture-templates
'(("t" "Test" entry (file+headline (concat org-dir "test.org" "test")
"* %?")))

The '(foo bar) syntax is equivalent to writing (list 'foo 'bar). So you can set org-agenda-files like this:
(setq org-agenda-files (list org-dir))
Alternatively, you can replace the apostrophe ' with a backtick ` to create a list and then use comma to evaluate a part of that list
(setq org-capture-templates
`(("t" "Test" entry (file+headline ,(concat org-dir "test.org" "test")
"* %?")))

Related

How to output elisp bytecode to a custom directory?

I need to output elisp bytecode generated by batch-compile to a custom directory. The customisation value byte-compile-dest-file-function seems to be relevant for this:
(defcustom byte-compile-dest-file-function nil
"Function for the function `byte-compile-dest-file' to call.
It should take one argument, the name of an Emacs Lisp source
file name, and return the name of the compiled file."
:group 'bytecomp
:type '(choice (const nil) function)
:version "23.2")
I went as far as /opt/local/bin/emacs -batch --eval '(defun my-dest-file-function (filename) (let ((pwd (expand-file-name ".")) (basename (replace-regexp-in-string ".*/" "" filename))) (concat (file-name-as-directory pwd) basename "c"))) (setq byte-compile-dest-file-function (quote my-dest-file-function)) (batch-byte-compile)' /Users/michael/Workshop/project/example/elisp/example1.el
The elisp code is easier to read in its unwrapped form:
(defun my-dest-file-function (filename)
(let ((pwd (expand-file-name "."))
(basename (replace-regexp-in-string ".*/" "" filename)))
(concat (file-name-as-directory pwd) basename "c")))
(setq byte-compile-dest-file-function (quote my-dest-file-function))
(batch-byte-compile)
The function my-dest-file-function computes the correct filenames but it does not seem to be used at all, nor the (batch-byte-compile) function to be used at all.
How can I correct the elisp code above to produce the desired effect? I want to avoid any single quote in the elisp code to work easily with the shell and Makefiles.
My emacs version is 24.5.1.
You need to wrap the whole thing in a progn:
(progn
(defun my-dest-file-function (filename)
(let ((pwd (expand-file-name "."))
(basename (replace-regexp-in-string ".*/" "" filename)))
(concat (file-name-as-directory pwd) basename "c")))
(setq byte-compile-dest-file-function (quote my-dest-file-function))
(batch-byte-compile))
Before, you were only executing the first statement, defun, which does nothing on its own.

a function that looks for "string" existing in a file path

I'm used to regex in Ruby, so i'm a lisp noob.
(global-set-key (kbd "C-c t")
(lambda()
(interactive)
(if string-match-p file-name-directory "spec"
(shell-command (concat "rspec " (file-name-directory (buffer-file-name))))
)
)
)
Basically i want to only run this line (or an else for 'test') if the file-name-directory has the word spec in it.
Example: /user/me/app/spec/test.rb
How does one get the if statement to work?
so far i get: Symbol's value as variable is void: string-match-p in the mini buffer. Thanks.
I assume you want this to act on the current buffer, if so, try this:
(global-set-key (kbd "C-c t")
(lambda()
(interactive)
(let* ((full-name (buffer-file-name))
(path (when full-name
(file-name-directory full-name))))
(when (and path (string-match "spec" path))
(shell-command (concat "rspec " path))))))

Asking emacs for default directory path "once"

I want to have a variable that keeps the default directory a user enters and keep using it throughout the run of emacs.
Basically, when the user executes a custom command, the prompt will ask for a default directory path to execute the command (only once) and whenever the user calls the same command emacs uses the same path onward.
How can I program that snippet of code in lisp?
I basically want this code in the igrep library to accept the input from user once and not ask again:
(defvar default-files-string-new "*.[sch]")
(defun igrep-read-files (&optional prompt-prefix)
"Read and return a file name pattern from the minibuffer.
If `current-prefix-arg' is '(16) or '(64), read multiple file name
patterns and return them in a list. Optional PROMPT-PREFIX is
prepended to the \"File(s): \" prompt."
(let* ((default-files (igrep-default-files))
(default-files-string (mapconcat 'identity default-files " "))
(insert-default-directory igrep-insert-default-directory)
(file (igrep-read-file-name
(igrep-prefix prompt-prefix
(if default-files
(format "File(s) [default: %s]: "
default-files-string)
"File(s): "))
nil (if default-files default-files-string "") nil nil
'igrep-files-history))
(files (list file)))
(if (or igrep-read-multiple-files
(and (consp current-prefix-arg)
(memq (prefix-numeric-value current-prefix-arg)
'(16 64))))
(let* ((key (igrep-default-key 'exit-minibuffer
minibuffer-local-completion-map
"\r"))
(prompt
(igrep-prefix prompt-prefix
(if igrep-verbose-prompts
(format "File(s): [Type `%s' when done] "
(key-description key))
"File(s): "))))
(while (and (setq file
(igrep-read-file-name prompt
nil "" nil nil
'igrep-files-history))
(not (equal file "")))
(setq files (cons file files)))))
(mapcar (lambda (file)
(if (file-directory-p file)
;; really should map expand-file-name over default-files:
(expand-file-name (if default-files default-files-string-new "*")
file)
file))
(nreverse files))))
You could use advices to do that:
(defvar wd-alist nil)
(mapc
(lambda (function)
(eval
`(defadvice ,function (around ,(intern (format "%s-wd" function)) activate)
(let ((wd (cdr (assoc ',function wd-alist))))
(unless wd
(setq wd (read-file-name "Default directory: "))
(push (cons ',function wd) wd-alist))
(let ((default-directory wd))
ad-do-it)))))
'(grep-find))
The variable wd-list stores the association (FUNCTION . PATH). The list mapc iterate over are the advised functions. Now, when calling find-grep, it asks for the working directory (after interactive arguments, so you first have to type the pattern and enter...) and stores it in wd-list for further use. Now your find-grep are always done in that directory.
You could have a custom variable for the sane default, and then have the user enter the path or accept the default on the first call.
(defcustom default-path "/tmp/foo" "Path")
(setq current-path nil)
(defun foo ()
(interactive)
(unless current-path
(setq current-path
(read-from-minibuffer
(format "Path [%s]" default-path) nil nil t nil default-path)))
(message "Path is: %s" current-path))
The first time you do M-x foo, it prompts for the path. A common idiom is to allow the user to specify a prefix argument when they want to change the value (after the first time.) This code will have the desired effect:
(defun foo (choose)
(interactive "P")
(when (or choose (not current-path))
(setq current-path
(read-from-minibuffer
(format "Path [%s]" default-path) nil nil t nil default-path)))
(message "Path is: %s" current-path))
Now doing M-x foo is the same as before, but C-0 M-x foo will prompt for a new value.
In your example, something like this will work.
(defun igrep-read-files (&optional prompt-prefix)
(interactive "P")
(when (or prompt-prefix (not current-path ))
(setq current-path
(read-file-name "Dir: " default-path nil t)))
(message (expand-file-name default-files-string-new current-path)))
Have a look at the code of sendmail-query-once.
Although it's not very fashionable to do this sort of thing.
Usually package writers pick a sane default and let the user
customize it as they want.

define your own tag in org-mode

There are Tags as in #+AUTHOR or #+LATEX in org-mode - are they called tags? I'd like to define my own tag which calls a function to preprocess the data and then outputs it - if the export target is LaTeX.
My solution was defining an own language, qtree, for SRC blocks.
#+BEGIN_SRC qtree
[.CP [.TP [.NP [] [.N' [.N Syntax] []]] [.VP [] [.V' [.V sucks] []]]]]
#+END_SRC
And process it accordingly. I even added a qtree-mode with paredit.
And a landscape parameter if the trees grow big. https://github.com/Tass/emacs-starter-kit/blob/master/vendor/assorted/org-babel-qtree.el
(require 'org)
(defun org-babel-execute:qtree (body params)
"Reformat a block of lisp-edited tree to one tikz-qtree likes."
(let (( tree
(concat "\\begin{tikzpicture}
\\tikzset{every tree node/.style={align=center, anchor=north}}
\\Tree "
(replace-regexp-in-string
" \\_<\\w+\\_>" (lambda (x) (concat "\\\\\\\\" (substring x 1)))
(replace-regexp-in-string
(regexp-quote "]") " ]" ; qtree needs a space
; before every closing
; bracket.
(replace-regexp-in-string
(regexp-quote "[]") "[.{}]" body)) ; empty leaf
; nodes, see
; http://tex.stackexchange.com/questions/75915
) ; For
; http://tex.stackexchange.com/questions/75217
"\n\\end{tikzpicture}"
)))
(if (assoc :landscape params)
(concat "\\begin{landscape}\n" tree "\n\\end{landscape}")
tree)))
(setq org-babel-default-header-args:qtree '((:results . "latex") (:exports . "results")))
(add-to-list 'org-src-lang-modes '("qtree" . qtree))
(define-generic-mode
'qtree-mode ;; name of the mode to create
'("%") ;; comments start with '%'
'() ;; no keywords
'(("[." . 'font-lock-operator) ;; some operators
("]" . 'font-lock-operator))
'() ;; files for which to activate this mode
'(paredit-mode) ;; other functions to call
"A mode for qtree edits" ;; doc string for this mode
)
They seem to be called keywords for in-buffer settings no more. Whatever they're called, they don't seem to be user-definable.
What you want to do is extremely related to a common way of handling whereas to export with xelatex or pdflatex as described on Worg.
The relevant part would be :
;; Originally taken from Bruno Tavernier: http://thread.gmane.org/gmane.emacs.orgmode/31150/focus=31432
(defun my-auto-tex-cmd ()
(if (string-match "YOUR_TAG: value1" (buffer-string))
(do something))
(if (string-match "YOUR_TAG: value2" (buffer-string))
(do something else))
(add-hook 'org-export-latex-after-initial-vars-hook 'my-auto-tex-cmd)

Concatenate strings in elisp

I need to concatenate path string as follows, so I added the following lines to my .emacs file:
(setq org_base_path "~/smcho/time/")
(setq org-default-notes-file-path (concatenate 'string org_base_path "notes.org"))
(setq todo-file-path (concatenate 'string org_base_path "gtd.org"))
(setq journal-file-path (concatenate 'string org_base_path "journal.org"))
(setq today-file-path (concatenate 'string org_base_path "2010.org"))
When I do C-h v today-file-path RET to check, it has no variable assigned.
What's wrong with my code? Is there any other way to concatenate the path string?
EDIT
I found that the problem was caused by the wrong setup, the code actually works. Thanks for the answers which are better than my code.
You can use (concat "foo" "bar") rather than (concatenate 'string "foo" "bar"). Both work, but of course the former is shorter.
Use expand-file-name to build filenames relative to a directory:
(let ((default-directory "~/smcho/time/"))
(setq org-default-notes-file-path (expand-file-name "notes.org"))
(setq todo-file-path (expand-file-name "gtd.org"))
(setq journal-file-path (expand-file-name "journal.org"))
(setq today-file-path (expand-file-name "2010.org")))
First of all, don't use "_"; use '-' instead.
Insert this into your .emacs and restart emacs (or evaluate the S-exp in a buffer) to see the effects:
(setq org-base-path (expand-file-name "~/smcho/time"))
(setq org-default-notes-file-path (format "%s/%s" org-base-path "notes.org")
todo-file-path (format "%s/%s" org-base-path "gtd.org")
journal-file-path (format "%s/%s" org-base-path "journal.org")
today-file-path (format "%s/%s" org-base-path "2010.org"))