Moving Left and Right in zsh (in macOS)

I use the command line a lot on my Macs, in particular, I use iTerm2.

When moving left and right in a command the shortcuts I knew about so far were:

Key (combination)Moves Cursor…
Right Arrow ‘→’One character right
Left Arrow ‘←’One character left
CTRL + aBeginning of the line
CTRL+ eEnd of the line

After adding the following lines to ~/.zshrc, I now can also move left and right per word using ALT-← and ALT-→ respectively:

bindkey "[D" backward-word # ALT-left-arrow  ⌥ + ←
bindkey "[C" forward-word  # ALT-right-arrow ⌥ + →

Especially when moving around in long command lines, this is really convenient & saves a lot of time.

Do you have keyboard shortcuts that you use regularly on the command line (or elsewhere)? I’d love to hear about them!

Tips for Conference Proposals & Sessions

Disclaimer: This year I’m one of the reviewers for the Agile Testing Days.

It’s proposal season again, at least for one of my favourite conferences, the Agile Testing Days; the call for papers is open until March 28th (for 2021).

There is a good number of articles and blogs available on the topic of Agile Testing Days proposals alone: I suggest to follow the advice Uwe gives with his blog post “Call for Papers Submission Pitfalls & How to Do it Better! Tales from a Conference Organizer“. There’s more info to find from that same conference over on YouTube: https://youtu.be/QxC-Ee51xmM

Mind The Context

Another important tip (especially for those thinking about a keynote) comes from Liz Keogh:

If it’s an opening keynote, I try to open people’s minds to learn and question. If it’s a closing keynote, I try to help them reflect on what they learned. Keynotes are there to frame the rest of the conference.

Liz Keogh on Twitter

I believe similar thinking applies to other sessions too: Make your session fit into the frame of the conference and what you know about the attendees expectations.

Tell a Story

I personally try to at least come up with a story, either one I made up or a personal one. Both worked well for me:

For a ½-day tutorial about testing and the Internet of Things (IoT), I set up the story of Goblin King Jareth the 42nd, who wanted to control his kingdom with a set of IoT devices and tasked the participants with testings these devices. The framing story helped to provide some reason to actually participate in the exercises.

For a (read: ‘the’ 🙂) keynote I gave at Agile Testing Days 2019, I chose the most personal story I possibly could: My diagnosis of and treatment for cancer – and why I still consider myself lucky. Read about it in “Being Lucky — A Keynote at the Agile Testing Days 2019“.

If you like to know more about telling a good story, be sure to read Huib Schoots’ blog post “Storytelling“! You’ll find — no surprise — a good story (and many links to more information, too).

Be Prepared

Things can go wrong: The notebook you planned to give the presentation with may crash. The projector may break or the sound system my fail. You may forget what you wanted to say. These things all happened to someone somewhere.

It’s better (and impressive!) to be prepared. For my keynote, I prepared index cards with notes of what I wanted to say when, when to make extra long breaks and other instructions, such as when to proceed to the next slide. At first I numbered them, so I could sort them, if I dropped them on the floor.

Numbered index cards

Later, I also put them on a thread: Now, even when I would drop them, they would still be sorted! This would have saved the talk, had I dropped those cards.

Index cards on a thread, to prevent shuffling

Some of the directions didn’t work out in the moment the presentation was live: The introduction was totally different from what I expected (and significantly louder!).

Mind the Last Possible Moment

One important, even obvious, aspect: Don’t miss the dead line. I did once and it’s annoying. Very annoying. — Most of the work was done for nothing, because I forgot to check the calendar. I learned it the hard way: If I’m too late to submit, it doesn’t matter how good the proposal was. Only if submitted within time, a paper has a chance to be selected.

I hope to see many great and inspiring proposals for the Agile Testing Days 2021!

Collecting Lists In a Ruby Hash and the ‘<<=' operator

The other day, I needed to quickly analyse a data set that came in form of a large CSV file. I wanted to collect a particular column of that table and collect all entries categorised by a key in another column.

A simplified version of the table could look like this:

Key Value1 Interesting_Value Other_Value
foo1723.5X
bar211.75Q
foo4212.6B
baz2717.8F
bar4947.2K

I strived for something like this:

result = { 
  foo: [23.5, 12.6],
  bar: [1.75, 47.2],
  baz: [17.8],
 }

Iterating over the rows is easy, and getting to the columns is no problem either: The CSV gem is well documented and supports this easily.

A nice way to accumulate data is Enumerable#each_with_object. Since I wanted the result to be grouped by a key value, I’d pass a Hash as the initial argument.

