This post is part 83 of 83 in the series Programming by Stealth

In this instalment we’ll finish our first exploration of Bootstrap 4 with a look at one its most versatile components, the so-called Card. This is one of those components that’s so generic it’s hard to describe, but once you learn about it you’ll start seeing it all over the web. Cards really are ubiquitous!

It’s important to stress that while we’re wrapping up our exploration of Bootstrap 4 with this instalment, that does not mean we’ve come close to covering every feature this impressive library offers. Instead, the aim was to cover the big-picture items, and leave you with enough experience to be able to learn the rest independently by reading Bootstrap’s excellent documentation.

You can download this instalment’s ZIP file here.

Listen Along: CCATP Episode 610

MP3 File

Read more

Tagged with:

This post is part 82 of 83 in the series Programming by Stealth

In this instalment we finish our exploration of promises with a look at the two new promise-related keywords added to JavaScript in ES 2017. These keywords allow us to write asynchronous code in a more human-friendly way.

You can download this instalment’s ZIP file here.

Listen Along: CCATP Episode 609

MP3 File

Read more

Tagged with:

How often does someone email you a file who’s content you need to copy-and-paste into a web form of some kind? Maybe it’s just me, but I find I need to do it a lot!

What I wanted was the ability to right-click any file with plain-text content (text, markdown, XML, JSON, Certificate Signing Requests, …) and send its content to the clipboard.

By combing Automator, the cat and pbcopy terminal commands, and a little JavaScript, I was able to build a nice service that can be accessed by right-clicking any file in any app that reports its outcome using a standard OS notification.

Download the Quick Action here, extract it, and copy it to your ~/Library/Services folder.

Read more

Tagged with:

This post is part 81 of 83 in the series Programming by Stealth

So far in our exploration of promises we’ve learned the core concept — a promise is an object that represents the status and/or result of an asynchronous task. Asynchronous tasks are inherently parallel, but we’ve learned how to use .then() and .catch() to create so-called promise chains, allowing promises to be executed in series. What we’ve not looked at yet is JavaScript’s native Promise class. This class is primarily used to create promises, but it also provides some useful utility functions. For now at least, we’re focusing on using promises rather than creating them, so we won’t be digging into how the Promise class’s contractor works. However, some of the utility functions are designed to help developers use promises in more powerful ways, so those will be our focus for this instalment. The most powerful of these utilities is Promise.all(), a function that allows us to create promise chains that perform some tasks in series, and others in parallel, allowing us to efficiently manage our asynchronous tasks.

You can download this instalment’s ZIP file here.

Listen Along: CCATP Episode 597

MP3 File

Read more

Tagged with:

This post is part 6 of 6 in the series Bash to Zsh

Having used Zsh rather than Bash for over a week it was time to make the move permanent by migrating my shell customisations from ~/.bashrc to ~/.zshrc. Your milage may vary, but I was pleased to find I didn’t need to make any changes, and, that I could get rid of one command from the script because Zsh defaults to a behaviour I had to explicitly opt in to with Bash.

TL;DR: environment variables (including PATH) and aliases work just the same in Zsh as they do in Bash, so if those are the only things you alter in your ~/.bashrc, then you can just copy it over to ~/.zshrc. But, if you alter Bash settings in your ~/.bashrc, you’ll need figure out the equivalent Zsh options and replace the relevant lines with the appropriate Zsh setopt or unsetopt Zsh commands.

Read more

Tagged with:

This post is part 1 of 6 in the series Bash to Zsh

During their 2019 World Wide Developers Conference (WWDC 2019) Apple announced that the default command shell for their next OS release (macOS Catalina) from the Bourne Again Shell (Bash) to the Z Shell (Zsh). Not only will Apple be switching the default in Catalina, they will be removing Bash completely in an as-yet unspecified future update. Apple’s advice is clear — make the switch now so you’re ready!

Never being one to try hold back the tide, I dove right in and made the switch within 5 minutes of reading about the announcement. This series will document my experience of making the change.

Read more

Tagged with:

This post is part 80 of 83 in the series Programming by Stealth

In the previous instalment we got our first introduction to the concept of promises in JavaScript. By the end of the instalment we’d learned how to use promises to deal with single asynchronous tasks, but not how to use promises to deal with multiple interdependent asynchronous tasks. That’s what we’ll be focusing on in this instalment. In the previous instalment we looked at the arguments to .then(), but we ignored its return value. It’s the return value from .then() that this instalment revolves around. That return value is the key to dealing with interdependent asynchronous tasks by combining multiple promises into so-called promise chains.

You can download this instalment’s ZIP file here.

Listen Along: CCATP Episode 597

MP3 File

Read more

Tagged with:

This post is part 5 of 6 in the series Bash to Zsh

As I continue my move from Bash to Zsh at Apple’s strong suggestion I continue to bump into little differences that cause me minor problems. Today it was the fact that while Bash treats comments as comments even when they’re entered in an interactive shell, Zsh does not, at least not by default on MacOS.

TL;DRsetopt INTERACTIVE_COMMENTS

Read more

Tagged with:

This post is part 4 of 6 in the series Bash to Zsh

At Apple’s advice I’ve switched the login shell from Bash to Zsh on all my Macs. For the most part, what worked in Bash works in Zsh, but sometimes I do still want to get back to Bash to test something or to check something. You might imagine that simply typing bash from a Zsh prompt would get you a Bash shell, and you’d be right, sort of. When you just run the command bash you get a bare shell without the customisations that would have been applied when you opened a new Terminal window with Bash as your default shell. This will be immediately obvious because the prompt will be the basic bash-3.2$ as opposed to the hostname, current folder, and you’re username like you were used to.

The solution is really simple — pass the -l flag to signify that you want your new shell treated like a login shell, and hey presto, you’re back to Bash just like you remembered it 🙂

So, if you switch your Mac to Zsh, you get back to the Bash experience you had before with the following command:

bash -l

Tagged with:

This post is part 3 of 6 in the series Bash to Zsh

At Apple’s recommendation I’ve moved from Bash to Zsh on all my Macs. This has been a mostly smooth transition, but I have run into a handful of little gotchas. This week it was an error when trying to execute a command I’d been using in Bash for years. The error started zsh: no matches found.

The cause of this error is a subtle but important difference in how Bash and Zsh handle file globbing (expansion of the * character) when no files match the specified pattern. By default, Bash happily expands expressions that don’t match anything into an empty list. Zsh’s default behaviour is to raise an error and prevent the command executing.

TL;DRsetopt NULL_GLOB to enable Bash-like behaviour, and unsetopt NULL_GLOB to revert back to the Zsh-like behaviour.

Read more

Tagged with:

keep looking »