Content AND Presentation

2018-08-18 Embedding files in Org-mode revisited

Some time ago I published a snippet of Elisp code to embed arbitrary files in Org-mode files using Base64 encoding. I was recently asked if it was possible to view this image.

Well, this being Emacs, of course it’s possible. The question is, how exactly. One way would be to call xdg-open (or equivalent) right after decoding the file to somewhere in the filesystem. (The file must be Base64-decoded, at least to some temporary directory, for any external program to do anything with it.) While I didn’t check it, I heard that the openwith mode might help with this.

Another possibility is to embed links to the files in the Org-mode file itself. This has the advantage of not having to run an external program and the disadvantage that it won’t “show” audio or video in the same way as images.

Anyway, here’s an updated version that inserts a link to the file you have just inserted. In the previous version, you had to change the filename manually; here, I decided to do this automatically (I just strip the path so that the file becomes local to the current directory).

(defun org-insert-file (filename)
      "Insert Elisp code block recreating FILE in the current
directory."
      (interactive "f")
      (let ((basename (file-name-nondirectory filename))
	    (base64-string
	     (with-temp-buffer
	       (insert-file-contents-literally filename)
	       (base64-encode-region (point-min) (point-max))
	       (buffer-string))))
	(save-excursion
	  (insert (format "[[./%s]]\n#+BEGIN_SRC emacs-lisp :results output silent\n  (with-temp-file %S\n    (insert (base64-decode-string\n      %S)))\n#+END_SRC" basename basename base64-string)))
	(forward-line)
	(copy-file filename basename 1)
	(org-display-inline-images)))

Notice a few things about this code. First of all, we use the file-name-nondirectory function, which strips the directory part from the filename. The forward-line is a nicety so that the point won’t end up invisible on the image. In order to copy the file to the current directory, we use the copy-file function with a third argument being any integer (this means that we allow overwriting a file, but request an explicit user confirmation for that). Finally, we turn on displaying inline images (which won’t do much good if the file is not an image – but in that case, we will just have a link, hopefully one that can be opened with C-c C-o).

CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryOrgMode

Comments on this page

2018-08-13 A tip on git stash

I don’t know about you, but I use git stash fairly often. (This might be just a bad habit, and committing might be a better idea, but I do find stashing useful, especially for minor changes I’d like to apply from time to time on different branches but never commit. Yes, console.log and friends, I’m looking at you, but also at turning on various “debug” variables.)

After some time, git stash list begins to look like this:

stash@{0}: On master: zzz
stash@{1}: On some_branch: change something
stash@{2}: On some_other_branch: zzz
stash@{3}: On some_other_branch: abandoned wip
stash@{4}: On some_other_branch: zzzzzzz
stash@{5}: On some_other_branch: zzz
stash@{6}: On some_other_branch: wip
stash@{7}: On yet_another_branch: zzz
stash@{8}: On and_another: zzz
stash@{9}: On develop: improve (?) watching
stash@{10}: On and_one_more: left outer join experiment (to delete)
stash@{11}: On and_more: to_delete
stash@{12}: On dont_you_have_enough: wip2
stash@{13}: On dont_you_have_enough: wip
stash@{14}: On no_i_dont: to_delete
stash@{15}: On this_starts_to_get_boring: to_delete
stash@{16}: On develop: zzz
stash@{17}: On but_who_cares: d3
stash@{18}: On master: zzz
...

Please don’t laugh at me too hard – I know this is terrible (and 100% real – I changed the names, of course, and actually made the list shorter (!), but it’s really what I have.)

It would be probably easier to decide which stashes can be safely dropped if you could list their timestamps instead of numbers.

But hey, this is Git, and that should be possible, no?

The git-stash manual entry says under git stash list:
The command takes options applicable to the git log command to control what is shown and how. See git-log(1).
And if you look at git-log manpage, you will find the --date=<format> option.

So, why don’t we try git stash list --date=iso?

stash@{2018-08-09 11:03:21 +0200}: On master: zzz
stash@{2018-07-27 10:55:35 +0200}: On some_branch: change something
stash@{2018-07-19 16:26:11 +0200}: On some_other_branch: zzz
...

Or how about git stash list --date=relative?

stash@{4 days ago}: On master: zzz
stash@{2 weeks ago}: On some_branch: change something
stash@{4 weeks ago}: On some_other_branch: zzz
...

Other interesting options include short (only date, not the time), format:... (almost anything that strftime can parse) and local. See the manpage of git-log for the details.

Actually, if you have some spare time, reading through git-stash manpage is a thrilling experience. For instance, the way stashes are kept is a clever trick, and I can’t yet decide whether it’s a compliment or otherwise…

CategoryEnglish, CategoryBlog, CategoryGit

Comments on this page

2018-08-06 Editing past Git commits

Everybody and their mother are now writing Git tutorials of various kinds, so I decided to jump on the bandwagon and do my own just like the thousands that already exist.

Just kidding. My one will be different.

Joking aside, I really could not find a decent, step-by-step tutorial for the situation I was in today: I wanted to use rebase --interactive to actually edit (not just reword) several past commits. So this is a kind of reminder for myself (even if very simple), and I suppose it might be useful for someone else, too.

Let us start with this.

cd /tmp
rm -rf rebase-edit-tutorial	# in case you run this again
git init rebase-edit-tutorial
cd rebase-edit-tutorial
echo 'Initial commit' > file.txt
git add file.txt
git commit -m 'Zeroth commit'

echo -e 'Atfer\nthe first commit.' > file.txt
git add file.txt
git commit -m 'First commit'

echo -e 'After\nteh second\ncommit.' >> file.txt
git add file.txt
git commit -m 'Second commit'

echo -e 'After\nthe third and last\ncommit.' >> file.txt
git add file.txt
git commit -m 'Third commit'

Running the above script will create a fake Git repo in the current directory, with three stupidly simple and meaningless commits. (Note that I included a “zeroth commit” – a parentless one – since I will want to start rebasing from the “First commit”. Rebasing from the root commit is possible with the --root option, but that would be an exceptional situation.)

Let’s now assume that we want to fix both typos introduced in the first and the second commit. (Can you spot them?) Here is a step-by-step recipe.

We start at the “First commit”. You have to give git rebase -i the last commit you don’t want to modify. (Yes, Git is weird.)

git rebase -i HEAD^^^

Next, we edit the list of commits so that the first two lines say edit instead of pick. We save the list and exit the editor.

Saying git status will give some information about what is happening right now. Saying cat file.txt will confirm where we are. Go on, try these things, I’ll wait. (In fact, it is a good idea to do git status after every command presented here to see what is going on.)

Good, you’re back. Now fix the typo and say

git add file.txt
git commit --amend -m 'First commit'
git rebase --continue

Notice how we used git commit --amend.

Let’s now fix the second commit in the editor and say

git add file.txt
git commit --amend -m 'Second commit'
git rebase --continue

Boom, done! Of course, as every tutorial will tell you, don’t do that if you already pushed your changes to some server, blah, blah – you already know it.

Now what many other tutorials don’t tell you is what happens if you forget to say --amend. The answer is simple: you will introduce new commits, right after the ones marked for editing.

Also, things might get a little more hairy if you fix stuff in the same place, or introduce editing conflicts – but that will have to wait for another time.

CategoryEnglish, CategoryBlog, CategoryGit

Comments on this page

More...

CategoryEnglish, CategoryBlog