As you may know, lately I’ve been trying to get used to using emacs. This has been going well, but there are some things I find myself missing from my old editors. One of them is the files list on the left side:
Sure, I can use dired, Speedbar, or any number of other solutions. But none of these work exactly like my old file browser. In despair, I got used to the
C-x C-f Do [tab] c [tab] [tab] d [tab] p [tab] [tab] ... workflow that autocompletion brings us. However, it never quite settled with me.
Lately, I’ve found myself using org-mode in a way that has been quieting the proverbial fire. I’ve been able to use org-mode as a project browser, let me show you how!
As you may know, org-mode is kind of a catch-all tool for organizing, note taking, and keeping todo lists. You can create hierarchical trees of headings. Hierarchical trees… Sound like anything we know?
I’ve been trying to use org-mode primarily as a TODO list to keep track of all the stuff I have going on. For projects that I’m working on, I’ve been creating TODO lists for the various source files I’m writing. A few links later, and we have the beginning of a project browser.
* TODO programming project
One of the nice things about tracking your own project is that you can decide what the tree looks like. An embedded project might group C and assembly source files separately, where a Haskell project might group source files by module nesting level.
Let’s talk C. We can create a
project.org file in the root of our project directory (where the Makefile is). Next, let’s create some headers:
* C * ASM * Unit Tests * Misc
Here, I’ve created 4 groups. C source goes in the C group, Assembly source goes in ASM, Unit test source files go in Unit Tests, and miscellaneous stuff like Makefiles, .gitignores, and READMEs go in Misc.
Next, let’s add some source files:
* C ** [[./main.c]] * ASM * Unit Tests * Misc
Here, I’ve added a link to
main.c to the C group. At this point, this file doesn’t exist. If you click on
main.c with org-mode enabled, the file will be opened in emacs, creating it if doesn’t exist! Sure, it’s manual, but I find it is not hard to keep up. If you commit your
project.org to your version control system, all members of the project can keep it updated and in sync.
However, what the manual updating buys you is the freedom to organize it how you like! We can add tasks to the tree:
* C ** [[./main.c]] *** TODO implement main *** TODO file header *** TODO add to git * ASM * Unit Tests * Misc
We can add deadlines:
*C ** [[./main.c]] *** TODO implement main DEADLINE: <2015-02-13 Fri> *** TODO file header *** TODO add to git * ASM * Unit Tests * Misc
We can add commentary:
* C ** [[./main.c]] *** TODO implement main DEADLINE: <2015-02-13 Fri> - I tried to implement main, but printf is such a hard function to use! I'll revisit this after I've had four beers... *** TODO file header *** TODO add to git * ASM * Unit Tests * Misc
…and this can lead to more tasks!
* C ** [[./main.c]] *** TODO implement main DEADLINE: <2015-02-13 Fri> - I tried to implement main, but printf is such a hard function to use! I'll revisit this after I've had four beers... **** TODO drink four beers *** TODO file header *** TODO add to git * ASM * Unit Tests * Misc
Let’s see your silly little file browser window do that!
No more. This ends now. This will not stand!
What’s my problem, you ask? I’ll tell you what. Emacs’ stupid undo system is my problem. Humor me for a second; fire up Emacs, and type the following:
foo bar baz
Still with me? Good, now press
…baz disappeared. “Well, duh! If you’re gonna whine about the fact that C-u doesn’t undo, then maybe you shouldn’t be using Emacs…” you say. Were that my issue, I’d be inclined to agree. Unfortunately, the problem is much worse. Enter the following into your buffer:
C-x u C-x u
See that? Yeah… Not OK. The buffer should be:
with the entry of
bar having been undone. Instead, the buffer is:
foo bar baz
with the entry of
oof and the undoing of the undoing of the entry of
baz having been undone.
Apparently, an undo operation itself goes onto the undo stack in Emacs. Meaning that if you undo enough times, it will redo all the undone operations, then undo them again, then undo the operations before. This lets us get the buffer back into any state it has ever been in, which sounds nice on paper. In practice, it’s yet another way that Emacs goes its own way, the rest of the world be darned. And I gotta say, its pretty annoying. In a normal program, you can just hold
Ctrl+u, and watch the undoes fly. In Emacs, you get to press
C-x, release, press
u, and release to undo one thing. Then do it again
Luckily for us, this being Emacs, there is likely a better way out there.
Undo tree mode is a minor mode for Emacs that helps us deal with this undo behavior. In the short amount of time that I’ve played with it, I’d say it makes the on-paper benefit of Emacs’ undo behavior a reality. But first, some installation.
Undo-tree-mode is in Melpa stable, however, I was unable to get it to work. To install undo-tree-mode, you can install it via Melpa, then add the following to your
Unfortunately, when I restarted Emacs, I got the following error:
Symbol's function definition is void: global-undo-tree-mode
does nothing to alleviate this situation, neither does opening
undo-tree.el and entering:
However, I was able to install it manually. First, I deleted all the files for undo-tree-mode from my
.emacs.d/ directory. Then I downloaded the current version of the plugin from the author's website, and placed it in my
~/.emacs.d/, naming it
undo-tree.el. Finally, I added the following lines to my
(add-to-list 'load-path "~/.emacs.d/") (require 'undo-tree) (global-undo-tree-mode t)
That first line is only required if you haven’t already added it elsewhere. Restart Emacs, and you should see that the
Undo-Tree minor mode is active.
Climbing The Tree
Now, let’s try that previous sequence of events.
foo bar baz C-x u
A new window should appear with the following in it:
s | | o | | o | | o | | o | | x
Neat. This represents the operations that you did. Try clicking through them (you can also use the arrow keys to browse). Each node is a state of the document,
x is the current state, and
s is the initial state. Select the node two nodes up from the leaf to undo entry of
baz. Lets continue our sequence:
oof C-x u
You should see a new tree that looks something like this:
s | | o | | o | | o | | o | / \ x o | | o
If you click around the tree, you’ll see the various states of your buffer. You’ll see that it is simple to restore any previous state of the buffer.
Now this is something I can get used to!
Deep in the depths of the DMP Lunar Bunker, I have a file server running. I prefer to do my computing on various internet connected devices rather than be tied to one computer. To this end, I try to keep my documents, images, and things of that nature centralized on the server so that I can get to it anywhere. This is all fine and good on a computer, but my iPad and various smartphones don’t have native support for mounting a smb share.
To that end, a project that I’ve had planned for a long time is to develop a web app running on my server to serve that stuff up through a web browser. That said, this post isn’t announcing the beginning of that project. I have enough on my plate: DMP Photo Booth still needs polish, I want to learn Haskell, I have a wedding to plan, and I have to spend this month figuring out what “Linear Algebra” is. Not to mention that the file server is in need of a software refresh. All of those things are higher priority. That said, as an excercise in learning Haskell, I’ve created a toy HTML generator.
That would be the name of my little suite of functions. I feel its name reflects the gravity of the project. All that it really is is a few types, and customized show instances. First, let’s take a look at my types:
type TagName = String type Attributes = [(String, String)] data Child = NullChild | TagChild Tag | StringChild String data Tag = NullTag | Tag TagName Attributes [Child]
First of all, forgive my sloppy indentation style. I haven’t really settled on a code style for Haskell yet. With that out of the way, let’s get to business.
This is just a type alias for a String. The concept of a math function is one that I understand, but I’ve always hated the trend of giving things useless names like
Σ instead of names like
Summation over. Sure, it was good enough for Aristotle, but I live in an age with things like “find and replace” and “code completion”. Maybe thousands of years from now, scholars will remember Chris Tetreault, father of the descriptive variable name. (HA!)
But I digress. I’ve created this alias to document when a String in a function argument or type constructor is a tag name.
This is a type alias for an array of String pairs. This type represents the attributes list of a Tag. Things like
src="https://doingmyprogramming.com/" It’s pretty self-explanatory. An empty list is an allowed value, and represents a tag with no attributes.
Now we’re getting a bit more complicated. If you picture a HTML document as a tree, then the child is the branches from the top level tag. There are three types of Child:
NullChild is the absence of a tag,
TagChild is a nested Tag,
StringChild is just some free floating text.
And now the meat of it.
Tag has two type constructors:
NullTag which is the absence of a tag, or
Tag takes 3 arguments: a
Attributes, and a list of
Child. This is all you really need to represent a basic HTML document. (no embedded CSS)
None of these types have
deriving(Show), because they require a custom implementation. Let’s look at that next.
First, let’s take a look at
Tag‘s Show implementation:
instance Show Tag where show NullTag = "" show (Tag n  ) = "<" ++ n ++ ">" show (Tag n a ) = "<" ++ n ++ flattenAttributes a ++ ">" show (Tag n  c) = show (Tag n  ) ++ foldl1 (++) (map show c) ++ "</" ++ n ++ ">" show (Tag n a c) = show (Tag n a ) ++ foldl1 (++) (map show c) ++ "</" ++ n ++ ">"
The show tag has 5 patterns:
- The first pattern is a
NullTag. It returns an empty string.
- The second pattern is a
Tagthat only has a
TagName. It places the
TagNamebetween angle brackets.
- The third pattern is one that also has an
Attributes. It flattens the
Attributes, and places it and the
TagNamebetween angle brackets
- The fourth pattern is one that has a
Childlist. It :
- Recursively calls
showwith the argument
(Tag n  ). This results in the opening tag being printed
Childlist, then folds the returned list of
Strings up using
foldl1 (++), concatenating all the returned
Strings into 1 large
- Closes the tag
- Recursively calls
- The fifth pattern has all fields. it works the same as the fourth, but calls the
show (Tag n a )instead.
The Show implementation for
Child is much simpler, and I don’t feel it requires explanation:
instance Show Child where show NullChild = "" show (TagChild x) = show x show (StringChild x) = x
But what about that
flattenAttributes function earlier? It looks like this:
flattenAttributes :: Attributes -> String flattenAttributes  =  flattenAttributes x = foldl (\acc (k,v) -> acc ++ " " ++ k ++ "=" ++ v) "" x
If given an Empty List, it returns an Empty List. In Haskell,
 is the same thing as
