VS Code Extension of the Day: Settings Sync

Note * This is the 7th post in a multipart series. If you want to read more, see our series index.

Settings Sync is the first extension I always install—it lets me restore my settings and extensions. It uses GitHub Gists to store the config, so you’ll have a slightly annoying setup process initially. But once it’s done, every time you change a setting or add an extension, it updates your Gist. Then, on a new install, it pulls down your settings and reinstalls all your extensions—so you can get everything set up really easily and quickly. Learn more and download it


VS Code Extension of the Day: Editor Config

Note This is the 6th post in a multipart series. If you want to read more, see our series index.

If you work in a team where choice is important, you may find everyone has a different editor. Today our team uses VS Code, Atom & IntelliJ.

EditorConfig is a set of extensions for many editors that tries to unify things like tabs vs. spaces, trailing spaces, empty lines at the end, etc. Think of this as your editor linting as you go. Unfortunately, support is limited for what can be done, but a lot of editors and IDEs are supported. Learn more and download it.


VS Code Extension of the Day: Dracula Official

Note This is the 5th post in a multipart series. If you want to read more, see our series index.

So not quite an extension—more of a theme—Dracula is a great dark theme for code. It’s a little more playful in its colors, which is a plus, but what makes it stand out is the Dracula community. There are tons of extensions to add Dracula to everything: I have my Slack, terminal.app, and IntelliJ all configured as well. It’s really great to have that consistency everywhere. Learn more and download it.


VS Code Extension of the Day: Code Runner

Note This is the 4th post in a multipart series. If you want to read more, see our series index.

Code Runner is a lightweight code execution tool. I think of it as the middle ground between a REPL environment and actually running code normally. So you can execute a single file or even highlight specific lines and execute just them. It supports an amazing array of languages—C, C++, Java, JavaScript, PHP, Python, Perl, Perl 6, Ruby, Go, Lua, Groovy, PowerShell, BAT/CMD, BASH/SH, F# Script, F# (.NET Core), C# Script, C# (.NET Core), VBScript, TypeScript, CoffeeScript, Scala, Swift, Julia, Crystal, OCaml Script, R, AppleScript, Elixir, Visual Basic .NET, Clojure, Haxe, Objective-C, Rust, Racket, AutoHotkey, AutoIt, Kotlin, Dart, Free Pascal, Haskell, Nim, and D. I personally use it all the time with JS & Kotlin. I haven’t needed to change any settings, though code-runner.runInTerminal sounds interesting.

Download it here.


VS Code Extension of the Day: Bracket Pair Colorizer

Note This is the 3rd post in a multipart series. If you want to read more, see our series index.

Initially, this extension allows your brackets { } [ ] ( ) to be set to a unique color per pair. This makes it really easy to spot when you’ve made a mistake and removed a closing bracket. Behind the obvious, there are a lot of really awesome extras.

You can make the brackets highlight when you click on them—when you click on one, its pair highlights via bracketPairColorizer.highlightActiveScope. You can also add an icon to the gutter of the other pair with bracketPairColorizer.showBracketsInGutter, which makes it trivial to work out the size of the scope.

It also adds a function bracketPairColorizer.expandBracketSelection, which is unbound by default but will allow you to select the entire area within the current bracket pair. Do it again, and it will include the next scope. For example, you can select the entire function, then the entire class. Learn more and download it


VS Code Extension of the Day: Bookmarks

Note This is the 2nd post in a multipart series. If you want to read more, see our series index.

The bookmarks extension adds another feature from Fat VS Code to code—the ability to bookmark a place in a document, file, or code and quickly navigate back and forth to it. One important setting you should change is bookmarks.navigateThroughAllFiles—set it to true to jump to any bookmark in your project. With false (the default), you can only navigate to bookmarks in the current file. Learn more and download it.


Learning Kotlin: Operators don't need to mean one thing

Note – This is the 18th post in a multipart series. If you want to read more, see our series index.

Following on from the previous post, we looked at operators and how to use them yourself by implementing the relevant operator methods. The first part I want to cover in this second post is the unary operators +, -, and !. When I was learning this, the term unary jumped out as one I didn’t immediately recognize, but a quick Wikipedia read made it clear. For example, if you use a negative unary with a positive number, it becomes a negative number... It’s primary school math with a fancy name.

One thing to remember about operators is that it’s totally up to you what they mean. So, for example, let’s start with a simple pet class to allow us to define what type of pet we have.

package blogcode

enum class animal { dog, cat }

data class pet(val type: animal)

fun main(args: Array<String>) {
    val myPet = pet(animal.dog)
    println(myPet)
}

This produces:

pet(type=dog)

Now, maybe in my domain, the reverse of a dog is a cat, so I can do this to make this reflect my domain:

package blogcode

enum class animal { dog, cat }

data class pet(val type: animal) {
    operator fun not(): pet = when(this.type) {
        animal.cat -> pet(animal.dog)
        animal.dog -> pet(animal.cat)
    }
}

