2

I wrote a Python script to parse an org file that I keep my tasks in, reformat those tasks, and save them to a taskpaper file so that I can easily view and process the tasks on my phone. The script works the way I want it to, but I have to rememeber to run it every time I want my tasks to 'sync'. I have been trying to use after-save-hook to run the script whenever I save changes to my org file, but I haven't been able to get it to work. I am new to Emacs, and don't know much about lisp. This is what I have come up with based mostly on the answer to this question.

(defun sync-to-taskpaper ()
  "Sync org file to taskpaper file for mobile access"
  (when (eq buffer-file-name "~/path/to/org/file.org")
    (shell-command "python3 ~/path/to/python/script.py")))

(add-hook 'after-save-hook #'sync-to-taskpaper)

I am not getting any error messages when I save the file, it just is not running my custom function. Is it possible to do it this way, and if so, what am I missing? Thank you for your help!

2
  • Have you tried running just (shell-command "python3 ~/path/to/python/script.py") and does it do what you want? You can type M-x eval-expression RET (shell-command "python3 ~/path/to/python/script.py") RET
    – lawlist
    Jun 16, 2015 at 15:39
  • Oh, good question! I just ran only that line of code from a *scratch* buffer using eval-buffer , and it did exactly what I want. The problem must be with my function then...(when (eq buffer-file-name "~/path/to/org/file.org") seemed to be the best thing I could come up with for "do this when the file in the buffer that I am saving is the file I want to run the script on", but I am not that confident that this is right.
    – elethan
    Jun 16, 2015 at 15:44

1 Answer 1

2

This is a mistake: (eq buffer-file-name "~/path/to/org/file.org").

Do not compare file names or any other strings using eq. See the Elisp manual, node Equality Predicates.

For strings, use string= or equal. For file names, use file-equal-p.

Here is another function that I also use to compare filenames, to see whether they reference the same file. It avoids accessing remote files when possible.

(defun same-file-p (file1 file2)
  "Return non-nil if FILE1 and FILE2 name the same file.
If either name is not absolute, then it is expanded relative to
`default-directory' for the test."
  (let ((remote1  (file-remote-p file1))
        (remote2  (file-remote-p file2)))
    (and (equal remote1 remote2)  (file-equal-p file1 file2))))
4
  • Thank you! I got it to work by comparing buffer-file-name to the org file path using string=. It took me a while though, because I just figured out that buffer-file-name returns the path to my file with /home/username/ instead of ~/ ...
    – elethan
    Jun 16, 2015 at 17:04
  • OK, but as my answer says, file names are specific thingies - they are not arbitrary strings. You are better off comparing them as file names, not just as strings. A common mistake, for example, is to manipulate them using functions such as concat and substringinstead of file-name functions - see the Elisp manual, node File-Names and its children. You can compare file names (e.g. their components) or you can compare the files they point to. There are many file names that can reference the same file.
    – Drew
    Jun 16, 2015 at 17:30
  • Got it. The documentation on file-equal-p is super brief, and my assumption was that it was comparing file objects or something like that. Lisp is so different from what I am used to in Python, at least from what I gather about it so far. Now I replaced string= in my function with file-equal-p, and it still works perfectly. Is this what you where suggesting? In other words, what I ended up with is (file-equal-p buffer-file-name "home/username/path/to/file.org"). When this evaluates as t it runs my script from the shell.
    – elethan
    Jun 16, 2015 at 18:00
  • Yes, but it is for you to decide whether you want to use file-equal-p, which tests the referenced files to see if they are the same file, instead of, say, testing only the file names. You can test file names using the various file-name component functions, but in that case you may miss the fact that two very different file names correspond to the same file. Testing remote files, in particular, can be costly. If you can get away with a quick-&-dirty filename comparison it is cheaper. But it might not always DTRT.
    – Drew
    Jun 16, 2015 at 19:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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