Things I learned recently, #1
I have a few blog posts in the mix, but I thought it’d be fun to write a shorter article based on some things I’ve learned in the last 1-2 weeks. So yeah, let’s try it out!
“Fire-drills” don’t need that much prep when focusing on soft skills
I recently ran a workshop where we did some fire-drills related to workflow. A fire drill is where you simulate a scenario, with people in the room theorising about what they would do. The idea is to have a discussion and reflections on how and what you do, without actually doing them. So not technical, no code involved, just role-playing through how a task or problem might be approached.
I had “characters” based on what I wanted to exemplify and talk about, and picked the “actors” based on who I thought would be able to naturally carry the role. The drills we went through were familiar to the actors and the audience, so it worked out pretty well. My reflection after was that if the people in the room are able to relate, or see themselves or their experiences in the characters, they’ll know what to do without too much prompting.
And as always, psychological safety is super important when you’re asking a couple of people to do something they might not be comfortable.
Getting the line number for an error in Bash
There’s a few flags for Bash which are pretty useful:
set -x
set -e
set -E
-x will print each line being evaluated, -e will make the script exit early once a return value is returned (i.e non-zero), and -E will make traps (exception handling) inherited.
set -x is particularly useful when debugging, or running a script on a server where it’s hand to have a clear log of what happened, but can be quite noisy for normal usage.
I’ve used these for a long time, but what I discovered recently is that Bash has a bunch of globals that allow you to examine the stack trace.
FUNCNAME is an array of all functions in the call stack
BASH_LINENO is an array of where in the file those functions are located
BASH_SOURCE is an array of each file which contains each function in the call stack
LINENO is the line number that is currently executing
When used with trap, these can be put together into a way to provide more info about errors. They can be used for explicit errors, too, but usually then you’d be able to know exactly where the error was. But a trap on ERR would catch unexpected errors.
function handle_error {
local retval=$?
local line="$1"
local caller="$2"
echo "Failed at $line: $caller"
trap - ERR
exit $retval
}
trap 'handle_error $LINENO $FUNCNAME' ERR
If anyone knows of a good, consistent, version of this with a full stack trace, I’d love to know!
Embedding gists in Substack
Substack is not great for writing lengthy code snippets, since it doesn't have syntax highlighting, and the editor isn't great for it. But I discovered that pasting a gist URL into the Substack editor will actually embed it into the post! So you get all the benefits of having a gist without sticking to Substack's shade of greys.
One caveat though, something about Substack’s embedding makes Gists think that there’s bidirectional Unicode text, even when there isn’t. I wouldn’t rely on this feature, since it’s not visible in the editor UI, so it’s probably not well supported.
Example:
class Link { | |
constructor(element){ | |
this.text = element.innerText; | |
this.url = element.href; | |
this.element = element; | |
} | |
get jumpToLink() { | |
// color already reviewed text blue | |
for (const element of document.querySelectorAll(".review-focused")) { | |
element.style.color = "blue"; | |
element.classList.remove("review-focused"); | |
} | |
// color the current text to review red | |
this.element.style.color = "red"; | |
this.element.classList.add("review-focused"); | |
// jump to a specific link, plus scroll down a bit | |
// so it's not directly at the top of the page | |
this.element.scrollIntoView(); | |
window.scrollBy(0, -100); | |
// return this for when the property has already | |
// been evaluated (i.e reviewed) so it's | |
// quick to see | |
return "Already reviewed!"; | |
} | |
} | |
[...document.querySelectorAll(".body > p > a")].map((x) => console.log(new Link(x))); |
Programming language database
The Programming Language Database is pretty self explanatory. It's a collection of many programming languages, with info on what features that have or don't have. Pretty useful for anyone looking into language design.
Picotron, a fantasy workstation
Pico8 has been my main tool for making games in recent years, but I've often longed for a version that was slightly higher in resolution or a bigger colour palette. Picotron is exactly that, wrapped in a virtual desktop to help separate the daily life from game dev life.
Videos that are too large to play on Slack
If a video file is too large on Slack, it'll tell anyone trying to play it that it's the wrong format. Downloading it will let you play it, but it won't be possible directly in the Slack client. A better option might be to put a video on as a protected / unlisted video on YouTube.
Sidenote: Slack has transcribing for videos, which is very nice.
Testing interactive terminal programs with Python
There’s a lot of examples out there for running a Bash script via Python. But there’s not many examples where a script may keep running and have multiple input/output interactions. If you’re trying to subprocess an interactive program (e.g git add -p), it can be hard to find good examples of how to do so!
The internet might recommend using communicate, or run, but I found using the read/write functions on the stdout/stdin simplest. The other options will close the stream by default after one write. One thing to remember though: make sure to flush stdin after writing.
process = subprocess.Popen(
[f"{script_path} _test_interactive"],
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
cwd=example_dir,
shell=True,
)
stdout: List[str] = []
ansi_escape = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
if process.stdout:
line = process.stdout.readline()
stdout.append(line.decode("utf-8"))
if process.stdin:
process.stdin.write(input.encode("utf-8"))
process.stdin.flush()
if process.stdout:
for line in process.stdout:
stdout.append(line.decode("utf-8"))
print([ansi_escape.sub("", line) for line in stdout])
Check-ins work, regardless of audience
We’ve added check-ins and check-outs to many of our workshops or meetings. The concept is to get everyone to say something, and pay attention for a minute, which sets a good vibe for the rest of the session. These might be focused around how people feel, e.g “what’s your battery level?”, “what colour do you feel?”, “what music genre do you feel like right now?”. Or they could be a bit deeper, such as those found in this generator. Give people the space to do what they want with it.
Usually, I have introduced the concept whenever there’s a new person who hasn’t done it before. But lately I’ve just been prompting people:
Everyone stand up (gesture with hands)
“We’re going to go around, state what colour we feel right now, and explain why”
“I’ll start, I’m yellow because I’m feeling bright and happy”
< point to next person >
Even people who have never encountered check-ins before, or don’t typically take part in big workshops, follow the format and get it right away. Not a huge surprise, but it’s super nice!