fun main(args: Array<String>) {
    val myPet = pet(animal.dog)
    println(!myPet)
}

This produces:

pet(type=cat)

And this is the core idea: while a unary operator has a specific purpose by default, you can totally use it the way that makes sense.

This is really awesome and powerful—but it doesn’t stop there. Normally, when we think of something like the unary ! with a boolean, it flips the value (true → false, or vice versa), but it remains a boolean. There’s nothing stating it has to work that way:

package sadev

enum class animal { dog, cat }

data class pet(val type: animal) {
    operator fun not(): String = "BEN"
}

fun main(args: Array<String>) {
    val myPet = pet(animal.dog)
    val notPet = !myPet
    println("myPet is ${myPet::class.simpleName} with a value of ${myPet}")
    println("notPet is ${notPet::class.simpleName} with a value of ${notPet}")
}

In the above, the output is:

myPet is pet with a value of pet(type=dog)
notPet is String with a value of BEN

In short, the ! of a dog pet is actually a String with the value of BEN. I have no idea how this is useful in real development, but it’s amazing that Kotlin is flexible enough to empower it.



VS Code - Extension of the Day

Over at the ZA Tech Slack, I’ve been posting an extension of the day in the #VSCode channel. It’s my way of sharing cool things with the group and also forcing myself to spend a bit of time reviewing my extensions and figuring them out a bit better. Since not everyone follows that, here’s the more permanent home for these mini posts on cool VS Code extensions:

  1. Better Comments
  2. Bookmarks
  3. Bracket Pair Colorizer
  4. Code Runner
  5. Dracula Official
  6. EditorConfig
  7. Settings Sync
  8. Paste JSON as Code

Learning Kotlin: Operators

Note * This is the 17th post in a multipart series. If you want to read more, see our series index.

This next post is an introduction to operators in Kotlin—not the basic "use a plus sign to add numbers together" stuff (you read this blog, you’ve got to be smart enough to figure that out). No, this post is about just how amazingly extensive the language is when it comes to supporting your classes’ use of them.

Adding Things Together

Let’s start with a simple addition example—I did say we wouldn’t do this. In the following code, we track scoring events in a rugby game and want to add them up to get the total score:

enum class scoreType {
    `try`, conversion, kick
}

data class score(val type: scoreType) {
    fun points() = when (this.type) {
        scoreType.`try` -> 5
        scoreType.conversion -> 2
        scoreType.kick -> 3
    }
}

fun main(args: Array<String>) {
    val gameData = listOf(
        score(scoreType.`try`),
        score(scoreType.conversion),
        score(scoreType.`try`),
        score(scoreType.kick)
    )
    var totalPoints = 0
    for (event in gameData) {
        totalPoints += event
    }
    println(totalPoints)
}

This obviously won’t compile—you can’t add a score and an Int? Right?! We could make this change, which is probably the better way, but for my silly example, let’s say this isn’t ideal:

totalPoints = event.points() + totalPoints

So to make our code compile, we just need a plus function marked with the operator keyword. The Kotlin compiler is smart enough to make it work:

data class score(val type: scoreType) {
    fun points() = when (this.type) {
        scoreType.`try` -> 5
        scoreType.conversion -> 2
        scoreType.kick -> 3
    }

    operator fun plus(other: Int) = this.points() + other
}

How cool is that?! If I wanted to support totalPoints += event further, we’d need to add a function to Int that tells it how to add a score. Thankfully, that’s easy with extension functions:

operator fun Int.plus(other: score) = this + other.points()

Extensive Support

While the above is a bit silly, imagine building classes for distances, time, weights, etc.—being able to have a kilogram and a pound class and add them together! What makes Kotlin shine is how extensive it is. Just look at this list:

ClassOperatorsMethodExample Expression
Arithmetic+, +=plusfirst + second
Augmented Assignments+=plusAssignfirst += second
Unary+unaryPlus+first
Increment & Decrement++incfirst++
Arithmetic-, -=minusfirst - second
Augmented Assignments-=minusAssignfirst -= second
Unary-unaryMinus-first
Increment & Decrement--decfirst--
Arithmetic*, *=timesfirst * second
Augmented Assignments*=timesAssignfirst *= second
Arithmetic/, /=divfirst / second
Augmented Assignments/=divAssignfirst /= second
Arithmetic%, %=remfirst % second
Augmented Assignments%=remAssignfirst %= second
Equality==, !=equalsfirst == second
Comparison>, <compareTofirst > second
Unary!not!first
Range..rangeTofirst..second
Inin, !incontainsfirst in second
Index Access[, ]getfirst[index]
Index Access[, ]setfirst[index] = second
Invoke()invokefirst()

I’ll go through some of these in more detail in future blog posts, but one worth calling out now:

Augmented Assignments vs. plus/minus

You might wonder why implementing plus above gave us support for both + and +=—and why the table lists += under both categories. Why both?

Because you may want to support only += without supporting +.