Dev Reference

Cross-language function lookups, CSS, Git commands, VSCode, and Regex, all in one place.

Documentation Sites: PHP JavaScript Java Ruby Python Wolfram Language HTML CSS Shell SQL Git VSCode Regex

String Operations

Replacing, splitting, joining, and matching text.

Replace all occurrences
str_replace('foo', 'bar', $str)
str.replaceAll('foo', 'bar')

Older engines: str.replace(/foo/g, 'bar')

str.replace("foo", "bar")

.replace() is literal and already replaces all instances (unlike .replaceAll, which takes regex).

str.gsub('foo', 'bar')
str.replace('foo', 'bar')
StringReplace[str, "foo" -> "bar"]
Replace with regex
preg_replace('/\d+/', 'NUM', $str)
str.replace(/\d+/g, 'NUM')
str.replaceAll("\\d+", "NUM")
str.gsub(/\d+/, 'NUM')
re.sub(r'\d+', 'NUM', str)
StringReplace[str,
  RegularExpression["\\d+"] -> "NUM"]

Or a native pattern: DigitCharacter.. -> "NUM"

Replace only first match (or first n)
preg_replace('/foo/', 'bar', $str, 1)

str_replace has no built-in limit.

str.replace('foo', 'bar')

A string (not regex) argument replaces only the first hit.

str.replaceFirst("foo", "bar")
str.sub('foo', 'bar')

.sub replaces only the first match; .gsub replaces all.

str.replace('foo', 'bar', 1)

Third argument caps the number of replacements.

StringReplace[str, "foo" -> "bar", 1]

Third argument caps the number of replacements.

Split into a list
explode(',', $str)
str.split(',')
str.split(",")

Takes a regex, so ., |, etc. need escaping.

str.split(',')
str.split(',')
StringSplit[str, ","]
Join a list into a string
implode(', ', $arr)
arr.join(', ')
String.join(", ", list)

Or list.stream().collect(Collectors.joining(", "))

arr.join(', ')
', '.join(arr)
StringRiffle[list, ", "]
Trim whitespace
trim($str)
str.trim()
str.strip()

Java 11+, Unicode-aware. Older code uses .trim() (ASCII whitespace only).

str.strip
str.strip()
StringTrim[str]
Substring / find index
substr($str, 2, 4)
strpos($str, 'needle')
str.substring(2, 6)
str.indexOf('needle')
str.substring(2, 6)
str.indexOf("needle")
str[2, 4]
str.index('needle')
str[2:6]
str.find('needle')
StringTake[str, {3, 6}]
StringPosition[str, "needle"]

StringTake uses 1-based, inclusive indices.

Change case
strtoupper($str)
strtolower($str)
str.toUpperCase()
str.toLowerCase()
str.toUpperCase()
str.toLowerCase()
str.upcase
str.downcase
str.upper()
str.lower()
ToUpperCase[str]
ToLowerCase[str]
Test / extract with regex
preg_match('/^\d+$/', $str, $m)
/^\d+$/.test(str)
str.match(/\d+/g)
Pattern.matches("^\\d+$", str)
Pattern.compile("\\d+").matcher(str)
str.match?(/^\d+$/)
str.scan(/\d+/)
re.match(r'^\d+$', str)
re.findall(r'\d+', str)
StringMatchQ[str, RegularExpression["^\\d+$"]]
StringCases[str, RegularExpression["\\d+"]]

Wolfram also has its own native string-pattern syntax as an alternative to regex.

Arrays / Lists

Creating, transforming, and querying collections.

Create a list & get its length
$arr = [1, 2, 3];
count($arr)
const arr = [1, 2, 3];
arr.length
List<Integer> list = List.of(1, 2, 3);
list.size()

Plain array: int[] a = {1,2,3}; a.length

arr = [1, 2, 3]
arr.length
arr = [1, 2, 3]
len(arr)
list = {1, 2, 3};
Length[list]
Map — transform each element
array_map(fn($x) => $x * 2, $arr)
arr.map(x => x * 2)
list.stream()
    .map(x -> x * 2)
    .collect(Collectors.toList())
arr.map { |x| x * 2 }
[x * 2 for x in arr]

Or list(map(lambda x: x * 2, arr))