"", so this will function as an empty
String. However, if not given an empty string the work is much more complicated.
foldl is called.
foldl‘s function signature is:
(a -> b -> a) -> a -> [b] -> a, which reads as: “foldl takes a function that takes an a, b, and returns an a. It also takes an a, and a list of b, and it returns an a”. In english, it needs a starting value, a list to fold up, and a function to be called on each list element. I call
foldl on an empty string and
x, which is the
Attributes passed into the function.
The funky bit in the middle of all of that,
(\acc (k,v) -> acc ++ " " ++ k ++ "=" ++ v), is called a Lambda. If you’ve ever written an anonymous function in Java, you’ve done this before. The
\ at the beginning tells Haskell that what follows is a Lambda. After that, you have your arguments. Remember the signature of the function to be passed into
(a -> b ->a). In this lambda,
a, and this is a
b, a Tuple of two
Strings. The part following the
-> is the function body. In this lambda, we concatenate the two pairs together into the form of
" k=v". That is then concatenated onto
acc, which is the results of all previous calls. The final result looks something like
" k1=v1 k2=v2 ... kn=vn", which is returned from the function.
So, now that’s all done, and the
Tag type is usable. It’s not user friendly though:
Tag "html"  [TagChild $ Tag "head"  [TagChild $ Tag "title"  [StringChild $ "DMP"]], TagChild $ Tag "body"  [TagChild $ Tag "a" [("href","doingmyprogramming.com")] [StringChild "Doing My Programming..."]]] <html><head><title>DMP</title></head><body><a href=doingmyprogramming.com>Doing My Programming...</a></body></html>
Barf, right? It’s like writing HTML, only harder! Clearly we need some helper functions to make working with this easier.
tagHtml :: [Child] -> Tag tagHtml c = Tag "html"  c tagHead :: Attributes -> [Child] -> Tag tagHead a c = Tag "head" a c tagTitle :: String -> Tag tagTitle t = Tag "title"  [StringChild t] tagBody :: Attributes -> [Child] -> Tag tagBody a c = Tag "body" a c pageSkeleton :: String -> [Child] -> Tag pageSkeleton t b = tagHtml [TagChild $ tagHead  [TagChild $ tagTitle t], TagChild $ tagBody  b]
Here is some basic helpers I whipped up while writing this. These four helpers will take just the fields needed to produce their respective tags. Now, we can make a basic page skeleton by calling the
pageSkeleton "DMP" [TagChild $ Tag "a" [("href","http://doingmyprogramming.com")] [StringChild $ "Doing My Programming..."]] <html><head><title>DMP</title></head><body><a href=doingmyprogramming.com>Doing My Programming...</a></body></html>
While that could use some work, it’s enough to see where this is going. Much like Perl’s CGI module, functions can be created to automate much of the boilerplate.
Reinventing The Wheel
All this is fine and good, but surely this has been done already, right? Considering Haskell’s hackage server is implemented in Haskell, it seems that there is almost certainly a better web development framework for Haskell than doopHtml. I encourage you to not develop your next web application with the doopHtml framework, nor should you include your expertise in doopHtml on your resume.
It was good practice though!