Step 1: each_with_object({})

However, since I’ve planned to append values for changing keys, the default value needed to be an Array, not the default of nil.

Step 2: each_with_object(Hash.new([])

This, however, returns the same empty Array, when a key isn’t found, but I wanted a new empty Array:

Step 3: each_with_object(Hash.new { [] })

This executs the block every time a default values is needed (i.e. the given key isn’t yet in the Hash).

The next step is to append the value found in a row to the (potentially new and empty) Array for the given key.

I thought it would work this way:

data_table.each_with_object( Hash.new { [] }) do |row, acc|
  acc[row['Key']] << row['Interesting_Value'] 
end

But, no, the result of this code is an empty Hash! It needs to be the <<= operator to work, as shown in the snippet of a pry session:

[2] pry(main)> data_table = CSV.read 'table.csv', headers: true
=> #<CSV::Table mode:col_or_row row_count:6>
[3] pry(main)> data_table.each_with_object( Hash.new { [] }) do |row, acc|
[3] pry(main)*   acc[row['Key']] <<= row['Interesting_Value']
[3] pry(main)* end
=> {"foo"=>["23.5", "12.6"], "bar"=>["1.75", "47.2"], "baz"=>["17.8"]}

It seems to me, that the Hash lookup with the given default value [] returns an Array, and the append operator << does in fact append the passed object to that Array, but then the result of that does not end up as a (new) value fo the given Hash key. In contrast, the <<= operator does assign the result of the append operation.

Seeing And Saying On The Command Line

Occasionally I like command line tools to also say the output, in addition to ‘printing’ it (to STDOUT).

A current context is starting a server locally with updated information. The start up takes time, so I tend to not wait at the command line for it to fully boot.

I wanted a noticeable signal when the thing is up – and also a confirmation that the version of the information source *is* actually updated. The commands tee and (the macOS) say do this for me:

tee >(say&)

tee copies the output of its input to STDOUT (usually the terminal) and the given file. The construction >(other command&) causes tee to send the input not to a file but to othercommand and the & causes that command to return immediately (instead of returning only after the command to finish).

Overall, I do something like this. The system returns a lengthy JSON string, so I use jq to get to the version information I’m looking for:

curl -s -u <username:thepassword> “<url_to_locally_running_service>” | jq “<path_to_version_info_in_json>” | tee >(say&)

The GitHub page explains that

jq is a lightweight and flexible command-line JSON processor.

https://stedolan.github.io/jq/

It’s well worth trying, if you’re dealing with JSON input on the command line.

Passing Multiple Arguments To One Rake Task

Occasionally, I want Rake tasks to take multiple arguments. If the number of these arguments are know beforehand, Rake provides a nice way to express that in the Rakefile (see the Rake documentation for more details).

However, sometimes I like to pass a varying number of arguments the a task, which shall all be processed in the same way. Maybe its user IDs that need to be removed from a database, or a given list of piles to be processed.

Today I found a way to do this, by using Rake::TaskArguments#extras . The method extras returns a list of all the extra arguments passed to a Rake task, that are not named in the task definition. If no argument name(s) are declared in the task definition, then all arguments will be ‘extra arguments’.

An example Rakefile is this:

task :list do |t, args|
  puts "In task '#{t.name}"
  puts 'Passed arguments:'
  puts args.extras.map { |extra| "  * #{extra}" }
end

Calling this task from the command line and its output (in zsh) looks like this:

$ rake list\[one,2,3.141]
In task 'list
Passed arguments:
  * one
  * 2
  * 3.141

Note, the \ before the opening bracket ‘[‘. In zsh, this is needed to escape the ‘[‘ (pairs of ‘[]’ have a special meaning in zsh). Also note, that there are no spaces between the arguments, just the comma.

If you prefer to add a space after the comma, there’s a way to achieve this (again in zsh): Drop the ‘\’ and instead put the task name and the arguments in quotes:

$ rake "list[one, 2, 3.141]"
In task 'list
Passed arguments:
  * one
  * 2
  * 3.141

$ rake 'list[one, 2, 42]'
In task 'list
Passed arguments:
  * one
  * 2
  * 42

In this example it doesn’t affect the output whether single or double quotes are used. Quoting in shells is … complicated, see for example: http://zsh.sourceforge.net/Guide/zshguide05.html#l112.

Did you find this helpful? Or do you know a better way to pass multiple arguments to one Rake task? Please let me know.


Navigation

%d bloggers like this: