Posts tagged workflow
I tweaked my language-of-the day script. There is now a major language of the day (racket, elixir, haskell) and a minor language of the day (cl, chicken, clojure, erlang, ocaml). Each day gets a major language and a minor language; the major gets more emphasis.
How much more can vary depending on mood, but this way not only does something get done in each language each day, but the three I am most interested in get more emphasis each day.
It seems like a nice setup. I’ll have to play around with it more to see where the annoyances are. The other day, for instance, was a haskell day but I got damned little accomplished due to trying to get stack to work properly.
The yakshave in question: no matter how I changed $TMPDIR and $STACK_ROOT and such, stack kept trying to download its local ghc into ~/.stack on my internal drive then cartoonishly fail at attempting to stuff it into my limited (I’m on crouton) tmpfs instead of using a tmp folder on an external drive with 2TB of space. Symlinks, according to github issues tracking, apparently work fine after stack setup has done its thing, but that wasn’t the problem I was having. I eventually concluded that it’d require serious yakshaving with executability of external drives and such, and gave up for now. In the end, I got little actual haskell done due to spending so much time trying to get its environment working.
Here’s my global org todo keywords:
'((sequence "TODO(t)" "STARTED(s)"
"|" "DONE(d)" "CANCELLED(c)")))
I have a YAKSHAVE org status that I can apply to tasks. I can C-c c a yakshave note (“figure out how to get stack to actually use $TMPDIR” etc) and keep doing what I was doing. I can clock in and out of it as I work on something, and see how much time was spent actually doing a task versus getting things to work. At some point I’ll log this ratio of task to yakshave by language, over time, etc.
Deferred/Next refer to tasks for a specific language that I’ll pick up again the next time its language-of-the-day rolls around.
What I’m doing is banging out a bunch of todos after language-of-the-day. C-c a t 1 r and I can see all of them. I can start one, C-c C-t it to started, and then make subtasks for it.
;; Enforce dependencies
(setq org-enforce-todo-dependencies t)
This makes a todo depend on sub-tasks. You can’t switch a task to DONE until every TODO in it is done. Yakshaves aren’t subtasks, and thus survive after the task is done as a reminder. Afterwards, I can switch the yakshave to a TODO, clock in, and start messing with it.
While writing this I popped out a yakshave task to see how to convert org source blocks to scribble code blocks. Github pages renders org and md, but I don’t know if I can tell it “this is a markdown file with org syntax you should also follow.” Hm, I wonder if frog can be made to deal with org files. In keeping with my goal of minimizing yakshaving, I decided to just indent the above code snippets into generic markdown blocks and play with it later.
I then made a note to figure out how to display clock minutes as pomodoro units just by dividing them by 25. I don’t really use pomodoro (I prefer to measure effort in cigarettes. A full gentoo stage one install is 1 pack. Getting Frog up and running: 3 cigarettes.) But, seeing things as 25 minute chunks is just more useful than seeing the raw amount of time spent. Doing the same thing later and seeing the effort drop is more impressive when you can see whole pomodoro units drop off rather than “oh it took 20 minutes less on each of these parts.”
I made a shell script that plops out a random programming language from the list of ones I’m playing with. I called it language-of-the-day.
In the morning, I add an entry to orgfile.org that drops the output of that script into today’s node and evals it. I then know what language to focus on that day.
I then C-c c and start adding todos for that language. Do foo, look up bar, try out baz, study source of quux, etc. C-c a t lets me see all these todos, and I can start working on them.
I can divide a todo into separate todo steps, set a time estimate for each, and see how long I expect the task to take. It’s possible to then compare the estimate with the reality, and see how laughable the former is. It’s possible to then look into the subtasks and see which ones were the most inaccurate. I can set a todo note to study whatever was causing that step to take so long.
Today’s language is Racket. I only have 3 todos: some exercism problems, studying the Racket style guide, and writing yasnippet/ultisnip templates specifically for Racket. The latter is gonna take a while, as I don’t feel at all like writing a snippet I will never use. I’d rather write code, note (C-c c n) when a snippet would come in handy, and keep working on it. Later, I can look at those notes and see which snippets would actually come in handy. I can also, without interrupting what I’m doing, make a note about inefficient editing habits. “find a better way to do blah” etc.
This workflow helps keep me from bouncing around too much, playing with trying the same thing in another language or editor or falling down the rabbit hole of yakshaving. I’m focusing on foolang, doing bar and quux, and can tell you exactly how long it took me to figure out how to frobulate the wibble. Afterward I can look the notes, spin them off into separate projects, remind myself that I really wanted to try out x in another language, etc.
It’s not a polished, highly automated set up for 2 reasons: I don’t like magic, and that way lays endless yakshaving. This way has enough rough edges that resisting the urge to yakshave them away is a good form of exposure therapy.
I’m spending some time getting org-mode configured the way I want. I’m trying to keep things as simple as possible, given how much yakshave potential there is in org mode. I have only a few files in ~/org:
Orgfile.org, which is the default general agenda file. It’s structured like this:
My blog.org is just a datetree.
Code.org is tough to figure out how to structure it. I initially thought of organizing by language, but I don’t like how that lacks telos. It encourages dicking around with no goal, just bouncing from thing to thing. I could organize by project, but that similarly lacks focus if there are multiple projects to bounce around in. I settled on just a datetree and tags. A datetree encourages a daily log of what I intend to do, what I actually did, and where I am going. I can just filter by tags and date until this becomes insufficient and I need to split off a project, in which case I’d rather add it to code.org instead of making a new orgfile. Again, I want to try as hard as possible to discourage dicking around bouncing from one thing to another without a goal.
I tend to get flustered when learning languages. I bounce from one to another, trying the same thing in each. “oh cool how would I do this in foo? Ah, gotta yakshave my emacs for bar.” Since every programming language sucks, I end up endlessly plunging down rabbit holes trying to yakshave things to work properly and smoothly. My focus gets distributed among n languages, m setups, and p annoyances. In this vast space, I end up wandering stochastically and occasionally bumping into useful things. This is no way to conquer a territory and hear the dialup modem screeching lamentations of its robots as you chase them before you.
Little ends up getting done, and I end up working at a cartoonishly slow pace as I bounce around playing with everything. Despite learning, I end up with little to show for it, and the lack of structure means I end up following an interesting avenue and completely neglecting what is usually considered a vital part of the language.
Right now, I’m focusing on Racket, Elixir, Clojure, and Common Lisp. oCaml, LFE, and Haskell as background noise, not the main focus. Clojure is a bit lower priority than Elixir; it’s just not a good lisp and the dev is not fun on a low-end device. Elixir is a better lisp than clojure and it’s not even trying. It didn’t even bother to bring its bag full of parentheses to the party and it still kicks clojure’s ass. Reminder to rant about this later.
That’s a lot of opportunity to get distracted on several levels, from other languages to yakshaving dev environments and workflows for them.
For instance, my normal workflow involves vim-slime and tmux. Vim-slime sends text to a specified tmux pane, it doesn’t know or care what repl is on the other end. It doesn’t know or care about nrepl or swank or any of that. Just where to dump the text. I prefer this over magic. Well, in LFE slurping a file into the repl dumps all previously slurped macros and defs. The repl is more stateful than most, so the workflow is a little awkward. I was pondering how to tweak vim-slime to have an LFE mode that would on C-c C-c first save, then send over the text (c "@%"), or something. I could yakshave on this happily, but it’s a distraction. I’m trying to minimize as much as possible the temptation to yakshave, so I forced myself mid-fork of vim-slime into lfe-slurp to stop and just accept a bit of extra typing.
My attempted solution to the focus problem is simple. For focus, I’m using exercism. Each language is on a different track, each has defined tasks to accomplish and progress is tracked. Most tracks have similar tasks, which nicely satisfies my “oh man I wonder how I’d do this in foo” impulse, but in a structured and focused way. Yakshaving is kept to a minimum: while working in racket, I can pop over to another pane, type “langjournal,” and note a todo about yakshaving vim to work better with it. Later, I can yakshave, but I can keep focused on what I was doing instead of falling down the rabbit hole.
I also have an enormous folder of interesting code laying on my 2tb external harddrive, from language cores and projects to ebooks. I can browse, offline, all the code I could want. Obviously, without structure I could endlessly study this without ever doing anything useful. With even a modicum of enforced structure, this actually becomes useful, instead of a labyrinth through which I’m chasing my own tail.
While doing the erlang track, I saw that rebar.config hardcoded rebar3. I did the task, gsubbed rebar3 to rebar (v2 is what I had), and ran the tests. They passed, I made a note. Went on #erlang, asked about rebar3, and decided to upgrade. I bootstrapped it in less than a minute, reverted rebar.config, and it worked as intended. Minimal yakshaving.
I figure as long as I keep things structured, push yakshaving out of the way into its own activity (“today I’m gonna get vim to work better with lfe”), and avoid temptation, I’ll have a much nicer time than my usual habits provide. Then, I’ll actually get stuff done, comprehensibly, instead of amassing largely useless knowledge.
This blog is going to be part of my workflow, forcing me to maintain a coherency which is usually lost reinventing a local PLEAC.