Current File and Directory in Emacs and Z Shell

My work environment is the command line (Z shell) and Emacs, bouncing back and forth between the two. The minor, but frequent, annoyance is when I am working on a file (or directory) in one, and need to do something on it in the other, and need to “manually” copy or type the file name between the environments.

This happened moments ago, when I was editing code for Cabin Notebook, and wanted to look at the current Git diff of the file. (Yes, I know I could do that exclusively in Emacs with the vc- functions, but my command line habits are deeply ingrained, and I like seeing the two side by side.)

So I was looking at the file in Emacs, and would have done what I always have, to just type out the name on the command line, probably the 24,000th time that I’ve done that.

I already had a Z shell function, cde, that changes to the directory of the current file in Emacs, with the code:

cde () {
   cd ${(Q)~$(emacsclient -e '(with-current-buffer
                              (window-buffer (selected-window))
                              default-directory) ')}

So that’s the basis of what I wrote. The first function displays the name of the current file (buffer) in Emacs:

ecf() {
    echo ${(Q)~$(emacsclient -e '(with-current-buffer 
                                  (window-buffer (selected-window))
                                  buffer-file-name) ')}

And the function that echoes the directory of the current buffer (yes, this could just be dirname `ecf`, but the below keeps in as all Emacs Lisp code):

ecd() {
    echo ${(Q)~$(emacsclient -e '(with-current-buffer
                                  (window-buffer (selected-window))
                                  default-directory) ')}

So now cde is just:

cde () {
    cd `ecd`

So there you have it, some tighter integration between the almighty Emacs and Z shell. More Z shell blithering of mine can be found here.

Opening All Files in a Git Commit

Sometimes even Linux crashes, or a machine loses power, in which case applications lose their history.

This has been an annoyance for me with Emacs and a project that I’m working on that is version controlled with Git, or perhaps I just want to open all of the files in a commit so that they are the most recent in my list of open files in Emacs.

Finally I’ve devised a one line solution, as is noted below.

The first step is to get a list of files from the most recent Git commit, with the output being only the file names — no commit message, author, committer, etc.. Easy enough, where --pretty=format: means “write no commit summary output”:

% git log --git log --name-only --pretty=format: -1

This will be fed into the command to open a file in Emacs, which in my case is function named ec. This is Z shell, but should work for Bash.

ec () {
    for i in $*
        emacsclient --no-wait $i

Why a function and not an alias? Because evidently emacsclient only takes one file name as an argument, so it needs to be called once for each file.

Since ec is a function (and the same restriction applies to aliases as well), it cannot be a command executed by xargs, which would have been:

% git log --name-only --pretty=format: -1 | xargs ec

which produces the message “xargs: ec: No such file or directory”.

The fix is to read each line into a variable, then run the function against it. Voila:

% git log --name-only --pretty=format: -1 | while read -r i; do ec $i; done

More of my Z shell blatherings are over here.

Emacs Find of the Day: Repeating Commands

One thing that I love about Emacs is that even after 20 years, I’m finding new (old, in actuality) functionality that makes my life better.

Today’s example is repeat-complex-command, which is normally bound to ctrl-x ESC ESC, as noted on the emacs wiki. The problem in my world is that I’m also using CUA mode, from the ergoemacs library, which redefines ctrl-x to do cuts (as in cut, copy, paste).

Normally that doesn’t cause an issue, since if you don’t have a region marked, then ctrl-x is apparently ignored by ergoemacs and is delegated to the default behavior, in which case ctrl-x ESC ESC brings up the previous command in the echo area, ready to be edited.

However, what has arisen as a nuisance in my experience is when I’ve done a search and replace in one region, then want to do a similar but not identical search and replace in a different region, such as renaming variables in two methods.

Normally I’d mark the first method, run search and replace (query-replace or query-replace-regexp), then go to the second method and mark it. At that point I’d like to bring up the previous search-and-replace and modify the command, but when I hit ctrl-x, the currently-marked region (the second method in this example) is cut, per behavior from ergoemacs.

The fix is to map a different key, in my case alt-j alt-j (the mnemonic being that the keys repeat) mapped to repeat-complex-command, per this snippet from my .emacs file(s):

(define-key global-map (kbd "M-j") jep:keymap)
(define-key global-map (kbd "C-j") jep:keymap)

;; CUA settings muck up ctrl-x, so use an alternative, alt-j alt-j:
(define-key jep:keymap (kbd "M-j") 'repeat-complex-command)

Yes, I map both alt-j and ctrl-j as equivalent keys that define my keymap, making it simpler when I have shortcuts that are prefixed with alt- and ctrl-. So alt-j alt-j flows better, as does ctrl-j ctrl-l (which inserts logging statements, if you’re wondering).

All of this is available at my github repository.

But wait — there’s more: the second nugget of the day is that after running repeat-complex-command, the echo area will display the previous command, of course. But then running alt-p will bring up the command prior to that, and alt-p the command prior to that one, etc. On the other hand, and in the opposite direction, alt-n moves forward through the list of commands.

I hope this helps, and I plan to post more about Emacs and what I find therein.

Emacs and colors being reset

I ran into this today, and couldn’t find a quick answer online.

I was updating yasnippet to the current release, and there was an error on startup about dropdown-list.el not be able to be found. That resulted in Emacs aborting the startup process before it reached the settings in my .emacs file that define the color settings.

So Emacs initialized with the default colors (dark on light), whereas my custom settings are light on dark. When I then exited Emacs, it saved the .emacs.desktop file, which I’d thought was just the list of files. However, it also contains the color settings, so after I’d worked around the yasnippet issue, and started Emacs again, it used the default color settings (from the loaded ~/.emacs.desktop file) instead of mine in .emacs.

The fix was to remove the line that begins with “(setq desktop-saved-frameset”, exit Emacs and start it again, in which case the color settings will be loaded from ~/.emacs instead. The next time Emacs is exited (or just desktop-save is run), then the color line in ~/.emacs.desktop will be updated.

This is probably quite an edge case, but I thought perhaps others might run into this issue. I hope this helps.

How much is (was) a Coke worth?

There is the classic experiment done with young children, making them choose between eating one marshmallow now, or having two if they wait 15 minutes.

A conversation last night reminded me of that.

In our conversation, I mentioned owning $3000 worth of Coca-Cola stock when I was 18, having inherited it from a relative. I recall selling the stock shortly after getting it, but I cannot recall what I spent the money on.

So we did a bit of calculation, and determined that if I’d held onto that stock from 1984 until present, it would now be worth over $240,000.

To see the concept of financial delayed gratification quantified, as above, is instructive and humbling.

Downgrading Subversion from 1.9.3 to 1.8.13, Ubuntu 16.04

I needed to run tests and fix an issue with Subversion 1.8, and on my recently-updated machine running Ubuntu 16.04 (Xenial), Subversion was installed as 1.9.3, which was the only version in the xenial repository.

So, a quick post of what I did, since googling produced no clear answer.

Download the 1.8.13 .deb files for subversion and libsvn1.

Install the latest from xenial repository (probably no changes, if you have Svn 1.9.3 installed):

% sudo apt-get install libapr1 libaprutil1 libsvn1

Remove libsvn1, because it is 1.9.3:

% sudo apt-get remove libsvn1

Remove (uninstall) Svn 1.9.3

% sudo apt-get remove subversion

Install downloaded packages “manually”

% sudo dpkg -i ./subversion_1.8.13-1ubuntu3_amd64.deb ./libsvn1_1.8.13-1ubuntu3_amd64.deb

Check version (should be 1.8.13):

% svn --version

Check the package:

% dpkg -l | grep subversion

And that’s it.

How to Order at a Restaurant

I recently went on a solo road trip (2700 miles), so I was able to practice ordering in a variety of new restaurants.

First, if you’re out, go to places other than what you’re used to. On my trip I avoided all chains (with the lone exception of Culver’s, which we don’t have in my area), so nearly all of the menus were new to me.

There are a few options when ordering. One is to order the dish you are not crazy about, i.e., that is something you might like. And if it’s a dish that that restaurant specializes in, go for it. Like many people, I generally dislike liver and onions, but one of the most memorable dishes I’ve ever had was exactly that, at a place renowned for it.

Try not to order what you make at home, or what you usually get. A million places make hamburgers (and I’ll humbly submit, mine are better than nearly all of them). So no burgers. No spaghetti. No meatloaf, etc. Try oysters, shrimp, and scallops (especially if you’re near the sea, or near a place where they get frequent shipments, i.e., a transportation hub).

The best is to ask the waiter/waitress, and don’t ask “what do you recommend?” First, from what I know of the restaurant business, they often are supposed to recommend certain dishes, often what is selling slowly or which for they have excessive ingredients.

It is recommended that with a doctor don’t ask “What do you think I should do?”. Instead ask “What would you do?” Similarly, ask the wait staff what they like most on the menu, which is different than asking “What do you [i.e., your manager] think I should eat?”

That is also a good approach when going to ethnic restaurants, to avoid being steered toward food that they think people of your (different) ethnicity would like. (I had a bit of an argument with a waitress in a Chinese restaurant, when I ordered pork bellies with Chinese spinach, from the “Chinese” section of the menu, and she tried to dissuade me, insisting on the kung pao chicken, which ironically was the first dish I ever had in a Chinese restaurant, many years earlier. And I quite liked the pork bellies, to her surprise.)

Another of my techniques is the three-finger selection. I splay my hand and drop it onto the menu, and I have to order one of the three dishes my fingers are pointing to.

I also recommend learning your wait staff’s names, and using them. I haven’t worked in that industry, but I’ve read and heard that it is exhausting and literally thankless. Being more personal with them is a great way to connect and converse, and I’ll selfishly admit that it has personal benefits: at an excellent meal on my trip, I talked at length with both the manager and the bartender. On my final bill, they comped me for one beer (Kwak, my favorite beer, and on tap), and dessert (pecan pie made with Gulden Draak, another of my favorite beers).

When eating out, it should be an adventure. After all, that’s one of the main reasons to go out, right?

Fakir 0.0.1 released

The initial version of Fakir has been released.

This gem is somewhat small, but contains some functionality that I’ve needed in various projects, such as getting a random element from an array (thus Fakir::Array#rand), and getting non-repeating random numbers, i.e. where [1, 1, 1, 2, 2] is actually random, but doesn’t look random, in the same way that [heads, heads, tails, tails] looks less random than [heads, tails, tails, heads].

Fakir::Random#rand goes even beyond that, with support for a “window” in which a number will not be repeated. Thus with a window of 3, a number will not be repeated within 3 invocations of rand.

This gem was developed for seeding Cabin Notebook, and I hope it’s of beneficial use for others.