Map[#*2 &, list]

Shorthand: 2*# & /@ list

Filter
array_filter($arr, fn($x) => $x > 2)

Keeps original keys — pair with array_values() to reindex.

arr.filter(x => x > 2)
list.stream()
    .filter(x -> x > 2)
    .collect(Collectors.toList())
arr.select { |x| x > 2 }
[x for x in arr if x > 2]

Or list(filter(lambda x: x > 2, arr))

Select[list, # > 2 &]
Reduce / fold to a single value
array_reduce($arr,
  fn($carry, $x) => $carry + $x, 0)
arr.reduce((acc, x) => acc + x, 0)
list.stream().reduce(0, Integer::sum)
arr.reduce(0) { |acc, x| acc + x }

For a plain sum, arr.sum is simpler.

functools.reduce(lambda acc, x: acc + x, arr, 0)

For a plain sum, sum(arr) is simpler.

Fold[Plus, 0, list]

For a plain sum, Total[list] is simpler.

Sort
sort($arr);
usort($arr, fn($a, $b) => $a <=> $b)

Both mutate in place and reindex keys.

arr.sort((a, b) => a - b)

Mutates in place. Without a comparator, sorts elements as strings.

Collections.sort(list);
list.sort(Comparator.naturalOrder())
arr.sort
arr.sort_by { |x| key(x) }

Non-destructive. Use sort! / sort_by! to mutate in place.

sorted(arr)
arr.sort()

sorted() returns a new list; .sort() mutates in place.

Sort[list]
SortBy[list, keyFn]

Non-destructive — returns a new sorted list.

Check membership
in_array($needle, $arr)
arr.includes(x)
list.contains(x)
arr.include?(x)
x in arr
MemberQ[list, x]

Objects

Key-value structures, and defining/using classes.

Create a key-value object
$obj = ['name' => 'Ada', 'age' => 36];

Or (object) [...] for a stdClass with -> access.

const obj = { name: 'Ada', age: 36 };
Map<String, Object> obj = new HashMap<>();
obj.put("name", "Ada");
obj.put("age", 36);

Immutable version: Map.of("name", "Ada", "age", 36)

obj = { name: 'Ada', age: 36 }
obj = {'name': 'Ada', 'age': 36}
assoc = <|"name" -> "Ada", "age" -> 36|>;
Get a property/value
$obj['name']

Object form: $obj->name

obj.name
obj['name']
obj.get("name")
obj[:name]
obj['name']
assoc["name"]
Set/update a property
$obj['name'] = 'Grace';

Object form: $obj->name = 'Grace';

obj.name = 'Grace';
obj.put("name", "Grace");
obj[:name] = 'Grace'
obj['name'] = 'Grace'
AssociateTo[assoc, "name" -> "Grace"]

Direct part assignment also works: assoc[["name"]] = "Grace"

Check if a key exists
array_key_exists('name', $obj)
'name' in obj
Object.hasOwn(obj, 'name')
obj.containsKey("name")
obj.key?(:name)
'name' in obj
KeyExistsQ[assoc, "name"]
Iterate over keys/values
foreach ($obj as $key => $value) { ... }
for (const [key, value] of Object.entries(obj)) { ... }

Or Object.keys(obj) / Object.values(obj)

for (var e : obj.entrySet()) { ... }
obj.each { |key, value| ... }

Or obj.keys / obj.values

for key, value in obj.items(): ...

Or obj.keys() / obj.values()

KeyValueMap[f, assoc]

Or Keys[assoc] / Values[assoc]

Merge two objects
array_merge($obj1, $obj2)
{ ...obj1, ...obj2 }
Map<String, Object> merged = new HashMap<>(obj1);
merged.putAll(obj2);
obj1.merge(obj2)

Keys from obj2 win on conflict.

{**obj1, **obj2}

Or obj1 | obj2 (3.9+). Keys from obj2 win on conflict.

Join[assoc1, assoc2]

Keys from assoc2 win on conflict, same as JS spread.

Define a class with properties & a method
class Person {
    public function __construct(
        public string $name,
        public int $age
    ) {}
    public function greet() {
        return "Hi, I'm {$this->name}";
    }
}
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  greet() {
    return `Hi, I'm ${this.name}`;
  }
}
class Person {
    String name;
    int age;
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    String greet() {
        return "Hi, I'm " + name;
    }
}
class Person
  def initialize(name, age)
    @name = name
    @age = age
  end
  def greet
    "Hi, I'm #{@name}"
  end
end
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def greet(self):
        return f"Hi, I'm {self.name}"
Person[name_, age_] := <|"name" -> name, "age" -> age|>
greet[p_Association] := "Hi, I'm " <> p["name"]

No built-in class syntax — the idiomatic pattern is a constructor function returning an Association, plus ordinary functions that operate on it.

Create an instance & call a method
$p = new Person('Ada', 36);
$p->greet();
const p = new Person('Ada', 36);
p.greet();
Person p = new Person("Ada", 36);
p.greet();
p = Person.new('Ada', 36)
p.greet
p = Person('Ada', 36)
p.greet()
p = Person["Ada", 36];
greet[p]

Dates & Times (5)

Getting the current time, formatting, parsing, and doing date math.

Current date/time
new DateTime()
new Date()
LocalDateTime.now()
Time.now

Or Date.today for a date-only object.

datetime.now()

Or date.today() for a date-only object.

Now

Or DateObject[] for a date-only object.

Format a date
$dt->format('Y-m-d')
date.toISOString().slice(0, 10)

No built-in format-string API (like Y-m-d);

new Intl.DateTimeFormat('en-US', {
  year: 'numeric', month: '2-digit', day: '2-digit'
}).format(date)
// -> "01/15/2024"

Intl.DateTimeFormat is the standard, locale-aware way to control the output shape. Reuse one formatter instance for repeated calls — it's relatively expensive to construct.

DateTimeFormatter.ofPattern("yyyy-MM-dd")
  .format(date)
dt.strftime('%Y-%m-%d')
dt.strftime('%Y-%m-%d')

Or dt.date().isoformat() for ISO 8601.

DateString[date, "ISODateTime"]
DateString[date, {"Year", "-", "Month", "-", "Day"}]
Parse a date string
DateTime::createFromFormat('Y-m-d', $str)
new Date(str)

Parsing is somewhat implementation-dependent for non-ISO formats.

LocalDate.parse("2024-01-15")
Date.parse('2024-01-15')
datetime.strptime('2024-01-15', '%Y-%m-%d')

Or date.fromisoformat('2024-01-15') for ISO strings.

DateObject["2024-01-15"]
Add days
$dt->modify('+7 days')
date.setDate(date.getDate() + 7)
date.plusDays(7)
date + 7
date + timedelta(days=7)
DatePlus[date, 7]
Difference between two dates
$d1->diff($d2)
(d2 - d1) / 86400000

Manual math on millisecond timestamps; no built-in duration helper.

ChronoUnit.DAYS.between(d1, d2)
(d2 - d1).to_i

Date subtraction returns a Rational number of days.

(d2 - d1).days
DateDifference[d1, d2]

JSON

Converting between JSON text and native data structures.

Parse JSON text
json_decode($str, true)

The true flag returns an associative array instead of an object.

JSON.parse(str)
new ObjectMapper().readValue(str, Map.class)

No built-in JSON support — needs a library (Jackson or Gson shown here).

JSON.parse(str)
json.loads(str)
ImportString[str, "RawJSON"]
Convert to JSON text
json_encode($arr)
JSON.stringify(obj)
new ObjectMapper().writeValueAsString(obj)
obj.to_json
json.dumps(obj)
ExportString[expr, "RawJSON"]

HTML Reference

Semantic elements, forms, media, and meta tags worth having on hand.

Document Structure
Boilerplate skeleton
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Page</title>
</head>
<body>
</body>
</html>
Character encoding & viewport meta
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

The viewport tag is required for responsive layouts to work at all on mobile — without it, the page renders zoomed out at desktop width.

SEO / social preview meta tags
<meta name="description" content="Page summary">
<meta property="og:title" content="Page title">
<meta property="og:image" content="/preview.png">

og:* (Open Graph) tags control how the page renders when shared on social platforms and in chat apps.

Link an external stylesheet / favicon
<link rel="stylesheet" href="/styles.css">
<link rel="icon" href="/favicon.ico">

Goes in <head>, unlike <script> which is usually placed at the end of <body> (or uses defer).

Preload / preconnect hints
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="preload" href="/hero.webp" as="image">

Hints the browser to fetch a critical resource earlier than it otherwise would — overusing them competes for the same bandwidth and can slow things down instead.

Canonical URL
<link rel="canonical" href="https://example.com/page">

Tells search engines which URL is the "real" one when the same content is reachable through multiple URLs (tracking params, http/https, trailing slash).

Inline stylesheet
<style>
  body { margin: 0; }
</style>

Valid in <head> or <body>, but conventionally kept in <head> alongside linked stylesheets.

Inline / external script, load timing
<script src="/app.js" defer></script>
<script>
  console.log('inline');
</script>

defer runs the script after parsing finishes, in document order — usually what you want for a page script placed in <head>. async runs it as soon as it's loaded, in whatever order that happens, which is fine for independent scripts (analytics) but not for ones with dependencies between them.

Semantic Layout Elements
Page landmarks
<header></header>
<nav></nav>
<main></main>
<aside></aside>
<footer></footer>

Prefer these over generic <div>s where they fit — screen readers use them as navigation landmarks.

Self-contained content block
<article>
  <h2>Title</h2>
  <p>...</p>
</article>

<article> is for content that could stand alone (a post, a card); <section> is for a thematic grouping within the page.

Collapsible disclosure widget
<details>
  <summary>Click to expand</summary>
  <p>Hidden content</p>
</details>

Native expand/collapse behavior with no JavaScript required.

Search landmark
<search>
  <form action="/search">
    <input type="search" name="q">
  </form>
</search>

Marks a search/filter form as a landmark region, same idea as <nav>. Newer element (Baseline 2024) — check target browser support before relying on it.

Unordered / ordered lists
<ul>
  <li>Item</li>
</ul>
<ol start="3" reversed>
  <li>Item</li>
</ol>

ol's start/reversed attributes control the numbering; use <ul> whenever order doesn't matter.

Description list (term/definition pairs)
<dl>
  <dt>HTML</dt>
  <dd>HyperText Markup Language</dd>
</dl>

Also fits key-value data like a glossary or metadata panel, not just dictionary-style definitions.

Text Formatting
Bold / italic vs strong/emphasis
<b>bold text</b>
<i>italic text</i>
<strong>important text</strong>
<em>emphasized text</em>

<b>/<i> are purely visual with no semantic weight; <strong>/<em> convey importance/stress emphasis to assistive tech and typically render the same way visually. Prefer the semantic pair unless the bold/italic really is just a stylistic choice (a book title, a keyword being defined).

Subscript / superscript
H<sub>2</sub>O
x<sup>2</sup>
Tables
Basic table structure
<table>
  <thead>
    <tr><th>Name</th><th>Age</th></tr>
  </thead>
  <tbody>
    <tr><td>Ada</td><td>36</td></tr>
  </tbody>
</table>

<thead>/<tbody> are optional but recommended — they let a long table's header repeat across printed pages and give styling hooks.

Table caption & footer
<table>
  <caption>Quarterly Revenue</caption>
  ...
  <tfoot>
    <tr><td>Total</td><td>$42k</td></tr>
  </tfoot>
</table>

<caption> must be the first child of <table>.

Merge cells across columns/rows
<td colspan="2">Spans two columns</td>
<td rowspan="2">Spans two rows</td>
Associate a header cell with its scope
<th scope="col">Name</th>
<th scope="row">Row label</th>

scope tells screen readers which cells a header applies to — important for any table more complex than a simple grid.

Forms & Inputs
Basic form with method/action
<form method="post" action="/submit">
  <input type="text" name="q" required>
  <button type="submit">Go</button>
</form>
Text-like input types
<input type="text">
<input type="email">
<input type="password">
<input type="search">
<input type="tel">
<input type="url">

Using the right type gets you built-in validation and the matching mobile keyboard for free — email/tel/url each swap in a purpose-built keyboard layout on mobile.

Number / range / date & time
<input type="number" min="0" max="10" step="1">
<input type="range" min="0" max="100">
<input type="date">
<input type="time">
<input type="datetime-local">
<input type="month">
<input type="week">

Date/time inputs return values in a fixed ISO-like format regardless of the user's locale, which native display uses for formatting.

Checkbox / radio / toggle-style
<input type="checkbox">
<input type="radio" name="choice">

Radios sharing the same name form a mutually-exclusive group.

File upload
<input type="file" accept="image/*" multiple>

accept is a hint the OS file picker uses to pre-filter — it's not a security control, so still validate the upload server-side.

Color picker
<input type="color" value="#b3541e">
Hidden field
<input type="hidden" name="csrf_token" value="...">

Still present in the DOM/page source — never a substitute for real server-side authorization.

Label an input
<label for="email">Email</label>
<input id="email" type="email">

Matching for/id lets clicking the label focus the input, and is required for screen readers to announce it correctly.

Dropdown select
<select name="color">
  <option value="r">Red</option>
  <option value="b" selected>Blue</option>
</select>
Multi-line text input
<textarea name="bio" rows="4" cols="40"></textarea>

Default content goes between the tags, not in a value attribute.

Autocomplete suggestions for an input
<input list="browsers" name="browser">
<datalist id="browsers">
  <option value="Chrome">
  <option value="Firefox">
</datalist>

Unlike <select>, the user can still type a value not in the list.

Group related fields with a caption
<fieldset>
  <legend>Shipping Address</legend>
  <input type="text" name="street">
</fieldset>

<legend> must be the first child of <fieldset>. Disabling the fieldset disables every field inside it at once.

Clickable submit/reset/generic button
<button type="submit">Save</button>
<button type="reset">Clear</button>
<button type="button">Just JS</button>

Inside a <form>, a <button> with no explicit type defaults to submit — a common source of accidental form submissions.

Progress / meter indicators
<progress value="70" max="100"></progress>
<meter value="0.7" min="0" max="1"></meter>

<progress> is for task completion; <meter> is for a scalar measurement within a known range (disk usage, a rating).

Output of a calculation
<output name="result" for="a b">42</output>
Client-side validation attributes
<input type="text" required minlength="3" pattern="[A-Za-z]+">

Enforced by the browser before submit, but never a substitute for server-side validation.

Media
Responsive image
<img src="photo.jpg" alt="Description" width="800" height="600" loading="lazy">

Explicit width/height prevent layout shift while the image loads; alt is required for accessibility (use alt="" if purely decorative).

Multiple sources / art direction
<picture>
  <source srcset="photo.webp" type="image/webp">
  <img src="photo.jpg" alt="Description">
</picture>

Falls back to the <img> if the browser doesn't support the listed source format.

Video with controls
<video src="clip.mp4" controls width="640"></video>
Embed another page/document
<iframe src="https://example.com/embed" title="Embedded content" loading="lazy"></iframe>

title is required for accessibility (screen readers use it to announce the frame). Add a sandbox attribute when embedding untrusted content to restrict what it's allowed to do.

Drawable bitmap surface
<canvas id="chart" width="400" height="200"></canvas>

Empty until drawn into via JS (2D context or WebGL) — width/ height set the actual pixel resolution, not just display size; scaling it with CSS instead of these attributes stretches and blurs the drawing.

Accessibility
Accessible name for icon-only controls
<button aria-label="Close">&times;</button>

Needed whenever there's no visible text label for a screen reader to read.

Hide decorative content from screen readers
<span aria-hidden="true">★</span>
Live region for dynamic updates
<div aria-live="polite">Saved!</div>

Announces content changes without moving focus. Use assertive only for urgent, interrupting messages.

CSS Reference

Selectors, layout, and common properties worth having on hand.

Selectors
Descendant / direct child
.card p
.card > p

The first matches any p nested anywhere inside .card; the > form matches only a direct child.

Adjacent / general sibling
h2 + p
h2 ~ p

+ matches the single element immediately following; ~ matches all later siblings.

Attribute selector
[data-state="open"]
[href^="https"]

^= starts-with, $= ends-with, *= contains.

nth-child / nth-of-type
li:nth-child(2n)
li:nth-child(2n+1)

2n selects even items, 2n+1 odd. nth-of-type counts only siblings of the same tag, ignoring other element types in between.

first/last-child, only-child
li:first-child
li:last-child
li:only-child
:not() / :is() / :where()
li:not(.active)
:is(h1, h2, h3) a

:where() behaves like :is() but always has zero specificity, so it's easy to override.

has() — parent/relational selector
.card:has(img)

Selects a .card only if it contains an img — the closest thing CSS has to a "parent selector".

Box Model & Sizing
box-sizing
box-sizing: border-box;

Width/height include padding and border, so the element doesn't grow past its declared size. Usually set once on *.

Shorthand order: margin/padding
margin: 10px 20px 10px 20px;

Clockwise from top: top, right, bottom, left. Two values set vertical/horizontal; one value sets all four.

Viewport-relative units
width: 100vw;
height: 100vh;
font-size: 4vmin;

vh/vw can misbehave on mobile with dynamic browser chrome — dvh/svh/lvh are the newer, more predictable alternatives.

clamp() for responsive values
font-size: clamp(1rem, 2vw + 0.5rem, 2rem);

Arguments are min, preferred, max — avoids a pile of media-query breakpoints for simple fluid scaling.

Fit an image/video within its box
img {
  width: 100%;
  height: 200px;
  object-fit: cover;
  object-position: center;
}

cover fills the box and crops overflow (most common for thumbnails); contain fits the whole image inside without cropping, leaving letterbox space; fill (the default) stretches and distorts the aspect ratio. object-position controls which part of the image stays visible when cropped.

Flexbox
Center content both axes
display: flex;
align-items: center;
justify-content: center;
Main axis vs cross axis
justify-content: space-between;
align-items: stretch;

justify-content works along the main axis (row by default); align-items works along the cross axis. Swap roles when flex-direction: column.

justify-content values:

flex-start
Packs items at the start of the main axis.
center
Packs items together in the middle.
flex-end
Packs items at the end of the main axis.
space-between
Spreads items out with the first and last flush against the edges.
space-around
Gives each item equal space on both sides, so gaps at the edges end up half the size of the gaps between items.
space-evenly
Makes every gap — including the edges — equal.

align-items values:

stretch (default)
Fills the cross-axis size of the container.
flex-start / center / flex-end
Packs items to the start, middle, or end of the cross axis without stretching them.
baseline
Aligns items by their text baseline — useful when they have different font sizes.

The unprefixed start/end are newer logical-direction equivalents of flex-start/flex-end that follow the container's writing mode instead of always meaning left-to-right/top-to-bottom.

Allow/prevent wrapping
flex-wrap: wrap;
Child sizing: grow, shrink, basis
flex: 1 1 200px;

Shorthand for flex-grow flex-shrink flex-basis. flex: 1 is common shorthand for "grow to fill available space".

Grid
Fixed-column grid
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
Responsive auto-fit grid
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));

