Disclaimer: If you are thinking I would be talking about sorting algorithms, then, well, sorry. This is about my experience trying to get the Dired Mode in emacs to sort files in a particular directory according to time, while keeping the default sorting by name intact. Emacs knowledge may be needed to understand/appreciate this, possibly some elisp knowledge too.
I use dired-sort-map.el in my init file, which allows me to sort the dired buffer by name, time, extension or size. This works pretty well. The default way to show files is by name. I am fine with that, except, I want the files in my Downloads folder to be listed by time(date modified). To do this manually is pretty easy. All I need to do is press two keys and voila dired-sort-map will do that. But I was not satisfied with that. I wanted it to happen automatically, after all I was making emacs do all sorts of things, why not this.
So I start out searching for ways to do this. I knew the rough steps involved.
- Get the function that dired-sort-map uses to sort by time.
- Make a function that will check if I am opening the Downloads folder and call function from step 1.
- Add a hook to dired mode for function from step 2.
That’s it. Three steps and I am pretty much done. Simple right? Well, the first one is the simplest, I can get that directly off emacs’ help. The third step involves writing just a single statement.
So, now for the second step. Now here it is immediately clear that I need to work with conditionals. Alas! I don’t know elisp, I had hoped that I would find code which does what I want done but soon I understand there is not going to be anything that will do something so specific. Which means I am soon learning lisp if conditions. Here I should probably mention that I have coded a little in C, Java, Python and Haskell by now, all of which have very intuitive syntax most of the time. Nowhere have I seen syntax the way lisp does it. Everything comes within parentheses. Also, every function name comes first. So you first write ‘equal’ and then you write the left and right operands. Weird. Or probably just lack of familiarity. After about half an hour I have the syntax for the if conditions that I will be using.
Now I need to figure out what conditions to use. My idea is to check if the mode is Dired mode and then check if the buffer is the Downloads buffer and if both these conditions are met then I’ll call the function from step 1, the one that sorts by time. New problem! I don’t know how to use multiple conditions, but, I should have guessed it. With lisp’s love of parentheses and function names at the start I should’ve guessed that the syntax would be
(and condtition1 condition2). So here I am equipped with my knowledge of ‘and’ and of ‘eq’ hoping to do something.
It takes a long time to figure out how to find the mode of a buffer. I see a lot of things being suggested but none of them seem to work in the condition. Not a single one of them gives the correct boolean when put inside eq’s parentheses(I didn’t have the guts to try equal, eql, equalp, tree-equal and string-equal). Similarly it takes a long time to get anything that will give me the name of the buffer. Soon I wonder if I am comparing things that are of different types. I learn how to find the type of something and then when I check I see that I am correct. I have been trying to compare strings and symbols(I still don’t know what that is!) The search starts again and when I have almost given up hope and am roaming around aimlessly(from stackoverflow to emacswiki and back) I stumble upon something that perfectly checks if the mode is dired mode.
If I hadn’t made that discovery I would’ve probably given up. I then renewed my efforts trying to find a way to check if it is the Downloads folder that is open. I forgot to mention that by this time I had lost all my work twice owing to not bothering to save them. Now working on a constantly-being-saved file, I keep searching and searching. This part takes a long long time. I learn a lot of things that help me in no way in this problem but finally I get something useful. This something comes from a wiki that explains how to kill many buffers of all places! I see a list being used to check if a buffer needs to be kept/removed. Much like invitation only parties. This something doesn’t work at first. I tweak around for some time and it finally works. Lists at last gave me what I wanted.
So, I am halfway through, somewhere just before the “debugging” part. I have got things hooked up(Yeah, a pun. Took me ages to find the correct dired hook to use(There are four!), so I am entitled one pun.(This is what lisp code looks like by the way, parentheses nesting and more parentheses(Although this doesn’t have enough parentheses to be a fair comparison))) Around this time I figure out that my code won’t work properly if there are two dired buffers named “Downloads”. There goes the work of hours down the drain. It won’t have been worth anything if I can’t get this thing to work perfectly now. I think of how I can get this working again and after some time I get the idea of using the directory’s full name.
Finding a way to get the name of the directory was all a blur. Going through Dired mode’s full help points me to one or two good candidates. Then I try to get one of them working. Unfortunately I start getting errors. I have now entered the “debugging” part of the curve. I get errors that make me think that infinite loops are happening somewhere, but I am not even using loops(I don’t know how to!(Parentheses!!(Okay, I have seen too much lisp)))!
Then I read the scant documentation of the four hooks in dired mode thinking that the problem lies somewhere in the hooking but gain no knowledge from there. I can’t figure out which one to use, so I try all of them. One of them starts giving me a subdirs-alist not found error. This particular error wrecked havoc in every dired buffer. It was so bad that I had to reopen emacs without the init file and then go and change the init file and restart emacs to get back on my feet. I try configuration after configuration and can’t get anything to work except the faulty code that used the buffer’s name instead of the whole directory.
After a long time I somehow find that the condition isn’t ever coming true. There is no problem with any hook. The condition was never evaluating to true. Somewhere around here I figure out that since I am hooking this, this function call only happens in Dired mode, so I don’t need to check if the mode is dired! Well, I did find out how to search and find stuff and copy-paste it. Unable to debug the other problem I change the whole condition. Instead of the faulty function call that I was making I find a variable which gives the same value as I was getting and compare against that. Finally it works! After roughly half a day of coding and learning and a lot of debugging I get it to work. It works flawlessly now, no lag, no errors, no warnings. I don’t even have to think about Downloads being time sorted or name sorted. I automated it.
Somewhere between changing from buffer name to the directory name I decided why not try to make such a thing for other sorting options too. A list of directories that would be sorted differently than the default. I am now thinking about how to get all of this into a single function and a very small thing. Basically riding the “ongoing development” part of the curve.
So, what did I get by spending a day trying to automate something that didn’t even take a full second to do. Was it worth all that time? Yes. Because I learnt. I learnt conditions, lists, hooks and a lot more. I learnt a truckload of stuff about lisp(elisp, rather). All this code stuff apart(which I doubt I’ll remember for long)I also learnt how to keep my calm when nothing was working, which in retrospection has been all the codes I ever did. More important than all the knowledge that I got out of this was the epiphany that I can make the computer behave the way I want it to behave. Things aren’t impossible, all it takes is to figure out how to commnad so that the computer obeys. It is a feeling unlike any other when you work for a full day trying to get a tiny thing correct and then finally reaching shore.
I titled this lessons trying to sort, but I am afraid I don’t have many lessons to talk of. All I can say is that it will always be worth it if you pick something up. Even if the effort doesn’t teach you anything(highly unlikely) you still would have the satisfaction of having done something that you wanted to do. There is no greater bliss.
PS: All images are from xkcd. He is awesome. When there is a site that tries to explain your site it’s a pretty good indicator of greatness. So here is one of my favorite cartoons by xkcd which relates to the post in some ways.