Tag Archives: tmux

A little development environment in vim and tmux

I’ve been doing a little project and took a moment to get a bit better at using tmux.

Every time I go into this project I set up some splits. A main window where I’ll edit files using vim, then I split a pane off to run the code or test suite on every save. Another split where I pip install after any changes to my requirements.txt file.

Since I do the same thing repeatedly I was pretty sure tmux has a way to set this up so I don’t need to do it by hand. I tried using tmux session saving plugins, but they are too much for what I need right now.

Turns out tmux is incredibly easy to script. This gist is very long and very informative on how to split windows in tmux and covered everything I needed.

#! /bin/sh

# split -h horizontally to take up 30% of the width to run my __main__.py file on every save of a python file
# this is -d detached so that focus remains on the main window
tmux splitw -d -h -p 30 'ls *.py | entr -c env/bin/python . ./goodreads_library_export.csv data.csv ~/books'
# split my second pane vertically with 20% for rerunning pip installs on save of requirements.txt
tmux splitw -d -t 2 -p 20 'ls requirements.txt | entr -c env/bin/pip install -r requirements.txt'
# create a little detached shell just in case I need to try something
tmux splitw -d -t 3
# open up the python files in tabs in my main pane
vim -p *.py 

entr is a great little tool I like for monitoring for file changes and running a command in response.

a quick development environment for a project

Hosting better screencasts in WordPress

When I was writing up a note about pingplotter I figured I should show how it works because that’s much better for understanding it.

This gobbled up an incredible amount of time, so I’m writing it down so I never have to figure it out again.

There’s a few terminal screencast recorders out there, but I picked asciinema since it seemed simple, it recorder everything as text, not an image and it seemed a very light format to playback. These things are true, and the pain I felt is mostly unrelated to any failings of asciinema.

Asciinema is great. I can record a session locally, play it back to check locally and then upload it to their hosting to share. All pretty cool!

# record a session, but skip pauses over 1 second
asciinema rec -i 1 pingplotter.cast
asciinema: recording asciicast to pingplotter.cast
asciinema: press <ctrl-d> or type "exit" when you're done
# type a bunch of things to demo
# then ctrl-d to stop recording
asciinema: recording finished
asciinema: asciicast saved to pingplotter.cast

# time to check to see if it was any good
asciinema play pingplotter.cast
# the saved session plays back

# good enough!
asciinema upload pingplotter.cast 
# asciinema gives you the URL of the upload
# you can give it a description and make it public

Since this website is still powered by WordPress, I wanted to share it here. The Asciinema url didn’t embed automatically, so I figured I could either embed a script from Asciinema or add a plugin to do the embed code.

Both of these failed – somehow the javascript from Asciinema wasn’t working in my Firefox. It worked in Chrome, but that’s not good enough. I figured I should just host the cast myself! Why do I need to embed this tiny file or load javascript or install plugins to do this?

I found a neat utility to convert an asciicinema screencast to an animated SVG.

Listen, SVG and animated SVG is incredibly powerful, and if you don’t know, you should learn about it. Animated gifs are heavy, don’t resize, and are full of rendering artifacts. SVG are vector graphics, which mean they are infinitely scalable up or down crisply in a much smaller size than most gifs. Every modern mobile and desktop browser supports them.

The cool utility is svg-term. It lets you take an asciinema file and turn it into an animated svg.

It’s very nicely made, but is unfortunately distributed with npm, a package manager designed to ruin you. The instructions svg-term gives you to install it are incredibly dangerous unless you know to set up your npm install to not install packages with root privileges, WHICH FOR SOME REASON ISN’T THE DEFAULT OR EVEN POSSIBLE. I looked at the npm documentation for something like pip install --user, but it doesn’t exist. Instead, the solution is to redefine global installs to mean user local installs. I’m not kidding.

I don’t want to ever have to figure this out again either, so I added it to my jumpstart script so it will be ready for the next computer I use.

cat pingplotter.cast| svg-term --out ~/pingplotter.svg

This worked great! I went to upload it to my WordPress site to share with you. It did not work great!

WordPress very reasonably recognizes that while I enthusastically love SVG, it can be a security hole. SVG files can embed all sorts of foolishness like JavaScript and other loopholes to escalate privileges. So WordPress prevents them from being uploaded. I opted to allow them with a plugin that sanitizes SVG files to remove the dangerous stuff but allow the rich graphical goodness. This worked great!

