Todo Lists
Saturday, January 22, 2011
It seems the thing to do these days is to write “a better todo list”. Probably there is at least one (maybe dozens) implemented in each programming language in existence. Factor even has its own todo web application.
When it comes to development, most developers keep lists of changes that need to be made or features that need to be implemented. Factor has its own todo list on the concatenative.org wiki. I know you are thinking what I’m thinking: wouldn’t it be great if we could keep the todo list alongside the code? In any event, it would make a nice demonstration of the vocabulary and help browser system.
metadata
First, some background. Every vocabulary supports various metadata associated with the code, including:
summary.txt |
a single line description of the vocabulary |
authors.txt |
a list of vocabulary authors |
resources.txt |
a list of files to include when deploying |
tags.txt |
a list of vocabulary tags used for organization |
platforms.txt |
a list of supported platforms if not cross-platform |
todo.txt
We are going to add to this a todo.txt
file containing a todo list of
improvements or additions that could be made to the vocabulary. The
format of the todo.txt
file will be a list of text, each on its own
line.
USING: arrays assocs formatting io io.pathnames kernel
sequences vocabs vocabs.loader vocabs.metadata ;
IN: todos
The path to the todo.txt
file is relative to the directory containing
the specified vocabulary:
: vocab-todo-path ( vocab -- string )
vocab-dir "todo.txt" append-path ;
We can get and set the list of todo items using vocab-file-contents and set-vocab-file-contents, respectively.
: vocab-todo ( vocab -- todos )
dup vocab-todo-path vocab-file-contents ;
: set-vocab-todo ( todos vocab -- )
dup vocab-todo-path set-vocab-file-contents ;
We could add new todo items at runtime:
: add-vocab-todo ( todo vocab -- )
[ vocab-todo swap suffix ] keep set-vocab-todo ;
Printing out the todo list for a specified vocabulary is pretty easy:
: todos. ( vocab -- )
vocab-todo [ print ] each ;
Using the child-vocabs word, we can look through a vocabulary hierarchy for all todo files, returning a map of vocabulary to non-empty list of todo items.
: all-todos ( vocab -- assoc )
child-vocabs [ dup vocab-todo 2array ] map
[ second empty? not ] filter ;
And then print them out from the Listener:
: all-todos. ( vocab -- )
all-todos [
[ "%s:\n" printf ] [ [ "- %s\n" printf ] each ] bi*
] assoc-each ;
Try It
Although we could make the todo.txt
files by hand, why not try using
Factor?
IN: scratchpad USE: tools.scaffold
IN: scratchpad "foo" scaffold-work
Creating scaffolding for P" resource:work/foo/foo.factor"
IN: scratchpad "foo.bar" scaffold-work
Creating scaffolding for P" resource:work/foo/bar/bar.factor"
Loading resource:work/foo/bar/bar.factor
IN: scratchpad "The first thing" "foo" add-vocab-todo
IN: scratchpad "The second thing" "foo" add-vocab-todo
IN: scratchpad "Another thing" "foo.bar" add-vocab-todo
IN: scratchpad "foo" todos.
The first thing
The second thing
IN: scratchpad "foo" all-todos.
foo:
- The first thing
- The second thing
foo.bar:
- Another thing
If you look in $FACTOR/work
, you will now find the foo/todo.txt
and
foo/bar/todo.txt
files that we just created.
help
We can use these words to make a dynamic help article containing all of the todo entries for loaded vocabularies:
USING: assocs help.markup help.syntax kernel todos ;
: $all-todos ( element -- )
drop "" all-todos [
[ $heading ] [ $list ] bi*
] assoc-each ;
ARTICLE: "vocab-todos" "Vocabulary todos"
{ $all-todos } ;
Once loaded, just run this to see the help article created by the previous example:
IN: scratchpad "vocab-todos" help
The code for this is on my GitHub.