# Welcome

Hi, I'm Rob. Thanks for visiting. I'm a full-stack software developer and these are my notes.

You can find me on [Github](https://github.com/robmurtagh), [Twitter](https://twitter.com/rjmurtagh), [Stack Overflow](https://stackoverflow.com/users/3052692/rjmurt), or at my [personal website](https://www.robmurtagh.com/).

## What notes I keep

This site is a record of things I don't find obvious in my day-to-day work. They are intended as a memory prompt rather than a complete explanation. Most of the notes here relate to software development on a Mac computer.

## How this site works

I keep notes in [Markdown](https://guides.github.com/features/mastering-markdown/) format, and build them as documentation pages using [Gitbook](https://www.gitbook.com/). You can find the published wiki [here](https://wiki.robmurtagh.com/) and the corresponding Github repo [here](https://github.com/robmurtagh/personal-wiki).

Please feel free to make a [Github pull request](https://help.github.com/articles/about-pull-requests/) if you think I could make any corrections or improvements.


# AWS

## AWS CLI

[Reference](https://docs.aws.amazon.com/cli/latest/reference/)


# Appsync

## Using API key auth

Add the following header to e.g. [Graphql Playground](https://github.com/prismagraphql/graphql-playground):

```javascript
{
  "x-api-key": "[DASHBOARD GENERATED API KEY]"
}
```


# Athena

## Add columns

```sql
ALTER TABLE db.table ADD COLUMNS (column_name string)
```

## Change column type (doesn't work?!)

```sql
ALTER TABLE db.table CHANGE column_name column_name timestamp;
```

## List all partitions

```sql
SHOW PARTITIONS appsflyer_stream
```

## Special characters

```sql
  SELECT column_name_1, "column-name-2", column_name_3, ##
  FROM db.table
  WHERE column_name_3 is not null
  ORDER BY timestamp_column DESC;
```

## Using a substring

```sql
SELECT event_name, substr(timestring, 1, 10) as datestring, count(##) AS count
FROM stream
WHERE test_mode != 'true' AND event_name = 'event_a'
GROUP BY event_name, substr(timestring, 1, 10)
ORDER BY datestring DESC
```

## Between timestamps

```sql
WHERE timestamp BETWEEN timestamp '2017-06-13 15:50:00.000' AND timestamp '2017-06-13 16:52:29.000'
```

## Null handling

```sql
WHERE column IS null
```

## Casting

```sql
SUM(CAST(sysvar_sales AS Double)) AS Sales
```

## Literals

```sql
true AS picnic_install
```


# S3

## Copy

```bash
aws s3 cp s3://example-src/ s3://example-dest/example-src/ --recursive
```

## Delete folder

```bash
aws s3 rm s3://example-bucket/example-folder/2018 --recursive --dryrun
```

## Get bucket size

```bash
aws s3 ls --summarize --human-readable --region eu-west-1 --recursive s3://example-bucket/
```

## Get bucket region

```bash
aws s3api get-bucket-location --bucket example-bucket
```


# Terminal


# brew

```bash
brew install tree zsh-autosuggestions
```


# curl

## Download raw HTML

The following allows us to see the original HTML etc before Javascript starts running and transforming the DOM:

```bash
curl -D - https://www.google.com/
```

```bash
curl -D - https://www.google.com/ > site.html
```


# git

## Amend the last commit

```bash
git commit --amend
git commit —-amend —-no-edit
```

## Squash commits

```bash
git rebase --interactive --root
```

## Force squash commits - e.g. down to root commit

```bash
rm -rf .git
git init
git add .
git commit -m "Initial commit"
```

## Forget file after adding to .gitignore

```bash
git rm --cached CREDENTIALS.py
```

## Push tags to origin

```bash
git push origin --tags
```

## General force push

```bash
git push -—force origin
```

## 'SVN update'

Something along the lines of the below should bring underlying versions up to date:

```bash
git stash
git pull
git stash pop
```

## Show remote URL

```bash
git remote show origin
```

## Useful resources

* [Using master, release and feature branches](https://medium.freecodecamp.org/how-to-use-git-efficiently-54320a236369) as a team

## Download one folder from repo

Use [DownGit](https://minhaskamal.github.io/DownGit/#/home)


# kubernetes

* You can describe a namespace (useful for e.g. `kube2iam`):

```bash
kubectl describe namespace [namespace]
```

* Gitops flux:

```bash
fluxctl sync --k8s-fwd-ns [namespace]
```

* Launch with terminal and custom entry point:

```bash
docker run -it --entrypoint=/bin/bash flyway/flyway:latest
```

* Work on dev machine:

```bash
kexec -it [pod] -- bash
```

* Deploy a yaml file with Kubernetes:

```bash
k create -f box.yaml
```

## Helm

* Helm deploy current directory chart:

```bash
helm install --name mysqltest2 .
helm install --name mysqltest2 --dry-run --debug .
```

```bash
helm repo list
helm repo update
helm search s3-mysqlrestore

helm plugin install https://github.com/chartmuseum/helm-push
helm push ./ https://dev-charts.k8s.corp.beno.ai
```

```bash
docker run -it --entrypoint bash gitlab.beno.ai:4567/ai/hypgen/biograph/aws:0.0.3
```


# ngrok

[ngrok](https://ngrok.com/) is incredibly useful for publishing `localhost` servers as temporary publicly available sites

Install it on your path and then run e.g.

```bash
ngrok http 8080
```

If you are running a `webpack-dev-server` you'll \[need to use]:(<https://stackoverflow.com/questions/45425721/invalid-host-header-when-ngrok-tries-to-connect-to-react-dev-server>):

```bash
ngrok http 8080 -host-header="localhost:8080"
```


# terminal

## Open a terminal from another (e.g. VSCode) terminal

```bash
open -a terminal .
```

## Add to path on Mac

```bash
vim /etc/paths
```

## Using pipe and grep

```bash
pip3 freeze | grep Xlsx
```

## Open current directory in finder

```bash
open .
```

## Find and kill process on a port

```bash
lsof -i tcp:3000
kill [PID]
```

## Recursively remove `node_modules`

```bash
find . -name "node_modules" -exec rm -rf '{}' +
```

## Location of a command in PATH

The following will return something along the lines of `hie is /Users/username/.local/bin/hie`:

```bash
type -a hie
```

## Common commands

* `clear` - clear the terminal
* `pwd` - print working directory
* `mkdir` - make directory
* `touch` - create a file (e.g. touch example.txt)
* `cp` - copy (e.g. cp file.txt target\_directory)
* `mv` - move (e.g. mv file.txt target\_directory), can also rename a file (e.g. mv old\_file\_name.txt new\_file\_name.txt)
* `rm` - remove (e.g. rm file.txt), can also remove files recursively (e.g. rm directory\_name)
* `echo` - send to stdout
* `cat` - read content of a file
* `alias` - set aliases (e.g. alias pd="pwd" means pd can be used interchangably with pwd)
* `export` - set environment variables!
* `env` - return list of environment variables
* `>` - redirect stdout to a file (e.g. echo "Hello" > hello.txt)
* `>>` - append stdout to a file
* `<` - redirct stdin to a command (e.g. cat < file.txt)
* `|` - pipe stdout of LHS as stdin to RHS
* `wc` - word count (of a text file)
* `uniq` - unique the contents of a file (on a line-wise basis?)
* `grep` - global regular expression print (-i adds case insensitivity, -R recursive, e.g. within directory)
* `sed` - 'streams editor', can be used for find and replace
* `nano` - text editor
* `source` - source \~/.bash\_profile makes all aliases available in the current session
* `history` - command history

## Environment settings

* Stored in:

```bash
~/.bash_profile
```

(where \~ is an alias for $HOME and . represents a hidden file)

## How cmd line works

* Most commands are stored in `/bin`
* `/bin` is a directory on the path (...and hence is available in a terminal session)
* Hence you can see all commands using: `cd /bin`, `ls`


# tmux

## Starting

```bash
tmux
tmux new -s sessionname
```

## Stopping

```bash
tmux kill-session -t sessionname
```

## Shortcuts

Tmux shortcut mode is:

```
^ + B
```

| Shortcut | Action             |
| -------- | ------------------ |
| `%`      | Split horizontally |
| `"`      | Split vertically   |
| `↓`      | Move panes         |


# zsh

I use [oh-my-zsh](https://github.com/ohmyzsh/ohmyzsh) as my primary shell.

## Turn on completions

Follow [these instructions](https://github.com/zsh-users/zsh-autosuggestions/blob/master/INSTALL.md#oh-my-zsh) to install command history tab complete.

## Turn off git branch prompts

```bash
git config --global oh-my-zsh.hide-status 1
```


# Design


# Sketch

The [Sketch Shortcut reference](http://sketchshortcuts.com/) is a really useful starting point. At the bottom it shows you how to 'Create Custom Shortcuts'. I tend to add the following manually:

## Collapse all groups

```
Alt + Cmd + C
```

## Sort artboards alphabetically

```
Cntrl + Shift + P
```

## Reverse sort artboards alphabetically

```
Cntrl + Shift + O
```

## Swap the position of two objects

* Install [Sketch Mate](https://github.com/getflourish/Sketch-Mate)
* Plugins > Sort > Reverse Positions


# Fusion360

## Basic mouse controls

* Pan: Click and drag middle wheel
* Orbit: Shift + Click and drag middle wheel
* Shortcuts: Right click + Drag

## Basic trackpad controls

* Pan: Two finger drag
* Orbit: Shift + Two finger drag
* Shortcuts: Two finger tap

## Rename a project

Data panel > Projects > Right click on project > Rename

## Useful shortcuts

* S - Model shortcuts > then search for command
* J - Joint > then hold command when hovering the object to joint for finer control


# TinkerCAD

[Tinkercad](https://www.tinkercad.com) is a great simple CAD program for 3D printing.

## Moving the camera

This isn't at all obvious, but as suggested by [this video](https://www.youtube.com/watch?v=TpwDAE5NgwE):

```
Shift + Right Click Drag
```


# Haskell


# Haskell

## GHCi

* `:reload` reload all names in scope
* `:quit`
* `:t 9` returns the type of `9`
* `:info []` returns lots of useful details about the implemented typeclasses
* `:k Int` returns the kind of `Int`
* `:set prompt  "\x03BB > "` would change the command prompt to `λ >`
* `:set -XExistentialQuantification` sets up the language extension

You can give [multiline input](https://en.wikibooks.org/wiki/Haskell/Using_GHCi_effectively) to GHCi as follows:

```
   *Main> :{
   *Main| let askname = do
   *Main|               putStrLn "What is your name?"
   *Main|               name <- getLine
   *Main|               putStrLn $ "Hello " ++ name
   *Main| :}
   *Main>
```

## General syntax

### Quick reference:

The best way to find out about these kind of constructs in ghci, e.g. `:info <*>`:

* `(.)` - Function composition
* `<*>`
* `$`

### Guard syntax

[Guard Syntax](https://en.wikibooks.org/wiki/Haskell/Control_structures#if_and_guards_revisited) allows us to conditionally check a statement within a pattern matching expression.

```haskell
describeLetter :: Char -> String
describeLetter c
   | c >= 'a' && c <= 'z' = "Lower case"
   | c >= 'A' && c <= 'Z' = "Upper case"
   | otherwise            = "Not an ASCII letter"
```

### 'where' clause

Define inline bindings (e.g. to functions or values). The [following example](http://learnyouahaskell.com/syntax-in-functions) uses guards and a where clase:

```haskell
bmiTell :: (RealFloat a) => a -> a -> String  
bmiTell weight height  
    | bmi <= 18.5 = "You're underweight, you emo, you!"  
    | bmi <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!"  
    | bmi <= 30.0 = "You're fat! Lose some weight, fatty!"  
    | otherwise   = "You're a whale, congratulations!"  
    where bmi = weight / height ^ 2
```

### 'as' Pattern

The 'as' pattern (described [here](https://stackoverflow.com/questions/1153465/what-does-the-symbol-mean-in-reference-to-lists-in-haskell), [here](http://learnyouahaskell.com/syntax-in-functions) and [here](https://www.haskell.org/onlinereport/exps.html#sect3.17.1)), gives us a way of matching a name for the entire element being pattern matched in a list:

The following would be read `all as (x:xs)`:

```haskell
capital :: String -> String  
capital "" = "Empty string, whoops!"  
capital all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x]
```

### Modules

[This page](http://learnyouahaskell.com/modules) from 'Learn you a Haskell' is a good reference.

* Import hiding

```haskell
import Data.List hiding (nub)
```

### Indentation

From [this page](https://en.wikibooks.org/wiki/Haskell/Indentation), the golden rule of indentation is:

> Code which is part of some expression should be indented further in than the beginning of that expression...All *grouped* expressions must be exactly aligned

But you can avoid indentation:

> Indentation is actually optional if you instead use semicolons and curly braces

## Types and Typeclasses

In the following snippet ([reference](https://wiki.haskell.org/Constructor)):

* `data` means we're declaring a new type
* `Expr` is the type constructor
* `I ...`, `Add ...`, `Mul ...` are the value constructors

```haskell
data Expr = I Int         -- integer constants
          | Add Expr Expr -- add two expressions
          | Mul Expr Expr -- multiply two expressions
```

* Adding `deriving (Show)` at the end of a data declaration automatically makes that type part of the Show typeclass ([reference](http://learnyouahaskell.com/making-our-own-types-and-typeclasses)):

```haskell
data Expr = I Int         -- integer constants
          | Add Expr Expr -- add two expressions
          | Mul Expr Expr -- multiply two expressions
          deriving (Show)
```

### Record syntax declarations

[Syntactic sugar](https://en.wikibooks.org/wiki/Haskell/More_on_datatypes#Named_Fields_\(Record_Syntax\)) providing data accessors:

```haskell
data Configuration = Configuration
    { username      :: String
    , localHost     :: String
    , remoteHost    :: String
    , isGuest       :: Bool
    , isSuperuser   :: Bool
    , currentDir    :: String
    , homeDir       :: String
    , timeConnected :: Integer
    }
```

You can pattern match against them:

```haskell
getHostData (Configuration { localHost = lh, remoteHost = rh }) = (lh, rh)
```

And create new versions with certain fields overwritten using:

```haskell
cfg { currentDir = newDir }
```

### `newtype` declarations

For the moment, I treat `newtype` as being broadly interchangable with `data` when creating a new type. There's documentation about it [here](https://wiki.haskell.org/Newtype).

### Typeclass: Semigroup

A set with an associative binary operation. Superset of Monoids.

### Typeclass: Monoids

[Monoid](https://en.wikibooks.org/wiki/Haskell/Monoids) is a typeclass with an associative `mappend` operation and an identity element.

> Integer numbers form a monoid under addition with 0 as identity element Integer numbers form a monoid under multiplication with 1 as identity element Lists form a monoid under concatenation with the empty list as identity element

`mappend` is given the infix synonym `(<>)`

### Generalised Algebraic Datatypes (GADTs)

The crux of [GADTs](https://en.wikibooks.org/wiki/Haskell/GADT) is that the provide a way to explicitly declare the type signature of each constructor.

The following language option is required:

```haskell
{-#LANGUAGE GADTs #-}
```

And then an example would be:

```haskell
data Maybe a where
   Nothing  :: Maybe a
   Just :: a -> Maybe a
```

## Miscellaneous

### Template Haskell

[Template Haskell](https://wiki.haskell.org/A_practical_Template_Haskell_Tutorial) is similar to Lisp macros.

```haskell
{-# LANGUAGE TemplateHaskell #-}
```

It is used e.g. by `lens` to generate the various lenses into data structures **at compile time**

### Forall Keyword

`forall` [imposes constraints on parameterising types](https://en.m.wikibooks.org/wiki/Haskell/Existentially_quantified_types) when defining new data types


# Stack, Cabal etc

[Stack](https://docs.haskellstack.org/en/stable/README/) is *a* (not the only) Haskell standard for scaffolding, building, packaging and managing dependencies for a project. It uses [Cabal](https://www.haskell.org/cabal/) under the covers. The interplay between Stack, Cabal and [HPack](https://github.com/sol/hpack) makes this area a bit of a minefield.

## Start a new stack project

In parent directory, where `simple` is the template from `stack templates` list:

```bash
stack new [project-name] simple
```

## Run ghci

GHCi session in the context of the current project:

```bash
stack ghci
```

## Build and run executable

```bash
stack build && stack exec package-name-exe
```

## Install a dependency

* For a global package install, (like `npm install -g package`) use cabal NOT stack:

```bash
cabal update && cabal install package
```

* For a local package install restricted to only a stack project (like `npm install --save package`):

```
    dependencies:
    - haskell-hspec
    - hspec
    - QuickCheck
```

* This will in turn generate an edit to the project's Cabal file `project.cabal`:

```
  build-depends:       base
                     , haskell-hspec
                     , hspec
                     , QuickCheck
```

## List depedencies

```bash
stack list-dependencies
```

## Pass and argument to stack ghc

```bash
stack ghc -- --supported-extensions
```

## Environment setup

### What is my global ghc, why, and how do I change it?

Global ghc could have been installed in all sorts of ways, it is found by running:

```bash
ghc -v
```

But really you probably want to be using a Stack managed global setup e.g. outside of a project folder, run one of the following commands:

```bash
stack ghci -v
stack ghc -v
```

This should tell you in the logs that you are using e.g. `.stack/global-project/stack.yaml`. The `resolver` field in this file will determine which ghc version you are using.

### What is my project GHC, why, and where is it stored?

The project ghc is set via the local `stack.yaml`, again using the resolver to determine the version. ghc itself will be installed somewhere centrally by Stack.

### What are my globally installed packages, why, and where are they stored?

The following command when run globally tells you all of the packages which are installed:

```bash
ghc-pkg list
```

### What are my project installed packages, why, and where are they stored?

```bash
stack list-dependencies
```

### Where does stack build my executables?

```bash
stack path --local-install-root
```

## Useful resources

* [Problems with Cabal and how to avoid](https://wiki.haskell.org/Cabal/Survival)
* [Cabal github repo](https://github.com/haskell/cabal)
* [Why is Stack not Cabal](https://www.fpcomplete.com/blog/2015/06/why-is-stack-not-cabal)
* [Stackage is Stable Hackage and packages here have been tested to avoid dependency conflicts](https://www.stackage.org/)
* [Stack.yaml versus .Cabal](https://docs.haskellstack.org/en/stable/stack_yaml_vs_cabal_package_file/)
* [Stack FAQs](https://github.com/commercialhaskell/stack/blob/master/doc/faq.md)

## Notes

The logic for resolving dependencies without and with Stack is as follows:

* Packages GHC can use > Are registered with "ghc-pkg register" > And (almost always) built with Cabal > With build dependencies resolved by cabal-install > From Hackage.
* Packages GHC can use > Are registered with "ghc-pkg register" > And (almost always) built with Cabal > With build dependencies resolved by stack > From Stackage (if possible...) or Hackage

Stackage specifies a 'resolver'

> a GHC version, a number of packages available for installation, and various settings like build flags"

[Global Stack managed dependencies](https://docs.haskellstack.org/en/stable/yaml_configuration/):

* `/etc/stack/config.yaml` - for system global non-project default options
* `~/.stack/config.yaml` - for user non-project default options

When stack is invoked outside a stack project it will source project specific options from `~/.stack/global-project/stack.yaml`. When stack is invoked inside a stack project, only options from `<project dir>/stack.yaml` are used, and `~/.stack/global-project/stack.yaml` is ignored.


# Javascript


# Javascript

## Spread syntax

Use the [Spread Syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) to expand an iterable (e.g. an object) into its components.

An example of merging with shallow clone would be:

```javascript
var obj1 = { a: "b" };
var obj2 = { c: "b" };
var obj3 = { ...obj1, ...obj2 };
console.log(obj3);
```

* `obj3` contains a copy of `obj1` and `obj2` as they were when `obj3` was created
* `obj3` is not a reference to the current state of `obj1` and `obj2`

## Executing asynchronous functions in series and parallel

Example snippet:

```javascript
const executeInSeries = async promises => {
  var results = [];
  for (let promise of promises) {
    results.push(await promise());
  }
  return results;
};

const executeInParallel = promises => {
  return Promise.all(promises);
};

const generateTimeoutPromise = () => {
  return new Promise((resolve, _reject) => {
    setTimeout(() => {
      console.log("COMPLETE: timeoutPromise");
      resolve("RESOLVED: Complete");
    }, 2000);
  });
};

executeInSeries([
  generateTimeoutPromise,
  generateTimeoutPromise,
  generateTimeoutPromise
]).then(results => {
  console.log("COMPLETE: executeInSeries");
  console.log("RESOLVED: executeInSeries");
  console.log(results);
});

executeInParallel([
  generateTimeoutPromise(),
  generateTimeoutPromise(),
  generateTimeoutPromise()
]).then(results => {
  console.log("COMPLETE: executeInParallel");
  console.log("RESOLVED: executeInParallel");
  console.log(results);
});
```

## .prettierrc Configuration

My preferred `.prettierrc` settings are:

```javascript
{
  "printWidth": 140,
  "trailingComma": "es5",
  "jsxBracketSameLine": true,
  "arrowParens": "always",
  "tabWidth": 4,
  "noSemi": true
}
```

On a JS project I tend to turn on format on save (VSCode > Preferences > Settings > Workspace Settings > `settings.json`)

```javascript
{
  "editor.formatOnSave": true
}
```

I use a `.prettierignore` for individual files I don't way to format within the project.

Finally I have the following setting to always turn off certain file types from formatting (VSCode > Preferences > Settings > User Settings > `settings.json`):

```javascript
"[handlebars]": {
  "editor.formatOnSave": false
}
```

## ESLint

ESLint apparently respects the following element of `package.json`:

```javascript
"engines": {
    "node": ">=10.6.0"
}
```

I tend to also add the following `.eslintrc` to support ES6 features:

```javascript
{
  "env": {
    "es6": true
  }
}
```


# npm

## Create command line utility for project

In your `package.json`, include (see also package.json docs [here](https://docs.npmjs.com/files/package.json)):

```javascript
{ "bin" : { "myapp" : "./cli.js" } }
```

Making sure the relevant script has the header:

```javascript
#!/usr/bin/env node
```

## Locally install the command line utility

```bash
npm link
```


# Vue

## Shorthands

`@` is a synonym for `v-on:` `v-bind` can be dropped (e.g. `v-bind:href='var1'` is the same as `:href='var1'`)


# CSS

## box-sizing

It's useful to be aware of [box-sizing](https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing) which governs how borders are included in `div` size calculations.

## Pseudo elements

* [Pseudo elements](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements) are worth remembering, they let you style an element based on some property of that element (e.g. `::first-line`), or add elements to the DOM in a suitable position (e.g. `::before`, `::after`).
* Proper syntax is `::selector`, however `:selector` seems to be more universally supported

## Tachyons

[Tachyons](http://tachyons.io) is an excellent 'functional CSS' library in which each class name has one responsibility. For example the Tachyons class `.ba` stands for `border-style:solid;border-width:1px`, there would not be a Tachyons class called e.g. `.button-active` as that would encompass many different - design specific - CSS functions.

### Tachyons Media Queries

Tachyons classes have suffixes:

* `[no-suffix]` = applies for all screensizes, and hence is the 'mobile' version
* `-ns` = not-small (min-width: 30em)
* `-m` = medium (min-width: 30em) and (max-width: 60em)
* `-l` = large (min-width: 60em)

## Diagonal block colour background

```markup
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title>Diagonal Background</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style>
      #elem-container {
        height: 100%;
      }
      #elem {
        position: relative;
      }
      #elem:before {
        content: ""; /* an empty div */
        height: 120%; /* with a height settable against parent container */
        width: 135%; /* wider than the page so you can't see the edges */
        position: absolute; /* outside of the document flow */
        z-index: -1; /* and behind the #elem */
        display: block;
        background-color: lightblue; /* and behind the #elem */
        transform: rotate(12deg);
        left: -15%; /* with offsets as required */
        top: -15%;
      }
    </style>
  </head>
  <body>
    <div id="elem-container">
      <div id="elem">
        <p>
          Lorem ipsum dolor sit amet, at per iudicabit periculis, an officiis
          salutandi vel. Sit an meis adhuc.
        </p>
        <p>
          Lorem ipsum dolor sit amet, at per iudicabit periculis, an officiis
          salutandi vel. Sit an meis adhuc.
        </p>
        <p>
          Lorem ipsum dolor sit amet, at per iudicabit periculis, an officiis
          salutandi vel. Sit an meis adhuc.
        </p>
        <p>
          Lorem ipsum dolor sit amet, at per iudicabit periculis, an officiis
          salutandi vel. Sit an meis adhuc.
        </p>
      </div>
    </div>
  </body>
</html>
```

## Diagonal background with before and after

```markup
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title>Page title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style>
      #elem-container {
        height: 100%;
      }
      #elem {
        position: relative;
      }
      #elem:before {
        content: ""; /* an empty div */
        height: 100%; /* with a height settable against parent container */
        width: 135%; /* wider than the page so you can't see the edges */
        position: absolute; /* outside of the document flow */
        z-index: -1; /* and behind the #elem */
        display: block;
        background-color: lightblue; /* and behind the #elem */
        transform: rotate(12deg);
        left: -15%; /* with offsets as required */
        top: -35%;
      }
      #elem:after {
        content: "";
        height: 120%;
        width: 135%;
        position: absolute;
        z-index: -2;
        display: block;
        background-color: darkblue;
        transform: rotate(-12deg);
        left: -15%;
        top: -5%;
      }
    </style>
  </head>
  <body>
    <div id="elem-container">
      <div id="elem">
        <p>
          Lorem ipsum dolor sit amet, at per iudicabit periculis, an officiis
          salutandi vel. Sit an meis adhuc.
        </p>
        <p>
          Lorem ipsum dolor sit amet, at per iudicabit periculis, an officiis
          salutandi vel. Sit an meis adhuc.
        </p>
        <p>
          Lorem ipsum dolor sit amet, at per iudicabit periculis, an officiis
          salutandi vel. Sit an meis adhuc.
        </p>
        <p>
          Lorem ipsum dolor sit amet, at per iudicabit periculis, an officiis
          salutandi vel. Sit an meis adhuc.
        </p>
        <p>
          Lorem ipsum dolor sit amet, at per iudicabit periculis, an officiis
          salutandi vel. Sit an meis adhuc.
        </p>
        <p>
          Lorem ipsum dolor sit amet, at per iudicabit periculis, an officiis
          salutandi vel. Sit an meis adhuc.
        </p>
        <p>
          Lorem ipsum dolor sit amet, at per iudicabit periculis, an officiis
          salutandi vel. Sit an meis adhuc.
        </p>
        <p>
          Lorem ipsum dolor sit amet, at per iudicabit periculis, an officiis
          salutandi vel. Sit an meis adhuc.
        </p>
      </div>
    </div>
  </body>
</html>
```


# Mac

## Paste without formatting

```
Command + Shift + V
```

## Reveal desktop

```
Cmd + F3
```

## Create new directory

(If the parent directory is too full there's nowhere to right click)

```
Cmd + Shift + N
```

## Switch between two windows of the same app

```
Command + `
```

## Show/hide hidden folders

```
Command + Shift + .
```

## Change default column width

```
Alt (aka Option, ⌥) + Drag Width
```

## Change default app

[RCDefault](http://www.rubicode.com/Software/RCDefaultApp/) lets you change the default application by e.g. file extension. When you install, it gets added to your system preferences panel

## Add custom app shortcuts

![Mac Shortcuts](https://3546211403-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LGypgp18DNbGtog9Ert%2F-LQZ-LTk2kIyV40NELr_%2F-LQZ-M8tHHhcjcQLnMt6%2Fmac-shortcuts.png?generation=1541423593092231\&alt=media)


# Python


# iPython

## List kernels

```bash
ipython kernelspec list
ipython3 kernelspec list
```

## Add kernels

Run the commands above, then open the files they return and make edits


# pip

## Full reinstall

```bash
sudo pip3 install --upgrade --force-reinstall pylint
```

## Where has `pip` installed everything related to a module?

```bash
pip3 show -f pylint > output.txt
```

## Alternative e.g. `pip3` syntax

```bash
python3 -m pip install [module]
```


# Virtualenv

## Python 3 virtual environment

```bash
virtualenv -p python3 --no-site-packages venv
```

## Activate the virtual environment

```bash
source venv/bin/activate
```


# Scala

## sbt (Scala Build Tool)

[Getting started](https://docs.scala-lang.org/getting-started-sbt-track/getting-started-with-scala-and-sbt-on-the-command-line.html) for quick installation etc

## sbt watch (\~) and rebuild:

```bash
sbt ~run
```

## sbt help

```bash
sbt help
```

## sbt shell

```bash
sbt console
```


# Rust

## Installation

Install [rustup](https://github.com/rust-lang-nursery/rustup.rs):

```bash
brew install rustup-init
rustup-init
```

Install [Rust Language Server](https://github.com/rust-lang-nursery/rls):

```bash
rustup update
rustup component add rls-preview rust-analysis rust-src
```

Install the [Rust Language Server VSCode extension](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust)

## Hello World

From [Rust by Example](https://doc.rust-lang.org/rust-by-example/):

```rust
// hello.rs
fn main() {
    println!("Hello World!");
}
```

```bash
rustc hello.rs
./hello
```

## Packaging etc

* Packaging is done with [Cargo](https://doc.rust-lang.org/cargo/index.html)
* Each distributed package is called a Crate
* The primary Crate registry is [Crates.io](https://crates.io/)
* A simple starting guide is [here](https://doc.rust-lang.org/cargo/getting-started/first-steps.html)

To create a new project, then compile and run it:

```bash
cargo new rust_example
cd rust_example
cargo run
```

* [Add dependencies](https://doc.rust-lang.org/cargo/guide/dependencies.html) to Cargo.toml


# VSCode

## Add `code` to terminal

See [this page](https://code.visualstudio.com/docs/setup/mac) for adding the `code` command so VSCode can be launched from terminal:

```bash
code some_directory
```

## Choose tab

```
Control + [Tab number]
```

## Go to definition

Usually you can Cmd + Click or use `F12`

## Go back from defintion

Preferences > Keyboard Shortcut > workbench.action.navigateBack:

```
Cntrl + -
```

## List all functions in a script

Preferences > Keyboard Shortcut > workbench.action.gotoSymbol:

```
Cmd + Shift + O
(optionally then type ':')
```


# Keyboard Shortcuts

## VSCode

| Shortcut        | Description               | VSCode Name                        | Custom shortcut? |
| --------------- | ------------------------- | ---------------------------------- | ---------------- |
| `⌘ + P`         | Go to file dialog         |                                    |                  |
| `⌘ + ⇧ + P`     | Shortcut dialog           |                                    |                  |
| `⌘ + ⇧ + /`     | Focus editor              | View: Focus Next Editor Group      | ✓                |
| `⌘ + ⇧ + T`     | Focus terminal            | Terminal: Focus Terminal           | ✓                |
| `⌘ + ⇧ + E`     | Focus file explorer       | View: Show Explorer                |                  |
| `⌘ + K , ↵`     | Keep editor page open     | View: Keep Editor                  |                  |
| `⌘ + K , ⌘ + W` | Close all open tabs       | View: Close All Editors            |                  |
| `⌘ + ⇧ + [`     | Next tab                  | View: Open Next Editor             |                  |
| `⌘ + ⇧ + ]`     | Prev tab                  | View: Open Previous Editor         |                  |
| `⌘ + ↓`         | Open editor from explorer |                                    | ✓                |
| `⌥ + ⌘ + C`     | Collapse explorer folders | File: Collapse Folders in Explorer | ✓                |
| `^ + -`         | Go back from definition   |                                    |                  |
| `^ + =`         | Go to definition          |                                    | ✓                |
| `^ + ⌥ + Z`     | Refresh git               | Refresh git                        | ✓                |

[Shortcuts reference](https://code.visualstudio.com/shortcuts/keyboard-shortcuts-macos.pdf)

## Mac, Chrome etc

| Shortcut    | Description                                                | Custom shortcut?                                                     |
| ----------- | ---------------------------------------------------------- | -------------------------------------------------------------------- |
| `⌥ + ⌘ + →` | Chrome: Next tab                                           |                                                                      |
| `⌘ + W`     | Mac: Close current tab                                     |                                                                      |
| `⌘ + M`     | Mac: Minimize the current tab to dock                      |                                                                      |
| `⌘ + ⇥ + ↓` | Mac: Use the arrow keys to navigate and reopen closed tabs |                                                                      |
| `^ + ⌘ + ↑` | Mac: Expand window                                         | ✓ (Keyboard > Shortcuts > App Shortcuts > All Applications > 'Zoom') |

## Character Index

* `⌘` = Command
* `^` = Control
* `↵` = Enter
* `⇥` = Tab
* `⌥` = Option (/Alt)
* `↑` = Up key
* `↓` = Down key
* `←` = Left key
* `→` = Right key


