Configuring projects in org mode, or defining variables in Lisp is strange
Org mode in GNU Emacs makes it somewhat easy to publish its files as a small static website. You define the files to publish, how to convert them, where to publish them, and so on. The bad news is that you need to manually write a big data structure in Emacs Lisp. Not what a Lisp newbie really wanted to hear (no customize page?) but I decided org mode was worth the pain. Speaking of pain, here's the data structure:
0: (set 1: (quote org-publish-project-alist) 2: ' 3: ( 4: ( 5: "tsn" 6: :base-directory "~/Documents/foog/tsn" 7: :base-extension "org" 8: :publishing-directory "/dev/null" 9: :publishing-function org-publish-org-to-html 10: ) 11: ) 12: )
All that work just to define a list of lists? I could just write it in Ruby as:
# pretend this function exists in Ruby
# def org_publish_to_html() end
org_publish_project_alist = [
[ "tsn",
:base_directory, "~/Documents/foog/tsn",
:base_extension, "org",
:publishing_directory, "~/Documents/foog/tsn_export",
:publishing_function, org_publish_to_html ]
];
The major difference is all this
And now, we plunge through the rabbit hole!
So, why call the
(symbolp 123) => nil ;; nil is false in Emacs Lisp (symbolp (quote 123)) => nil ;; 123 passes through... (symbolp (quote "abc")) => nil ;; abc passes through (symbolp (quote foo)) => t ;; but foo is a symbol.
Okay, so now we can distinguish between a value and a reference. The next step is assigning a value to a reference. This is where
(set foo 123) => Lisp error: (void-variable foo)
That silly Lisp interpreter, trying to get a value while we are in the middle of setting it. That's where
(set (quote foo) 123) => 123 ;; No one does this (set 'foo 456) => 456 ;; 'foo = (quote foo) (setq foo 789) => 789 ;; People do this one.
INTERMISSION
Now that variable assignment has been hashed out we can pick up speed a bit and finish this off:
- Line 1 specifies the symbol we want to use.
- Line 2 is just a macro for
, so the contents will be returned without being evaluated.(quote)
- Line 3 starts a list. To me this implies that the variable
will contain an array of ... well, not sure yet.org-publish-project-alist
- Line 4 starts a list. This list will be the first item in the list defined by
.org-publish-project-alist
- Line 5 is just a string. It is the first element in the list. Calling
on the list started at line 4 would return "tsn".(car)
- Line 6 contains the 2nd and 3rd items in the list.
is a keyword symbol (:base-directory). "~/Documents/foog/tsn" is the next element in the list.(symbolp :base-directory) => t
- Lines 7-9 define the remnant of the list started at line 4.
- The remaining lines are the obligatory closing parens.
Probably because I am very new to Lisp I don't understand why flat lists are used to store this data. Key value pairs are a great fit for hash maps or associative lists (the variable name ends with alist...). My first attempt to restructure the data would be:
(setq org-projects
'(
("tsn"
(:base-directory . "~/Documents/foog/tsn")
(:base-extension . "org")
(:publishing-directory . "~/Documents/foog/tsn_export")
(:publishing-function . org-publish-org-to-html))
("css"
(:base-directory . "~/Documents/foog/tsn/css")
(:base-extension . "css"))
("img"
(:base-directory . "~/Documents/foog/tsn/images")
(:base-extension . "jpg|png"))
))
The difference being that key value pairs are stored in an associative list. This lets you take advantage of built in functions for getting property values.
(mapcar
(lambda (elt)
(let
((project (car elt))
(properties (cdr elt)))
(print (format "Project %s has base extension %s"
project
(cdr (assoc :base-extension properties))))))
org-projects)
Output: ("Project tsn has base extension org" "Project css has base extension css" "Project img has base extension jpg|png")
Wow, look at all the rambling. At least now I understand how to manually configure org mode's projects.
Lisp is neat.
GNU’ve got to be kidding me — Makefiles?
It's very nerdy but several years ago I really enjoyed getting to learn and use GNU Make. It's best known for compiling and linking C and C++, but it really is a powerful general purpose tool. I'm trying to get back into it and decided to publish that refresher process. Jibe or jive as you will!
First, here is foo.cpp:
#include <iostream>
int main() {
std::cout << "Hello, world" << std::endl;
return 0;
}
And here is the Makefile to compile it, link it, and run it:
run: foo.cpp
g++ foo.cpp
./a.out
There are three concepts here.
-
-- this is the target, the goal, what you are trying to do.run
-
-- the dependencies of the goal.foo.cpp
-
andg++ foo.cpp. Look ma, shell commands! Nothing more, nothing less than the CLI environment many live and breathe../a.out
Just type 'make' and
will follow shortly. This is a pretty bad Makefile though for lots of reasons. Only having one step to compile, link, and run means compiling and linking will happen everytime the Makefile is processed. To fix that, give each stage its own rule:
run: a.out
./a.out
a.out: foo.o
g++ foo.o
foo.o: foo.cpp
g++ -c foo.cpp
Running, linking, and compiling from top to bottom. Make automatically tracks modification dates of dependencies. It will only execute shell commands for objects with modified dependencies. Here is the output from the first time I ran this Makefile.
g++ -c foo.cpp g++ foo.o ./a.out Hello, worldWithout changing foo.cpp I immediately ran make again. Here was the output:
./a.out Hello, worldSo that takes care of one glaring problem in the original Makefile. But I just created bar.cpp (it compiles, trust me) and I don't want to add a nearly duplicate rule. That would mean duplicating rules everytime I add a new source file, right?
Make solves that with a page from the Perl playbook; a little punctuation is good, and too much punctuation is awesome! This is perfectly clear, right?
a.out: %.o
g++ $^
%.o: %.cpp
g++ -c $<
'%' is a wildcard character, similar to '+' and '*' in traditional regular expressions. The others I pulled from the documentation on automatic variables, but they refer to the dependencies in the rule (things following the : character).
So how'd that go? FAIL.
make: *** No rule to make target %.o', needed bya.out'. Stop.
And this is where I remembered gmake has a healthy, happy family of different types of rules. Using '%' in the target of a rule makes it a pattern rule. But the rule for a.out is not a pattern rule, so it looked at %.o as a literal file name. What if I use
instead?
g++ -c bar.cpp
g++ .o
Undefined symbols:
"_main", referenced from:
start in crt1.10.5.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
make: ** [a.out] Error 1
Crap, it did what I said, not what I meant. I said match *.o, which becomes true as soon as one is created. What I wanted was to match ALL the .o files. No getting around that, but at least we can act a little more grown up and use <gasp>variables</gasp>.
SRCS = foo.cpp bar.cpp OBJS = foo.o bar.oAnd that works. But now we have another problem! Who wants to update the Makefile everytime a new cpp file is added?? Well, of course there is a solution for this. Half is strange and half is really cool:a.out: $(OBJS) g++ $^
SRCS = $(wildcard *.cpp) OBJS = $(SRCS:.cpp=.o)The strange half is calling a GNU Make function 'wildcard'. That just seems strangely difficult for something reasonably common. Anyways, the cool part was the syntactic sugar to create OBJS by replacing .cpp with .o from $SRCS.
That's about all the refresher I can handle for now. It should be enough to get me going... having done non-trivial cross-platform builds with gmake I know more is possible but I don't need it sitting here at home. At least I know great documentation will be ready when I need it.