I then decided to demo using tmux and glances, which meant I had to do a lot more typing in the demo, which expanded the size of the screencast. Poor svg-term began to crap out because I was exceeding the size of the javascript heap by feeding it a file larger than 1 mb. Fair enough, I don’t want to have a big file anyway!

The solution here is to script as much as possible ahead of time. The asciinema commandline takes a -c command argument which makes it execute a command as soon as it startes recording. Since tmux also lets you script up what you want it to do, I ended up with this.

asciinema rec -i 1 -c 'tmux new "pingplotter ; read" \; split-window "glances ; read" \; select-layout even-horizontal' pingplottertmux.cast

I’m telling asciinema to open up tmux and start recording. I’m telling tmux to start with pingplotter in a window, then open a new pane with glances and make the layout side-by-side. Each of those panes will close when the command they are running is done. Now I can just use ctrl-a <space> a few times to rotate the layout, ctrl-c to kill the panes, tmux exits and asciinema stops recording.

The file size ended up being small enough for svg-term and now you get this!

Anyhoo, black people are human beings with real lives and I don’t want my tax dollars to be used to murder them. Please, call your city representatives to urge them to shrink the police budget and use that money for social services that prevent crime and pain. If you can’t figure out your local representation, please learn how. If you won’t, please at least call your federal reps to ask them to stop giving the city police things like machine guns and tanks.

Week 3011

Getting ready for my first trip to Hyderabad!

Health

Been working on dragon flags and handstand pushups at the gym. Only 3 biking days this week :(. On the other hand, they were all good days. It’s cold enough now to break out the gloves here in NYC, so I’m looking forward to warmer days in Hyd for the next few weeks. I wonder if I can rent a bike there easily?

Family

One of the reasons for that: I got to take Max Lazer to go see Tinga Tinga. He got to see it, I just got to be part of the parental escort through the subways to Times Square. He handled it great, but it was amazing to see the way the teachers handle 22 kindergartners getting through the subway system.

Z is teething and it’s so tough on her. I hope it ends soon. On the other hand, I managed to get both kids to sleep in the same room at the same time on Wednesday and Thursday we got Z to sleep the whole night through!

My Kobo broke and I sent it off to be replaced, but I must have an e-reader for the trip so I am now the owner of a Kindle Paperwhite as well. As someone who’s now owned and used a Nook, Kobo and Kindle, I’ll write up my take on it. Should have some time on the 16 hours or so of flight time!

Code

Been helping folks at work learn some more advanced Python. I get excited every time I talk about list or dictionary comprehensions because they were a real light when I was learning python in the beginning.

You often need to transform data structures and the first way is usually to just iterate a list, construct new instances of something else, then pop them into a list of new things.

Say you have a list of cool coders you want to talk about.

 


from collections import namedtuple
Coder = namedtuple('Person', 'name login url')
cool_coders = [Coder(name="Grace Hopper", login="ghopper", url="https://en.wikipedia.org/wiki/Grace_Hopper"),
Coder(name="Ada Lovelace", login="ladyada", url="https://en.wikipedia.org/wiki/Ada_Lovelace"),
Coder(name="Jenn Schiffer", login="jennmoney", url="https://jennmoney.biz/"),
Coder(name="Nina Zharenko", login="nnja", url="https://www.nnja.io/"),
]

intro = "Here's a list of some cool coders and more you can learn about them: "

Maybe you want to produce a markdown sentence listing them.

coder_markup = []
for programmer in cool_coders:
    coder_markup.append( "[{}]({})".format(programmer.name, programmer.url) )
markup = intro + ", ".join(coder_markup)

Sure, that could be more complicated and have more changes or filtering that needs to be done. But what’s nice about a comprehension is that it helps cut down boilerplate and it makes things clearer.

coder_markup2 = ["[{}]({})".format(coder.name, coder.url) for coder in cool_coders]
markup = intro + ", ".join(coder_markup2)

And of course, if we were on python 3.6 we could make that even smaller by just using fstrings.

I’ve been using tmux pretty heavily, but now I get annoyed that on reboot I have to rebuild all of my workspaces. So now I’ve installed tmuxinator. It should be useful for setting up project/workspaces and then firing them up after a reboot.

Of course – I don’t just install tmuxinator. I set it so that it can auto-install on any account I’ve got with my jumpstart script.  If you know any cool tricks or experiences you want to share about either, I’m eager to learn.