Category: Uncategorized

Conveniently start a JavaScript shell (jsc) on macOS

For one of my projects I wanted an easy way to try JavaScript on a command line (similar to pry or irb in Ruby). Here’s how I found out where the program is located and how to set up my Mac to conveniently start it.

1. Find out where jsc is located on the machine:

$ find / -name jsc -type f 2>/dev/null
/System/iOSSupport/…/JavaScriptCore.framework/Versions/A/Helpers/jsc
/System/…/JavaScriptCore.framework/Versions/A/Helpers/jsc
/System/Volumes/Data/…/JavaScriptCore.framework/Versions/A/Helpers/jsc
/System/Volumes/Data/…/JavaScriptCore.framework/Versions/A/Helpers/jsc    

Searching from the root folder may be a bit excessive, though. You may consider a more limited search.

2. Look into the ‘system frameworks’ for versions

The path /System/Library/Frameworks/… was where I went to look what else is inside:

$ ll /System/Library/Frameworks/JavaScriptCore.framework/Versions
total 0
drwxr-xr-x  4 root  wheel  128 Jan  1  2020 .
drwxr-xr-x  4 root  wheel  128 Jan  1  2020 ..
drwxr-xr-x  5 root  wheel  160 Jan  1  2020 A
lrwxr-xr-x  1 root  wheel    1 Jan  1  2020 Current -> A

Aha, there’s a link named Current that (currently) points to A. I used this link in the next step. This way I can still use the same link, even if (when!) an OS update causes the file that’s linked to changes.

3. Link to the current version

I set a link somewhere in within $PATH. I have a bin folder in my home directory, so it put the link there:

ln -s /System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc ~/bin/jsc

3. Set a variable ‘console’ for output

To output things, use this to define a variable console in a running JavaScript shell.

var console = {log : debug};

While jsc provides a print function, I find it convenient to stick to the more idiomatic console.log.

4. Use ‘jsc’

$ jsc
>>> var console = {log : debug};
undefined
>>> console.log(function(){})
--> function (){}
undefined
>>> 1 + 1
2 

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!

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.

Generating a Preview on LeanPub Using Rake

While working on the e-books I published on LeanPub, I have developed a number of useful approaches to get fast(er) feedback on how the book looks. Two earlier blog posts describe some of this:

While this provides a nice feedback cycle, sometimes I like to generate a new preview without pushing to the GitHub repository I am using to share the book content with LeanPub. This happens, when I change settings on the Leanpub site that affect the generation of the book (the title image, font faces and sizes are set via the book’s pages on LeanPub, not a configuration file in the repository).

While I could click thought the UI and navigate to the page where I can generate a new preview, I prefer using a command line tool from my local machine: Rake

The Setup

A warning: The LeanPub API documentation says: “Using the Leanpub API requires a Pro plan.

To use the LeanPub API, an API key is needed. The link to the API documentation above has information where to get that key. To easily use this API key, I store it in an environment variable LEANPUB_API_KEY.

The Rake Task Definition

In the repository of my book I have a Rakefile containing the task definitions. Here’s the one to trigger the generation of a preview on Leanpub:

require 'rest-client'

namespace :leanpub do
  LEANPUB_BASE_URL = "https://leanpub.com/<book_id_on_leanpub>"
  namespace :preview do
    desc "Generate new Preview on LeanPub"
    task :generate do |t|
      what_to_generate = t.name.split(':')[1]
      url = "#{LEANPUB_BASE_URL}/#{what_to_generate}.json"
      begin
        RestClient.post url, api_key: ENV['LEANPUB_API_KEY']
      rescue RestClient::Exception => e
        puts "Got error #{e.message} in", caller.first
        exit 1
      end
      puts "Generation of preview was triggered"
    end
  end
end

I can now easily generate a preview, without having to leave the IDE I’m using to write the book (or the command line) using this:

$ rake leanpub:preview:generate
Generation of preview was triggered