Columns wrap automatically as space allows — no media query needed. auto-fill instead of auto-fit keeps empty tracks rather than stretching existing items.

Place an item by line or name
grid-column: 1 / 3;
grid-row: span 2;
Positioning & Stacking
Position values
position: relative;
position: absolute;
position: fixed;
position: sticky;

absolute is positioned relative to the nearest ancestor with a position other than static; sticky toggles between relative and fixed based on scroll.

z-index stacking
z-index: 10;

Only applies to positioned elements (anything but static). A new stacking context (e.g. from transform or opacity < 1) can trap z-index values inside it regardless of how high they are.

Typography & Text
Truncate with ellipsis (single line)
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;

All three are required together.

Truncate with ellipsis (multi-line)
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;

Widely supported despite the -webkit- prefix, but still worth a fallback max-height for the rare unsupported target.

Prevent long words from overflowing
overflow-wrap: break-word;
Colors & Custom Properties
Define & use a CSS variable
:root {
  --accent: #b3541e;
}
.btn {
  color: var(--accent);
}
Variable with a fallback
color: var(--accent, #333);

Fallback is used only when --accent is unset, not when it's invalid.

Transparency via alpha channel
background: rgb(0 0 0 / 50%);
background: #00000080;
Color function formats
color: hsl(24 71% 39%);
color: oklch(55% 0.14 45);

hsl() is easy to reason about for tweaking lightness/saturation by hand. oklch() is perceptually uniform — bumping its lightness value changes perceived brightness consistently across hues, which hsl() doesn't guarantee.

Mix two colors
background: color-mix(in srgb, var(--accent) 70%, white);

Handy for deriving a hover/tint shade from one base color instead of hand-picking a second hex value.

currentColor
border: 1px solid currentColor;

Resolves to the element's own color value — useful so an icon's stroke or a border automatically tracks text color without a second variable.

Linear / radial gradient
background: linear-gradient(to right, var(--accent), #f3e4d7);
background: radial-gradient(circle, #fff, var(--accent));
Force accessible color contrast
color: light-dark(#24231f, #f7f7f5);

Picks the first value in light mode and the second in dark mode, based on the element's color-scheme — a lighter-weight alternative to duplicating rules inside a prefers-color-scheme media query.

Transitions & Animation
Basic transition
transition: transform 0.2s ease-in-out;

Prefer animating transform/opacity over layout properties like width/top — they don't trigger reflow.

Keyframe animation
@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
.el {
  animation: fade-in 0.3s ease-out;
}
Media & Container Queries
Responsive breakpoint
@media (max-width: 600px) {
  .sidebar { display: none; }
}
@media (min-width: 900px) {
  .sidebar { display: block; }
}

max-width targets screens at or below the breakpoint (mobile-first overrides going down); min-width targets screens at or above it (the more common mobile-first base-up approach).

Container query
.wrap { container-type: inline-size; }
@container (min-width: 400px) {
  .card { flex-direction: row; }
}

Reacts to the size of a containing element rather than the viewport — useful for components reused at different widths.

prefers-color-scheme
@media (prefers-color-scheme: dark) {
  :root { --bg: #111; }
}
@media (prefers-color-scheme: light) {
  :root { --bg: #fff; }
}

Uses the system's prefered color scheme: dark or light.

Shell Commands

Everyday POSIX/bash one-liners for files, text, and processes.

Files & Directories
Find files by name
find . -name "*.log"
Find and delete matching files
find . -name "*.tmp" -delete

Or -exec rm {} \; on systems without GNU find's -delete.

Find files modified in last N days
find . -mtime -7 -type f

Negative -7 means "less than 7 days ago"; plain 7 means "exactly 7".

Disk usage of a directory
du -sh ./some-dir
Free disk space
df -h
Copy/move recursively, preserving structure
cp -r src/ dest/
rsync -av src/ dest/

rsync is safer for large/ongoing syncs — it resumes and only copies changed files.

Text & Search
Search recursively for a pattern
grep -rn "TODO" ./src

-n shows line numbers, -r recurses into directories.

Search with extended regex, case-insensitive
grep -Eri "error|warn" ./logs
Print a specific column of each line
awk '{print $2}' file.txt

Fields split on whitespace by default; set -F, for CSV-style delimiters.

Replace text in-place across files
sed -i '' 's/foo/bar/g' file.txt

The '' after -i is required on macOS/BSD sed for in-place edits with no backup suffix; GNU sed (Linux) omits it.

First/last N lines of a file
head -n 20 file.txt
tail -n 20 file.txt
Follow a growing file (logs)
tail -f app.log
Sort and remove duplicate lines
sort file.txt | uniq

uniq only collapses adjacent duplicates, so the input must be sorted first.

Count lines/words/bytes
wc -l file.txt
Processes & Jobs
Find a process by name
ps aux | grep node

pgrep -a node does the same without the grep-matches-itself noise.

Kill a process by PID or name
kill -9 <pid>
pkill -f node

-9 (SIGKILL) can't be caught/ignored — try a plain kill (SIGTERM) first so the process can clean up.

What's listening on a port
lsof -i :3000
Run in background / detach
long-task &
nohup long-task & disown

nohup + disown lets the process survive the shell session ending, not just backgrounding within it.

Permissions & Environment
Change file permissions
chmod +x script.sh
chmod 644 file.txt
Change owner/group
chown user:group file.txt
Set/read an environment variable
export API_KEY="secret"
echo "$API_KEY"
Persist a variable across new shells
echo 'export API_KEY="secret"' >> ~/.zshrc

Use ~/.bashrc/~/.bash_profile instead if the shell is bash.

Redirection & Pipes
Redirect stdout / append / stderr
cmd > out.txt
cmd >> out.txt
cmd 2> err.txt
Redirect both stdout and stderr together
cmd > all.txt 2>&1

Order matters — 2>&1 must come after the stdout redirect to point stderr at the same already-redirected target.

Chain commands: pipe, and, or
cmd1 | cmd2
cmd1 && cmd2
cmd1 || cmd2

&& runs the next command only on success (exit code 0); || only on failure.

Substitute a command's output inline
echo "Today is $(date)"
SSH
Connect to a remote host
ssh user@host

Add -p 2222 if the server listens on a non-default port.

Connect using a specific private key
ssh -i ~/.ssh/id_ed25519 user@host
Generate a new key pair
ssh-keygen -t ed25519 -C "you@example.com"

Prefer ed25519 over the older rsa type — smaller keys, same or better security.

Copy a public key to a remote host's authorized_keys
ssh-copy-id user@host

Without it, append manually: cat ~/.ssh/id_ed25519.pub | ssh user@host "cat >> ~/.ssh/authorized_keys"

Run a single remote command and exit
ssh user@host "df -h && uptime"
Copy files to/from a remote host
scp local-file.txt user@host:/remote/path/
scp user@host:/remote/path/file.txt ./

Add -r to copy directories recursively. rsync -av -e ssh is usually a better choice for large or repeated transfers.

Mount a remote directory over SSH
sshfs user@host:/remote/path ./local-mount

Requires sshfs installed (e.g. via macFUSE on macOS). Unmount with umount ./local-mount.

Local port forwarding (tunnel a remote service)
ssh -L 8080:localhost:80 user@host

Makes the remote host's port 80 reachable at localhost:8080 on your machine — handy for reaching a service (e.g. a database or admin panel) that isn't exposed publicly.

Keep a session open in the background
ssh -f -N -L 8080:localhost:80 user@host

-N means "no remote command", -f backgrounds the process after authentication — useful for a long-lived tunnel.

Configure a host alias
cat >> ~/.ssh/config <<'EOF'
Host myserver
  HostName 203.0.113.10
  User deploy
  IdentityFile ~/.ssh/id_ed25519
EOF

Afterward, just ssh myserver picks up the host, user, and key automatically.

SQL

Core ANSI SQL — mostly consistent across Postgres, MySQL, and SQLite. Edge cases noted where dialects diverge.

Querying
Select specific columns with a filter
SELECT id, name FROM users WHERE age > 18;
Sort and limit results
SELECT * FROM users
ORDER BY created_at DESC
LIMIT 10;

SQL Server uses TOP 10 instead of LIMIT.

Skip rows (pagination)
SELECT * FROM users
ORDER BY id
LIMIT 10 OFFSET 20;
Distinct values
SELECT DISTINCT country FROM users;
Pattern match / wildcard search
SELECT * FROM users WHERE email LIKE '%@gmail.com';

% matches any run of characters, _ matches exactly one. Use ILIKE in Postgres for case-insensitive matching.

Match against a list of values
SELECT * FROM users WHERE status IN ('active', 'trial');
Check for NULL
SELECT * FROM users WHERE deleted_at IS NULL;

= NULL never matches anything — NULL comparisons always require IS [NOT] NULL.

Joins
Inner join
SELECT o.id, u.name
FROM orders o
JOIN users u ON u.id = o.user_id;

Only returns rows with a match on both sides.

Left join
SELECT u.name, o.id
FROM users u
LEFT JOIN orders o ON o.user_id = u.id;

Keeps every row from users even when there's no matching order — unmatched columns come back NULL.

Find rows with no match (anti-join)
SELECT u.*
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE o.id IS NULL;
Aggregation
Group with an aggregate function
SELECT user_id, COUNT(*) AS order_count
FROM orders
GROUP BY user_id;
Filter groups after aggregation
SELECT user_id, COUNT(*) AS order_count
FROM orders
GROUP BY user_id
HAVING COUNT(*) > 5;

WHERE filters rows before grouping; HAVING filters groups after aggregation — an aggregate like COUNT(*) can't be used in WHERE.

Common aggregate functions
SELECT COUNT(*), SUM(amount), AVG(amount), MIN(amount), MAX(amount)
FROM orders;
Modifying Data
Insert a row
INSERT INTO users (name, email) VALUES ('Ada', 'ada@example.com');
Insert and return the new row
INSERT INTO users (name) VALUES ('Ada') RETURNING id;

Postgres/SQLite support RETURNING; MySQL doesn't — use LAST_INSERT_ID() instead.

Update matching rows
UPDATE users SET status = 'active' WHERE id = 42;

Always pair UPDATE/DELETE with a WHERE — an omitted clause affects every row in the table.

Insert or update on conflict (upsert)
INSERT INTO users (id, name) VALUES (1, 'Ada')
ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name;

MySQL equivalent: ON DUPLICATE KEY UPDATE name = VALUES(name).

Delete matching rows
DELETE FROM users WHERE id = 42;
Schema
Create a table
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  name TEXT NOT NULL,
  created_at TIMESTAMP DEFAULT NOW()
);

SERIAL is Postgres-specific auto-increment; MySQL uses AUTO_INCREMENT, SQLite uses INTEGER PRIMARY KEY.

Add / drop a column
ALTER TABLE users ADD COLUMN age INT;
ALTER TABLE users DROP COLUMN age;
Add an index
CREATE INDEX idx_users_email ON users (email);
Users & Permissions
Create a user with a password
CREATE USER app_user WITH PASSWORD 'change-me';

MySQL: CREATE USER 'app_user'@'%' IDENTIFIED BY 'change-me'; — the @'%' host part controls which hosts the user may connect from (@'localhost' restricts it to local connections only).

Change a user's password
ALTER USER app_user WITH PASSWORD 'new-password';

MySQL: ALTER USER 'app_user'@'%' IDENTIFIED BY 'new-password';

Remove a user
DROP USER app_user;

Fails if the user still owns objects or has granted privileges pending — reassign or revoke those first. Add IF EXISTS to avoid an error when the user is already gone.

Grant table privileges
GRANT SELECT, INSERT, UPDATE ON users TO app_user;

Use GRANT ALL PRIVILEGES ON users TO app_user; for full access, or ON ALL TABLES IN SCHEMA public (Postgres) to apply to every existing table at once.

Revoke table privileges
REVOKE INSERT, UPDATE ON users FROM app_user;
List a user's granted privileges
SELECT * FROM information_schema.role_table_grants
WHERE grantee = 'app_user';

MySQL: SHOW GRANTS FOR 'app_user'@'%';

Window Functions & CTEs
Row number within a partition
SELECT id, user_id,
  ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at) AS rn
FROM orders;

Useful for picking "the latest row per group" by filtering rn = 1 in an outer query.

Running total
SELECT id, amount,
  SUM(amount) OVER (ORDER BY id) AS running_total
FROM orders;
Common table expression (CTE)
WITH big_orders AS (
  SELECT * FROM orders WHERE amount > 1000
)
SELECT * FROM big_orders WHERE user_id = 42;

Mainly for readability — most modern optimizers no longer treat a CTE as an opaque barrier the way older Postgres versions did.

Git Commands

Reverts, resets, rebases, branches, and worktrees worth remembering.

History & Commits
Reverting a PR
git revert -m 1 <merge-commit-hash>
Resetting to an earlier commit
git reset --hard <commit-hash> | <HEAD-{n}> | HEAD
Cherry-pick a commit hash
git cherry-pick <commit-hash>
Cherry-pick a merged PR commit hash
git cherry-pick -m 1 <commit-hash>
Rebase from HEAD
git rebase -i <branch-name> | <HEAD-{n}>
Rebase from initial commit
git rebase -i --root
Amend the last commit
git commit --amend --no-edit

Drop --no-edit to change the commit message too. Never amend a commit that's already been pushed/shared unless you intend to force-push.

Compact one-line log graph
git log --oneline --graph --decorate --all
Who changed this line (blame)
git blame -L 10,20 path/to/file
Find the commit that introduced a bug
git bisect start
git bisect bad
git bisect good <known-good-commit>

Git checks out a midpoint commit after each step — mark it git bisect good/bad until it narrows down the offending commit, then git bisect reset.

Inspecting Changes
Diff working directory vs last commit
git diff

Add --staged (or --cached) to diff staged changes instead.

Diff two branches/commits
git diff main..feature-branch
Show a file at a specific commit
git show <commit-hash>:path/to/file
Search commit messages / diffs for a string
git log --grep="fix login"
git log -S "functionName"

-S (the "pickaxe") finds commits that added/removed a given string in the diff, not just the commit message.

Undoing & Cleaning Up
Unstage a file (keep changes)
git restore --staged path/to/file
Discard uncommitted changes to a file
git restore path/to/file

Destructive — permanently discards local edits with no undo.

Stash / list / restore work in progress
git stash push -m "wip"
git stash list
git stash pop

pop applies the most recent stash and removes it from the list; apply does the same but keeps it stashed.

Remove untracked files
git clean -nd
git clean -fd

Always run -n (dry run) first to see what would be deleted before running -f for real.

Remotes & Syncing
Fetch and prune deleted remote branches
git fetch --prune
Update local branch list from a fork/remote
git remote add upstream <url>
git fetch upstream
Push a new local branch and track it
git push -u origin HEAD
Force-push safely
git push --force-with-lease

Fails instead of overwriting if someone else pushed to the branch since your last fetch — safer than a plain --force.

Branches
Renaming a branch
git branch -m <old-branch-name> <new-branch-name>
Deleting a branch
git branch -d <branch-to-delete>
List branches, including remotes
git branch -a
Create and switch to a new branch
git switch -c <new-branch-name>

Older equivalent: git checkout -b <new-branch-name>.

Worktrees
Adding a worktree
git worktree add <branch-name>
Moving a worktree to a new location
git worktree move <old-branch-location> <new-branch-location>
Listing a worktree
git worktree list
Removing a worktree
git worktree remove <path>
Combining All Commits
Squash all commits into one
git switch yourBranch
git reset --soft master

Removes all commits but keeps the changes staged. Commit them together with git commit -m "commit message", then push with git push --force or git push --force-with-lease.

Regex Syntax

Core building blocks — mostly consistent across PCRE, JavaScript, and Python's re. Edge cases noted where flavors diverge.

Anchors & Boundaries
Start / end of string
^foo
foo$

With a multiline flag, ^/$ match start/end of each line instead.

Word boundary
\bcat\b

Matches "cat" but not "concatenate". \B is the negation (non-boundary).

Character Classes
Any character
.

Doesn't match a newline unless a "dotall"/"s" flag is set.

Digit / non-digit
\d
\D
Word character / non-word
\w
\W

\w is [A-Za-z0-9_].

Whitespace / non-whitespace
\s
\S
Custom set / negated set
[aeiou]
[^aeiou]

A ^ as the first character inside [...] negates the set.

Character range
[a-z0-9]
Quantifiers
Zero or more / one or more / optional
a*
a+
a?
Exact / range count
a{3}
a{2,4}
a{2,}
Lazy (non-greedy) match
".*?"

Without the ?, .* is greedy and matches as much as possible — often too much across multiple quoted strings.

Groups & Alternation
Capture group
(foo|bar)

Referenced later as $1/\1 depending on the tool.

Non-capturing group
(?:foo|bar)

Groups for alternation/quantifiers without creating a numbered backreference.

Named capture group
(?<year>\d{4})-(?<month>\d{2})

Referenced as $<year> (JS) or (?P=year) / m.group('year') (Python).

Backreference to an earlier group
(\w+)\s\1

Matches a repeated word, like "the the". Use \1 in most flavors, $1 in replacement strings.

Lookaround
Lookahead / negative lookahead
foo(?=bar)
foo(?!bar)

Matches "foo" only if (not) followed by "bar", without including "bar" in the match.

Lookbehind / negative lookbehind
(?<=foo)bar
(?<!foo)bar

Not supported in all flavors/older engines — check target support before relying on it.

Common Flags
Case-insensitive
/foo/i

Python: re.IGNORECASE. PCRE/grep: -i or inline (?i).

Global (all matches, not just first)
/foo/g

JS-specific flag. Most other languages return all matches by default via a "findall"/"scan"-style function instead.

Multiline (^ and $ match per line)
/^foo/m

Python: re.MULTILINE.

Dotall (. matches newlines too)
/foo.bar/s

Python: re.DOTALL.

VSCode

Search patterns for the editor's find/replace.

Find mis-formatted i18n text
i18n="([0-9a-zA-Z]+)"
Trailing whitespace
[ \t]+$

Enable the regex toggle, leave replace empty to strip trailing spaces/tabs on every line.

Blank/empty lines
^\s*$\n

Requires "match on multiple lines" enabled. Replace with nothing to collapse blank lines.

console.log statements
console\.log\((.*)\);?\n?

Matches the whole line including the trailing newline, so replacing with nothing removes it cleanly.

TODO / FIXME comments
\/\/\s*(TODO|FIXME).*$
Swap function call args (capture groups)
myFunc\((\w+), (\w+)\)

Replace with myFunc($2, $1) to swap the two arguments.

Quoted string contents
"([^"]*)"

Capture group $1 holds the text between the quotes — useful for swapping quote style or wrapping in a function.

Single-quote to double-quote strings
'([^']*)'

Replace with "$1". Won't handle escaped quotes inside the string.

Unused single-line imports
^import .* from ['"].*['"];\n

Search first to confirm the import is actually unused before replacing with nothing.

CSS hex color to rgb() parts
#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})

Capture groups $1 $2 $3 hold the R, G, B hex pairs.

Lines containing a word (whole-word match)
^.*\bdeprecated\b.*$

\b word boundaries stop it from also matching "undeprecated" or "deprecatedFlag".

No matches. Try a different search term.