4

I am writing an org file that org babel will tangle into "custom.el" as shown here and here.

My problem is that on one machine the path to my agenda files is C:/Users/Username/Dropbox/file.org while on anther machine it is C:/Users/DifferentUserName/Dropbox/file.org.

I can setq the org-directory to the the correct path on different machines with:

(setq org-directory 
  (car  ;; with car returned value is type 'string' witout car returned type is 'cons'  
      (delq nil
         (mapcar (lambda(x) (and (file-directory-p x) x))
                       '("c:/Users/marka/Dropbox/Apps/OrgMode"
                         "c:/Users/Mark/Dropbox/Apps/OrgMode"
                         "c:/Users/msmith/Dropbox/Apps/OrgMode")))))   

With a single agenda file, using concat (concat org-directory "/gtd_work.org") returns the desired path to the agenda file "c:/Users/Mark/Dropbox/Apps/OrgMode/gtd_work.org".

Unfortunately multiple uses of the concat function when nested in the setq appears to stop functioning:

>  (setq org-agenda-files                             
>             '((concat org-directory "/gtd_work.org")
>               (concat org-directory "/gtd_proging.org")
>               (concat org-directory "/gtd_home.org")
>               (concat org-directory "/DailyRoutine.org")))

Using C-h v to find the value of org-agenda-files yields:

org-agenda-files is a variable defined in `org.el'.
Its value is ((concat org-directory "/gtd_work.org")
 (concat org-directory "/gtd_proging.org")
 (concat org-directory "/gtd_home.org")
 (concat org-directory "/DailyRoutine.org"))

Additionally I have tried:

  1. Removing the single quote in the setq, this raises an Invalid function: (concat org-directory "/gtd_work.org") exception.
  2. mapcar and mapc raise Wrong type argument: stringp, (concat org-directory "/gtd_work.org") exceptions.
  3. Using ~/file.org without concat returns nil

I am doing this in scratch right now as config.org is w.i.p. Will org concat the path to the agenda files? Am I not using concat correctly? If I write out the full path for each file on each computer and use (mapcar (lambda (x) (and (file-exists-p x) x)) it will correctly select the machine specific path, however, this results in the first world problem of having to specify 20~40 paths rather than 8~12.

Solution by amitp below works for both the setq and for the:

(setq org-agenda-files
      (delq nil
            (mapcar (lambda (x) (and (file-exists-p x) x))

Thanks everyone for the help.

4
  • 1
    How about programmatically distinguishing between machines and just live with different paths? For example, evaluate (x-server-version) and/or use other methods to distinguish the OS, etc. -- e.g., system-type; feature-p 'ns, etc. That way, the paths will be programmatically adjusted depending upon which computer you are using. To synchronize, I use rsync instead of Dropbox and I do it manually as needed. I sync my whole installation to desktops and laptops, and to an iPhone (backup) and up to a shared web server (backup).
    – lawlist
    Jun 18, 2016 at 4:08
  • 1
    Please place a check-mark next to the correct answer; and, if you are happy with either of the answers, then click the up-arrow button to give them a an extra brownie-point. In addition to @amitp answer below, you can also use a back-tick instead of a single-quote and place a comma before anything in the list that needs to be evaluated. I can't do a back-tick in a comment because of the formatting that stackexchange uses, so I can't do a demonstration of the back-tick -- here is a comma demonstration though: ,(concat ....) Perhaps @amitp could update the answer with another example.
    – lawlist
    Jun 19, 2016 at 20:56
  • Tick done, I did try and up vote earlier but as I have only been "writing" elisp for 2 days now I have not been around enough to collect the required 15 reputation. I appreciate the guidance on protocol as well. Jun 19, 2016 at 21:18
  • Backticks are a little tricky but yes, … `(,(concat …) ,(concat …)) will be the same as (list (concat …) (concat …)) in this case. Backtick/comma is useful when you want to partially quote something, but some piece of it you want to evaluate without the quotes.
    – amitp
    Jun 19, 2016 at 23:54

2 Answers 2

5

The single quote (') tells lisp not to evaluate(run) the thing, but to leave it as is. When you write '((concat org-directory "/gtd_work.org") …) it tells it not to actually run the concat function, but instead leave the word "concat" in there. When you removed the ' it didn't work either because it didn't know that you wanted all those things put into a list. The good news is that it's easy to make them into a list: the function name is list so you replace '(…) with (list …).

Try changing

(setq org-agenda-files
         '((concat org-directory "/gtd_work.org")
           (concat org-directory "/gtd_proging.org")
           (concat org-directory "/gtd_home.org")
           (concat org-directory "/DailyRoutine.org")))

to

(setq org-agenda-files
         (list
           (concat org-directory "/gtd_work.org")
           (concat org-directory "/gtd_proging.org")
           (concat org-directory "/gtd_home.org")
           (concat org-directory "/DailyRoutine.org")))
3

Instead of using just the string value, perhaps use expand-file-name? I believe this expands to the correct cross platform value on windows.

You could define a user constant to make it easy to use in multiple places, just like this bit from spacemacs core:

(defconst user-home-directory
  (expand-file-name "~/")
  "User home directory (~/).")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.