The Rakefile will likely change, for example to also support publishing a new version of the current ebook, or to make it more flexible in order to handle different ebooks.

Update (8. Jan 2021): It turns out that this is really useful: LeanPub provides a web hook to generate a _sub set_ of the book that also generates the PDF (but not the ebook and mobi file). This saves some time from pushing to GitHub to being able to review the generated file. I now use this web hook most of the time.

I now only generate for full book in all formats when I want to check that the book looks good enough to be published. Since this happens less regularly than pushing to the repository, I use the Rake task.

A Double Self Retro On Its Way To A Multi Self Retro

So, I read Bruce’s post (and the blog post it links to, as well 😄) over on Twitter:

I liked the post and Bruce wrote:

If you wanna join in, please feel free and I’m sure we’ll both be happy to share what you write!

Bruce, the legend

Thank you the invitation, Bruce (and Chris, I assume)!

What is this and why did you agree to do a double self retro?

We’re approaching the end of a year that swooshed by rather quickly (especially the part after mid-March) and which was … different, to say the least. To me, it’s worthwhile reflecting on what happened and where it has led to.

What did you think your goals were when you started the year?

Simply put: To survive. After battling cancer in 2018 & a good part of 2019, I hoped to return to some form of normal life. — As far as that’s desirable or possible after that time. I hoped to find a project to work on. And I did. In fact, I had the opportunity to (re-) join the same project (but different team), that I left way to abruptly due to the illness. It’s incredible to find such acceptance.

How did your goals change through the year?

After the first follow-up examination, when it was clear that everything’s totally fine, my doctor advised me to enjoy the summer. I took this as a goal, and am pleased to say: It worked well. I started to go swimming in the North Sea — and didn’t stop going (but I do stay in the water a lot shorter!).

How did you recalibrate in the year, when things changed?

They didn’t change that much. During the chemo therapy part of my treatment, I had to pretty much self-isolate, so I was used to it. It was ‘just’ that everybody else now also kept a good distance.

I also started working on “Softwarepeople … Work From Home“, a free ebook with contributions by people from all over the planet. I helped me to have a reason to contact folks and see what the situation is like elsewhere.

Highest point of the year

When people whom I admire & respect a lot agreed to contribute to the book.

Lowest point of the year

I had to have one (small, compared to what I went through before) surgery early March. Coming out of the hospital, into a lock-down, was frustrating.

Which item of clothing have you worn the most?

Probably this super-cosy jacket I bought on Rømø in Denmark. It has a few labels on it saying “Alive And Kicking”. Apart from being really comfy, I find that to be a nice fit to the whole situation.

Have you discovered any new tools?

I rediscovered GraphViz, a tool to, well, visualise graphs. I even wrote a small tool to turn tables that describe paths though a set of steps in to a graph description, that GraphViz then turns into an image file. I wrote posts about GraphViz and how I used it:

Best coping mechanisms

I started going to the gym very regularly, well until they had to close due to the pandemic.

Did any songs help you cope with the year?

  • Amy MacDonald – Pride
  • Neil Diamond – Beautiful Noise

and, I admit it,

  • Adriano Celentano – Prisencolinensinainciusol

TV shows that helped you cope

None.

Who is your favourite new friend of 2020, and why is it Chris?

Because, he’s Chris (Baumann). With apologies to the other Chrisses I know. I took the question verbatim from Bruce, and it explicitly asked for Chris (but not which Chris). 😃

What have you learnt about yourself this year?

Swimming helps me to focus.

Any regrets?

If any: That I didn’t switch from gym-based sport to home-alone sport faster.

What have you enjoyed?

Swimming, even since the temperature dropped below comfortable, working in my new team, the online edition of the Agile Testing Days and the coding puzzles at AdventOfCode.

What advice would you give to past you…January 2020?

I’d use the words of Douglas Adams: ‘Don’t Panic!’

Navigation

%d bloggers like this: