Using Emacs for Mac OS X 25.1.1 and gnupg2 2.0.30 installed via homebrew on macOS Sierra 10.12.2.
Emacs works correctly and gnugp2 also works well on the command line level (email addresses removed):
pu#pumbair.local 528 ~/Dropbox/org $ echo "Hello World" >text.txt
pu#pumbair.local 536 ~/Dropbox/org $ gpg -a -e -r x#y <text.txt >text.gpg
pu#pumbair.local 537 ~/Dropbox/org $ gpg -d text.gpg
You need a passphrase to unlock the secret key for
2048-bit RSA key, ID 37B58834, created 2017-01-18 (main key ID 45C04EA8)
gpg: encrypted with 2048-bit RSA key, ID 37B58834, created 2017-01-18
Hello World
My ./emacs/init.el says
; gpg
(require 'epa-file)
(epa-file-enable)
(setq epg-gpg-program "/usr/local/bin/gpg2")
and
pu#pumbair.local 505 ~/.emacs.d $ file /usr/local/bin/gpg2
/usr/local/bin/gpg2: Mach-O 64-bit executable x86_64
but I cannot seem to get Emacs to use gpg2; Meta-x epa-list-keys yields:
GPG error: "no usable configuration", OpenPGP
I'm using gpg and gpg2 here but the first is a symlink to the latter.
What did I miss?
EDIT
Browsing trough EasyPG's source I got the impression that it only worked with gpg2 2.1+ so I uninstalled the homebrew version and installed version 2.1.17 from Sourceforge but that didn't help either.
So I ended up browsing some source files related to this question and mailed Daiki Ueno directly. He replied quickly, telling me to use custom-set-variables instead of setq:
(require 'epa-file)
(custom-set-variables '(epg-gpg-program "/usr/local/bin/gpg2"))
(epa-file-enable)
I assume this is obvious to Emacs people but I hardly use Emacs for anything else than org-mode, so it wasn't for me.
gpg in only inside /usr/local/gnupg-2.2/bin. In Eamcs, (getenv "Path") and exec-path only contains /usr/bin, but new version of macOS restricts the access of /usr/bin.
My solution is to create a symbolic link and add the path into the emacs environment and its exec path.
cd /usr/local/bin
ln -s ../gnupg-2.2/bin/gpg2 gpg
Inside .emacs
(setenv "PATH" (concat (getenv "PATH") ":/usr/local/bin"))
(setq exec-path (append exec-path '("/usr/local/bin")))
Related
I'm writing a script to automatically install some elisp. I'd like to find the value of user-emacs-directory so that I can copy the file to the right directory. Is there any way to do this from the shell?
I was hoping it would work to run:
$ emacs --batch --eval="(print user-emacs-directory)"
Symbol's value as variable is void: user-emacs-directory
but as you can see that was not fruitful. Then I tried loading my .emacs file first:
$ emacs --batch -l ~/.emacs --eval="(print user-emacs-directory)"
Loading /Users/noah/dotfiles/emacs/init.el (source)...
Symbol's function definition is void: global-visual-line-mode
but that also chokes. Googling hasn't led me to an answer yet. Any ideas?
edit: The specific problem was that I was using an old version of Emacs (22.1.1). Running Emacs 24.4.1 works:
$ emacs -l ~/.emacs --batch --eval="(print user-emacs-directory)" 2>/dev/null
"~/dotfiles/emacs"
(which is the custom value I've set in my own ~/.emacs file)
Note that I'm redirecting stderr to /dev/null to suppress some loading messages.
Works for me on vanilla GNU Emacs 24.5.1 shipped with Ubuntu:
$ emacs -Q --batch --eval="(princ user-emacs-directory)"
~/.emacs.d/
note princ instead of print to avoid extra whitespace and quote marks.
--batch implies -q which means there is no user-emacs-directory
edit: Ugh. No, -q doesn't mean that at all. As sds points out, the proposed code should probably be working. That'll teach me to jump to conclusions. I'd delete this answer, but as the original approach evidentially doesn't work for Noah for some reason, I'll leave this here just in case it still helps...
Typically you just want $HOME/.emacs.d/
See C-hig (emacs) Find Init RET for more info.
I love eshell's TRAMP integration. With it I can do cd /ssh:foo:/etc to
ssh into a remote machine and visit its /etc/ directory. I can also do
find-file motd to open this file in my local emacs. However, what if I need to use sudo to change the file? I know I can give the
full path, like so:
find-file /sudo:foo:/etc/motd
but is there a way to open the file via TRAMPs sudo support, without having to type the full path?
I managed to came up with the following eshell alias that works for me:
alias sff 'find-file "${pwd}/$1"(:s/ssh/sudo/)'
It should be fairly obvious what it does. It prepends the working directory
path, but with the string ssh replaced by sudo. Thus it only works for
remote files accessed over ssh. I rarely edit files using sudo locally, so
that's not a problem for me. However, we can make it work for local files too, at the cost of complexity:
alias sff 'find-file "${pwd}/$1"(:s,^,/sudo::,:s,::/ssh:,:,)'
That is, prepend /sudo:: (which is how to sudo for local files) and
subsequently replace any ocurrence of ::/ssh: with :. (I would have just removed :/ssh:, but eshell's :s/// construct didn't accept an empty
replacement.)
I found an alternative answer that works very well over at EmacsWiki.
Using that you'd still open the file with find-file as usual, but then
invoke M-x sudo-edit-current-file (shown below) to re-open the file as root
using Tramp. I think this is a very elegant solution, because often I
initially just want to look at a file, then later find that I need to edit it.
Here's the function, in case it disappears from the page above:
(set-default 'tramp-default-proxies-alist (quote ((".*" "\\`root\\'" "/ssh:%h:"))))
(require 'tramp)
(defun sudo-edit-current-file ()
(interactive)
(let ((position (point)))
(find-alternate-file
(if (file-remote-p (buffer-file-name))
(let ((vec (tramp-dissect-file-name (buffer-file-name))))
(tramp-make-tramp-file-name
"sudo"
(tramp-file-name-user vec)
(tramp-file-name-host vec)
(tramp-file-name-localname vec)))
(concat "/sudo:root#localhost:" (buffer-file-name))))
(goto-char position)))
This is somewhat weird, I compiled from source postgresql. I've had no problem using psql at all.
$ psql -d rita
psql (9.3.2)
Type "help" for help.
rita=>
`
However when I try to run M-x sql-postgres on emacs, it prompts for user, password, database, host. But when I input the data in the minibuffer just appears: Unable to locate SQL program psql. I hope anyone can tell me how can I fix this, or what is happening.
Your psql isn't on the standard path.
You are likely setting the PATH in
~/.bashrc, and Emacs will not see it unless you launch Emacs from the terminal.
A solution is:
(setq sql-postgres-program "/usr/local/pgsql/bin/psql")
Or ln -s to /usr/bin if you want.
Alternatively, you can add the path to the psql binary to your emacs 'exec-path list as follows:
(add-to-list 'exec-path "/path/to/program")
(setenv PATH (mapconcat 'identity exec-path ":"))
I run Emacs on a Mac as my development environment. Launching emacs from the Dock doesn't include the path for programs installed via MacPorts. This is going to be a standard problem for anyone who has "non-standard" exec path elements and launches Emacs via their GUI. For me, OSX : MacPorts : /opt/local/... this includes psql, mysql, py-flakes and others. I could either set a variable for each add-on or modify exec-path. The setenv is needed where the elisp function defers searching the exec-path to the shell. The C-c C-v binding in python mode leverages the shell and the $PATH environment to find py-flakes.
The add-to-list is a simple solution that prepends the path to the list. One could make a case for more complex path wrangling in your .emacs file. YMMV.
Assume that I have in a certain directory several org-mode files: foo1.org, foo2.org, etc. I would like to have a script (maybe a makefile) that I could invoke something like
$ generate-pdfs
and foo1.pdf, foo2.pdf, etc. will be generated.
I thought that something like emacs --batch --eval <MAGIC> is a good start, but I don't know the magic.
A solution that is solely inside emacs could be of interest as well.
As you said, Emacs has the --batch option to perform operations with Emacs from the shell. In addition to that, you can use the -l flag to load Emacs Lisp code from a file and execute it, and the -f flag to execute a single Lisp function.
Here is a basic example, which exports a single org-mode file to HTML:
emacs myorgfile.org --batch -f org-html-export-to-html --kill
Perhaps you want something more advanced like exporting/publishing a full org-mode project. I do not have sample code for that, but it should not be too complicated.
I also have a sample Makefile I wrote some time ago to export all org-mode files in the directory to HTML (and also copy the HTML files to another directory):
OUT_DIR=/some/output/dir/html
# Using GNU Make-specific functions here
FILES=$(patsubst %.org,$(OUT_DIR)/%.html,$(wildcard *.org))
.PHONY: all clean install-doc
all: install-doc
install-doc: $(OUT_DIR) $(FILES)
$(OUT_DIR):
mkdir -v -p $(OUT_DIR)
%.html: %.org
emacs $< --batch -f org-html-export-to-html--kill
$(OUT_DIR)/%.html: %.html
install -v -m 644 -t $(OUT_DIR) $<
rm $<
clean:
rm *.html
EDIT:
With Org-mode 8 and the new export engine the function for HTML export has changed.
To make the previous examples work with Org 7 or older, replace org-html-export-to-html with org-export-as-html.
I expect to publish (by the end of this week-end) OrgMk, a suite of Makefile and standalone Bash scripts (usable as well under Cygwin) just to do that! Even more: generation of HTML, Ascii, Beamer, etc.
You'll find it on my GitHub account: https://github.com/fniessen/ (where I already have Emacs configuration files, color themes and other stuff such as an Org Babel refcard -- in progress).
Mark a few org files in dired and call this:
(defun dired-org-to-pdf ()
(interactive)
(mapc
(lambda (f)
(with-current-buffer
(find-file-noselect f)
(org-latex-export-to-pdf)))
(dired-get-marked-files)))
If you know what async is, wrap the call as it can take a while.
update:
Here's a version that combines the awesome dired approach with the lame
other one:)
(defun dired-org-to-pdf ()
(interactive)
(let ((files
(if (eq major-mode 'dired-mode)
(dired-get-marked-files)
(let ((default-directory (read-directory-name "dir: ")))
(mapcar #'expand-file-name
(file-expand-wildcards "*.org"))))))
(mapc
(lambda (f)
(with-current-buffer
(find-file-noselect f)
(org-latex-export-to-pdf)))
files)))
How can I edit Google Drive text documents using Emacs and mirror my changes back to the Google Doc?
I found a Google command line program, as well as something called gclient, which is part of Emacsspeak, but they seem to require Linux or Windows, and I'm on OSX using Aquamacs. Or maybe I just don't understand how to install them.
Is this doable?
googlecl can be installed from macports. You can then open files with local emacs using emacs server.
Once it is installed, you can follow these commands:
$ google docs list # gets a list of the files
$ google docs get <FILE> /tmp/edit$$.txt # gets the <FILE> to /tmp/edit$$.tmp
$ emacsclient /tmp/edit$$.tmp
$ google docs upload /tmp/edit$$.tmp <FILE>
However, I've found that google docs get doesn't work as well as it should.
There is no need to Fetch, Edit(emacs), and Push the file back.
First install "Google Drive" on your mac.
Then you can edit the file directly. Look under ~/Google\ Drive.
Another option using gdrive (requires helm for completion)
(defvar gdocs-folder-id "<gdrive folder for exported docs>"
"location for storing org to gdocs exported files, use 'gdrive list -t <foldername>' to find the id")
(defun gdoc-export-buffer ()
"Export current buffer as google doc to folder irentified by gdocs-folder-id"
(interactive)
(shell-command
(format "gdrive upload --convert --mimetype text/plain --parent %s --file %s"
gdocs-folder-id buffer-file-name)))
(defun gdoc-import-buffer (doc)
"Import a file in gdocs-folder-id into current buffer"
(interactive
(list
(completing-read "Choose one: "
(split-string
(shell-command-to-string
(format "gdrive list -q \"'%s' in parents\"" gdocs-folder-id)) "\n"))))
(insert (replace-regexp-in-string (string ?\C-m) (string ?\C-j) (shell-command-to-string
(format "gdrive download -s --format txt --id %s" (car (split-string doc " ")))))))
It all seems to work if you open from a terminal, e.g.:
open -a emacs "Google Drive/My Drive/path/to/file.txt"
Saving the file works, but you can't open a new file once you're in emacs, and Google Drive seems to get confused if you try to create a new file from within emacs.