Selection Manipulator
The Ultimate Text Processing Toolkit for VS Code
Selection Manipulator offers over 1,000 powerful tools (1,014 commands) to manipulate, transform, and analyze text directly in your editor. From everyday tasks like sorting and JSON formatting to advanced cryptography, network analysis, and Japanese text conversion, this extension supercharges your workflow.
📖 Browse all commands with examples (English / 日本語): every command by category, with a description and an input → output example, plus search and category filters.
✨ Features
📝 Text Manipulation
- Sort: Organize lines or selections by string, number, occurrence, or length (Ascending/Descending), and by natural order, ignoring case, locale, kana order, a column, a regex capture, date, semantic version, IP address, hex number, word count, last word or reversed string; sort and remove duplicates, sort paragraphs, or sort lines keeping their indented children (several with a Clipboard version).
- Unique: Instantly remove duplicate lines.
- Extract: Filter and extract matching text, lines, emails, URLs, IPs, or lines by length (equal/less/greater) to a new tab or clipboard.
- Edit: Reverse text, shuffle content (lines or characters), remove cursors, separate multi-selections, remove characters from edges, mask text.
- Insert: Date (ISO, Locale, Timestamp, Era), Markdown Link, Enclosed Text (Quotes, Brackets, Japanese Symbols).
- Enclose: Enclose with a custom prefix/suffix or HTML tag, quote each line or word, build SQL IN lists and array literals, triple/smart quotes, guillemets, escaped double quotes, Japanese brackets, HTML/block comments,
${} / {{ }} / %% placeholders, ASCII box, Markdown code span with an automatic fence, add lines before/after, unquote each line, cycle or remove outer brackets.
- Convert Date: Convert between ISO 8601, Locale String, and Timestamp (Seconds/Milliseconds), AD <-> Wareki.
- Date: Time zones (one or several), weekday, ISO week, day of year, difference between dates, add days / months, relative time, custom patterns, compact
YYYYMMDD, Japanese format, month calendar, ISO 8601 durations, seconds <-> HH:MM:SS, Excel serials, date ranges, age, quarter and fiscal year, and cron expressions explained with their next runs.
- Morse Code: Convert text to Morse Code (Alphanumeric/Japanese Kana) and vice versa.
- Unicode: Normalize (NFC / NFD / NFKC / NFKD), remove zero-width, control, non-ASCII characters or emoji (keeping emoji ZWJ sequences whole), reveal invisible characters as
<U+XXXX>, show code points, UTF-8 bytes and UTF-16 code units and turn code points back into text, count graphemes, extract emoji, mathematical bold / italic / monospace, circled, upside-down, strikethrough, underline, superscript and subscript text, detect confusable (homoglyph) and bidi control (Trojan Source) characters, smart quotes, em dashes and ellipses, detect scripts, and transliterate Cyrillic to Latin.
- Multi Cursor & Selection: Keep odd / even / every Nth selection, remove the first / last / empty / duplicate selections, keep or remove selections matching a regex, align cursors, expand to the word / inside quotes / inside brackets, trim or shrink selections, extend to a delimiter, split selections by a delimiter / regex / into words, put cursors at the first non-whitespace character, select a column, all numbers / quoted strings / URLs or the indentation, rotate / swap / copy the selected texts, and show selection info.
- Markdown: Increase / decrease heading levels, generate a table of contents (of the selection, or of the whole document at the cursor), convert lines to bullet / numbered / task lists, toggle task checkboxes, remove list markers, renumber ordered lists, bold / italic / strikethrough, setext headings to ATX, wrap in a code fence or a details block, blockquote, image, linkify URLs, format tables, convert to HTML (a safe built-in subset) or plain text, heading to anchor link, footnotes, inline links to reference links, and front matter to JSON.
- Text Transform: Repeat a selection N times, truncate or shorten in the middle, pad start / end with a custom character, insert a separator every N characters,
tr-like translate / delete / squeeze characters, remove digits or punctuation, keep digits only, reverse each word, sort or deduplicate words and characters, word and character frequency tables, remove URLs, mask all but the last N characters, Leetspeak, and remove text between delimiters.
- Line & Selection (Extended): Keep lines N to M, remove the first / last N lines, insert a blank line every N lines, cut a character range of each line, paste selections side by side, remove duplicate lines keeping the last, split lines by a regex, join lines as a natural-language list, lines common to / only in two selections, number non-blank lines, arrange lines into N columns, select all email addresses / IP addresses / hex colors / UUIDs / ISO dates, expand to the sentence or paragraph, keep only duplicate texts, and join all selections into the first.
- Format: Remove blank rows, zero-pad numbers, and more.
- Cleanup: Remove empty lines, line numbers, join/split lines, trim lines (Start/End/All), normalize whitespace, strip HTML, unsmart quotes, remove duplicate lines.
- Whitespace: Convert leading tabs/spaces, re-indent (2 <-> 4), dedent, indent/outdent by N, expand/unexpand tabs, collapse or remove blank lines, unwrap paragraphs, hard wrap, visualize spaces and tabs, center/right align, align by
= / : / , / a custom delimiter, add spaces around operators.
- Line: Keep/remove lines containing text or matching a regex, keep every Nth / odd / even / first N / last N lines, keep duplicated or unique lines, remove duplicates (ignore case/whitespace, adjacent), add line numbers, reverse words, rotate/swap/interleave lines, join backslash-continued lines, join every N lines, split sentences or fixed-width lines, remove comment lines, extract lines between markers or the longest/shortest line, count lines/words/characters (several with a Clipboard version).
- Advanced Case: Smart Title Case, APA Title Case, SpongeBob Case, Screaming Snake, Humanize, Slugify, Remove Accents, Swap Case, Sentence Case per sentence, Locale-aware Upper/Lower, Pluralize/Singularize, Detect/Cycle naming style.
- Math: Sum, Average, Min, Max, Hex <-> Decimal, Date Calculation; median, mode, standard deviation, variance, count, product, range, percentile, a statistics summary (each selection on its own) and cumulative sum.
- Number: Round, floor, ceil, truncate, absolute value, negate, add / remove thousands separators, format by locale, decimal <-> hex / binary / octal and any base from 2 to 36, to / from scientific notation, to percent, bytes <-> human readable (KiB / MB …), English words and ordinal suffixes, decimal to fraction.
- Unit Conversion: px <-> rem, kg <-> lb, Celsius <-> Fahrenheit, km <-> mile, cm <-> inch.
- Numbers & Math (Extended): Round to significant figures or the nearest multiple, clamp to a range, Roman numerals and English number words to numbers, fractions to decimals, multiply by N, IEEE 754 bits and two's complement hex, greatest common divisor, least common multiple, prime factorization, differences between consecutive numbers, collapse / expand integer ranges, m <-> ft, m² <-> tsubo (坪) and degrees <-> radians.
- CSV: Convert between CSV and Markdown Table.
- CSV / TSV: Convert CSV to and from JSON arrays and TSV, and to HTML tables, SQL INSERT statements, YAML, ASCII tables and key-value records; convert whitespace-separated tables to CSV; transpose, extract, remove, swap and align columns, trim cells, remove duplicate rows, filter rows, add an index column, fill empty cells from above, change the delimiter, quote or unquote fields, and show the sum of a column or the row and column count.
💻 Developer Utilities
- JSON & XML: Format (Pretty Print), Minify, Stringify, Parse, Flatten/Unflatten JSON, XML<->JSON.
- Encoding: Base64 Encode/Decode/Deflate/Inflate.
- Encode / Decode: HTML entities (named and numeric), Unicode escapes (
\uXXXX / \u{...}), Base64URL, Base32, Base58, Ascii85, Base64 per line, Gzip/Gunzip Base64, Data URI, Hex and binary UTF-8 bytes, Punycode (IDN), Quoted-Printable, form encoding (x-www-form-urlencoded), ROT13/ROT47/Caesar/Atbash, NATO phonetic alphabet.
- Case Conversion: Switch between Camel, Snake, Kebab, Pascal, Constant, Dot, Path, Sentence, Title, Cobol, Ada, Flat, Camel_Snake, Pascal_Snake, CSS Custom Property, BEM and Hashtag cases. Convert only the keys of a JSON document (Camel/Snake/Kebab/Pascal).
- Escaping: Escape/Unescape text (JSON stringify/parse compatibility).
- Programmatic: Convert between JSON<->YAML, Hex<->RGB, Toggle quotes, Env file to JSON; JS / Python / Java / Go string literals and JS template literals; escape for regular expressions, SQL, POSIX shell, PowerShell, CSV and Markdown; TypeScript interfaces, Go structs and Python TypedDicts from sample JSON; format, minify and upper-case SQL; minify and format CSS; Hex <-> HSL and short / long hex colors; remove
console.log, sort imports, string concatenation to template literals; curl commands to fetch(); HTML to JSX; bump semantic versions; chmod numeric <-> symbolic (text conversion only: nothing is executed or sent).
- Data Format: Convert JSON to and from TOML, INI, .properties, JSON Lines and JS object literals, JSONC / JSON5 to JSON, and JSON to Query String, Env and XML; sort, merge, validate, count and clean up JSON, extract values by path, pluck and group arrays, generate a JSON Schema, format and sort YAML, and parse Cookie, Set-Cookie, HTTP headers and User-Agent strings to JSON.
- Data Formats (Extended): Sort, filter and chunk JSON arrays, pick, omit and rename keys, remove empty values, set a value at a path, JSON arrays to Markdown tables and to objects by key, objects to key-value entries; YAML to flow style, Validate YAML, multi-document YAML to a JSON array; Format TOML; Validate XML (well-formedness, entities never resolved) and list XML element paths; LTSV to and from JSON; CSV column commands to reorder, merge, split, count by value and fill empty cells.
- Encoding, Escaping & Hashes (Extended): Base32hex, Base45 and Base62 encode / decode, uuencode / uudecode, percent-encoding of every byte, escape CSS identifiers and LDAP filter / DN values, XPath string literals, C string literals and C / Java unescaping.
- Developer (Extended): Rust (serde), Kotlin (kotlinx.serialization), C# (System.Text.Json), Zod and Swift (Codable) types from sample JSON; lowercase SQL keywords; hex to OKLCH, WCAG contrast ratios and inverted hex colors; sort CSS declarations and convert CSS declarations to and from JS style objects; remove JS / TS comments; C# verbatim strings, Rust raw strings and shell here-documents; HTTP status codes and MIME types from fixed tables; normalize UUIDs, CIDR range information, expand / compress IPv6 and IPv4 <-> integer (text only: nothing is compiled, run or sent).
🔐 Cryptography & Security
- Hashing: Generate MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/256, SHA3-256, SHA3-384, SHA3-512, SHAKE256 (output length N), BLAKE2b-512 and BLAKE2s-256 hashes, SHA-256 per line, SHA-256 as Base64 (CSP) and SRI (
sha384-…) values.
- HMAC: Create HMAC-SHA256, HMAC-SHA512, HMAC-MD5, HMAC-SHA1 (for compatibility only), HMAC-SHA384, HMAC-SHA3-256 and HMAC-SHA3-512 signatures.
- Checksum: CRC-32, CRC-32C, CRC-16/CCITT-FALSE, Adler-32 and FNV-1a 32-bit (error detection, not tamper detection), Luhn, IBAN and ISBN check digit validation (not for cryptographic use).
- Encryption: Securely Encrypt and Decrypt text using AES.
- Decoders: Decode JWT, SAML Request/Response, and X.509 Certificates.
🌐 Network & Analysis
- URL: Parse URL to JSON, Parse URL Parameters to JSON.
- DNS: Perform comprehensive DNS lookups (A, AAAA, MX, NS, TXT, etc.).
- HAR Visualization: Visualize HTTP Archive (HAR) logs as Mermaid Sequence Diagrams.
🇯🇵 Japanese Text Support
- Width Conversion: Convert between Full-width and Half-width characters (including Katakana).
- Kana Conversion: Convert between Hiragana and Katakana.
- Japanese Text: Kana <-> romaji (Hepburn / Kunrei), numbers <-> kanji numerals and daiji, punctuation (
、。 <-> ,.), old <-> new kanji forms, small kana to normal, ruby notation (remove or convert to HTML), full-width alphanumerics to half-width keeping kana, ideographic spaces, wave dashes, hyphens and long vowel marks, spaces between Japanese and alphanumerics, composing dakuten, hiragana to half-width katakana, circled numbers, prefecture names <-> JIS codes, postal codes, extracting kanji and katakana words, counting characters (manuscript paper, by character type), and selecting platform-dependent characters.
- Japanese, Unicode & Markdown (Extended): Vertical text, gojuon index rows, search keys, 万 / 億 notation, corporate number check digits (validation only, never looked up), decomposing dakuten and readings in parentheses to ruby; mathematical script, fraktur, double-struck and small capital letters, Python Unicode escapes and flag emoji <-> country codes; sorting and transposing Markdown tables, removing and extracting links, reference links to inline links, GitHub alert blocks and
<kbd> keys.
🎨 Fun & Generators
- Mock Data: Generate Random UUIDs, Passwords, IPv4, IPv6, Lorem Ipsum.
- Generators: UUID v7, ULID, NanoID, hex / Base64URL tokens, integers, decimals and dates in a range, lines picked from a selection, MAC addresses, colors, dummy e-mail addresses, names (English and Japanese), phone numbers and Japanese text, booleans, dice rolls, and sequences for multiple cursors (letters, Roman numerals, dates, numbers, hex, kana, circled numbers, IPv4), repeated characters, column rulers and braced GUIDs.
- Dates, Generators & Random (Extended): Add ISO 8601 durations, seconds to ISO 8601 durations, start / end of the month, add and count business days (Monday to Friday), RFC 3339 with the offset of a time zone, ISO weeks to date ranges, the sexagenary cycle (干支), 12-hour <-> 24-hour times, the time in Snowflake IDs, ULIDs, UUID v7 and MongoDB ObjectIds; brace expansion (no shell is run), multiplication tables, Fibonacci numbers, prime numbers, time sequences and the Cartesian product of selections; passphrases, random strings from your own characters and shuffled words (Node.js
crypto).
- ASCII Art: Generate "Cowsay" speech bubbles.
- Math: Evaluate expressions, calculate Sum/Average/Min/Max, Median, Mode, Standard Deviation, Variance, Percentile and a Statistics Summary.
🚀 Key Usage
- Select the text you want to process.
- Open Command Palette (
Cmd+Shift+P / Ctrl+Shift+P).
- Type
Selection Manipulator to explore all commands.
- (Or right-click and use the context menu).
Pro Tip: Commands that generate output in a new tab (e.g., Base64 Encode) now open a Read-Only tab. This prevents the "Save changes?" prompt when closing the tab. These tabs persist until manually closed.
Command Showcase: https://imahiro-t.github.io/selection-manipulator/ lists every command by category, with its description and an input → output example in English and Japanese, and lets you search and filter them. The page is generated from the data in scripts/showcase-data/ with npm run showcase (npm run showcase:check verifies that it is up to date) and published to GitHub Pages on every push to main.
Usage Guide
This document provides a comprehensive list of features available in Selection Manipulator, along with examples of their usage.
Many commands come in two variables:
- Standard: Opens the result in a new tab.
- Replace: Replaces the selected text directly.
1. Text Modification
Remove Cursor / Characters
- Remove Cursor Above/Below: Helps align multi-cursor selections.
- Remove Character from Each Side: Trims one character from both start and end of selection.
- Convert to Multi Selection: Splits a multi-line selection into individual cursors (one per line). Supports interval (every Nth line).
- Select Matches: Select all occurrences of a specific string within the current selection(s).
Edit & Enclose
- Reverse Selections: Reverses the order of characters in the selection.
- Reverse String: Reverses the characters within the selection (e.g.,
abc -> cba).
- Mask with Asterisk: Masks the selected text with asterisks (
*) (e.g., pass -> ****).
- Toggle Quotes: Toggles between single (
') and double (") quotes.
- Enclose Text: Wrap text with:
- Quotes:
'Single', "Double", `Backtick`
- Brackets:
(Paren), [Square], {Curly}, <Angle>
- Japanese:
「Single」, 『Double』, 【Bracket】, <Angle>, (Paren), [Square], {Curly}
Extended Enclose & Quote Commands
These commands replace each selection in place. With multiple selections, each selection is processed on its own, and a command that asks for input asks only once. They are added to the Enclose submenu of the context menu, after the existing Enclose / Quote commands.
In the examples, · is a space and ⏎ is a line break. A value in parentheses is the value you enter.
- Enclose the whole selection (like the existing Enclose / Quote commands, an empty selection gets the pair inserted at the cursor):
- Enclose: Custom (Prefix / Suffix): Asks for a prefix and then a suffix:
abc (<<, >>) -> <<abc>>. If both are empty, nothing is changed.
- Quote: Triple Double (""" """):
abc -> """abc""".
- Quote: Guillemets («»), Smart Double (“”), Smart Single (‘’):
abc -> «abc», “abc”, ‘abc’.
- Quote: Double with Escaping: Escapes
\ as \\ and " as \", then adds double quotes: say "hi" -> "say \"hi\"". Line breaks are not escaped.
- Enclose: Japanese White Lenticular (〖〗) / Tortoise Shell (〔〕) / Double Angle (《》) / Single Angle (〈〉) Bracket:
注意 -> 〖注意〗, 注 -> 〔注〕, 書名 -> 《書名》, 論文 -> 〈論文〉.
- Enclose: HTML Tag (Custom): Asks for a tag name (1-64 letters, digits and hyphens):
abc (b) -> <b>abc</b>.
- Enclose: HTML Comment:
abc -> <!--·abc·-->. Block Comment (/* */): abc -> /*·abc·*/.
- Enclose: Placeholder (${}):
name -> ${name}. Mustache ({{ }}): name -> {{·name·}}. Percent (%%): PATH -> %PATH%. Pipes (||): abc -> |abc|.
- Enclose: Backtick Code (Auto Fence): Encloses the text in one more backtick than the longest run of backticks inside, so the result is a valid Markdown code span:
a`b -> ``a`b``. A space is added on both sides when the text starts or ends with a backtick (`a -> ``·`a·``), or when it starts and ends with a space or line break and is not only spaces (·a· -> `··a··`), as CommonMark removes one such space.
- Process the lines, words or brackets of the selection (an empty selection is not changed, and no input box is shown):
- Enclose Each Line: Custom: Asks for a prefix and then a suffix:
a⏎b ([, ]) -> [a]⏎[b]. If both are empty, nothing is changed.
- Quote Each Line: Double ("") / Single (''):
a⏎b -> "a"⏎"b" / 'a'⏎'b'.
- Quote Each Word: Double (""), Enclose Each Word: Parentheses (()): Every run of non-whitespace characters is a word; the whitespace and line breaks between the words are kept:
a·b -> "a"·"b" / (a)·(b).
- Quote: SQL IN List: Quotes each line in single quotes (an inner
' becomes '') and joins them with , in parentheses on one line: a⏎O'Neil -> ('a', 'O''Neil'). A line with a backslash (\), a yen sign (¥, U+00A5) or a control character other than tabs and line breaks (such as NUL or DEL) is an error and nothing is changed (line 2 contains a backslash (\), …, line 2 contains a control character), like Convert to SQL INSERT (see the limitations of the CSV / TSV commands).
- Quote: Array Literal: Quotes each line in double quotes (an inner
\ becomes \\ and " becomes \") and joins them with , in square brackets on one line: a⏎b -> ["a", "b"].
- Unquote Each Line: Removes one pair of matching quotes (
" ' `) around the text of each line: "a"⏎'b' -> a⏎b. Whitespace before and after the quotes is kept (··"a" -> ··a).
- Enclose: ASCII Box: Draws a box as wide as the longest line:
abc -> +-----+⏎|·abc·|⏎+-----+. Shorter lines are padded with spaces.
- Enclose: Lines Block (Before / After Lines): Asks for a line to insert before and then a line to insert after the selection:
a⏎b (BEGIN, END) -> BEGIN⏎a⏎b⏎END. If the selection ends with a line break (for example a selection of whole lines), the after line is added after that line break and followed by another one, so the next line is not joined: a⏎b⏎ -> BEGIN⏎a⏎b⏎END⏎. Either line may be empty (an empty line is inserted).
- Enclose: Cycle Brackets: Changes the outer brackets
() -> [] -> {} -> (): (a) -> [a].
- Enclose: Remove Matching Outer Brackets: Removes the outer pair only:
((a)) -> (a). Handles () [] {} <> and 「」 『』 【】 () [] {} <> 〔〕 〖〗 《》 〈〉.
- Line-wise commands (Enclose Each Line, Quote Each Line, Unquote Each Line, ASCII Box) do not count one trailing line break of a selection as a line and keep it, and join the lines with the document's line ending (LF or CRLF).
Limitations of the extended enclose & quote commands
- Empty and blank lines: Enclose Each Line and Quote Each Line leave empty lines as they are but enclose lines that contain only whitespace (
a⏎⏎·· -> "a"⏎⏎"··"). SQL IN List and Array Literal skip empty and whitespace-only lines, use the other lines as they are (leading and trailing spaces are not trimmed: ·a -> ('·a')), keep one trailing line break of the selection after the list, and change nothing if every line is blank.
- Unquote Each Line: Only straight quotes are removed (not
“” or ‘’), only when the same quote character is at both ends of the trimmed line text ("a' and a lone " are not changed), and only one pair (""a"" -> "a").
- ASCII Box: The width is counted in code points. Full-width characters and tabs count as one column, and an emoji counts as one column per code point, so an emoji with a skin tone modifier (
👍🏽, 2 columns) or a ZWJ sequence (👨👩👧, 5 columns) takes several columns. The box is not aligned when such characters are displayed with a different width.
- HTML Tag: Attributes are not supported (
b onclick=x is rejected), and the selected text is not HTML-escaped (<script> becomes <b><script></b>).
- HTML Comment / Block Comment: A
--> or */ inside the selection is not changed, so the comment can end early.
- Cycle Brackets / Remove Matching Outer Brackets: The text must start with an opening bracket and end with the matching closing bracket (no surrounding spaces). Only brackets of the same kind are counted to find the match, and brackets inside quotes are counted too. Text where the first bracket closes before the end (
(a)(b)) is not changed, while a mix of kinds such as (a]) is treated as enclosed. Cycle Brackets handles only (), [] and {}.
- Input: Prefixes, suffixes and the before / after lines can be 0-1,000 characters without line breaks; tag names 1-64 characters. If you cancel an input box, nothing is changed. The selections are read again after the input boxes close, so an edit made while an input box is shown does not make the command change an outdated range.
- Output size: A run that would add more than 10,000,000 characters in total (shared by all selections, for example a long prefix on many lines or an ASCII Box around many lines of different lengths) is refused with a warning and leaves the text unchanged.
- Zero Padding: Pads numbers with leading zeros (e.g.,
1 -> 001).
- Markdown Link: Creates a Markdown link from selection and clipboard URL.
- Insert Date: Inserts ISO 8601, Locale String, or Unix Timestamp.
2. Text Cleanup
Comprehensive tools to clean up and normalize code or text.
- Remove Empty Lines: Removes lines containing only whitespace.
- Remove Line Numbers: Removes leading numbering (e.g.,
1., [1], 1)).
- Trim Lines: Trim Start, End, or All whitespace.
- Join / Split Lines: Join lines with space/comma, or split text by space/comma.
- Normalize Whitespace: Replaces multiple spaces with a single space (
a b -> a b).
- Strip HTML Tags: Removes HTML tags, keeping inner text (
<b>bold</b> -> bold).
- Unsmart Quotes: Converts smart quotes (
“, ”) to straight quotes (").
- Remove Duplicate Lines: Keeps only the first occurrence of identical lines.
- Split/Join Lines (Custom): Split or join text using a custom delimiter.
Whitespace Commands
All whitespace commands replace each selection in place. With multiple selections, each selection is processed on its own. They are also grouped in the Whitespace submenu at the end of the Selection Manipulator context menu.
In the examples, · is a space, ⇥ is a tab and ⏎ is a line break (except where noted for Visualize / Restore).
- Indentation:
- Leading Tabs to Spaces (2) / (4):
⇥foo -> ····foo (4). Only tabs at the start of a line are converted.
- Leading Spaces to Tabs (2) / (4):
····foo -> ⇥foo (4). Leftover spaces that do not fill a tab are kept (······foo -> ⇥··foo).
- Re-indent 2 to 4 / 4 to 2 Spaces:
··a⏎····b -> ····a⏎········b. Leftover spaces are kept.
- Remove Common Indent (Dedent):
····a⏎······b -> a⏎··b. Whitespace-only lines are ignored when finding the common indent; a space and a tab are not treated as the same.
- Trim Leading Whitespace:
··a··⏎·b -> a··⏎b.
- Indent / Outdent Lines by N Spaces: Asks for N (1-100, default
4) once, then applies it to every selection: a⏎b (N=3) -> ···a⏎···b, ····a⏎·b (N=2) -> ··a⏎b.
- Expand All Tabs / Unexpand Spaces to Tabs (Tab Stops): Uses tab stops of 4, including tabs inside a line:
a⇥b <-> a···b.
- Blank Lines & Line Breaks:
- Collapse Consecutive Blank Lines:
a⏎⏎⏎⏎b -> a⏎⏎b (whitespace-only lines count as blank).
- Insert Blank Line Between Lines:
a⏎b -> a⏎⏎b.
- Remove Trailing / Leading Blank Lines:
a⏎b⏎⏎⏎ -> a⏎b, ⏎⏎a⏎b -> a⏎b.
- Clear Whitespace-only Lines:
a⏎··⏎b -> a⏎⏎b.
- Unwrap Paragraphs:
a⏎b⏎⏎c⏎d -> a b⏎⏎c d (blank lines between paragraphs are kept).
- Hard Wrap at 80 / N Columns: Wraps at word boundaries. The N version asks for N (1-1000, default
80) once: aa bb cc (N=5) -> aa bb⏎cc.
- Spaces Inside Lines:
- Remove All Whitespace:
a·b⇥c⏎d -> abcd.
- Collapse Inline Spaces (Keep Indent):
··a···b -> ··a b.
- Special Spaces to Normal Space:
a{U+00A0}b -> a·b (NBSP, thin space and similar spaces).
- Add Spaces Around Operators:
a=b+c -> a = b + c. Strings, template literals and comments are not changed.
- Remove Space Before Punctuation:
hello , world ! -> hello, world! (, . ! ? ; :).
- Ensure Space After Comma:
a,b,c -> a, b, c.
- Visualize:
- Visualize Spaces and Tabs: Replaces a space with
· (U+00B7) and a tab with → (U+2192): a·b⇥c -> a·b→c (the · and → in the output are the real characters).
- Restore Visualized Spaces and Tabs: The reverse:
a·b→c -> a·b⇥c (the · and → in the input are the real characters U+00B7 and U+2192).
- Alignment:
- Center Align / Right Align Lines: Pads each line with leading spaces based on the longest line:
a⏎abc -> ·a⏎abc / ··a⏎abc.
- Pad Lines to Same Length:
a⏎abc -> a··⏎abc.
- Align by Equals Sign (=):
a = 1⏎bbb = 2 -> a···= 1⏎bbb = 2.
- Align by Colon (:):
a: 1⏎bbb: 2 -> a:···1⏎bbb: 2.
- Align Columns by ",":
a,bb,c⏎ccc,d,e -> a,··bb,c⏎ccc,d,·e.
- Align by Custom Delimiter: Asks for a delimiter once:
a => 1⏎bb => 2 (=>) -> a··=> 1⏎bb·=> 2.
Limitations of the whitespace commands
- Line breaks: Line-based commands keep one line break at the end of the selection and insert line breaks with the document's line ending (LF or CRLF).
- Width: Widths are counted in code points. A full-width character (such as Japanese) or a combining character counts as one column, an emoji counts as one column per code point (an emoji with a skin tone modifier such as
👍🏽 takes 2 columns, a ZWJ sequence such as 👨👩👧 takes 5), and a tab counts as one column except in Expand / Unexpand Tabs. So text with Japanese characters or tabs does not look aligned after the alignment and hard wrap commands.
- Alignment is per selection: Center / Right Align, Pad Lines and the Align commands align the lines inside each selection. Select all the lines as one selection; one cursor per line does not align them.
- Output size limit: Center / Right Align, Pad Lines, the Align commands and Indent Lines by N stop if one run would add more than 10,000,000 characters in total (counted over all selections), for example Pad Lines on a selection with a very long minified line. Nothing is changed and a warning is shown. If any selection fails, no selection is changed.
- U+FEFF (BOM): It is not treated as whitespace, except by Remove All Whitespace, which removes it. A BOM at the start of a line is kept by Trim Leading Whitespace, and a line with only a BOM is not a blank line.
- Special Spaces to Normal Space: Converts U+00A0, U+1680, U+2000-U+200A, U+202F and U+205F. The ideographic space (U+3000), the zero-width space (U+200B) and U+FEFF are not converted.
- Visualize / Restore: Restore also turns
· and → that were in the text before visualizing into spaces and tabs, so a round trip is not always lossless.
- Unwrap Paragraphs: Lines in a paragraph are joined with one space, also in Japanese text. The indent of the first line is kept.
- Hard Wrap: A word longer than the width is not split. Wrapped lines get the indent of the original line. A line longer than the width is refilled word by word, so runs of spaces inside it (such as the spaces before an aligned comment) become one space. Lines within the width are not changed.
- Indent / Outdent / Unexpand: Indent Lines by N does not add spaces to whitespace-only lines. Outdent Lines by N stops at a tab. Unexpand never turns a single space between words into a tab.
- Align by Equals Sign: Lines are aligned at the start of the operator that contains the first
=, and operators such as +=, !=, <=, == and => are not split. So a = 1⏎bb += 2 becomes a··= 1⏎bb += 2 (the = and the + are in the same column). The right side is not changed: a=1⏎bb = 2 -> a··=1⏎bb = 2.
- Align by Colon: The
: in :: is not a delimiter. Lines with a URL (http://...) or a ternary operator may be aligned at an unexpected :. A key: line with an empty value gets no trailing spaces.
- Align Columns by ",": Commas inside quoted CSV fields are not recognized. The width of a column is decided only by the cells that are not the last cell of their line. Empty cells at the end of a line (
a,b,) are not padded, so no trailing spaces are added.
- Align by Equals / Colon / Comma / Custom Delimiter: A line with nothing (or only whitespace) before the delimiter is left unchanged and is not used for the width.
- Align by Custom Delimiter: The delimiter is literal text (not a regular expression) of 1-100 characters, without line breaks and not only whitespace. With
=, a += 1 can become a + = 1, so use Align by Equals Sign for code.
- Add Spaces Around Operators: This is not a full parser; it assumes C-like or JavaScript-like code.
- Target operators:
=== !== **= == != <= >= += -= *= /= %= => && || ** = + - * / %. Other operators such as <, >, ++, --, ->, ::, ?, :, &, |, ^, <<= and ??= are not changed (and not split).
+, -, * and ** are treated as unary (not changed) at the start of a line, after another operator or (, and after the keywords return case typeof void delete throw yield await in of instanceof new else do function (so return -1 and function* g() are kept).
- Strings, template literals (including nested
${...}), // comments and /* */ comments are not changed. Template literals and block comments that span lines are tracked only inside the selection.
- Not recognized: regular expression literals (
/a+b/ -> / a + b /), # comments, Python's // (treated as a comment) and keywords of other languages (such as Python's not). A ) always ends a value, so if (a) -b -> if (a) - b. A property with the same name as a keyword is treated as the keyword (obj.function*2 is not changed).
- Whitespace at the end of a line after an operator is kept as it is.
- Remove Space Before Punctuation: Spaces at the start of a line (indentation such as
··.foo()) and at the start of the selection are kept. It also changes code such as a ? b : c -> a? b: c.
- Ensure Space After Comma: Digit grouping is not recognized (
1,000 -> 1, 000), and a,,b becomes a, , b.
- Remove Trailing Blank Lines: When the selection ends at the start of a line and more lines follow (a selection made with
Shift+Down, Cmd+L / Ctrl+L or a triple click), one line break is kept so the next line is not joined. Only when the selection reaches the end of the document is the last line break removed too (a⏎b⏎⏎⏎ -> a⏎b).
- Remove Trailing / Leading Blank Lines: If the selection starts in the middle of a line (for example at the end of
ab), the start of the selection is treated as the rest of that line, not as a blank line, and one line break is kept so that line is not joined with the text after the selection (selecting from the end of ab to the start of z in ab⏎⏎⏎z gives ab⏎z). Likewise, if the selection starts at the start of a line and ends inside the indentation (leading whitespace) of a later line, Remove Trailing Blank Lines removes the blank lines and the selected whitespace but keeps one line break, so the text after the selection is not joined with the previous line (selecting from the start of a to just before z in a⏎⏎··z gives a⏎z). Only the selected whitespace is removed: if the selection ends partway through the indentation, the unselected part of it is kept (selecting from the start of a to the middle of the indentation in a⏎⏎····z gives a⏎··z). If the selected part of the last line contains any non-whitespace text, nothing is removed.
Line Commands
All line commands except Count Lines, Words and Characters and the (Clipboard) versions replace each selection in place. With multiple selections, each selection is processed on its own, and a command that asks for a value asks only once. Empty selections are ignored. They are also grouped in the Line submenu at the end of the Selection Manipulator context menu.
In the examples, · is a space, ⇥ is a tab and ⏎ is a line break. A value in parentheses is the value you enter.
- Filter:
- Keep / Remove Lines Containing Text:
apple⏎banana⏎cherry (an) -> banana / apple⏎cherry. The text is literal and case-sensitive.
- Keep / Remove Lines Matching Regex:
a1⏎b⏎c2 (\d) -> a1⏎c2 / b. JavaScript syntax with the u flag, case-sensitive (see the limitations below).
- Keep Every Nth Line / Remove Every Nth Line: Keeps / removes the lines whose line number is a multiple of N (N: 1-1,000,000, default
2): a⏎b⏎c⏎d (N=2) -> b⏎d / a⏎c.
- Keep Odd Lines / Keep Even Lines:
a⏎b⏎c -> a⏎c / b (the first line is line 1).
- Keep First N Lines / Keep Last N Lines: N: 1-1,000,000, default
10: a⏎b⏎c (N=2) -> a⏎b / b⏎c. Nothing changes if N is not less than the number of lines.
- Remove Comment Lines: Removes lines starting with
# or // (leading whitespace is ignored): # a⏎b⏎// c -> b.
- Duplicates:
- Keep Only Duplicated Lines: Keeps one copy of each line that appears two or more times, in the order of first appearance:
a⏎b⏎a⏎c⏎b -> a⏎b.
- Keep Lines Appearing Once:
a⏎b⏎a -> b.
- Remove Duplicate Lines (Ignore Case):
Apple⏎apple⏎b -> Apple⏎b (the first line is kept).
- Remove Duplicate Lines (Ignore Whitespace): Ignores leading and trailing whitespace (not whitespace inside a line) and keeps the first line as it is:
a⏎··a⏎b -> a⏎b.
- Remove Adjacent Duplicate Lines: Like
uniq: a⏎a⏎b⏎a -> a⏎b⏎a.
- Blank lines are counted as normal lines.
- Numbering:
- Add Line Numbers:
a⏎b -> 1: a⏎2: b.
- Add Line Numbers (Zero Padded): Pads to the digit count of the number of lines, without a colon: 10 lines
a⏎…⏎j -> 01 a⏎…⏎10 j.
- Numbers start from 1 in each selection. Both formats can be removed with Remove Line Numbers.
- Reorder:
- Reverse Word Order in Each Line:
a b c⏎d e -> c b a⏎e d. The whitespace between words and at the start / end of a line stays in place: ··a·b⇥c -> ··c·b⇥a.
- Rotate Lines Down:
a⏎b⏎c -> c⏎a⏎b.
- Swap Adjacent Line Pairs:
a⏎b⏎c⏎d⏎e -> b⏎a⏎d⏎c⏎e (with an odd number of lines, the last line stays).
- Move Lines Containing Text to Top:
b⏎x1⏎c⏎x2 (x) -> x1⏎x2⏎b⏎c (both groups keep their order).
- Interleave First and Second Half:
a⏎b⏎1⏎2 -> a⏎1⏎b⏎2. With an odd number of lines, the first half is the larger one: a⏎b⏎c⏎1⏎2 -> a⏎1⏎b⏎2⏎c.
- Duplicate Each Line:
a⏎b -> a⏎a⏎b⏎b.
- Join & Split:
- Join Backslash-continued Lines:
ls·\⏎··-l⏎pwd -> ls·-l⏎pwd (see the rules below).
- Join Every N Lines (Custom Delimiter): Asks for N (1-1,000,000, default
2) and then a delimiter (literal text of 0-100 characters, default ,; empty joins without a delimiter): a⏎b⏎c⏎d (N=2, ,) -> a,b⏎c,d. The last group may have fewer than N lines.
- Split Sentences into Lines:
Hello. Bye! -> Hello.⏎Bye!. Splits after . ! ? followed by whitespace, and after 。. Closing quotes and brackets after the punctuation (" ' ” ’ ) ] 」 』) stay with the sentence, and the whitespace at the split is removed.
- Split into Fixed-width Lines: Asks for a width (1-1,000, default
80): abcdef (N=2) -> ab⏎cd⏎ef. Each line is split on its own, counted in code points.
- Prefix / Suffix:
- Remove Prefix / Suffix from Each Line:
- a⏎- b (- ) -> a⏎b, a;⏎b; (;) -> a⏎b. The text is removed once, only from lines that start / end with exactly that text (indentation and trailing spaces are not ignored).
- Extract:
- Extract Lines Between Markers: Asks for a start marker and then an end marker:
x⏎BEGIN⏎a⏎END⏎y (BEGIN, END) -> a. A marker line is a line that contains the marker, and the marker lines are not included. All blocks are extracted in order. The start and end markers may be the same text. A block without an end marker runs to the end of the selection. A selection without a start marker line is left unchanged; if no selection has one, No lines were found between the markers is shown.
- Extract Longest Line / Extract Shortest Line:
a⏎abc⏎ab -> abc, abc⏎a⏎ab -> a. Counted in code points; on a tie the first line is taken. Extract Shortest Line skips blank and whitespace-only lines.
- Count:
- Count Lines, Words and Characters: Shows the total of all selections in a notification and does not change the text:
a b⏎c -> 2 lines, 3 words, 5 chars. A trailing line break is not counted as a line, words are runs of non-whitespace characters, and characters are code points with each line break (including CRLF) counted as one. With several selections, (N selections) is added.
- Clipboard versions: Keep Lines Containing Text, Keep Lines Matching Regex, Keep Only Duplicated Lines, Keep Lines Appearing Once, Remove Adjacent Duplicate Lines and Extract Lines Between Markers also have a (Clipboard) version that copies the result to the clipboard instead of changing the editor (no notification on success).
- The results of the selections are joined with the document's line ending, without a line break at the end. Selections whose result is empty are skipped, and so are selections without a start marker line (Extract Lines Between Markers).
- If nothing is left, the clipboard is not changed and a notification is shown (
No lines to copy. The clipboard was not changed., or No lines were found between the markers).
Limitations of the line commands
- Line breaks: A trailing line break of the selection is kept, and lines are joined with the document's line ending (LF or CRLF), so a selection with mixed line endings gets the document's line ending. Join Backslash-continued Lines is the exception (see below). If every line of the selection is removed, the result is empty and no line break is left.
- Selections starting or ending in the middle of a line: Commands that remove, reorder, number or extract lines (all commands in Filter, Duplicates, Numbering, Prefix / Suffix and Extract, and Rotate, Swap, Move to Top, Interleave and Duplicate Each Line) treat a partial first line (the selection starts after the start of a line) and a partial last line (the selection ends before the end of a line) as parts of lines outside the selection: they are left unchanged, are not counted, and one line break is kept next to them, so the text before or after the selection is never joined with another line. For example, selecting from
a to just before yy in xxa⏎b⏎cyy and removing lines containing b gives xxa⏎cyy. So, for example, Extract Lines Between Markers does not see a marker that is only in a partial first or last line. When the selection has no full line (such as from the middle of xxa to the start of the next line), these commands change nothing. A selection within one line is treated as one line.
- Commands that keep partial lines: Reverse Word Order, Join Backslash-continued Lines, Join Every N Lines, Split Sentences and Split into Fixed-width Lines treat partial first and last lines as normal lines (the width of Split into Fixed-width Lines is counted from the start of the selection).
- Clipboard versions: They ignore where the selection starts and ends and treat the selected text as whole lines, so the result can differ from the replacing version. For example, selecting from
a to the start of next in xxa⏎q⏎next and running Keep Lines Containing Text (q) leaves the editor unchanged, but the (Clipboard) version copies q.
- Join Backslash-continued Lines: A line is continued only if it ends with an odd number of backslashes; only the last one is removed (
a\⏎b -> ab, a\\\⏎b -> a\\b), and an even number (a\\⏎b) is literal and not joined. A line with whitespace after the backslash is not continued. The spaces and tabs at the start of the next line are removed, the spaces before the backslash are kept, and no space is added. Continuations chain (a·\⏎b·\⏎c -> a·b·c). With CRLF, the character before \r\n is checked. The last line of the selection and the line before the trailing line break are not joined, because the next line is outside the selection. The line breaks that are not joined are kept as they are (LF, CRLF or CR).
- Regular expressions (Keep / Remove Lines Matching Regex and its Clipboard version): The pattern is 1-500 characters and is checked when you enter it. It runs in a separate worker thread and is stopped after 2 seconds (for example
^(a+)+$ on a long line), and the selections can be up to 10,000,000 characters in total. In both cases a warning is shown and nothing is changed. If the document is edited while the pattern is running, the selection is not changed and a warning is shown.
- Output size limit: Add Line Numbers (both versions), Duplicate Each Line, Join Every N Lines, Split Sentences and Split into Fixed-width Lines stop if one run would add more than 10,000,000 characters in total (counted over all selections). Nothing is changed and a warning is shown.
- Input values: Text and markers are literal and case-sensitive, 1-1,000 characters without line breaks (they are not regular expressions). The selections and their text are read after you finish entering the values, so edits made to the document while an input box is shown (for example by a formatter) are taken into account; if no non-empty selection is left by then, nothing is done.
- Split Sentences: Abbreviations such as
e.g. or Mr. are also treated as sentence ends. . without whitespace after it (3.14) is not a split, a line is not split at its end, and existing line breaks are kept. Full-width ? and ! are not treated as sentence ends.
- Remove Duplicate Lines (Ignore Case): Lines are compared with
toLowerCase(), which does not depend on the locale (for example, Turkish İ is not handled specially).
3. Sort, Unique & Shuffle
Sort Lines
Sorts selected lines based on various criteria.
- Criteria: String, Number, Line Length, Occurrence Count.
- Order: Ascending, Descending.
- Variations: Sort the entire line or just the selection.
Extended Sort Commands
These commands never change the editor: like the existing sort commands, they open the result in a new editor, and the (Clipboard) versions copy it to the clipboard instead. They are in the Sort Lines and Sort Selections submenus of the context menu.
In the examples, · is a space and ⏎ is a line break. A value in parentheses is the value you enter, and [a] is a selection.
- Sort Lines (the lines of all selections are sorted as one list; one trailing line break of each selection is not counted as a line):
- Natural Order (Ascending / Descending): Numbers in the text are compared as numbers:
file10⏎file2 -> file2⏎file10. Letters are compared linguistically (a < B), not by code point.
- Ignoring Case (Ascending / Descending):
b⏎A⏎a -> A⏎a⏎b. Lines that differ only in case keep their order, also in the descending order (A⏎b⏎a -> b⏎A⏎a).
- Locale (Ascending / Descending): Asks for a locale (a BCP 47 tag such as
en, fr or ja, up to 64 characters; the default is the VS Code display language) and sorts with Intl.Collator: f⏎é⏎e (en) -> e⏎é⏎f. A malformed or unsupported locale is rejected when you enter it.
- Kana Order: Sorts in Japanese syllabary order, treating hiragana, katakana and half-width katakana as the same:
カ⏎あ⏎き -> あ⏎カ⏎き.
- Column (Ascending / Descending): Asks for a delimiter (literal text of 1-100 characters, default
,; enter \t for a tab) and then a column number (1-1,000, default 1): b,2⏎a,1 (,, 2) -> a,1⏎b,2. The cell is trimmed; numbers are compared by value and other text in natural order.
- Regex Capture: Asks for a regular expression and uses its first capture group (or the whole match if the pattern has no group) as the key:
id=10⏎id=9 (id=(\d+)) -> id=9⏎id=10. Numbers are compared by value and other text in natural order.
- Date (Ascending / Descending): Uses the first year-first date of each line (
2026-03-01, 2026/03/01 or 2026.03.01, optionally with a time such as T10:00:00.123 or ·10:00 and a time zone Z, +09:00 or +0900): 2026-03-01 b⏎2025-12-31 a -> 2025-12-31 a⏎2026-03-01 b.
- Semantic Version: SemVer 2.0.0 precedence, with an optional leading
v or V. The whole line (ignoring leading and trailing whitespace) must be a version; a line such as pkg 1.2.0 or 1.2.0 release has no key: 1.10.0⏎1.2.0⏎1.2.0-rc.1 -> 1.2.0-rc.1⏎1.2.0⏎1.10.0. Build metadata (+build) does not change the order.
- IP Address: Uses the IPv4 / IPv6 address at the start of each line (a
/prefix and an IPv6 zone ID %eth0 are allowed): 10.0.0.10⏎10.0.0.9 -> 10.0.0.9⏎10.0.0.10. IPv4 addresses come before IPv6 addresses, and the same address sorts without a prefix first, then by prefix length.
- Hex Number: Uses the first token of each line as a hex number (
0x is optional): 0x1F⏎0xA -> 0xA⏎0x1F.
- Word Count:
a b c⏎a -> a⏎a b c.
- Last Word:
Ann Smith⏎Bob Adams -> Bob Adams⏎Ann Smith.
- Reversed String: Sorts by the line read backwards, so lines with the same ending (such as a file extension) are grouped:
a.ts⏎b.js⏎c.ts -> b.js⏎a.ts⏎c.ts.
- Remove Duplicates: Sorts ascending and removes duplicate lines (like
sort -u): b⏎a⏎b -> a⏎b.
- Paragraphs: Sorts blocks of lines separated by blank lines:
b⏎b2⏎⏎a⏎a2 -> a⏎a2⏎⏎b⏎b2.
- Keeping Indented Children: The least indented lines are sorted, and the lines below each of them (more deeply indented lines and blank lines) move with it:
b⏎··b1⏎a⏎··a1 -> a⏎··a1⏎b⏎··b1.
- Sort Selections (the non-blank lines of all selections are sorted, like the existing Sort Selections commands):
- Natural Order:
[v10] [v2] -> v2⏎v10.
- Ignoring Case:
[b] [A] -> A⏎b.
- Length (Ascending / Descending): Counted in code points:
[ccc] [a] -> a⏎ccc.
- Clipboard versions: Natural Order, Ignoring Case, Column and Semantic Version of Sort Lines, and Natural Order of Sort Selections also have a (Clipboard) version.
- The result is joined with LF (
⏎), also in a CRLF document. If the result is empty (for example, only blank lines are selected for Paragraphs), no editor is opened and the clipboard is not changed; a notification is shown instead (No lines to sort. No document was opened. / No lines to copy. The clipboard was not changed.).
- The sorts are stable: lines with the same key keep their original order.
Limitations of the extended sort commands
- Lines without a key: Lines without a key (no date, no semantic version, no IP address, no hex number, no match of the regular expression, or too few columns) are put last in their original order, in both the ascending and the descending order.
- Column and Regex Capture: Numbers and text are kept apart so that the order stays consistent when they are mixed: in the ascending order all numbers come first (by value) and then the text (in natural order), and the descending order is the exact reverse (text first):
b,10⏎a,9⏎c,x (,, 2) -> a,9⏎b,10⏎c,x / c,x⏎b,10⏎a,9. A number is a decimal such as 1, -1.5, .5 or 1e3. The Column sort splits each line at the literal delimiter and does not handle quoted CSV fields ("a,b").
- Regular expressions (Regex Capture): JavaScript syntax with the
u flag, case-sensitive, 1-500 characters, checked when you enter it. It runs in a separate worker thread and is stopped after 2 seconds (for example ^(a+)+$ on a long line), and the selections can be up to 10,000,000 characters in total. In both cases a warning is shown and nothing is opened. A line where the first group does not take part in the match (the line b for (a)?b) has no key.
- Date: Only year-first dates are read (
MM/DD/YYYY and DD/MM/YYYY cannot be told apart). Only the first date of a line is used; if it is not a valid date (2026-02-30, 25:00) or has an out-of-range time zone (+25:00, +09:60), the line has no key. A date or time without a time zone is taken as UTC, and so is one with a malformed time zone such as +09:001 (the time zone is ignored, unlike an out-of-range one). Only the first three digits of a fraction of a second are used.
- Hex Number: The first token counts as a hex number whenever the whole token is hex digits (with an optional
0x), so words such as face, bad or add also get a hex key. Tokens with other characters (deadline, bad-name, 0xZZ) and 0x alone have no key.
- Remove Duplicates: Only lines that are exactly the same are duplicates. Lines that differ only in case or in Unicode normalization (NFC / NFD) are all kept.
- Paragraphs: Lines with only whitespace separate paragraphs. The result has exactly one empty line between paragraphs; leading, trailing and repeated blank lines are removed. With several selections, the boundaries between selections do not separate paragraphs.
- Keeping Indented Children: Only the top level is sorted; the children keep their order. Indentation is counted in characters (a tab counts as one). Lines before the first least indented line (leading blank lines or more deeply indented lines) stay at the top in their order.
- Locale and kana order: The order comes from
Intl.Collator of the VS Code runtime and may differ slightly between versions.
Unique & Shuffle
- Unique Selections: Removes duplicate lines.
- Shuffle: Randomly shuffles the selected lines, selections, or characters.
- Diff Selection: Shows the difference between two selections.
Filter and move data to a new tab or clipboard.
- Extract Lines: By Regex match or manual selection.
- Extract by Length: Equal to, Less than, Greater than, or Range of N characters.
- Extract Specific Data:
- Email:
support@example.com. The addresses are found in linear time, so a long selection does not stall the editor.
- URL:
https://example.com
- IP Address:
192.168.1.1
5. Case Conversion
Convert text between naming conventions and cases.
- Code Cases: Camel, Pascal, Snake, Kebab, Constant (
UPPER_SNAKE), Dot, Path.
- Text Cases: Upper, Lower, Capital, Sentence, Title (Smart).
- Fun/Other: SpongeBob (
sPoNgEbOb), Screaming Snake, Humanize, Slugify.
- Remove Accents:
Crème -> Creme.
Extended Case Commands
- Case Only (delimiters kept):
- Swap:
Hello World -> hELLO wORLD.
- Sentence (Preserve Acronyms):
the API URL is ready -> The API URL is ready.
- Title (APA Style):
a guide through the woods -> A Guide Through the Woods (words of 4+ letters are capitalized; hyphenated words too: state-of-the-art -> State-of-the-Art).
- Upper First / Lower First:
hello World -> Hello World, HelloWorld -> helloWorld.
- Alternating Words:
one two three -> ONE two THREE.
- Uppercase Known Acronyms:
userId apiUrl -> userID apiURL (built-in list of 42 acronyms such as id, url, http, json).
- Sentence (Each Sentence):
hello. how are you? fine. -> Hello. How are you? Fine.
- Capitalize Each Line / Lowercase Each Line Start: lines
foo bar / baz -> Foo bar / Baz (indentation is kept).
- Upper (Locale) / Lower (Locale): Asks for a locale tag (e.g.
tr) once, then applies it to every selection: istanbul (tr) -> İSTANBUL.
- Naming Conventions:
- Cobol:
userName -> USER-NAME
- Ada:
user name -> User_Name
- Flat / Upper Flat:
User Name -> username / USERNAME
- Camel Snake / Pascal Snake:
user name id -> user_Name_Id / User_Name_Id
- Acronym:
portable network graphics -> PNG
- CSS Custom Property:
primaryColor -> --primary-color
- BEM:
card title active -> card__title--active (4th and later words join the modifier)
- Hashtag:
hello world -> #HelloWorld
- Detect & Cycle:
- Detect Style: Shows the naming convention of each selection in a notification (e.g.
Detected case: snake_case) without changing the text.
- Cycle: camelCase -> snake_case -> kebab-case -> PascalCase -> CONSTANT_CASE -> camelCase (
userName -> user_name).
- JSON Keys to Camel / Snake / Kebab / Pascal: Converts only the object keys of the selected JSON (nested objects and arrays included):
{"user_name":"a_b"} -> {"userName":"a_b"}. Values, whitespace, indentation, key order and escapes are kept byte for byte.
- Pluralize / Singularize: Converts the last English word of each line, keeping its case: lines
category / child -> categories / children, userAccount -> userAccounts, API -> APIs, USER_BOX -> USER_BOXES.
Limitations of the extended case commands
- Sentence (Preserve Acronyms): Words written only in capitals are treated as acronyms, so an all-caps sentence (
THE API IS READY) is left unchanged. Mixed-case words such as iOS are lowercased (ios).
- Title (APA Style): An all-caps input of two or more words is lowercased first, so acronyms in it are not kept (
THE API GUIDE -> The Api Guide). A single all-caps word (API) is left as is.
- Detect Style: PascalCase is recognized only when it starts with a capital followed by a lowercase letter or digit, so identifiers starting with an acronym (
URLParser) are reported as unknown.
- Cycle: A single word stops at
user (User -> USER -> user), because flatcase goes back to the start of the cycle. Leading and trailing whitespace is removed.
- Uppercase Known Acronyms: The first part of a word with two or more parts is never changed (
IdToken stays, ApiUrl -> ApiURL); words with digits (utf8) are not in the list; consecutive acronyms can be hard to read (getHttpsUrl -> getHTTPSURL).
- Sentence (Each Sentence): A sentence starting with a quote (
"hello.) and a position with no space after the period (hello.world) are not capitalized.
- JSON Keys: If two different keys in the same object would become the same key (
{"user_id":1,"userId":2} to camel), that selection is left unchanged and an error is shown; other selections are still converted. Invalid JSON shows Invalid JSON: ... and is left unchanged. Keys that would become empty (non-ASCII only such as ユーザー, or __) are kept as is, and symbols or emoji inside a key are dropped ("😀_x" -> "x").
- Pluralize / Singularize: Rule-based with a small built-in dictionary, so irregular words not in the dictionary are not guaranteed (
waltzes -> waltze, bases always becomes base). A stand-alone all-caps word that is not a known acronym cannot be told apart from an all-caps English word (BOX -> BOXES), so it gets an upper-case S (DTO -> DTOS); write DTOs to get DTO back with Singularize.
- Only the last run of letters on each line is converted, including letters before a symbol. A known file extension right after a
. is left unchanged when it is all lower-case, all upper-case or capitalized (file.ts, FILE.TS, file.Ts, index.json; so a capitalized member name such as style.Css is left unchanged too), but extensions not in the built-in list and common member names are still converted (console.log -> console.logs).
- Lines ending with a one-letter word (
a, s), a possessive or a contraction (user's, it's, we're, the users') are left unchanged. A single word in single quotes ('users') is converted, but several words in single quotes ('the users') are not.
- Known acronyms ending with
S (DNS, HTTPS, CSS, OS, iOS, SMS, GPS, AWS) are left unchanged in both directions. An all-caps word ending with S that is not in this list follows the same already-plural check as lower-case words: singular -ss / -us / -is words and dictionary words are still pluralized (CLASS -> CLASSES, STATUS -> STATUSES, GAS -> GASES), while other words are treated as plurals (ABS is unchanged by Pluralize and becomes AB with Singularize). Acronym plurals with a lowercase s are not affected (DTOs -> DTO, TODOs -> TODO). One of the acronyms ending with S above followed by a lowercase es becomes the acronym again with Singularize (CSSes -> CSS, DNSes -> DNS; Pluralize leaves it unchanged).
- In an all-caps identifier the suffix is upper-case too (
USER_ID -> USER_IDS, USER_BOX -> USER_BOXES); a stand-alone acronym or an all-caps part after a lowercase letter gets a lowercase s (API -> APIs, userID -> userIDs).
- Words that are already plural are left unchanged by Pluralize (
users, IDs, APIs, categories, children). The check is: a word ending with s whose singular pluralizes back to it. So singular words ending with s that are not -ss / -us / -is words and not in the dictionary are left unchanged too, even when the correct plural is different (chaos, pancreas, thermos, yes, ms).
JSON / XML / YAML
- Format (Pretty Print): Formats minified JSON/XML.
- Minify: Compresses code.
- Convert:
- JSON <-> YAML
- XML -> JSON
- Env File -> JSON
- Stringify/Parse: Escape/Unescape JSON strings.
- Flatten/Unflatten: Convert between nested JSON and dot-notation.
CSV
- CSV <-> Markdown Table: Convert between Comma-Separated Values and Markdown table syntax.
- CSV / TSV: Convert, reshape and inspect CSV and TSV (see Table Commands below).
Encoding
- Base64: Encode, Decode, Deflate, Inflate.
- URL: Encode/Decode URI or URI Components.
- Escape/Unescape: Handle standard string escaping (newlines, quotes).
Encode / Decode Commands
The standard versions open the result in a new read-only editor and never change the text, like the existing Base64 commands. The (Replace) versions of Encode / Decode HTML Entities, Escape / Unescape Unicode (\uXXXX) and Encode / Decode Hex replace each selection in place. With multiple selections, each selection is converted on its own: the standard versions open one editor with the results in document order, joined with the document's line ending (LF or CRLF), and the (Replace) versions replace every selection. Empty selections are skipped, and nothing happens if every selection is empty. The standard versions are in the Encode / Decode submenu of the Transform context submenu, and the (Replace) versions in the Encode / Decode submenu of the Replace context submenu.
In the examples, · is a space and ⏎ is a line break. A value in parentheses is the value you enter.
- HTML:
- Encode HTML Entities: Escapes
& < > " ' (as & < > " '): <a href="x"> -> <a href="x">.
- Decode HTML Entities: Decodes decimal (
あ) and hexadecimal (あ) character references and the supported named entities: <b>·あ -> <b>·あ.
- Encode All Characters as Numeric Entities: Despite the title, only non-ASCII characters are converted, one decimal reference per code point; ASCII is kept:
aあ -> aあ.
- Unicode escapes:
- Escape Unicode (\uXXXX): Non-ASCII UTF-16 code units become
\u with 4 lower-case hex digits (a surrogate pair becomes two escapes): あ😀 -> \u3042\ud83d\ude00.
- Unescape Unicode (\uXXXX): Decodes
\uXXXX (4 hex digits) and \u{…} (1-6 hex digits), joining a surrogate pair written as two \uXXXX: \u3042 -> あ, \ud83d\ude00 -> 😀. A \u that is not in one of these forms (C:\users) is kept.
- Escape Unicode (\u{...}): Non-ASCII characters become
\u{…} per code point with upper-case hex digits: 😀 -> \u{1F600}.
- Base encodings (text is encoded as UTF-8 bytes):
- Encode / Decode Base64URL: URL-safe alphabet (
- _) without padding: foo? <-> Zm9vPw. The decoder also accepts correct = padding.
- Encode / Decode Base32: RFC 4648 alphabet with
= padding: foo <-> MZXW6===. The decoder ignores case, and the padding may be omitted.
- Encode / Decode Base58: Bitcoin alphabet; each leading zero byte is
1: hello <-> Cn8eVZg.
- Encode / Decode Ascii85: Adobe variant enclosed in
<~ ~>, with z for four zero bytes: hi <-> <~BP@~>. The decoder accepts the text with or without <~ ~>.
- Encode / Decode Base64 (Each Line): Encodes or decodes each line on its own; empty lines stay empty and the line breaks (LF or CRLF) are kept:
a⏎b <-> YQ==⏎Yg==. The decoder ignores spaces and tabs at both ends of a line.
- Gzip Base64 / Gunzip Base64: Compresses with gzip and encodes the result as standard Base64, and the reverse:
hi <-> H4sIAAAAAAAAE8vIBACsKpPYAgAAAA==. This is a different format from the existing Deflate / Inflate commands. The time stamp, extra flags and operating system fields of the gzip header are fixed values, so the same text always gives the same result.
- Encode as Data URI (text/plain):
hi -> data:text/plain;charset=utf-8;base64,aGk=.
- Bytes as hex and binary:
- Encode Hex (UTF-8 Bytes): Lower-case hex digits without separators:
abc -> 616263.
- Decode Hex (UTF-8 Bytes): Tokens are separated by spaces, tabs or line breaks, and case is ignored:
61·62·63 -> abc. A token is either bare hex digits (6162) or starts with 0x / 0X, and each 0x group must have an even number of digits (0x61·0X62, 0x6162 and 0x610x62 are all ab). A 0x in the middle of bare digits (100x20), a doubled prefix (0x0x61), a 0x without digits and an odd number of digits are errors.
- Encode Binary (UTF-8 Bytes): Eight bits per byte, separated by a space:
Hi -> 01001000·01101001. Decode Binary ignores whitespace and needs a multiple of 8 bits of 0 and 1.
- Internationalized domain names:
- Encode Punycode (IDN) / Decode Punycode (IDN): Converts the whole selection, as one domain name, with the
domainToASCII / domainToUnicode functions of Node.js: 例え.jp <-> xn--r8jz45g.jp. Spaces, tabs and line breaks at both ends are ignored.
- Mail and forms:
- Encode Quoted-Printable: UTF-8 bytes other than printable ASCII, and
=, become =XX (upper-case); a space or tab at the end of a line becomes =20 / =09, and lines longer than 76 characters get a soft line break (= and a line break of the document's line ending) without splitting an =XX: café -> caf=C3=A9. The original line breaks are kept.
- Decode Quoted-Printable: Decodes
=XX (any case) and removes soft line breaks: caf=C3=A9 -> café. As in RFC 2045, spaces and tabs at the end of each encoded line are removed first (abc··⏎def -> abc⏎def); encoded ones (=20 / =09) are kept.
- Encode Form (x-www-form-urlencoded): Like an HTML form: a space becomes
+, and everything except letters, digits and * - . _ becomes %XX of its UTF-8 bytes: a·b&c -> a+b%26c. Line breaks are encoded as they are (%0A).
- Decode Form (x-www-form-urlencoded):
+ becomes a space and %XX is decoded: a+b%26c -> a·b&c.
- Ciphers (for obfuscation, puzzles and learning only; they are not encryption):
- Cipher: ROT13:
Hello -> Uryyb. ROT47 (also rotates ASCII digits and symbols, ! to ~): Hello -> w6==@. Atbash (a <-> z): abc -> zyx.
- Cipher: Caesar Shift (N): Asks once for the shift (an integer with an optional sign and up to 9 digits; a negative number shifts backwards):
abc (3) -> def. If you cancel the input box, nothing is done. The selections are read again after the input box closes.
- Only the ASCII letters
A-Z / a-z are changed (ROT47: the ASCII characters !-~); other letters such as é, ß or ffi are kept.
- Text to NATO Phonetic Alphabet: Letters (any case) and digits become code words (
Alfa, Bravo, … X-ray, … Zulu, Zero … Nine), joined with a space; a run of whitespace inside a line becomes one /, and any other character is kept as its own word: ab1 -> Alfa·Bravo·One, ·ab·1· -> Alfa·Bravo·/·One. Whitespace at both ends of each line is dropped, and line breaks are kept.
Limitations of the encode / decode commands
- Errors: The decoders reject malformed input (characters outside the alphabet, a wrong length or padding, a last character with non-zero unused bits, broken gzip, an invalid
%XX or =XX, …) and decoded bytes that are not valid UTF-8 text. They are stricter than the existing Base64 Decode, which replaces invalid bytes with �. If any selection fails, no selection is changed and no editor is opened, and an error names the problem (and which selection, when there are several); selected text quoted in the message is shortened to 60 characters (with …).
- Decode HTML Entities: The named entities supported are the five XML entities (
amp lt gt quot apos), the Latin-1 entities (nbsp to yuml, U+00A0-U+00FF) and common symbols such as copy reg trade hellip mdash ndash lsquo rsquo ldquo rdquo bull euro larr rarr ne le ge (not all HTML5 entities). Unknown names and an & without ; are kept as they are. A numeric reference to 0, a surrogate (�) or a value beyond U+10FFFF is an error.
- Lone surrogates: The encoders that work on UTF-8 bytes (Base64URL, Base32, Base58, Hex, Binary, Quoted-Printable, Ascii85, Gzip Base64, Form, Base64 (Each Line) and Data URI) reject a selection that contains a lone surrogate (half of a surrogate pair, such as U+D83D without the following U+DE00) with an error instead of replacing it with
�, and no selection is changed.
- Unescape Unicode: A lone surrogate (
\ud83d without a following low surrogate, \ude00 alone, \u{D800}) and \u{…} beyond U+10FFFF are errors. A valid escape is decoded wherever it appears, for example in a Windows path such as C:\u0041, and a preceding \ is not treated as escaping it.
- Punycode: The domain name must be on one line: a line break or tab inside the selection is an error (select one domain name at a time). An invalid domain name is an error, and the selection can be up to 1,000 characters. Node.js applies the UTS #46 mapping in both directions, so ASCII letters become lower case and some characters are expanded or removed:
ffi -> ffi, ㍿ -> 株式会社 (Decode) or xn--6oqv20b1zgzxr (Encode), and Encode removes a soft hyphen (U+00AD). Because of this expansion, the result can be longer than the selection; it is covered by the output size limit below.
- Base58: Encode accepts up to 10,000 UTF-8 bytes and Decode up to 14,000 characters (whitespace excluded), as the conversion slows down quadratically with longer input.
- Gunzip Base64: Data that decompresses to more than 10 MiB (10,485,760 bytes) is rejected.
- Output size: A run whose results would exceed 10,000,000 characters in total (shared by all selections) is refused with a warning, and nothing is changed or opened. For most commands this is checked with a conservative estimate before converting, so input close to the limit may be refused even if the actual result would be smaller (for example, Encode Binary refuses more than about 1.1 million bytes).
- Quoted-Printable: Unencoded spaces and tabs at the end of a line are lost when decoding, as required by RFC 2045 (text encoded with Encode Quoted-Printable round-trips, as it encodes them).
The standard versions open the result in a new read-only editor and never change the text; with multiple selections, each selection is converted on its own and the results are joined in document order with the document's line ending (LF or CRLF). The (Replace) versions replace each selection with its result. Validate JSON and Count JSON Elements show their result in a notification, and Merge JSON Objects (Selections) merges all selections into one result. Empty selections are skipped, and nothing happens if every selection is empty. If any selection fails, no selection is changed and no editor is opened, and an error names the problem (and which selection, as selection 2 of 3: …, when there are several). The standard versions are in the new Data Format submenu of the Transform context submenu, and the (Replace) versions in the new Data Format submenu of the Replace context submenu. The existing JSON, XML and YAML commands are unchanged.
In the examples, · is a space and ⏎ is a line break. A value in parentheses is the value you enter.
- Output format: A command that turns JSON into JSON (Sort JSON Keys, Remove Null Values, Remove Duplicates in JSON Array, Pluck, Group by and Parse Nested JSON Strings) keeps the layout of the selection: a selection on one line gives one line without spaces, and a selection on several lines gives JSON indented with 2 spaces. Commands that turn another format into JSON write JSON indented with 2 spaces, like the existing Format and YAML to JSON commands.
- JSON structure:
- Sort JSON Keys / (Replace): Sorts the keys of every object in UTF-16 code unit order; the order of arrays is kept:
{"b":1,"a":{"d":2,"c":3}} -> {"a":{"c":3,"d":2},"b":1}.
- Remove Null Values from JSON: Removes keys and array elements whose value is
null, at every level; objects and arrays that become empty are kept: {"a":null,"b":[1,null]} -> {"b":[1]}.
- Extract JSON Value by Path: Asks for a path and shows the value there; a string is shown without quotes, and other values as JSON:
{"a":{"b":[5]}} (a.b[0]) -> 5. A path that does not exist is an error.
- List JSON Paths: Lists the path of every leaf (a value that is not an object or array, or an empty object or array), one per line:
{"a":{"b":1},"c":[2]} -> a.b⏎c[0]. Each line can be entered as is in Extract JSON Value by Path. A value at the top level that is not an object or array gives $.
- Extract JSON Keys: The keys of the top-level object, one per line:
{"a":1,"b":2} -> a⏎b.
- Merge JSON Objects (Selections): Deep-merges the JSON objects of two or more selections in document order (a later value wins, and arrays are replaced, not merged) and opens one editor:
{"a":1} and {"b":2} -> {"a":1,"b":2}. With fewer than two non-empty selections, only a warning is shown.
- Validate JSON: Checks each selection as strict JSON (RFC 8259) and shows
Valid JSON (Valid JSON (3 selections) with several), or Invalid JSON at line L, column C: reason for the first error, with the line and column in the document, and selects the character that caused it: for {"a":1,}, Invalid JSON at line 1, column 8: unexpected character "}" and the } is selected. When the text ends too early, the cursor is put at the end of the selection.
- Remove Duplicates in JSON Array: Removes repeated elements of the top-level array and keeps the first one; objects are compared by their content, ignoring the order of their keys:
[1,2,1,{"a":1},{"a":1}] -> [1,2,{"a":1}].
- Pluck Field from JSON Array: Asks for a field (a path such as
id or user.name) and gives an array of that field of every element; an element without it gives null, so the positions are kept: [{"id":1},{"id":2}] (id) -> [1,2].
- Group JSON Array by Field: Asks for a field and groups the elements of the array by its value, in the order the groups first appear:
[{"t":"a","v":1},{"t":"a","v":2}] (t) -> {"a":[{"t":"a","v":1},{"t":"a","v":2}]}. An element without the field, or with an object or array there, is an error that names the element.
- Count JSON Elements: Shows the number of elements of an array, keys of an object, and nodes in total in a notification:
[1,2,3] -> 3 elements (4 nodes in total); 1 key, 1 value for a value that is not an object or array. With several selections: Selection 1: …; Selection 2: ….
- Generate JSON Schema from JSON: Makes a draft 2020-12 schema from a sample, with
$schema, type, properties and required (the keys of the sample), items for arrays (the element schema, anyOf when the elements differ, {} for an empty array), and integer for whole numbers: {"a":1} -> {"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"a":{"type":"integer"}},"required":["a"]} (written with 2 spaces). The $schema URL is only written as text; nothing is downloaded.
- Parse Nested JSON Strings: Replaces string values that hold a JSON object or array (starting with
{ or [) with their parsed value, at every level: {"a":"{\"b\":1}"} -> {"a":{"b":1}}. Strings such as "123" or "true" stay strings.
- Paths: Extract JSON Value by Path, Pluck and Group by use the same notation as List JSON Paths:
.name for a key that is an identifier, [0] for an array index and ["any key"] (a JSON string) for any other key, with an optional $ at the start: a.b[0], $["b-c"][1], ["a.b"]. $ alone is the whole value. A path can be up to 1,000 characters; a wrong path is shown in the input box. If you cancel the input box, nothing is done, and the selections are read again after it closes.
- JSON to other formats:
- Convert JSON to Query String: A flat object with
URLSearchParams: {"a":1,"b":"x·y"} -> a=1&b=x+y. An array of values repeats the key ({"a":[1,2]} -> a=1&a=2), null is an empty value, and a nested object is an error.
- Convert JSON to Env: A flat object as
KEY=VALUE lines that the existing Env to JSON reads back: {"A":"1","B":"x·y"} -> A=1⏎B="x·y". A value with spaces, #, = or quotes is enclosed in "…" (or '…' when it contains "), and a value with $, a backtick or \ is always enclosed in single quotes ({"A":"$HOME"} -> A='$HOME'), so that shells, Docker Compose and dotenv do not expand it. null is an empty value.
- Convert JSON to XML / (Replace): Builds XML and formats it with the existing xml-formatter:
{"a":{"b":1}} -> <a>⏎··<b>1</b>⏎</a>. An object with one key becomes the root element; anything else (several keys, an array, a single value, or one key whose value is an array) is enclosed in <root>. An array becomes repeated elements with the same name (<item> for an array inside an array), null an empty element, and & < > " ' are escaped.
- Convert JSON to TOML / (Replace):
{"a":{"b":1}} -> [a]⏎b = 1. Values come first, then [table] headers (a table that only holds other tables gets no header of its own), and an array of objects becomes [[array]] tables. null is an error, as TOML has no null; an integer beyond ±(2^53−1) is written as a float (.0).
- Convert JSON to INI: Up to two levels: top-level values first, then a
[section] for each object: {"db":{"host":"x"}} -> [db]⏎host=x. A value with spaces at either end, ; or #, or enclosed in quotes is written in "…" so that Convert INI to JSON reads it back.
- Convert JSON to .properties: Nested keys joined with
. and array elements as name[n]: {"a":{"b":1}} -> a.b=1. Spaces, : = # ! in keys, a leading space in values, \ and control characters are escaped; other non-ASCII characters are written as they are (a UTF-8 .properties file).
- Convert JSON Array to JSON Lines / (Replace):
[{"a":1},{"a":2}] -> {"a":1}⏎{"a":2}.
- Convert JSON to JS Object Literal: Quotes keys only when needed and uses single quotes:
{"a":1,"b-c":2} -> {·a:·1,·'b-c':·2·} (one line for a selection on one line, 2 spaces otherwise). The key __proto__ is written as ['__proto__'], so that it stays an ordinary key when the code runs.
- Other formats to JSON:
- Convert TOML to JSON / (Replace):
[a]⏎b = 1 -> {"a":{"b":1}}. Uses the extension's own parser for the main TOML 1.0 syntax (no new dependencies; see the limitations below).
- Convert INI to JSON:
[section], key=value or key: value, and comment lines starting with ; or #: [db]⏎host=x -> {"db":{"host":"x"}}. Keys before the first section go to the top level, values are strings, and quotes around a whole value are removed. A later duplicate key wins, and sections with the same name are merged.
- Convert .properties to JSON:
# / ! comments, =, : or whitespace as the separator, continuation lines and escapes; keys are split at . into nested objects and name[n] into arrays: a.b=1 -> {"a":{"b":"1"}}. Values are strings. A key that is both a value and a parent (a=1 and a.b=2) is an error.
- Convert JSON Lines to JSON Array / (Replace): Empty lines are skipped:
{"a":1}⏎{"a":2} -> [{"a":1},{"a":2}]. An error is reported as line L, column C: reason.
- Convert JSONC / JSON5 to JSON: Accepts comments, trailing commas, unquoted and numeric keys, single-quoted strings, line continuations, hex numbers,
.5 / 5. and +: {a:·1,·//·c⏎} -> {"a":1}.
- Convert JS Object Literal to JSON: A JavaScript object literal with literal values only; in addition to the JSON5 syntax, it accepts template literals without
${, _ in numbers, 0o / 0b, \u{…} and a computed key that is a single string literal (['a']): {·a:·1,·'b':·[true]·} -> {"a":1,"b":[true]}. The text is parsed, never run.
- YAML:
- Format YAML / (Replace): Reads and writes the YAML again with the existing js-yaml, indented with 2 spaces:
a:···{b:·1} -> a:⏎··b:·1.
- Sort YAML Keys: Also sorts the keys at every level:
b:·1⏎a:·2 -> a:·2⏎b:·1.
- Both use the YAML 1.2 Core schema, so dates and times stay as they are written (
2020-01-01 is not turned into a time stamp). The result ends with a line break only if the selection does (in a CRLF document, a selection ending with CRLF), so the Replace version does not add or remove one.
- HTTP:
- Parse Cookie Header to JSON:
a=1;·b=x -> {"a":"1","b":"x"}. A leading Cookie: is removed, values are not decoded (quotes around a whole value are removed), and a repeated name gives an array of its values.
- Parse Set-Cookie to JSON:
id=1;·Path=/;·Secure -> {"name":"id","value":"1","path":"/","secure":true}. Known attributes (any case) are expires, maxAge (a number when it is an integer), domain, path, secure, httpOnly, sameSite, partitioned and priority; other attributes use their lower-case name (an attribute named name or value is an error). Several lines give an array, one cookie per line.
- Parse HTTP Headers to JSON:
Accept:·a⏎X-Id:·1 -> {"Accept":"a","X-Id":"1"}. A request or status line at the start (GET / HTTP/1.1, HTTP/1.1 200 OK) and empty lines are skipped, a line starting with whitespace continues the previous value, and a repeated name (any case) gives an array. A line without : is an error.
- Parse User-Agent to JSON: Tells the browser (major version) and OS with built-in rules: a Chrome on Windows 10 User-Agent ->
{"browser":"Chrome 120","os":"Windows 10"}. It knows Edge, Opera, Samsung Internet, Firefox, Chrome, Safari and Internet Explorer, and Windows, iOS, Android, macOS, ChromeOS and Linux; anything else is Unknown. Several lines give an array.
Limitations of the data format commands
- Size and nesting: A selection can be up to 5,000,000 characters, and objects and arrays can be nested up to 500 levels (YAML: see below). A run whose results would exceed 10,000,000 characters in total (shared by all selections) is refused with a warning, and nothing is changed or opened; for indented JSON, JS object literals and JSON Schema, this is estimated before the result is built, so a deeply nested result that would be too large is refused at once.
- JSON values: Like the existing JSON commands, keys that look like integers (
"0", "10") always come first in numeric order (so Sort JSON Keys puts "10" before "a" and "2" before "10"), integers beyond Number.MAX_SAFE_INTEGER lose precision, and a later duplicate key wins. Keys such as __proto__ and constructor are kept as ordinary keys.
- Group by: A group name is the value itself for a string and its JSON text otherwise, so the number
1 and the string "1" (likewise null and "null", true and "true") end up in the same group.
- TOML: Convert TOML to JSON supports comments, bare, quoted and dotted keys,
[table], [[array of tables]], inline tables, arrays (also on several lines, with trailing commas and comments), the four kinds of strings (with a line-ending \ in multi-line basic strings), decimal / hex / octal / binary integers with _, floats, booleans, and offset date-times, local date-times, local dates and local times, which are written to JSON as strings exactly as written. Redefining a key or table, extending an inline table or a static array, mixing [x] with [[x]], and extending a table made by a [header] with a dotted key in its parent table are errors. inf, nan and integers beyond ±(2^53−1) are errors, as JSON cannot hold them exactly. Dates and times are checked for their format and ranges (month 01-12, day 01-31, …), not against the calendar (2024-02-30 is accepted). Errors are reported as line L: reason.
- JSONC / JSON5 and JS object literals: Only literal values are accepted.
Infinity, NaN, undefined, identifiers used as values, functions, computed keys other than one string literal, spread, ${} in template literals and BigInt are errors.
- YAML: Format YAML and Sort YAML Keys go through a JavaScript object, so comments are lost and the value is written again in js-yaml's style: numbers are written in decimal (
0x1F -> 31), ~ and Null become null, True becomes true, quotes may be added or removed, and anchors are renamed (&ref_0 / *ref_0; aliases are kept as references, not expanded). Keys that look like integers become quoted string keys and move to the front in numeric order, even without sorting (10:·a⏎2:·b -> '2':·b⏎'10':·a). The merge key << is kept as an ordinary key and not merged (<<:·*ref_0). Tags outside the Core schema (!!binary, !!timestamp, !!set, …), several documents (---) and a selection with only comments, empty lines or --- are errors. YAML can be nested up to 100 levels (js-yaml's own limit; through aliases, up to 500 levels), and an alias that refers to itself is an error. YAML with anchors and aliases is limited to (number of mappings and sequences) × (number of references to them) ≤ 300,000,000; YAML without anchors has no such limit.
- XML: Element names are limited to ASCII letters, digits,
_, . and -, start with a letter or _, and must not start with xml (in any case); any other key (non-ASCII letters, spaces or other symbols) is an error, as the bundled xml-formatter cannot format other names. An empty array produces no element, and a value with control characters or a lone surrogate is an error.
- Env: Keys are limited to letters, digits,
_, . and -. A value with a line break, a value with both " and ', and a value with ' together with $, a backtick or \ are errors, as they cannot be quoted safely. An object or array as a value is an error.
- INI: Two levels only; arrays, a third level, a line break in a value, and
= [ ] ; #, a line break, spaces at either end or an empty string in a key are errors.
- .properties: An empty object or empty array is not written, and an empty object or array inside an array is an error (reading it back would shift the indices). A key with
., [ or ] cannot be converted, as it would be read back as nesting. When reading, an index can be at most the current length of the array (a[1]=x alone is an error).
- Set-Cookie and User-Agent: The User-Agent detection is simple and rule based, and Windows 11 cannot be told from Windows 10 (both are
Windows 10). A User-Agent can be up to 2,000 characters on each line.
Table Commands
The CSV / TSV commands read the selection as CSV (RFC 4180: fields in double quotes, "" for a quote inside them, and delimiters and line breaks inside quoted fields; LF, CRLF and CR line breaks). The standard versions open the result in a new read-only editor and never change the text; with multiple selections, each selection is converted on its own and the results are joined in document order with the document's line ending (LF or CRLF). The (Replace) versions replace each selection with its result (only the selections whose text changes, as one undo step). Sum Column and Show Row and Column Count show their result in a notification and never change the selection (with several selections: Selection 1: …; Selection 2: …). Empty selections are skipped, and nothing happens if every selection is empty. If any selection fails, no selection is changed and no editor is opened, and an error names the problem (and which selection, as selection 2 of 3: …, when there are several). The standard and notification versions are in the new CSV / TSV submenu of the Transform context submenu, and the (Replace) versions in the new CSV / TSV submenu of the Replace context submenu. The existing CSV <-> Markdown Table commands are unchanged.
In the examples, · is a space, ⇥ is a tab and ⏎ is a line break. A value in parentheses is the value you enter.
- Common rules:
- Header: Convert to JSON Array, Convert to SQL INSERT, Remove Duplicate Rows, Filter Rows, Sum Column, Add Index Column, Convert to YAML, Convert to HTML Table, Convert to ASCII Table, Show Row and Column Count and Convert Rows to Key-Value Records treat the first row as the header; the other commands treat every row the same (Extract Column, Remove Column and Swap Columns look at the first row only when a column is entered by name).
- Columns: A column is entered as its number (1 for the first column) or as the exact, case-sensitive text of a header cell. A value made only of digits is always a column number (spaces around it are ignored), so a header that is only digits cannot be entered by name; a name is compared exactly as entered, spaces included (use the number for a header such as
·b in a,·b). A number out of range, a name that no header cell has, and a name that several header cells have are errors. Entered values can be up to 1,000 characters without tabs, line breaks or other control characters. If you cancel an input box or the list, nothing is done, and the selections are read again after it closes.
- CSV output: Commands that write CSV write every cell again with minimal quoting: only a cell with the delimiter,
" or a line break (CR or LF) is quoted, and " is doubled. Quotes that are not needed are removed (Quote All Fields is the exception), so a (Replace) version may change more of the text than you expect. A row with no cells or with one empty cell is written as "", so that it is not read back as an empty line (and lost).
- Final line break: The result ends with one line break only if the selection ends with one, so the (Replace) versions do not add or remove one.
- Headers and values: Convert to JSON Array, Convert to SQL INSERT, Convert to YAML and Convert Rows to Key-Value Records pair each value with its header: a row with more cells than the header is an error (
row 3 has more cells than the header (3 > 2)), and a missing value in a shorter row is an empty string. Convert to JSON Array and Convert to YAML refuse a header with the same column name twice. __proto__ and similar names are ordinary keys.
- No rows: A selection with no rows (only empty lines or line breaks) is an error (
no rows found), so a (Replace) version never replaces a selection with nothing. With only the header row, Convert to JSON Array and Convert to YAML give [], Convert to SQL INSERT and Convert Rows to Key-Value Records are errors (no data rows (only the header was found)), Sum Column shows a warning, Show Row and Column Count shows 0 rows × N cols, no empty cells, the other commands that treat the first row as the header give a table with only the header (Add Index Column adds the # column: a,b -> #,a,b), and the commands that treat every row the same convert that row like any other row (Transpose gives one column: a,b -> a⏎b).
- Convert:
- CSV - Convert to JSON Array / (Replace): An array of objects, one for each data row; values are always strings, and the JSON is indented with 2 spaces:
a,b⏎1,2 -> [{"a":"1","b":"2"}] (written on several lines).
- CSV - Convert from JSON Array / (Replace): The header is the union of the keys of all objects, in the order they first appear:
[{"a":1,"b":2}] -> a,b⏎1,2. Strings are written as they are, numbers and booleans as JSON, null and a missing key as an empty cell, and a nested object or array as compact JSON text. Every element must be an object; an empty array (the JSON array is empty), objects that all have no keys (the objects have no keys) and a number out of range such as 1e400, also inside nested values (element 1: a number is out of range), are errors. The JSON can be nested up to 500 levels.
- CSV - Convert to TSV / (Replace):
a,b⏎1,2 -> a⇥b⏎1⇥2. A cell with a tab, " or a line break is quoted (as Excel does).
- CSV - Convert from TSV: Tab-separated text (such as cells pasted from Excel, quoted cells included) to CSV:
a⇥b⏎1⇥2 -> a,b⏎1,2.
- CSV - Change Delimiter: Asks for the new delimiter and writes the CSV with it:
a,b (;) -> a;b. The delimiter is exactly one character (one Unicode code point, so one emoji is fine); type \t (two characters) for a tab, as a tab cannot be typed into the input box. ", line breaks and other control characters are refused.
- CSV - Convert to HTML Table / (Replace): One
<tr> per line, <th> cells for the first row and <td> cells for the others, indented with 2 spaces: a,b⏎1,2 -> <table>⏎··<tr><th>a</th><th>b</th></tr>⏎··<tr><td>1</td><td>2</td></tr>⏎</table>. & < > " ' in cells are escaped, and short rows are filled with empty cells.
- CSV - Convert to SQL INSERT: Asks for the table name (
users or schema.users) and writes one INSERT statement for each data row, with the first row as the column names: id,name⏎1,O'Neil (users) -> INSERT INTO users (id, name) VALUES ('1', 'O''Neil');. See the limitations below for the SQL it writes. The SQL is only written, never run.
- CSV - Convert to YAML: An array of mappings with the existing js-yaml (YAML 1.2 Core schema); values are strings, so numbers are quoted:
a,b⏎1,2 -> -·a:·'1'⏎··b:·'2'.
- CSV - Convert to ASCII Table:
a,b⏎1,2 -> +---+---+⏎|·a·|·b·|⏎+---+---+⏎|·1·|·2·|⏎+---+---+. A line break or a tab in a cell becomes one space, so that the borders stay straight; with only the header row, the result is a border, the header and a border.
- CSV - Convert from Whitespace-separated Table: Splits each line at runs of spaces and tabs (for example, the output of a command):
NAME···AGE⏎bob····30 -> NAME,AGE⏎bob,30. Spaces at either end of a line are ignored, empty lines are skipped, and quotes are not read.
- CSV - Convert Rows to Key-Value Records: Each data row as
header: value lines, with an empty line between records: a,b⏎1,2 -> a:·1⏎b:·2. A line break in a header or value becomes one space, so that each line is one pair and empty lines only separate records.
- Columns and rows:
- CSV - Transpose / (Replace): Swaps rows and columns:
a,b⏎1,2 -> a,1⏎b,2. Short rows are filled with empty cells first.
- CSV - Extract Column: Asks for a column and gives only that column, header included:
a,b⏎1,2 (2) -> b⏎2.
- CSV - Remove Column: Asks for a column and removes it:
a,b,c⏎1,2,3 (2) -> a,c⏎1,3. A table with only one column is an error, and a short row without that column is kept as it is.
- CSV - Swap Columns: Asks for two columns, one after the other, and swaps them:
a,b⏎1,2 (1, 2) -> b,a⏎2,1. The same column twice is an error.
- CSV - Align Columns: Pads each cell except the last of its row with spaces up to the widest cell of its column (as written, quotes included):
a,bb⏎ccc,d -> a··,bb⏎ccc,d. The result can be read back by the CSV / TSV commands, as spaces after a closing quote are skipped.
- CSV - Trim Cell Padding: Removes spaces and tabs at either end of every cell (the reverse of Align Columns):
a··,bb⏎ccc,d -> a,bb⏎ccc,d.
- CSV - Remove Duplicate Rows: Keeps the header and the first of the data rows that are exactly the same:
a⏎1⏎1 -> a⏎1.
- CSV - Filter Rows by Column Value: Asks for a column, a condition (
Equals or Contains) and a value, and keeps the header and the data rows whose cell matches (case-sensitive): n,v⏎a,1⏎b,2 (v, Equals, 2) -> n,v⏎b,2. The value may be empty (Equals with an empty value keeps the rows whose cell is empty).
- CSV - Add Index Column: Adds a
# column numbered from 1: a⏎x⏎y -> #,a⏎1,x⏎2,y.
- CSV - Fill Empty Cells from Above: Fills each empty cell with the value above it (every row is data, and a cell with only spaces is not empty):
a,1⏎,2 -> a,1⏎a,2.
- Quotes:
- CSV - Quote All Fields: Encloses every cell, empty cells included, in
": a,b -> "a","b".
- CSV - Remove Unnecessary Quotes: Keeps the quotes only on cells with the delimiter, a line break or
": "a","b,c" -> a,"b,c".
- Notifications:
- CSV - Sum Column: Asks for a column and shows the sum and average of its numbers:
n,v⏎a,1⏎b,2 (v) -> sum=3, avg=1.5. A number is a decimal such as -1.5, .5 or 1e3 (spaces around it are ignored), empty cells are ignored, and other cells are counted as (1 non-numeric cell skipped). A number too large for floating-point numbers (1e400) is counted as non-numeric too: v⏎1e400⏎2 (v) -> sum=2, avg=2 (1 non-numeric cell skipped). The result is rounded to 15 significant digits (0.1 + 0.2 shows 0.3). A column without numbers (no numeric cells in the column) and a sum beyond the range of floating-point numbers (the sum is out of range) are shown as warnings.
- CSV - Show Row and Column Count: Shows the number of data rows (without the header) and columns, and the number of empty cells (missing cells of short rows included) in each column:
a,b⏎1,⏎2,3 -> 2 rows × 2 cols, b: 1 empty (1 row × 1 col, no empty cells when there are none). A column is named by its header (column N when the header is empty), cut to 60 characters, and up to 10 columns are listed (…and N more).
Limitations of the CSV / TSV commands
- Size: A selection can be up to 5,000,000 characters. A table whose rows × columns (of its longest row) is more than 10,000,000 cells is refused with a warning (
the table is too large: R rows × C columns is more than 10,000,000 cells) by every command, even one that does not fill short rows, so a very ragged table (one very long row and many short ones) may be refused. A run whose results would exceed 10,000,000 characters in total (shared by all selections) is refused with a warning; for Align Columns, Convert to ASCII Table, Convert to JSON Array and Convert to YAML this is checked before the result is built. In both cases nothing is changed or opened.
- Parsing: Empty lines are skipped, so a table with empty lines loses them, and a byte order mark at the start is removed. A
" inside an unquoted field is an ordinary character. Spaces and tabs after a closing quote are skipped, but spaces before an opening quote are not, so in a,·"b,·c" the quote is not a quote and ·"b and ·c" become two cells (as RFC 4180 says). An unclosed quote and other text after a closing quote are errors with the line in the selection (line 2: a quoted field is not closed). Convert from Whitespace-separated Table does not read quotes at all, so a value with spaces is split.
- Rows: Remove Duplicate Rows compares rows exactly, so ragged rows such as
1 and 1, are different rows.
- Width: Align Columns and Convert to ASCII Table count the width in code points (like the existing Align commands), so full-width characters, emoji and combining characters do not line up. Align Columns counts a line break inside a quoted cell as part of the width, so such a table does not line up (it is still read back correctly), and Convert to ASCII Table writes control characters other than tabs and line breaks as they are, counted as one character wide.
- Key-Value Records: As a line break in a header becomes a space, two different headers such as
"a⏎b" and a·b look the same.
- Convert from JSON Array: Like the existing JSON commands, keys that look like integers (
"0", "10") come first in numeric order within each object (the key order of JavaScript objects), and the header takes the keys in the order they first appear, so such keys do not always come first in the header ([{"b":1},{"0":2,"10":3}] -> header b,0,10; [{"b":1,"0":2}] -> header 0,b); integers beyond Number.MAX_SAFE_INTEGER lose precision (12345678901234567890 -> 12345678901234567000), and numbers too small for floating-point numbers (1e-400) are written as 0.
- SQL INSERT: The SQL is written as standard SQL: every value is a string literal in single quotes with
' doubled (an empty cell is '', not NULL), and a table or column name that is not a plain identifier (^[A-Za-z_][A-Za-z0-9_]*$; for the table, such identifiers joined with . as in schema.table are also written as they are) is enclosed in double quotes with " doubled. A value, column name or table name with a backslash (\) is an error and nothing is changed, even for valid data such as a Windows path (C:\Users), because MySQL / MariaDB in their default mode (without NO_BACKSLASH_ESCAPES) read \ as an escape character, so a cell could end the string and add SQL of its own. A yen sign (¥, U+00A5) is an error for the same reason, because it is saved as a backslash (the byte 0x5C) in Shift_JIS, CP932 and EUC-JP; the full-width ¥ (U+FFE5) and \ (U+FF3C) are accepted. A control character other than tabs and line breaks (U+0000 to U+0008, U+000B, U+000C, U+000E to U+001F and DEL U+007F, NUL included) is an error too, because it is invisible and would go into the query unnoticed; tabs and line breaks are valid inside a string literal and are kept. When a value or name has several of these characters, a control character is reported first, then a backslash, then a yen sign. The same rules (control characters, backslash and yen sign) apply to Quote: SQL IN List and Escape SQL String Literal. For MySQL / MariaDB, names in double quotes also need ANSI_QUOTES. An empty column name is an error. A reserved word used as a plain identifier (order) is not quoted, so some databases may reject the SQL (it does not change what the SQL does).
- Line breaks: Results are written with LF and then with the document's line ending, so in a CRLF document line breaks inside quoted cells become CRLF too.
7. Cryptography & Security
Hashing & Encryption
- Hash: MD5, SHA-1, SHA-256, SHA-512.
- HMAC: Keyed-hash for the above algorithms.
- AES Encryption: Encrypt/Decrypt text with a passphrase (AES-256-CBC).
- Encrypt outputs the v2 format
v2:<salt>:<iv>:<ciphertext> (hexadecimal). The key is derived from the passphrase with scrypt and a random 16-byte salt, and the IV is a random 16 bytes; both are new for every encryption, so the same text and passphrase give a different result each time.
- Compatibility mode: text encrypted by earlier versions (
<iv>:<ciphertext>, and <ciphertext> alone, which used a zero IV) can still be decrypted. Those formats used a fixed salt, so they are only decrypted, never produced; when a decryption uses them, a notification suggests encrypting the text again in the v2 format.
Hash and Checksum Commands
Every command hashes the selected text exactly as it is selected, as UTF-8 bytes: the text is not trimmed, and a CRLF line break is hashed as the two characters CR and LF. Hex output is lower case. The standard versions open a new read-only editor, like the existing Create Hash commands: for each selection, the selected text (trimmed, as a heading) followed by its result. The (Replace) versions replace each selection with its result. Multiple selections are processed in document order; empty selections are skipped, and nothing happens if every selection is empty. The Crypto submenu of the Transform context submenu has the Create Hash, Create HMAC and SRI commands, the new Checksum submenu of Transform has the four Checksum commands, and the Crypto submenu of the Replace context submenu has the (Replace) versions.
In the examples, ⏎ is a line break, a value in parentheses is the value you enter, and a long result is shortened with ….
- Create Hash:
- SHA-224, SHA-384, SHA-512/256:
abc -> 23097d22… (SHA-224), cb00753f… (SHA-384), 53048e26… (SHA-512/256).
- SHA3-256, SHA3-512, BLAKE2b-512, BLAKE2s-256:
abc -> 3a985da7… (SHA3-256), b751850b… (SHA3-512), ba80a53f… (BLAKE2b-512), 508c5e8c… (BLAKE2s-256). The Node.js of VS Code does not provide these algorithms, so the extension computes them with its own implementation (FIPS 202 and RFC 7693, checked against OpenSSL); the results are the standard values.
- Create Hash (SHA-384) (Replace), Create Hash (SHA3-256) (Replace), Create Hash (BLAKE2b-512) (Replace): Replace each selection with its hash.
- Hashes for the web:
- Create Hash (SHA-256, Base64): SHA-256 as standard Base64, for example for a CSP
'sha256-…' source: abc -> ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=.
- Create SRI Hash (sha384): A Subresource Integrity
integrity value: abc -> sha384-ywB1P0WjXou1oD1pmsZQBycs….
- Create Hash per Line (SHA-256): Hashes each line on its own and keeps the line breaks (LF, CRLF or CR); empty lines stay empty, and a line break at the end is kept:
a⏎b -> ca978112…⏎3e23e816…. The result opens in a new read-only editor without headings; with multiple selections, the results are joined with the document's line ending.
- Create HMAC (SHA-1, SHA-384, SHA3-256): Asks once for the key in a password input box and computes the HMAC of each selection:
abc (key) -> 4fd0b215… (SHA-1), 30ddb9c8… (SHA-384), 09b6dbab… (SHA3-256). If you cancel the input box, nothing is done. The key must not be empty or contain a lone surrogate. The key is not saved, logged or shown in the result or in a message. The input box is not shown if every selection is empty, and the selections are read again after it closes. HMAC-SHA3-256 uses the extension's own SHA3-256 (block size 136 bytes).
- HMAC-SHA1 is for checking compatibility with existing systems only. For a new design, use HMAC-SHA256 or stronger.
- Checksum (CRC-32 (IEEE), Adler-32, FNV-1a 32-bit): Eight lower-case hex digits:
hello -> 3610a686 (CRC-32), 062c0215 (Adler-32), 4f9f2cab (FNV-1a). The extension computes them itself, without new dependencies.
- These checksums detect accidental errors only; they cannot detect tampering. Use a cryptographic hash or an HMAC for that.
- Checksum: Luhn Validate: Checks the check digit of a number with the Luhn algorithm and shows the result in a notification; the selection is not changed, and the number is not shown in the notification:
79927398713 -> Luhn: valid.
- Spaces, tabs and line breaks at both ends are ignored, and a single space or hyphen between two digits is ignored as a separator (
4111 1111 1111 1111, 4111-1111-1111-1111). A leading or trailing hyphen (-79927398713), two separators in a row (7--9927398713), + and any other character make the text not a number (only digits, spaces and hyphens are allowed), and fewer than two digits make it not a number (at least 2 digits are required).
- With one selection, the notification is
Luhn: valid, Luhn: invalid or Luhn: not a number (…) with the reason. With 2 to 10 selections, it lists each selection by number without the reason: Luhn: [#1](https://github.com/imahiro-t/selection-manipulator/issues/1) valid, [#2](https://github.com/imahiro-t/selection-manipulator/issues/2) invalid, [#3](https://github.com/imahiro-t/selection-manipulator/issues/3) not a number. With 11 or more, it shows only the counts: Luhn: 12 selections: 5 valid, 4 invalid, 3 not a number.
Limitations of the hash and checksum commands
- Lone surrogates: A selection that contains a lone surrogate cannot be converted to UTF-8 and is an error, instead of being hashed as
� (Luhn Validate reports it as not a number). If any selection fails, no selection is changed and no editor is opened.
- Output size: A run whose results would exceed 10,000,000 characters in total (shared by all selections) is refused with a warning, and nothing is changed or opened. Only Create Hash per Line can get near this limit (64 characters per line).
- Create Hash per Line: Each line break is kept in the result, but a line break of a single CR may be shown as the line ending of the new editor, because VS Code uses one kind of line ending per editor.
- Performance: SHA-3, BLAKE2 and HMAC-SHA3-256 run in JavaScript and are much slower than the other hashes (about 0.1 to 0.7 seconds for 10 MB); a very large selection can make VS Code wait for a few seconds.
Decoders
- JWT: Decode JSON Web Tokens header/payload.
- SAML: Decode SAML Requests/Responses.
- X.509: View Certificate details.
8. Network & Analysis
- DNS Lookup: A, AAAA, MX, NS, TXT, etc.
- HAR Visualization: Convert HTTP Archive (HAR) logs to Mermaid sequence diagrams. HAR to Sequence Diagram Image renders the diagram in a Webview with the Mermaid library bundled with the extension; it does not access the network.
9. Generators & Random
- UUID: Generate Random UUID v4.
- Password: Generate strong random passwords.
- IP Address: Random IPv4 / IPv6.
- Lorem Ipsum: Placeholder text.
Generator Commands
Thirty generator commands are added: the nineteen Random - … commands go to the existing Random context submenu (after UUID and Lorem Ipsum), and the eleven Generate - … commands to a new Generate context submenu (after the Line submenu in the Selection Manipulator menu); all of them are also in the Command Palette. Every random value comes from Node.js crypto (randomBytes, randomInt and randomUUID; Math.random is not used), with no new dependencies and no network access. The existing Random commands (UUID, Password, IPv4, IPv6 and Lorem Ipsum) are unchanged.
In the examples, ⏎ is a line break, a value in parentheses is the value you enter, and a / b / c is what three cursors get (from the first cursor in the document to the last).
- Common rules:
- Where the text goes: Each selection and cursor gets its own value, in document order (by where it starts, not the order you made the cursors): a selection is replaced and an empty cursor gets an insertion, all in one edit (one undo step). Sequences count in that order, and random values are made separately for each selection and cursor. Commands that write several lines (Pick N Lines, Number Range, Column Ruler) use the document's line ending (LF / CRLF).
- Selected text: Only Pick One Line, Pick N Lines and Dice Roll read the selected text; the other commands ignore it and replace it.
- Input: A command that asks for input asks only once for all selections and cursors, starts with a default value, checks what you type while you type it (up to 100 characters), reads the selections again after the input box closes, and does nothing if you cancel it; values you enter are not saved.
- Errors: If anything is wrong (an invalid value, too many cursors for a sequence, a selection that cannot be used), nothing is changed and an error says why (
The selection was not changed: …, with selection 2 of 3: for the commands that read the selections when there are several). More than 100,000 selections and cursors is an error (nothing is changed), and a selection read by Pick One Line, Pick N Lines or Dice Roll can be up to 1,000,000 characters (checked before anything is asked). A run whose results would exceed 10,000,000 characters in total is stopped and refused with a warning (…Use fewer cursors or a smaller amount.); nothing is changed.
- Context menu: The context menu of Selection Manipulator is shown only when text is selected, as before; with only cursors, run the commands from the Command Palette.
- IDs and tokens:
- Random - UUID v7: A time-ordered UUID (RFC 9562): the current time in milliseconds, version 7, the variant
10 and 74 random bits, in lower case: 0192f0c1-8e3a-7c4d-9b1e-3f2a….
- Random - ULID: 26 characters of Crockford Base32 (upper case): 10 for the time in milliseconds and 16 for 80 random bits:
01J8Z3K5Q7W9X2Y4Z6A8B0C1D2.
- With several cursors, the UUIDs and ULIDs of one run are sorted before they are written, so that they are in ascending order in the document even within the same millisecond. Values of different runs are not guaranteed to increase (two runs within the same millisecond can give a smaller value).
- Random - NanoID: 21 characters of
A-Za-z0-9_-: V1StGXR8_Z5jdHi6B-myT.
- Random - Hex String: Asks for a number of random bytes (1 to 1,024, default 16) and writes them in lower-case hexadecimal (twice as many characters): (
16) -> 9f86d081884c7d659a2feaa0c55ad015.
- Random - Base64 Token: Asks for a number of random bytes (1 to 1,024, default 24) and writes them in Base64URL (
- and _, no padding): (24) -> 32 characters.
- Generate - GUID (Braced Uppercase): A version 4 UUID (
crypto.randomUUID) in upper case in braces, as in Windows / .NET: {3F2504E0-4F89-41D3-9A0C-0305E82C3301}.
- Numbers, dates and choices:
- Random - Integer in Range: Asks for
min..max (both ends included, decimal integers such as -5..5, default 1..100): (1..6) -> 4. Both ends must be safe integers (from -9007199254740991 to 9007199254740991), min must not be greater than max, and the range can hold up to 2^48 − 1 integers.
- Random - Float in Range: Asks for
min..max (both ends included, plain decimal numbers such as -0.5..2.25 with absolute values up to 1,000,000,000; no exponents, Infinity or NaN; default 0..1) and then the number of decimal places (0 to 10, default 3): (0..1, 3) -> 0.582. The value is picked uniformly from the numbers with that many decimal places and written with exactly that many (no decimal point for 0 places, and 0.000 rather than -0.000). No floating-point arithmetic is used, so 0.1..0.3 with 3 places gives exactly 0.100 to 0.300. The ends can have at most that many decimal places as written (1.000 with 2 places is an error), each end times 10^places must be at most 9007199254740991 (1000000000..1000000000 with 10 places is an error), and the range can hold up to 2^48 − 1 values.
- Random - Date in Range: Asks for
YYYY-MM-DD..YYYY-MM-DD (both ends included, 0001-01-01 to 9999-12-31; default the current year, 2026-01-01..2026-12-31) and picks a day uniformly: (2026-01-01..2026-12-31) -> 2026-05-17. A date that does not exist or a first date after the second is an error.
- Random - Boolean:
true or false.
- Random - Dice Roll: Rolls the dice written in the selection as
NdM (N dice with M sides; d or D; spaces around the whole expression are ignored, but none are allowed inside it, so 2 d 6 is an error; N from 1 to 100, M from 2 to 1,000,000) and writes the total with each die: 2d6 -> 7 (3+4), 1d20 -> 13 (13). For empty cursors (and selections of only spaces, tabs and line breaks), it asks once for the dice (default 1d6) and uses them for all of them. A selection that is not a dice roll is an error that quotes it (cut to 60 characters).
- Random - Pick One Line: Replaces each selection with one of its lines, picked separately for each selection:
a⏎b⏎c -> b. Lines of only spaces and tabs are not picked, and the spaces around the picked line are kept.
- Random - Pick N Lines: Asks for N (1 to 10,000, default 2) and replaces each selection with N of its lines without repeats, in random order:
a⏎b⏎c⏎d (2) -> d⏎a. Lines of only spaces and tabs are not picked; equal lines at different positions can both be picked; N greater than the number of lines is an error.
- Pick One Line and Pick N Lines leave empty selections and selections of only spaces, tabs and line breaks unchanged, and if nothing else is selected, the warning
Select the lines to pick from. is shown (nothing is changed).
- Network and colors:
- Random - MAC Address: A unicast, locally administered address (the first byte is
x2, x6, xa or xe), lower case with colons: 02:5e:a1:3c:77:0b.
- Random - Hex Color:
#3fa2c8 (lower case).
- Dummy data (from small built-in lists of common words, names and neutral sentences):
- Random - Dummy Email: A word, 4 digits and the reserved domain
example.com (RFC 2606) only: user4821@example.com.
- Random - Dummy Name: An English first name and last name:
Emily Clark.
- Random - Dummy Japanese Name: A family name and a given name with a half-width space:
佐藤 花子.
- Random - Dummy Phone Number (JP): A mobile number of the form
090-0xxx-xxxx (each x a random digit): 090-0123-4567. It is meant for samples and tests, but whether the number is unassigned has not been checked and is not guaranteed; do not call or text it.
- Random - Japanese Dummy Text: Asks for a number of sentences (1 to 1,000, default 3) and writes that many sentences from a built-in list, each picked independently (the same sentence can come twice in a row), without spaces or line breaks between them: (
3) -> これはダミーの文章です。新しい機能の説明文がここに入ります。….
- Sequences (each cursor gets the next value in document order):
- Generate - Alphabet Sequence:
a / b / c; after z comes aa, ab, … (lower case only).
- Generate - Roman Numeral Sequence:
I / II / III / IV, up to 3,999 (MMMCMXCIX).
- Generate - Date Sequence: Asks for the first date (
YYYY-MM-DD, default today in local time) and gives each next cursor the next day: (2026-09-28) -> 2026-09-28 / 2026-09-29 / 2026-09-30. The last date must not be after 9999-12-31.
- Generate - Hex Sequence: Asks for the first hexadecimal number (1 to 13 digits; default
0x00) and keeps its prefix (0x, 0X or none), its width (zero padding; a longer number simply gets longer) and its case: (0x0A) -> 0x0A / 0x0B / 0x0C, (ff) -> ff / 100 / 101, (0x09) -> 0x09 / 0x0A. Letters are lower case only when the input has only lower-case letters; with upper-case letters, mixed case or no letters, they are upper case.
- Generate - Kana Sequence: Asks which order to use: Gojūon (hiragana, 46 kana
あいうえお…わをん: the plain kana only, with を and ん, without ゐ ゑ, small kana and voiced kana): あ / い / う, or Iroha (katakana, 47 kana イロハニホヘト…セス, with ヰ and ヱ, without ン): イ / ロ / ハ.
- Generate - Circled Number Sequence:
① / ② / ③, up to ㊿ (50).
- Generate - IPv4 Sequence: Asks for the first address (default
192.0.2.1, a documentation address of RFC 5737) and counts up across the parts: (192.0.2.1) -> 192.0.2.1 / 192.0.2.2 / 192.0.2.3, 192.0.2.255 is followed by 192.0.3.0. Only plain dotted decimal addresses are read (each part 0 to 255 without leading zeros; no CIDR), and the last address must not be after 255.255.255.255.
- The sequences with a last value do not wrap around: more cursors than values (Roman numerals 3,999, Gojūon 46, Iroha 47, circled numbers 50, dates up to 9999-12-31, IPv4 up to 255.255.255.255) is an error and nothing is changed.
- Generators:
- Generate - Number Range: Asks for
start..end or start..end step s (step in any case, integers only, each a safe integer; default 1..10) and writes the numbers from start toward end, one per line; each cursor gets the whole list: (1..10 step 3) -> 1⏎4⏎7⏎10. Without a step, it counts by 1, or by -1 when start is greater than end (3..1 -> 3⏎2⏎1). The list stops at the last number that does not pass end (1..10 step 4 -> 1⏎5⏎9). A step of 0, a step that goes away from end, and a list of more than 100,000 numbers are errors.
- Generate - Repeat Character to Width: Asks for the character(s) to repeat (1 to 16 characters, default
=; spaces are kept as typed, so a space or - can be repeated; tabs, line breaks and other control characters are errors) and the width (1 to 10,000 characters, default 80), and repeats them up to exactly that width, cutting the last repeat: (=, 20) -> ====================, (-+, 5) -> -+-+-. Widths are counted in characters (code points), and a character outside the BMP (such as an emoji) is never cut in half.
- Generate - Column Ruler: Asks for a number of columns (1 to 1,000, default 80) and writes two lines: the first has the tens digit at every 10th column (
0 at column 100, 1 at column 110, …) and the middle dot · (U+00B7, the actual character) elsewhere, the second the ones digit of every column: (30) -> ·········1·········2·········3⏎123456789012345678901234567890.
Limitations of the generator commands
- Randomness: Values are random, not unique: two runs (or two cursors) can in theory get the same NanoID, token, name or number, as with any random generator. The dummy names, e-mail addresses, sentences and phone numbers come from small built-in lists and repeat often.
- Time: UUID v7 and ULID use the clock of the computer running VS Code; the ascending order is only guaranteed among the values of one run. By default, Date in Range covers the current year (January 1 to December 31) and Date Sequence starts from today, both in local time.
- Dummy phone numbers: The numbers have the form
090-0xxx-xxxx. This range is not taken from an official list of fictional numbers, and whether a number is unassigned is not checked and cannot be guaranteed; do not call or text it.
- Context menu: With only cursors (no selected text), the context menu of Selection Manipulator is not shown; use the Command Palette.
10. Calculation & Numbers
Math & Statistics
- Evaluate:
1 + 2 * 3 -> 7.
- Statistics: Sum, Average, Min, Max of selected numbers; Median, Mode, Standard Deviation, Variance, Count, Product, Range, Percentile and Statistics Summary of each selection on its own (see Number Commands below).
- Running Total: Cumulative Sum replaces each line of the selection with the sum of the lines up to it (see Number Commands below).
- Base Conversion: Hex <-> Decimal; Decimal <-> Binary / Octal / Hex and any base from 2 to 36 (see Number Commands below).
- Number Formatting: Round, Floor, Ceil, Truncate, Abs, Negate, thousands separators, locale format, scientific notation, percent, bytes, English words, ordinals and fractions (see Number Commands below).
Counting & Date
- Increment/Decrement: Increase/decrease numbers (From 1, From N, By 1, By N).
- Date Calculation: Days between dates (see also Difference Between Two Dates, Add Days / Months and the other Date Commands).
- Unit Conversion:
- Length: px <-> rem (Base 16), km <-> mile, cm <-> inch.
- Weight: kg <-> lb.
- Temperature: Celsius <-> Fahrenheit.
- The km / mile, cm / inch and Celsius / Fahrenheit commands are described in Number Commands below.
Number Commands
The statistics commands (Math - Median to Math - Statistics Summary) never change the text: they open the result in a new read-only editor, one line for each selection (in document order, joined with the document's line ending), so 1⏎3⏎2⏎10 -> 2.5. All the other number commands (Math - Cumulative Sum, Number - … and Unit: …) replace each selection with its result (only the selections whose text changes, as one undo step). Every selection is computed on its own, also by the statistics commands: unlike the existing Sum, Average, Min and Max, which add up the numbers of all selections together, Median of two selections gives two lines. Empty selections and selections of only spaces, tabs and line breaks are skipped, and if nothing else is selected, the warning Select the numbers to use. is shown (before any input box). If any selection fails, no selection is changed and no editor is opened, and an error names the problem (The selection was not changed: … or No result was shown: …, with selection 2 of 3: when there are several selections). A command that asks for input asks only once for all selections, reads the selections again after the input box closes, and does nothing if you cancel it; values you enter are not saved. The statistics commands are added to the Calculate context submenu, Cumulative Sum and the Number commands to the Number submenu of the Replace context submenu, and the Unit commands to the Unit Conversion submenu of the Transform context submenu, after the existing commands. The existing Sum, Average, Min, Max, Hex <-> Decimal, Increment / Decrement and px / rem / kg / lb commands are unchanged.
In the examples, · is a space, ⏎ is a line break, and a value in parentheses is the value you enter.
- Common rules:
- Numbers in the statistics commands: Every decimal number in the selection is used (
-1.5, .5, 1e3), wherever it is: a 1 b 2.5 has the numbers 1 and 2.5. A number must not touch a letter, a digit, _, or a ., + or - before it, or a letter, a digit, _ or . followed by a digit after it, so 10px, a1, the 09 and 29 of 2026-09-29 and the 2 of 1+2 are not numbers (a . at the end of a sentence is fine: 1.5.). A comma is a separator, not a thousands separator: 1,234 is the two numbers 1 and 234. A number too large for floating-point numbers (1e400) is an error.
- No numbers: If a selection has text but no numbers (
abc), nothing is shown and a warning says so (No result was shown: no numbers found, or …: selection 2 of 3: no numbers found). Math - Count Numbers is the exception: it gives 0 for that selection.
- Result lines: A selection of only spaces, tabs and line breaks is skipped and gets no line in the result, so with such selections the lines of the result no longer match the selections one to one (the first line is the first selection that has text).
- Lines in the replacing commands: Each line must be one number of the kind the command reads, with spaces and tabs around it if you like; they are kept, as are empty lines (and lines of only spaces and tabs) and LF / CRLF line breaks:
·2.5·⏎⏎-1.5 (Floor) -> ·2·⏎⏎-2. If any line is not a number, the whole command is cancelled with the line in the selection: line 2: "abc" is not a number (the text is cut to 60 characters). Unless a command says otherwise, a number is a decimal such as -1.5, .5, +2 or 1e3; Infinity, NaN, 0x… and numbers with thousands separators are not.
- Rounding: Results are shown without floating-point noise: a result that is a safe integer (up to 9,007,199,254,740,991 either way) is shown as it is, and any other result is rounded to 15 significant digits (
0.1 + 0.2 -> 0.3, -0 -> 0). Median, Mode, Product, Range, Percentile, Cumulative Sum, the sum / min / max / median of Statistics Summary and the value of To Scientific Notation use this rule. Variance, Standard Deviation, the mean / σ / s of Statistics Summary and the six Unit commands are rounded to 4 decimal places instead (half away from zero, without trailing zeros: σ=2, s=2.1381), so a very small result becomes 0 (1e-200⏎3e-200 (Standard Deviation) -> σ=0, s=0; 0.00001 (km to mile) -> 0). Very large and very small results are written in JavaScript's exponent notation (1e+21, 1e-7), and a result beyond the range of floating-point numbers is an error (the result is out of range).
- Precision: The statistics commands, Cumulative Sum, Round, Floor, Ceil, Truncate, To Scientific Notation, Format by Locale and the Unit commands use floating-point numbers, so input with more than 15 to 17 significant digits loses precision (
12345678901234567890 (Floor) -> 12345678901234567000). Absolute Value, Negate, the thousands separator commands, From Scientific Notation, To Percent, the base conversions, the byte conversions, To English Words, the ordinal suffix and Decimal to Fraction work on the digits as text or with BigInt and keep every digit.
- Statistics (new editor):
- Math - Median:
1⏎3⏎2⏎10 -> 2.5 (the mean of the two middle numbers when there is an even number of them).
- Math - Mode: The number that appears most often:
1⏎2⏎2⏎3 -> 2. Several numbers that appear equally often are listed in ascending order (1 2 2 3 3 -> 2, 3); if there are two or more numbers and each appears once, it is an error (every number appears once, so there is no mode). A single number is its own mode.
- Math - Standard Deviation: The population (σ) and sample (s) standard deviations:
2⏎4⏎4⏎4⏎5⏎5⏎7⏎9 -> σ=2, s=2.1381. With one number, s=n/a.
- Math - Variance: The population and sample variances:
1⏎2⏎3 -> 0.6667 / 1. With one number, 0 / n/a. A variance beyond the range of floating-point numbers (1e160⏎3e160) is an error, but squares in between do not overflow (1e155⏎-1e155 (Standard Deviation) -> σ=1e+155, s=1.41421356237309e+155).
- Math - Count Numbers:
a 1 b 2.5 -> 2 (0 for a selection without numbers).
- Math - Product:
2⏎3⏎4 -> 24. Math - Range: the largest minus the smallest number: 3⏎9⏎1 -> 8.
- Math - Percentile: Asks for a percentile from 0 to 100 (decimals allowed) and interpolates linearly, like Excel's
PERCENTILE.INC and NumPy's default: 1⏎2⏎3⏎4⏎5 (90) -> 4.6.
- Math - Statistics Summary:
1⏎2⏎3 -> count=3, sum=6, mean=2, min=1, max=3, median=2, σ=0.8165, s=1 (s=n/a with one number).
- Replace each number:
- Math - Cumulative Sum: Replaces each line with the sum of the lines up to it:
1⏎2⏎3 -> 1⏎3⏎6. Empty lines are kept and add nothing. While the sum is a safe integer it is exact (1234567890123456⏎1 -> 1234567890123456⏎1234567890123457); otherwise it is rounded to 15 significant digits, so a sum past 9,007,199,254,740,991 or after a decimal changes the 16th digit and beyond (9007199254740991⏎1 -> 9007199254740991⏎9007199254740990, 0.1⏎0.2⏎1234567890123456 -> 0.1⏎0.3⏎1234567890123460).
- Number - Round: Asks for the number of decimal places (0 to 15) and rounds half away from zero on the decimal digits, so
1.005 (2) -> 1.01 and -2.5 (0) -> -3: 3.14159 (2) -> 3.14. No trailing zeros are added (1.2 (2) -> 1.2).
- Number - Floor / Ceil / Truncate: Down, up and toward zero:
-2.5⏎2.7 -> -3⏎2 (Floor), 2.1 -> 3 (Ceil), -2.7 -> -2 (Truncate). -0 is written as 0.
- Number - Absolute Value / Negate: Only remove or add the sign, and keep the digits as they are written (leading zeros, trailing zeros and the exponent):
-5 -> 5, +5 -> 5 (Absolute Value); 5⏎-3 -> -5⏎3, 1.50 -> -1.50, 007 -> -007 (Negate). A zero only loses its sign and never gets -: -0.00 -> 0.00 (both), 0.00 and 0e5 stay as they are (Negate).
- Number - Add Thousands Separator:
1234567.89 -> 1,234,567.89. Reads a decimal without an exponent, with no separators or correct ones (so running it twice changes nothing). Unlike Absolute Value and Negate, it removes leading zeros of the integer part: -0012345 -> -12,345, 000.5 -> 0.5. Like Absolute Value and Negate, a zero loses its sign (-000 -> 0, -0.00 -> 0.00, +0 -> 0), while any other value keeps it (+1234.5 -> +1,234.5).
- Number - Remove Thousands Separator:
1,234,567 -> 1234567. Misplaced separators (12,34) are an error (has misplaced thousands separators).
- Number - Format by Locale: Asks for a BCP 47 locale (letters, digits and
-, up to 35 characters, and supported by Intl) and formats with Intl.NumberFormat (up to 20 decimal places): 1234.5 (de-DE) -> 1.234,5. The characters are exactly what the Intl of VS Code gives, so some locales use special spaces (for example, U+202F in fr-FR).
- Number - Decimal to Hex / Binary / Octal: A decimal integer (up to 1,000 digits, with a sign if you like) to lower-case digits with
0x, 0b or 0o: 255 -> 0xff, 10 -> 0b1010, 8 -> 0o10, -255 -> -0xff. A decimal such as 1.5 is an error.
- Number - Hex / Binary / Octal to Decimal:
0xff -> 255, 0b1010 -> 10, 0o10 -> 8. The prefix is optional (FF -> 255), case does not matter, a sign is allowed, and up to 1,000 digits are read.
- Number - Convert Base (2-36): Asks for the base of the selected numbers and the base to convert to (each 2 to 36):
zz (36, 10) -> 1295. The digits must belong to the first base (case does not matter, no prefix, a sign is allowed, up to 1,000 digits), and the result is in lower case without leading zeros.
- Number - To Scientific Notation:
12300 -> 1.23e+4 (0 -> 0e+0).
- Number - From Scientific Notation:
1.23e+4 -> 12300. Only numbers with e or E are read, the exponent can be up to 1,000 either way, and the digits are kept as written (1.50e1 -> 15.0).
- Number - To Percent: Moves the decimal point two places to the right and adds
%, keeping the digits: 0.125 -> 12.5%, 0.1250 -> 12.50%. Numbers with an exponent are an error.
- Number - Bytes to Human Readable: A whole number of bytes (up to 30 digits) in binary units with up to 2 decimal places:
512 -> 512 B, 1536 -> 1.5 KiB (KiB, MiB, GiB, TiB, PiB, EiB, ZiB, YiB). A value that rounds up to 1024 moves to the next unit (1048575 -> 1 MiB), and values beyond YiB stay in YiB (1024 YiB).
- Number - Human Readable to Bytes:
1.5 MiB -> 1572864. A number (not negative, up to 30 digits) followed by a unit, with or without spaces between them: B, KB MB GB TB PB EB ZB YB (powers of 1000) or KiB MiB GiB TiB PiB EiB ZiB YiB (powers of 1024), in any case (1 kb -> 1000). It is computed exactly and a fraction of a byte is rounded, so every result of Bytes to Human Readable can be read back.
- Number - To English Words: An integer (up to 36 digits, up to decillions) in American English without
and: 42 -> forty-two, -123 -> minus one hundred twenty-three, 0 -> zero. A decimal is an error.
- Number - Add English Ordinal Suffix: Adds
st, nd, rd or th to an integer, keeping its digits: 1⏎2⏎11 -> 1st⏎2nd⏎11th (-1 -> -1st, +1 -> +1st, 0 -> 0th).
- Number - Decimal to Fraction: A decimal without an exponent (up to 30 digits) to a fraction in lowest terms:
0.75 -> 3/4, 0.1 -> 1/10, 1.5 -> 3/2, -0.5 -> -1/2, 0.500000 -> 1/2, 3 -> 3. A decimal is taken exactly, except that one with 6 or more decimal places is read as a repeating decimal when a fraction whose denominator is at most 99 and has a prime factor other than 2 and 5 (so that it really repeats) matches its digits, rounded or cut off: 0.333333 -> 1/3, 0.666667 -> 2/3, 0.142857 -> 1/7. Otherwise the exact fraction is kept (0.314159 -> 314159/1000000, 0.33333 -> 33333/100000). An input that happens to match such a fraction is also read that way: 0.123456 -> 10/81.
- Units (replace each number, rounded to 4 decimal places, without a unit symbol, unlike the existing kg / lb commands):
- Unit: Celsius to Fahrenheit / Fahrenheit to Celsius:
100 -> 212, 212 -> 100.
- Unit: km to mile / mile to km (1 mile = 1.609344 km):
10 -> 6.2137, 1 -> 1.6093.
- Unit: cm to inch / inch to cm (1 inch = 2.54 cm):
2.54 -> 1, 1 -> 2.54.
Limitations of the number commands
- Size: A selection can be up to 5,000,000 characters (a longer one is an error). A run whose results would exceed 10,000,000 characters in total (shared by all selections) is stopped while it is converting and refused with a warning (
…the result would be longer than 10,000,000 characters. Select less text.); nothing is changed or opened. The digit limits above (1,000 for the base conversions, 30 for the byte conversions and Decimal to Fraction, 36 for To English Words, an exponent of 1,000 for From Scientific Notation) are checked before any conversion, so no input can make VS Code wait for long.
- Commas: The statistics commands never read
1,234 as one thousand two hundred thirty-four; remove the separators first (Remove Thousands Separator).
- Floating point: Commands that use floating-point numbers (see Precision above) cannot give more than 15 to 17 correct significant digits. The mean used by Standard Deviation, Variance and Statistics Summary is corrected for rounding, so copies of one value give
σ=0 (also 800,000 copies of 1e308), but the σ of different values can still be off in the last digits relative to the numbers.
11. Japanese Text Support
- Width Conversion: Full-width <-> Half-width (Alphanumeric + Katakana).
- Kana Conversion: Hiragana <-> Katakana.
Japanese Text Commands
Thirty-five Japanese - … commands (romaji, kanji numerals, punctuation, old and new kanji forms, ruby, width and spacing, character counts, prefectures, postal codes and platform-dependent characters) are added to the Japanese context submenu (under Transform), after the existing commands, and to the Command Palette. Their tables (romaji, kanji numerals, old and new kanji forms, prefectures, JIS X 0208) are constants in the extension: no new dependencies and no network access. The existing Japanese commands (width and kana conversions) are unchanged.
In the examples, · is a space, ⏎ is a line break, and a value in parentheses is the value you choose.
- Common rules:
- Output: Most commands open the result in a new read-only editor (the results of several selections in document order, joined with the document's line ending). Punctuation to Comma and Period, Punctuation to Touten and Kuten, Remove Ruby Notation, Ideographic Space to Space, Normalize Wave Dash, Normalize Hyphens and Long Vowel Marks, Circled Numbers to Parentheses, Format Postal Code, Remove Spaces Between Japanese Characters, Compose Dakuten and the six (Replace) versions replace each selection (only the selections whose text changes, as one undo step). Count Characters (Manuscript Paper) and Count by Character Type show a notification for all selections together, and Detect Platform-dependent Characters selects what it finds. A (Replace) version gives exactly the same result as its standard version.
- One value per line: Number to Kanji Numeral, Kanji Numeral to Number, Number to Daiji, Prefecture Name to/from JIS Code and Format Postal Code read each line of a selection as one value. Spaces and tabs around a value are kept, as are empty lines (and lines of only spaces and tabs) and LF / CRLF line breaks. If any line cannot be read, the whole command is cancelled with the line in the selection:
line 2: "abc" is not a kanji numeral (the text is cut to 60 characters). The other commands convert the whole text of each selection.
- Selections and errors: Empty selections and selections of only spaces, tabs and line breaks are skipped, and if nothing else is selected, the warning
Select the text to convert. is shown. If any selection fails, nothing is changed, opened or selected, and an error names the problem (The selection was not changed: …, No result was shown: … or Nothing was selected: …, with selection 2 of 3: when there are several selections).
- Romaji:
- Japanese - Kana to Romaji (Hepburn) (also (Replace)) / Japanese - Kana to Romaji (Kunrei): Hiragana and katakana (also half-width katakana) to romaji:
しんじゅく -> shinjuku / sinzyuku. Long vowels are written as they are spelled, without macrons (とうきょう -> toukyou), and ー repeats the vowel before it (ラーメン -> raamen). ん is n, and n' before a vowel or y (かんい -> kan'i); っ doubles the next consonant (がっこう -> gakkou; Hepburn writes t before ch: まっち -> matchi, Kunrei matti), and a っ without a consonant after it is xtsu (Kunrei xtu): あっ -> axtsu. を is o, and ヵ ヶ are ka ke. Iteration marks (ゝ ゞ ヽ ヾ), a ー after anything but a kana and everything that is not a kana are kept.
- Japanese - Romaji to Hiragana (also (Replace)): Hepburn and Kunrei romaji in any case to hiragana:
sushi -> すし, SI -> し. Each run of ASCII letters (with ' between letters) is converted only when all of it can be read; otherwise it is kept: hello -> hello. nn and n' are ん (kan'i -> かんい, konnnichiha -> こんにちは), as are n before a consonant and m before b / p (shimbun -> しんぶん). Two equal consonants are っ (kitte -> きって, also mamma -> まっま), as is t before ch (matcha -> まっちゃ). Small kana are written with x (xa -> ぁ, xtsu / xtu -> っ); the l spellings are not supported (la is kept).
- Numbers:
- Japanese - Number to Kanji Numeral (also (Replace)):
1234 -> 千二百三十四, 10000 -> 一万, 1100010 -> 百十万十, 0 -> 〇. A whole number from 0 to 99,999,999,999,999,999,999 (九千九百九十九京…) in ASCII or full-width digits, optionally with , every three digits (1,234); signs and decimals are errors.
- Japanese - Kanji Numeral to Number (also (Replace)):
三億五千万 -> 350000000. Plain digit sequences (二〇二六 -> 2026), ASCII and full-width digits mixed in (3億5000万 -> 350000000) and daiji (壱百弐拾参 -> 123, 壹萬貳阡 -> 12000) are also read, up to 99,999,999,999,999,999,999. 十, 百 and 千 alone mean one of them (十 -> 10), but a larger unit needs a number before it: 一万, not 万 (万 is an error). Units out of order (万万, 十百, 千万億), more than one digit before 十 百 千 (20百), 〇十, more than four digits after a unit of 万 or larger (1億23456) and , are errors.
- Japanese - Number to Daiji:
123 -> 壱百弐拾参, 11000 -> 壱萬壱千, 0 -> 零 (the same numbers as Number to Kanji Numeral; 壱 is also written before 拾, 百 and 千).
- Punctuation, kanji forms and kana:
- Japanese - Punctuation to Comma and Period (,.):
今日は、晴れ。 -> 今日は,晴れ.. Japanese - Punctuation to Touten and Kuten (、。): 今日は,晴れ. -> 今日は、晴れ。.
- Japanese - Old Kanji to New (Kyujitai to Shinjitai) (also (Replace)):
國學 -> 国学, with the 305 old forms shown in parentheses in the Jōyō kanji table (辨 瓣 辯 -> 弁); the CJK compatibility ideographs U+FA30 to U+FA6A (old forms such as 海 and 社) become their ordinary characters.
- Japanese - New Kanji to Old (Shinjitai to Kyujitai):
国学 -> 國學, with the same table, except 弁 芸 欠 予 余 台 糸 缶 虫, which are kept: 弁 has three old forms, and the others are also old characters with a different meaning of their own. CJK compatibility ideographs are never written.
- Japanese - Small Kana to Normal:
きゃっと -> きやつと; also small katakana (ヵ ヶ -> カ ケ), ゕ ゖ, ㇰ-ㇿ and half-width ァ-ッ.
- Counting (notifications; the text is never changed):
- Japanese - Count Characters (Manuscript Paper): The characters of all selections together and the number of 400-character sheets of manuscript paper, rounded half up to one decimal place:
1,234 字 / 原稿用紙 3.1 枚 (20 characters are 0.1 枚, 19 are 0.0 枚). Characters are code points (an emoji is one character); line breaks are not counted, but spaces and ideographic spaces inside a selection are. Selections of only spaces, tabs and line breaks are skipped (not counted).
- Japanese - Count by Character Type:
東京タワーへgo -> 漢字 2 / カタカナ 3 / ひらがな 1 / 英数字 2, counting all selections together; types without characters are left out. Each character counts once, as the first of: 漢字 (Han script with 々 〆 〇), カタカナ (full-width and half-width, with ー ー ゙ ゚, ヵ and ヶ), ひらがな, 英数字 (ASCII and full-width letters and digits), 記号 (Unicode punctuation and symbols, such as 、 ・ ! and emoji) and その他 (anything else, such as ①, Hangul and é). White space (also the ideographic space) is not counted; if nothing else is selected, the warning Select the text to convert. is shown.
- Ruby:
- Japanese - Remove Ruby Notation: Removes
|東京《とうきょう》 (also with |) -> 東京, 東京《とうきょう》 -> 東京 and a reading of only kana in parentheses right after a kanji: 東京(とうきょう) / 東京(とうきょう) -> 東京. Without |, the base is the run of kanji just before 《: 《…》 after anything but a kanji (かな《かな》, 「《書名》」) is kept as double angle brackets. A base and a ruby cannot be empty or contain a line break; parentheses with anything but kana (東京(東京)) are kept.
- Japanese - Ruby Notation to HTML:
|東京《とうきょう》 and 東京《とうきょう》 -> <ruby>東京<rt>とうきょう</rt></ruby>, with the same rules as Remove Ruby Notation (readings in parentheses are not converted). Only the base and the ruby are HTML-escaped (& < > " '); the rest of the text is written as it is.
- Width, spaces and dashes:
- Japanese - Full-width Alphanumerics to Half (Keep Kana):
ABC123カナ -> ABC123カナ: full-width ASCII letters, digits and symbols (U+FF01 to U+FF5E) only; kana (also half-width) and the ideographic space are kept, unlike the existing Full-width to Half-width.
- Japanese - Ideographic Space to Space:
東京 大阪 -> 東京 大阪.
- Japanese - Normalize Wave Dash: Asks which character to use (
〜 Wave Dash U+301C or ~ Full-width Tilde U+FF5E) and changes both to it: 1〜3、4~5 (〜) -> 1〜3、4〜5. It asks only once for all selections, reads the selections again after the choice, and does nothing if you cancel it.
- Japanese - Normalize Hyphens and Long Vowel Marks:
コ−ヒ− 03ー1234 -> コーヒー 03-1234. A hyphen-like character (‐ ‑ ‒ – — ― − -) right after a kana becomes ー (ー after a half-width katakana: カ−ト -> カート), also when it is followed by a digit (カ‐1 -> カー1), and several in a row all do; a long vowel mark or hyphen-like character between two digits (ASCII or full-width) becomes -. The ASCII - is never changed (カ-1 stays).
- Japanese - Remove Spaces Between Japanese Characters:
日本 語 の hello world -> 日本語の hello world. Spaces, tabs and ideographic spaces between two Japanese characters (kanji, kana and Japanese punctuation such as 「 and 。) are removed; line breaks are kept, and spaces between full-width alphanumerics are kept (ABC DEF).
- Japanese - Add Space Between Japanese and Alphanumerics (also (Replace)):
Vue3で開発 -> Vue3·で開発. A space is added between a kanji or kana and an ASCII letter or digit (in either order), but not where there is already a space, next to punctuation (、A and 「B」で stay) or next to full-width alphanumerics (Aで stays), so running it again changes nothing.
- Japanese - Circled Numbers to Parentheses:
①② -> (1)(2); ⓪, ①-㊿ and ⑴-⒇.
- Extraction:
- Japanese - Extract Kanji:
東京タワーへ行く -> 東京行, line by line: lines without kanji are left out (々 is a kanji; ヶ in 3ヶ月 is not).
- Japanese - Extract Katakana Words:
東京タワーとスカイツリー -> タワー⏎スカイツリー (one word per line in text order, repeats kept, joined with the document's line ending). A word is a run of katakana (also half-width), with ・ only between two katakana (ジョン・スミス); a leading ー ー ゙ ゚ is dropped, and a ヵ or ヶ alone (3ヶ月) is not a word.
- When nothing is found in any selection,
No kanji was found in the selection. / No katakana word was found in the selection. is shown instead of an empty editor (a selection without any gives an empty line when others have some).
- Prefectures and postal codes (one value per line):
- Japanese - Prefecture Name to/from JIS Code: A name (official
東京都 or short 東京) -> its two-digit JIS X 0401 code 13; a code (13, 1 or 01, also in full-width digits) -> the official name 東京都. A code other than 01-47 is an error (is not a prefecture code (01-47)), as is any other text (is not a prefecture name or code).
- Japanese - Format Postal Code:
1000001 -> 〒100-0001. Seven digits (also full-width), optionally with - or - after the third digit and a leading 〒 (with spaces after it); anything else is an error (is not a 7-digit postal code). No address is looked up.
- Kana composition:
- Japanese - Hiragana to Half-width Katakana:
がっこう -> ガッコウ (voiced marks are separate characters). Only hiragana is converted, and a ー right after converted hiragana becomes ー (すごーい -> スゴーイ). Katakana (and a ー after it), punctuation, alphanumerics and ゎ ゐ ゑ, which have no half-width form, are kept.
- Japanese - Compose Dakuten:
か゛は゜ -> がぱ. A voiced or semi-voiced sound mark (゛ ゜ or the combining U+3099 / U+309A) right after a full-width kana is composed with it only when the two make one character (ウ゛ -> ヴ, ゝ゛ -> ゞ); other pairs (あ゛, half-width カ゛) are kept, and the rest of the text is not normalized.
- Platform-dependent characters:
- Japanese - Detect Platform-dependent Characters: Selects every character outside JIS X 0208 and JIS X 0201 (ASCII,
¥, ‾ and half-width katakana) in the selections: ①髙橋 -> ① and 髙 are selected, and the first is scrolled into view. Emoji, Hangul and accented Latin letters (é) are found too; line breaks and tabs never are. When nothing is found, No platform-dependent character (outside JIS X 0208) was found in the selection. is shown; more than 10,000 characters is an error and nothing is selected.
Limitations of the Japanese text commands
- Size: A selection can be up to 1,000,000 characters (a longer one is an error). A run whose results would exceed 10,000,000 characters in total is refused with a warning (
…the result would be longer than 10,000,000 characters. Select less text.); nothing is changed or opened.
- Romaji: Kana to Romaji is a simple syllable-by-syllable conversion: it does not know words, so particles are written as they are spelled (
は is ha, へ is he) and long vowels are not joined. Romaji to Hiragana converts any run of letters it can read, so English words that happen to be romaji are converted too (Tokyo -> ときょ); select only the romaji.
- Kanji forms: The old and new forms follow the Jōyō kanji table only; old forms that are not in it (such as
髙) and variants of names are not converted.
- Platform-dependent characters: The check is based on JIS X 0208 (rows 1 to 84 as Shift_JIS encodes them, without the Windows extensions such as the NEC special characters of row 13), so characters that most modern systems display fine but that are outside JIS X 0208 (Windows characters such as
①, Ⅰ and ㈱, and JIS X 0213 kanji such as 髙) are reported too. 〜 and ~, which Shift_JIS and Windows (CP932) map differently, are both treated as JIS X 0208 characters.
12. ASCII Art / Fun
- ASCII Art: Wraps text in a balloon with an ASCII character (Cowsay, Tux, Ghost, Meow, Pig, Face, Daemon, Dragon, Stegosaurus, Turkey, Turtle, Elephant, etc.).
Example:
Before:
Hello World
After:
_____________
< Hello World >
-------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
13. Date Conversion
Convert selected date strings between various formats.
- Formats: ISO 8601, Locale String, Unix Timestamp (Seconds / Milliseconds).
- Japanese Era (Wareki): Convert AD Year to Japanese Era (e.g.,
2025 <-> 令和7年).
- Supports: Meiji, Taisho, Showa, Heisei, Reiwa.
Date Commands
Thirty Date - … commands (time zones, weekdays, ISO weeks, differences, relative time, patterns, calendars, durations, Excel serials, ranges, ages, fiscal years and cron expressions) are added to the Date Conversion context submenu, after the existing commands, and to the Command Palette. They use only Date and Intl, with no new dependencies and no network access. The existing date commands (Convert Date, Insert Date, Date Calculation, Sort Lines by Date and the Japanese era commands) are unchanged.
In the examples, · is a space, ⏎ is a line break, and a value in parentheses is the value you enter. The current time of the examples is Monday 2026-09-28 12:00 (local time).
- Common rules:
- One value per line: Each line of a selection is one value (except Date - Difference Between Two Dates). Spaces and tabs around a value are kept, as are empty lines (and lines of only spaces and tabs) and LF / CRLF line breaks. If any line cannot be read, the whole command is cancelled with the line in the selection:
line 2: "abc" is not a date (the text is cut to 60 characters).
- Dates the new commands read:
YYYY-MM-DD or YYYY/MM/DD (the month and day may have 1 or 2 digits, the year 0001 to 9999), optionally followed by T or one space and a time HH:mm, HH:mm:ss or HH:mm:ss.SSS (1-3 digits; the hour must have 2 digits), and optionally Z or an offset ±HH:MM / ±HHMM (up to ±23:59). A date that does not exist (2026-02-30, 2026-13-01), an out-of-range time (25:00) and other formats (2026.09.28, Sep 28 2026) are errors: unlike the existing Convert Date commands, the text is not read with new Date(…).
- Points in time: The commands that need a point in time (Convert to UTC String, the three time zone commands and Convert to Relative Time) take a date or time with an offset as it is, a date without a time as 00:00 UTC, and a date and time without an offset as the local time of the computer VS Code runs on. They also read a Unix timestamp (
-? and 1 to 13 digits; up to 30,000,000,000 is seconds, anything larger milliseconds, as in the existing Convert Date commands). The other commands work on the calendar date and time as written and never convert time zones.
- Output: Most commands open the result in a new read-only editor (the results of several selections in document order, joined with the document's line ending; the results of Show in Multiple Time Zones and Explain Cron Expression are separated by an empty line; Show in Multiple Time Zones also separates the results of several values in one selection by an empty line). Append Weekday, Add Days, Add Months, Insert Month Calendar, Generate Date Range and the (Replace) versions replace each selection (only the selections whose text changes, as one undo step). Convert to Time Zone (Clipboard) copies the result and shows
Copied the result to the clipboard.; Show Weekday shows a notification.
- Selections and errors: Empty selections and selections of only spaces, tabs and line breaks are skipped, and if nothing else is selected, the warning
Select the dates to use. is shown (before any input box). If any selection fails, nothing is changed, opened or copied, and an error names the problem (The selection was not changed: …, No result was shown: … or, for the Clipboard version, Nothing was copied: …, with selection 2 of 3: when there are several selections). A command that asks for input asks only once for all selections, reads the selections again after the input box closes, and does nothing if you cancel it; values you enter are not saved.
- Settings (checked every time a command runs; an invalid value stops only the commands that use it, before any input box, with
the setting selection-manipulator.date.… is invalid):
selection-manipulator.date.timeZones: the IANA time zones of Show in Multiple Time Zones (1 to 20 names; default ["UTC", "Asia/Tokyo", "America/Los_Angeles"]).
selection-manipulator.date.weekdayLanguage: ja (default, (月)) or en ( (Mon)) for Append Weekday.
selection-manipulator.date.fiscalYearStartMonth: the first month of the fiscal year (1 to 12, default 4) for Show Quarter and Fiscal Year.
- Time zones (
Intl.DateTimeFormat):
- Date - Convert to UTC String (RFC 7231): The HTTP header format of
toUTCString(): 2026-09-28 -> Mon, 28 Sep 2026 00:00:00 GMT, 2026-09-28T09:00:00+09:00 -> Mon, 28 Sep 2026 00:00:00 GMT.
- Date - Convert to Time Zone (also (Replace) and (Clipboard)): Asks for an IANA time zone (up to 64 characters of letters, digits,
_, +, - and /, and supported by Intl): 2026-09-28T00:00:00Z (Asia/Tokyo) -> 2026-09-28 09:00:00 +09:00, 2026-07-01T00:00:00Z (America/New_York) -> 2026-06-30 20:00:00 -04:00 (daylight saving time is applied). An offset in seconds (a historical local mean time) is written as ±HH:MM:SS. A result outside the years 0001 to 9999 is an error.
- Date - Show in Multiple Time Zones: One line for each time zone of the
timeZones setting, <name> HH:mm, with (前日) or (翌日) when the date there is before or after the date in UTC: 2026-09-28T00:00:00Z -> UTC 00:00⏎Asia/Tokyo 09:00⏎America/Los_Angeles 17:00 (前日). The IANA names are shown instead of abbreviations such as JST or PDT, which Intl cannot give reliably.
- Weekdays, weeks and days:
- Date - Show Weekday: Shows the weekday in a notification and never changes the text:
2026-09-28 -> Monday(月). With several values (of all selections, in document order; empty lines are not counted), each is shown with its value: 2026-09-28: Monday(月), 2026-09-29: Tuesday(火); after 20 values the rest are only counted (, … and 5 more), and each value is cut to 60 characters.
- Date - Append Weekday:
2026-09-28 -> 2026-09-28 (月) ((Mon) with weekdayLanguage en); spaces after the value stay after the weekday.
- Date - ISO Week Number:
2026-09-28 -> 2026-W40; the ISO week-numbering year can differ from the calendar year (2027-01-01 -> 2026-W53).
- Date - Day of Year:
2026-09-28 -> 271.
- Calculation:
- Date - Difference Between Two Dates: Two dates on each line, separated by a tab,
/, .., ~, 〜, ~ or , (the first of these found is used), or exactly two selections of one date each. The result is the later minus the earlier as written (negative if the second is earlier): 2026-01-01 / 2026-09-28 -> 270 days, 2026-09-28 / 2026-09-25 -> -3 days. If either has a time: 2026-01-01T00:00 / 2026-01-02T01:30 -> 1 day 1 hour 30 minutes (seconds are cut off). Either both or neither must have an offset when either has a time; otherwise it is an error (line 1: write a time zone offset on both dates or on neither, without line 1: for two selections). Anything other than two dates on each line or exactly two selections of one date each is an error (select two dates, or write two dates on each line).
- Date - Add Days / Add Months: Asks for a number (days from -1,000,000 to 1,000,000; months from -120,000 to 120,000) and keeps the separator, the time and the offset as written (the month and day are written with 2 digits):
2026-09-28 (+5) -> 2026-10-03, 2026/9/28 10:00 (-30) -> 2026/08/29 10:00. Add Months moves a day that does not exist to the end of the month: 2026-01-31 (+1) -> 2026-02-28. A result outside the years 0001 to 9999 is an error.
- Date - Convert to Relative Time:
Intl.RelativeTimeFormat in Japanese: 2026-09-25 -> 3 日前. A date without a time is compared with today's local date (今日 for today; days while the difference is under 30 days, then calendar months while it is under 12 months, then calendar years: 2026-10-30 -> 1 か月後); a time or timestamp is compared with the current time (seconds, minutes and hours below a day: 2026-09-28T11:59:30 -> 30 秒前, then as for dates).
- Date - Calculate Age: The age today:
1990-04-01 -> 36. Someone born on February 29 gets a year older on March 1 in other years. A date in the future is an error.
- Date - Show Quarter and Fiscal Year: The calendar quarter, and the fiscal year named after the year it starts in, with
上期 for its first 6 months and 下期 after them: 2026-09-28 -> 2026 Q3 / FY2026 上期, 2027-03-31 -> 2027 Q1 / FY2026 下期 (with fiscalYearStartMonth 4).
- Formats:
- Date - Format with Pattern (also (Replace)): Asks for a pattern (1 to 100 characters) and writes the date and time as written (a date alone is 00:00:00):
2026-09-28T09:05:00 (yyyy/MM/dd HH:mm) -> 2026/09/28 09:05. Tokens: yyyy yy (year), MM M (month), dd d (day), HH H (hour 0-23), hh h (hour 1-12), mm m, ss s, SSS (milliseconds), a (AM / PM), EEEE (Monday) and E (Mon). Text inside '…' is written as it is, and '' is a '. The pattern is read from left to right, and a run of the same letter is one token: a run of a token letter with another length (yyy, EE, EEE, MMM, SS, aa) is an error (unsupported pattern token "EEE"), as is an unterminated '. Letters that are not tokens are written as they are, so YYYY-MM-DD gives YYYY-09-DD: the year and day are the lower-case yyyy and dd.
- Date - Convert to Compact (YYYYMMDD) (also (Replace)):
2026-09-28 -> 20260928 (a time is dropped). Date - Convert from Compact (YYYYMMDD) (also (Replace)): 20260928 -> 2026-09-28 (8 digits that make a date that exists).
- Date - Convert to Japanese Format:
2026-09-28 -> 2026年9月28日 (a time is dropped).
- Date - Convert to Excel Serial: The 1900 date system of Excel:
2026-09-28 -> 46293, 2026-09-28T12:00 -> 46293.5 (a time adds a fraction of up to 10 decimal places). For compatibility with Excel, which counts a February 29, 1900 that did not exist, dates before 1900-03-01 are one less (1900-02-28 -> 59, 1900-03-01 -> 61). Dates before 1900-01-01 are an error.
- Date - Convert from Excel Serial:
46293 -> 2026-09-28, 46293.5 -> 2026-09-28 12:00:00. A fraction is rounded to seconds, and a value that rounds to 24:00:00 becomes 00:00:00 of the next day: 59.9999999 -> 1900-03-01 00:00:00 (the next day of 1900-02-28, not the 1900-02-29 of Excel). 60 (and 60.5, …), which Excel reads as the February 29, 1900 that does not exist, is an error, as is a value after 9999-12-31 (up to 2958465, or a fraction that rounds past it).
- Durations:
- Date - ISO 8601 Duration to Human:
PT1H30M -> 1 時間 30 分, P1Y2M3W4DT5H6M7.5S -> 1 年 2 か月 3 週 4 日 5 時間 6 分 7.5 秒, PT0S -> 0 秒. Zero parts are left out; only the last part may have a fraction (. or ,); each number has up to 15 digits; a sign is not accepted.
- Date - Seconds to HH:MM:SS:
3661 -> 01:01:01, -3600 -> -01:00:00, 360000 -> 100:00:00 (an integer within the safe integer range).
- Date - HH:MM:SS to Seconds:
01:01:01 -> 3661, 1:05 (M:SS) -> 65, -1:00:00 -> -3600 (minutes and seconds with 2 digits, 0 to 59).
- Generators:
- Date - Insert Month Calendar: Replaces a month (
YYYY-MM or YYYY/MM, or a date of that month) with a cal-style calendar starting on Sunday (each day right-aligned in 2 characters, one space between days, no trailing spaces, no title line): 2026-09 -> Su Mo Tu We Th Fr Sa⏎·······1··2··3··4··5⏎·6··7··8··9·10·11·12⏎…⏎27·28·29·30.
- Date - Generate Date Range: Replaces
start..end (also ~, 〜 or ~, with spaces around it if you like) with every date from start to end, one per line (in descending order if the start is later), written with the separator of the start date: 2026-09-28..2026-09-30 -> 2026-09-28⏎2026-09-29⏎2026-09-30. Only dates without a time are read, and a range can have up to 10,000 dates.
- Date - Explain Cron Expression: Explains a 5-field cron expression (minute, hour, day, month, weekday) in Japanese with the next 5 runs after the current local time:
0 9 * * 1 -> 毎週月曜 09:00(次回: 2026-10-05 09:00, 2026-10-12 09:00, 2026-10-19 09:00, 2026-10-26 09:00, 2026-11-02 09:00). Common patterns are described in words (毎日 00:00, 毎週月曜・金曜 09:00, 毎月1日 00:00, 毎時 30 分, 15 分ごと), anything else field by field (0 9 13 * 5 -> 分: 0, 時: 9, 日: 13, 月: すべて, 曜日: 5(次回: …)). *, numbers, lists, ranges, steps (*/15, 1-5/2, 5/10), month names JAN-DEC and weekday names SUN-SAT (in any case) and weekdays 0-7 (0 and 7 are Sunday) are supported; L, W, #, ?, macros such as @daily and any number of fields other than 5 are errors. As in standard (Vixie) cron, when both the day and the weekday are restricted, a day that matches either runs. Runs are searched up to 8 years ahead, so an expression that never runs gives (次回: なし) (0 0 30 2 *).
Limitations of the date commands
- Size: A selection can be up to 1,000,000 characters, a range up to 10,000 dates, and Explain Cron Expression reads up to 1,000 non-empty lines in all selections together (each up to 200 characters; more is an error before anything is searched), shows 5 runs and searches 8 years ahead. A run whose results would exceed 10,000,000 characters in total is stopped and refused with a warning (
…Select less text.); nothing is changed or opened.
- Local time: A date and time without an offset is the local time of the computer running VS Code (for Convert to UTC String, the time zone commands and Convert to Relative Time), and Convert to Relative Time, Calculate Age and Explain Cron Expression use the current local date and time, so their results depend on where and when they run. A date without a time is 00:00 UTC for Convert to UTC String and the time zone commands, but a calendar date for Convert to Relative Time.
- Cron: The next runs are calendar dates and times in local time, and daylight saving time is not taken into account (a time skipped or repeated by a change of daylight saving time is not treated specially). Only the forms of
L, W, # and ? (such as L, 5L, 15W, LW, 1#2 and ?) are reported as not supported; any other value that is neither a number nor a month or day name of its field (such as JULY, WEDS, or JUL in the day-of-week field) is reported as an invalid value of that field.
- Excel: Only the 1900 date system is supported (not the 1904 date system of old Mac versions of Excel), and serials 1 to 59 (1900-01-01 to 1900-02-28) are counted from 1899-12-31 while later ones are counted from 1899-12-30, as in Excel (see above).
- Show in Multiple Time Zones: The results of several values in one selection are separated by one empty line (
UTC 00:00⏎Asia/Tokyo 09:00⏎America/Los_Angeles 17:00 (前日)⏎⏎UTC 12:00⏎…). When the values are already separated by an empty (or blank) line, that line is kept and no second one is added.
- Format with Pattern: Only the tokens above are supported; letters of other libraries such as
YYYY, DD or MMM are written as they are or are errors, as explained above.
Intl: Time zone names, offsets, daylight saving time and the text of Convert to Relative Time come from the Intl data (ICU) of the VS Code you use, so they can change with its version.
14. Morse Code
Convert text to dots and dashes, and vice versa.
- Text to Morse: Supports Alphanumeric (International) and Japanese Kana (Wabun).
- Morse to Text: Decodes Morse code to text.
- Morse to Text (Kana): Explicitly decodes as Japanese Kana (Wabun Code) to resolve ambiguities.
15. Unicode
Thirty Unicode - … commands (normalization, invisible characters, code points and bytes, graphemes, emoji, styled letters, confusable and bidi control characters, typography, scripts and Cyrillic transliteration) are added to a new Unicode context submenu (after the Generate submenu in the Selection Manipulator menu) and to the Command Palette. They use only built-in Unicode processing (String.prototype.normalize, Intl.Segmenter, \p{…} regular expressions and TextEncoder) and tables that are constants in the extension: no new dependencies and no network access. The existing Unicode escape commands (Escape / Unescape Unicode in the Encode / Decode submenus), Unsmart Quotes and the Japanese character type count are unchanged.
In the examples, · is a space, ⏎ is a line break, {U+200B} is the one character U+200B (written this way because it is invisible or combines with the character before it), and a value in parentheses is the value you choose.
- Common rules:
- Output: Most commands replace each selection (only the selections whose text changes, as one undo step). Show Code Points, Show UTF-8 Bytes per Character, Show UTF-16 Code Units and Extract Emoji open the result in a new read-only editor (the results of several selections in document order, joined with the document's line ending). Count Graphemes and Detect Scripts show a notification for all selections together, and Detect Confusable Characters and Detect Bidi Control Characters select what they find (and show a notification of what was found).
- Selections and errors: Empty selections and selections of only spaces, tabs and line breaks are skipped, and if nothing else is selected, the warning
Select the text to convert. is shown. If any selection fails, nothing is changed, opened or selected, and an error names the problem (The selection was not changed: …, No result was shown: … or Nothing was selected: …, with selection 2 of 3: when there are several selections). LF and CRLF line breaks are kept.
- Characters are never cut apart: Surrogate pairs, combining marks, emoji ZWJ sequences, skin tone modifiers, flags and keycaps are kept whole by every command (the styling commands work on grapheme clusters or code points, never on UTF-16 code units).
- Normalization:
- Unicode - Normalize NFC / NFD / NFKC / NFKD:
String.prototype.normalize: e{U+0301} -> é (NFC), é -> e{U+0301} (NFD), ガ①fi -> ガ1fi (NFKC), fi -> fi (NFKD).
- Invisible and control characters:
- Unicode - Remove Zero-width Characters: Removes U+200B (zero-width space), U+200C (ZWNJ), U+200D (ZWJ), U+2060 (word joiner), U+FEFF (BOM) and U+180E:
a{U+200B}b -> ab. A ZWJ that joins two emoji is kept, so emoji ZWJ sequences are not broken: a ZWJ is kept only when the character before it is an emoji (\p{Extended_Pictographic}, optionally followed by a skin tone modifier or U+FE0E / U+FE0F) and the character after it is an emoji too. 👨{U+200D}👩{U+200D}👧, 🧑🏽{U+200D}💻 and ❤{U+FE0F}{U+200D}🔥 are unchanged, while 👍{U+200D} -> 👍, 👍{U+200D}a -> 👍a and a{U+200D}b -> ab. ZWJ and ZWNJ are also removed from scripts where they matter (such as Devanagari or Persian), as the command intends.
- Unicode - Reveal Invisible Characters: Writes invisible and control characters as
<U+XXXX>: a{U+200B}b -> a<U+200B>b. These are the control characters (Cc) except tab, LF and CR, the format characters (Cf: ZWSP, ZWJ, ZWNJ, BOM, soft hyphen, bidi controls, tag characters …), U+2028 / U+2029 and the space characters (Zs, such as the no-break space U+00A0) except the ordinary space and the ideographic space U+3000. ZWJs and tag characters that belong to an emoji sequence are kept by the same rule as Remove Zero-width Characters (the ZWJ of 👨{U+200D}👩{U+200D}👧 and the tags of the flag of England stay; 👍{U+200D} -> 👍<U+200D>, and a tag character that follows no emoji becomes <U+E0061> and so on). Code Points to Text turns the result back.
- Unicode - Remove Control Characters: Removes U+0000 to U+001F except tab, LF and CR, U+007F and U+0080 to U+009F (C0 / C1):
a{U+0007}b -> ab.
- Unicode - Remove Non-ASCII Characters: Removes every character from U+0080 up:
café ☕ -> caf·.
- Code points and bytes:
- Unicode - Show Code Points: The code points of each line as
U+XXXX separated by spaces (upper-case hexadecimal, at least 4 digits), keeping the line breaks: あ😀 -> U+3042 U+1F600. Spaces and tabs are shown too (U+0020, U+0009).
- Unicode - Code Points to Text:
U+XXXX and <U+XXXX> (either case, 4 to 6 hexadecimal digits) become the characters they name, and the spaces and tabs between two such tokens are removed; everything else is kept: U+3042 U+1F600 -> あ😀, a<U+200B>b -> a{U+200B}b. It turns the results of Show Code Points and Reveal Invisible Characters back. A surrogate (U+D800 to U+DFFF) and a value beyond U+10FFFF are errors ("U+D800" is a surrogate code point, not a character).
- Unicode - Show UTF-8 Bytes per Character: One line per grapheme cluster,
character: bytes in upper-case hexadecimal: aあ -> a: 61⏎あ: E3 81 82. Line breaks, spaces and invisible characters are shown as <U+XXXX> (<U+00A0>: C2 A0), and a line break is a line of its own (a CRLF is <U+000D><U+000A>: 0D 0A).
- Unicode - Show UTF-16 Code Units: The same with UTF-16 code units:
😀 -> 😀: D83D DE00.
- Unicode - Count Graphemes: The number of grapheme clusters (user-perceived characters, by
Intl.Segmenter) and the length (UTF-16 code units) of all selections together, in a notification: 👨{U+200D}👩{U+200D}👧 -> 1 grapheme / length 8.
- Emoji:
- Unicode - Remove Emoji:
ok👍 -> ok. An emoji is a grapheme cluster that contains a character with the emoji presentation (\p{Emoji_Presentation}), U+FE0F, a regional indicator (flags) or U+20E3 (keycaps), and it is removed whole, with its skin tone modifiers and ZWJs. Text symbols without the emoji presentation (©, ®, ™, ❤ without U+FE0F) and plain digits and # are not emoji.
- Unicode - Extract Emoji: The emoji only, in order and without separators:
ok👍 go🚀 -> 👍🚀. When there is none in any selection, No emoji was found in the selection. is shown instead of an empty editor.
- Styled letters (each replaces only the characters it has a form for; everything else is kept):
- Unicode - Mathematical Bold:
abc -> 𝐚𝐛𝐜; A-Z, a-z and 0-9.
- Unicode - Mathematical Italic:
abc -> 𝑎𝑏𝑐; A-Z and a-z (h is ℎ U+210E; digits are kept, as there are no italic digits).
- Unicode - Mathematical Monospace:
abc -> 𝚊𝚋𝚌; A-Z, a-z and 0-9.
- Unicode - Circled Letters:
abc -> ⓐⓑⓒ; A-Z (Ⓐ), a-z, 0 (⓪) and 1-9 (①), one character at a time.
- Unicode - Upside Down Text: Turns the text by 180 degrees: letters, digits and some punctuation are replaced with characters that look like them upside down, and the order of the characters is reversed:
hello -> ollǝɥ. With several lines, the order of the lines is reversed too (ab⏎cd -> pɔ⏎qɐ), while line breaks at the start and at the end of the selection stay where they are. Characters without an upside-down form (such as Q) are kept, and running it twice gives the text back for the characters that have one.
- Unicode - Combining Strikethrough / Combining Underline: Adds U+0336 / U+0332 after every grapheme cluster except line breaks, tabs and other control characters:
abc -> a{U+0336}b{U+0336}c{U+0336} / a{U+0332}b{U+0332}c{U+0332}.
- Unicode - Superscript / Unicode - Subscript: Asks what to convert: Digits and Signs (the default, first in the list: the digits and
+ - = ( ) only; x2 -> x², H2O -> H₂O) or Digits, Signs and Letters (also the letters that have a superscript or subscript form: x2 -> ˣ²; there are superscripts for all lower-case letters except q and for some capitals, and subscripts for some lower-case letters only). It asks only once for all selections, reads the selections again after the choice, and does nothing if you cancel it.
- Detection (these select what they find and never change the text):
- Unicode - Detect Confusable Characters: Selects Cyrillic and Greek letters that look like Latin letters (homoglyphs) where they are likely to be a disguise:
pаypal (with a Cyrillic а) -> the а is selected, and 1 confusable character found: "а" (U+0430) looks like "a" is shown (each kind of character once, in order of appearance). A word is a run of letters, combining marks and digits; anything else (spaces, symbols, _, -, .) separates words, so pаypal123 is one word, pаy-pal is pаy and pal, and раура.com is раура and com. A lookalike is found:
- in a word that also contains a Latin letter (Cyrillic or Greek):
pаypal, user_nаme, Tοkyο (Greek ο), ΑPI (Greek Α);
- in a word made only of Cyrillic lookalikes (such as
раура), only when the word has two or more letters, another word of the same line contains a Latin letter, and the line has no Cyrillic or Greek letter that is not a lookalike: login раура and раура.com -> the five letters of раура are selected.
- Ordinary Russian and Greek text is not reported: its lines have no Latin word or have letters that are not lookalikes (
я, и, л, λ, accented vowels …), and one-letter words (а, с, о) are never reported. When nothing is found, No confusable characters were found. is shown and the selections are kept.
- Unicode - Detect Bidi Control Characters: Selects the bidirectional control characters used by Trojan Source attacks (U+202A to U+202E and U+2066 to U+2069):
a{U+202E}b -> the U+202E is selected, and 1 bidi control character found: U+202E (right-to-left override) is shown. When nothing is found, No bidi control characters were found. is shown.
- Both select up to 10,000 characters in all selections together (more is an error and nothing is selected), and the first one found is scrolled into view.
- Typography:
- Unicode - Convert to Smart Quotes:
"a" it's -> “a” it’s (the opposite of the existing Unsmart Quotes). " becomes “ at the start of the selection or a line, after white space, an opening bracket (( [ { <) or a dash (- – —), and after ‘ (a nested quotation), and ” anywhere else. ' between two letters or digits is the apostrophe ’; otherwise it becomes ‘ at the same places (after “ instead of ‘) and ’ anywhere else. So "" -> “”, "'hi'" -> “‘hi’” and '90s -> ‘90s.
- Unicode - Typographic Dashes and Ellipsis: Exactly two hyphens become an em dash and exactly three dots an ellipsis:
wait... -- ok -> wait… — ok. Longer runs such as --- (a Markdown rule or front matter) and .... are kept.
- Scripts and transliteration:
- Unicode - Detect Scripts: The scripts (the Unicode
Script property) of the letters of all selections together and how many letters each has, in order of appearance, in a notification: abcあア漢 -> Latin 3, Hiragana 1, Katakana 1, Han 1. Digits, symbols, spaces and combining marks (the Common and Inherited scripts) are not counted; 33 common scripts (Latin, Greek, Cyrillic, Arabic, Hebrew, Devanagari, Thai, Hangul, Hiragana, Katakana, Han …) are named, and letters of any other script are counted as Other. When there are no letters, No letters of any script were found (only digits, symbols and spaces). is shown.
- Unicode - Transliterate Cyrillic to Latin:
Привет -> Privet, with one fixed value per letter (a simplified BGN/PCGN for Russian) and ASCII-only output: е is always e (Ельцин -> Eltsin), ж zh, х kh, ц ts, щ shch, ю yu, я ya, and ъ ь are removed. The letters Russian lacks come from Ukrainian and Belarusian (є ye, і i, ї yi, ґ g, ў w: Україна -> Ukrayina) and Serbian and Macedonian (ђ dj, ј j, љ lj, њ nj, ћ c, џ dz, ѓ gj, ќ kj, ѕ dz: Љубљана -> Ljubljana). Where the languages read a letter differently, the Russian value is used (г is g, и is i). A value of several letters is all capitals next to capitals (ЖУК -> ZHUK) and capitalized otherwise (Жук -> Zhuk). Decomposed letters (и + U+0306, е + U+0308) give the same result as й and ё; other characters are kept.
Limitations of the Unicode commands
- Size: A selection can be up to 1,000,000 characters (a longer one is an error). A run whose results would exceed 10,000,000 characters in total (Show Code Points, Show UTF-8 Bytes and Show UTF-16 Code Units write about ten characters per character) is stopped and refused with a warning (
…Select less text.); nothing is changed or opened.
- Unicode version: Normalization, grapheme clusters, emoji and scripts come from the Unicode data of the JavaScript engine of the VS Code you use, so the results for very new characters can change with its version.
- Reveal Invisible Characters: Only the characters listed above are revealed. Characters that look empty but are letters or marks, such as the Hangul filler U+3164, and a variation selector U+FE0F on its own (
a{U+FE0F}b) are kept as they are.
- Remove Emoji / Extract Emoji: A character with the emoji presentation followed by the text presentation selector U+FE0E (
⌚{U+FE0E}) is still treated as an emoji.
- Detect Confusable Characters: The table has only well-known Cyrillic and Greek lookalikes (not the full Unicode confusables list; full-width Latin letters are Latin and are not reported), and detection favors few false alarms over finding everything. A word made only of lookalikes is not found on a line without a Latin word (a line of only
раура) or on a line that also has Cyrillic or Greek letters that are not lookalikes, and a word made only of Greek lookalikes is never found (ΑΡΙ key); Greek letters are found only inside a word with Latin letters.
- Convert to Smart Quotes: The rules look only at the character before a quote, so an apostrophe at the start of a word becomes an opening quote (
'90s -> ‘90s, 'n' -> ‘n’), and a " right after an existing curly “ becomes a closing quote (“"x" -> “”x”). Select only prose, not code.
- Typographic Dashes and Ellipsis: Every
-- is converted, also in code and in HTML comments (<!-- -->); select only prose.
- Transliterate Cyrillic to Latin: The fixed values differ from the full BGN/PCGN rules (
ye for е at the start of a word or after a vowel is not used) and from the official Ukrainian and Belarusian romanizations (г is g, not h; и is i, not y).
16. Developer (Programmatic)
Thirty-five developer commands (string literals for JavaScript, Python, Java and Go, escaping for regular expressions, SQL, shells, CSV and Markdown, types from sample JSON, SQL and CSS formatting, colors, JavaScript clean-ups, curl to fetch, HTML to JSX, semantic versions and chmod) are added to the existing Programmatic context submenu (after its JSON / YAML, Hex / RGB and Toggle Quotes commands) and to the Command Palette (when there is a selection). They only rewrite text: no SQL, shell or curl command is ever run, nothing is sent over the network, no file is read, and everything is implemented in the extension with no new dependencies. The existing Programmatic commands are unchanged.
In the examples, · is a space, ⇥ is a tab, ⏎ is a line break, and a value in parentheses is the value you choose.
- Common rules:
- Output: The commands open the result in a new read-only editor (the results of several selections in document order, joined with the document's line ending). The six (Replace) versions (Convert to JS String Literal, Escape Regex Special Characters, Escape SQL String Literal, Convert JSON to TypeScript Interface, Format SQL and Convert HTML to JSX) do the same conversion and replace each selection instead (only the selections whose text changes, as one undo step).
- Selections and errors: Empty selections are skipped. Selections of only spaces, tabs and line breaks are converted by the string literal and escaping commands (Convert to JS / Python String Literal, Convert to Java String Concatenation, Convert to Go Raw String, Convert to JS Template Literal, Escape Regex Special Characters, Escape SQL String Literal, Quote for POSIX Shell / PowerShell, Escape CSV Field, Escape Markdown Special Characters and their (Replace) versions:
··· -> '···'), because such text can be a value you want to quote; every other command skips them. If nothing is left, the warning Select the text to convert. is shown. If any selection fails, nothing is changed or opened, and an error names the problem (The selection was not changed: … or No result was shown: …, with selection 2 of 3: when there are several selections, and line 2: for the commands that convert one value per line). LF and CRLF line breaks are kept.
- String literals:
- Convert to JS String Literal (and (Replace)):
it's⏎ok -> 'it\'s\nok'. \ and ' are escaped, LF, CR and tab become \n \r \t, other control characters and DEL become \xhh, U+2028 / U+2029 become \u2028 / \u2029, and a lone surrogate becomes \uhhhh (it cannot be written to a UTF-8 file).
- Convert to Python String Literal: Chooses the quotes like Python's
repr: " when the text contains ' but no ", ' otherwise (it's -> "it's", a'b"c -> 'a\'b"c'). \, the chosen quote, \n \r \t are escaped, other control characters, DEL and U+0080 to U+009F become \xhh, and a lone surrogate becomes \uhhhh; other non-ASCII characters are kept.
- Convert to Java String Concatenation: One
"…\n" + literal per line, joined with the document's line ending: a⏎b -> "a\n" +⏎"b". A line break at the end of the selection ends the last literal with \n (a⏎b⏎ -> "a\n" +⏎"b\n"). \ " tab, backspace and form feed have short escapes, and other control characters become 3-digit octal escapes (\001); \uXXXX is never written, so a \u000a in the text becomes \\u000a and is not a Java Unicode escape.
- Convert to Go Raw String:
a⏎b -> `a⏎b`; a backquote inside is written as a concatenation: a`b -> `a` + "`" + `b`.
- Convert to JS Template Literal:
cost ${x} -> `cost \${x}` (\, ` and ${ are escaped).
- Escaping:
- Escape Regex Special Characters (and (Replace)):
a.b*c? -> a\.b\*c\?. \ ^ $ . * + ? ( ) [ ] { } | / are escaped (- is not), so the result used as a whole pattern matches only the original text, with or without the u flag.
- Escape SQL String Literal (and (Replace)):
O'Reilly -> O''Reilly (only ' is doubled, as in standard SQL; add the surrounding quotes yourself). Text with a backslash (\), a yen sign (¥, U+00A5) or a control character other than tabs and line breaks (such as NUL or DEL) is an error and nothing is changed or opened (see the limitations below).
- Quote for POSIX Shell:
it's -> 'it'\''s' ($, ` and \ have no meaning inside single quotes).
- Quote for PowerShell:
it's -> 'it''s'; the curly single quotes U+2018 to U+201B, which PowerShell also reads as quotes, are doubled too.
- Escape CSV Field:
a,"b" -> "a,""b""". The field is quoted only when it contains ,, " or a line break (the same rule as the CSV / TSV commands).
- Escape Markdown Special Characters:
*a* _b_ -> \*a\* \_b\_. \ ` * _ [ ] < > # | ~ are always escaped; + - = only at the start of a line (after the indentation), . and ) only right after a number at the start of a line (1. x -> 1\. x), and & only at the start of a character reference (& -> \&; © -> \&\#169;).
- Types from sample JSON (Convert JSON to TypeScript Interface (and (Replace)), Convert JSON to Go Struct, Convert JSON to Python TypedDict):
- The selection must be a JSON object or an array of objects (the objects of an array are merged into one
Root type); it is read with JSON.parse only. A key that is missing from some of the merged objects is optional (TypeScript ?:, Go omitempty, Python NotRequired[...]), a null value makes the type nullable (string | null, str | None), an empty array is unknown[] / []interface{} / list[Any], and nested objects become their own types named after their keys (Owner for "owner", numbered when names collide). Objects can be nested 200 levels deep.
- TypeScript:
{"id":1,"tags":["a"]} -> interface Root {⏎··id: number;⏎··tags: string[];⏎}; a key that is not an identifier is quoted ('first-name': string;).
- Go:
{"user_id":1} -> type Root struct {⏎⇥UserID int `json:"user_id"`⏎}, with the columns aligned like gofmt and initialisms in upper case (ID, URL, HTTP …). Integers and decimals together are float64, a value that is null in some objects keeps its type (not a pointer), and different types together are interface{}. A key that encoding/json cannot use as a tag name gets a comment (// encoding/json cannot use this key as a tag name).
- Python:
{"id":1} -> from typing import TypedDict⏎⏎⏎class Root(TypedDict):⏎····id: int, with only the needed imports and the nested classes before Root. A type whose keys are not all valid identifiers (or are keywords such as class) uses the functional form Owner = TypedDict('Owner', {⏎····'first-name': str,⏎}).
- SQL (Format SQL (and (Replace)), Minify SQL, Uppercase SQL Keywords; simple, dialect-neutral processing of the text; the SQL is never run):
- Format SQL:
select a from t where b=1 -> SELECT a⏎FROM t⏎WHERE b = 1. Keywords are upper-cased, a line starts before each main clause (SELECT, FROM, WHERE, GROUP BY, ORDER BY, HAVING, LIMIT, the JOINs, UNION, INSERT, VALUES, UPDATE, SET, DELETE, RETURNING …), AND / OR of WHERE and HAVING start an indented line, a subquery (SELECT …) is indented by 2 spaces, and statements are separated by a blank line after ;. Comments are kept.
- Minify SQL:
SELECT a⏎-- c⏎FROM t -> SELECT a FROM t. Comments are removed (optimizer hints /*+ … */ and MySQL /*! … */ are kept) and white space is collapsed to one space.
- Uppercase SQL Keywords:
select name from users -> SELECT name FROM users; only keywords (not function names) change, and strings, quoted identifiers and comments are untouched.
- Supported forms:
'…' strings (with ''), "…", `…` and […] quoted identifiers, -- comments (with a space after --) and /* */ comments. # and a -- without a space after it (--x, --1) keep the rest of their line as it is, with the line break after it, in all three commands: in MySQL they start a comment, while in SQL Server (#temp) or MySQL 1 --1 (1 - -1) they are code, so the text is copied unchanged (not formatted or upper-cased) to mean the same in every dialect.
- CSS (Minify CSS, Format CSS):
- Minify CSS:
a {⏎··color: red;⏎} -> a{color:red}. Comments are removed (/*! … */ is kept), white space is collapsed and removed next to { } ; , :, and the last ; of a block is removed; the space of a descendant selector such as a :hover and of values such as calc(1px + 2px) is kept. When removing a comment would join two tokens (a/**/b, 1/**/%), it is shortened to /**/ instead.
- Format CSS:
a{color:red} -> a {⏎··color: red;⏎}: one declaration per line indented by 2 spaces (nested rules such as @media deeper), , in selector lists, and a blank line between top-level rules. Selecting only declarations (color:red;margin:0) works too.
- Colors (one color per line; spaces around the color and lines of only white space are kept):
- Convert Hex to HSL:
#ff0000 -> hsl(0, 100%, 50%). Reads #rgb, #rgba, #rrggbb and #rrggbbaa (the # is optional, either case); with alpha, hsla(0, 100%, 50%, 0.5). Hue, saturation and lightness are rounded to integers, alpha to 2 decimal places.
- Convert HSL to Hex:
hsl(120, 100%, 25%) -> #008000. Reads hsl() and hsla() with commas or with spaces and / alpha (hsl(0 100% 50% / 50%) -> #ff000080), a hue with or without deg, and alpha as a number or a percentage; the output is lower case, with 8 digits when alpha is below 1.
- Toggle Hex Color Short / Long:
#aabbcc -> #abc, #abc -> #aabbcc (also 4 <-> 8 digits); a color that cannot be shortened (#aabbcd) is kept, and the case and the # are kept as written.
- JavaScript / TypeScript code:
- Remove console.log Statements:
a();⏎console.log(x);⏎b(); -> a();⏎b();. Removes the lines that are only a console.log(…) or console.debug(…) call (after the indentation, followed only by ;, spaces or a // comment), also a call that spans several lines. Strings, template literals, comments and regular expressions are read correctly, so a ) inside them does not end the call.
- Sort Import Statements:
import b from 'b';⏎import a from 'a'; -> import a from 'a';⏎import b from 'b';. Each run of consecutive import statements (default, named, namespace, import type, multi-line { … }, with { … }) is sorted by module name, ignoring case, and stably. Blank lines, comment lines, other code and side-effect imports (import './style.css';) separate the runs and are never moved.
- Convert String Concatenation to Template Literal:
'Hi ' + name + '!' -> `Hi ${name}!`. The expression is split at the + outside parentheses; '…' / "…" strings are inserted as text (` and ${ are escaped), template literals are inserted as they are, other terms become ${…} (1 + 2 + 'a' + b * -1 -> `${1 + 2}a${b * -1}`). Leading and trailing spaces and a final ; are kept.
- Convert curl Command to fetch:
curl -X POST -d 'a=1' https://example.com -> fetch('https://example.com', {⏎··method: 'POST',⏎··headers: {⏎····'Content-Type': 'application/x-www-form-urlencoded',⏎··},⏎··body: 'a=1',⏎});. The command is only split into words like a POSIX shell does (single, double and $'…' quotes, \, line continuations, # comments; a leading $ prompt is removed); $VAR, $(…) and backquotes are kept as written, never expanded or run. Supported options: -X, -H, -d / --data-raw / --data-ascii / --data-binary / --data-urlencode, --json, -F / --form-string, -u, -A, -e, -b, -I, -G, --url, --oauth2-bearer and combined short options (-sSL, -XPOST). Output and connection options (-L -s -S -k -v -i --compressed -o -m …) are ignored silently, and other options are listed in a // Ignored curl options: … comment. The method is -X, otherwise HEAD for -I, GET for -G, POST when there is a body, and GET (not written) otherwise. To give the same request as curl, -d adds Content-Type: application/x-www-form-urlencoded and --json adds Content-Type and Accept: application/json unless you set them, -H 'Name:' removes such a default header, -u becomes a Basic authorization header, -G puts the data in the query string (before a #fragment), and a URL without a scheme gets http:// (http: for //host). All strings are written as JS string literals.
- Convert HTML to JSX (and (Replace)):
<label class="a" for="b"> -> <label className="a" htmlFor="b">. class -> className, for -> htmlFor, other attributes get their React names (tabindex -> tabIndex, viewbox -> viewBox, onclick -> onClick), names with - or : become camelCase (stroke-width -> strokeWidth, xlink:href -> xlinkHref) except data-* and aria-*, and style="color: red; -webkit-box-flex: 1" -> style={{ color: 'red', WebkitBoxFlex: '1' }}. Void elements are closed (<br> -> <br />), comments become {/* … */}, <!DOCTYPE> and <?xml …?> are removed, { } < > in text become {'{'} and so on, and the content of <script> and <style> becomes a template literal. Tags do not have to be balanced, so a fragment such as a single start tag can be converted.
- Bump Semantic Version: Asks which part to raise (patch, minor or major; once for all selections, and nothing is done if you cancel) and raises it on every line:
1.2.3 (minor) -> 1.3.0. Follows SemVer 2.0.0 and the rules of npm semver.inc: a pre-release version is released by the matching bump (1.2.3-beta.1 (patch) -> 1.2.3, (major) -> 2.0.0), build metadata is removed, and a leading v is kept.
- Convert chmod Numeric / Symbolic:
755 -> rwxr-xr-x, rwxr-xr-x -> 755, one value per line. 4-digit values include setuid, setgid and sticky (4755 -> rwsr-xr-x, shown as s / S / t / T), and the symbolic form can have the file type letter of ls -l and a trailing ., + or @ (-rw-r--r--@ -> 644, drwxr-xr-t -> 1755).
Limitations of the Developer commands
- Size: A selection can be up to 1,000,000 characters (a longer one is an error), and a run whose results would exceed 10,000,000 characters in total is refused with a warning (
…Select less text.); nothing is changed or opened. JSON, SQL parentheses, CSS blocks and nested template literals can be nested up to 200 levels.
- Selections of only white space: Only the string literal and escaping commands listed above convert them; the other commands skip them (as if nothing were selected).
- String literals and escaping: Convert to Go Raw String keeps a CR as it is (a raw string cannot escape it, and Go removes CRs from raw strings). Escape SQL String Literal writes standard SQL (only
' is doubled) and refuses text with a backslash (\) or a yen sign (¥, U+00A5, saved as a backslash in Shift_JIS, CP932 and EUC-JP) with an error, even for valid data such as C:\Users, because MySQL / MariaDB in their default mode (without NO_BACKSLASH_ESCAPES) read \ as an escape character, so the text could end the string and add SQL of its own; escaping \ as \\ would be wrong for standard SQL. It also refuses a control character other than tabs and line breaks (NUL and DEL included), as Convert to SQL INSERT and Quote: SQL IN List do; tabs and line breaks are kept. Escape CSV Field does not quote a field only because it has spaces at the start or the end (a stays a).
- Types from sample JSON: The types are guessed from one sample, so they are a starting point that you may need to edit. Numbers are told apart by their value, so
1.0 and 1e2 count as integers (int in Go and Python) because JSON.parse reads them as whole numbers. Integer-like keys ("10") come first, as JavaScript orders them. The TypedDict output needs Python 3.11 or later when it uses NotRequired, and Python 3.10 or later otherwise (str | None); the Go output does not use pointers for null.
- SQL: The processing is simple and not tied to one dialect. These forms are refused with an error by all three commands, because the dialects read them differently: PostgreSQL
$$…$$ / $tag$…$tag$ and E'…' strings, nested block comments (/* /* */ */), and '…' or "…" strings with an odd number of \ right before a quote character anywhere inside (a MySQL backslash escape such as 'it\'s' or '\''; the standard SQL string 'C:\' is refused too, while an even number such as 'a\\' is accepted). On a line with # or a -- without a following space, the rest of the line is not formatted or upper-cased (FROM #temp where x = 1 stays as it is), and that rest of the line must not start a string, a quoted identifier or a /* comment that continues on the next line (a MySQL comment such as # that's is refused; write -- with a space for an ordinary comment). Format SQL refuses parentheses that do not match (including a parenthesis opened in such a line and closed on a later line), always ends the line after a line comment, and keeps a line that starts with # or -- in the input (a comment, or SQL Server code such as a #temp name or --x) on a line of its own instead of joining it to the end of the previous line (SELECT a⏎# note⏎FROM t -> SELECT a⏎ # note⏎FROM t, select a from⏎#t where x=1 -> SELECT a⏎FROM⏎ #t where x=1); a # or -- after code on the same line (a # c, FROM #temp) stays on that line.
- CSS: The processing is simple; custom property values that contain
{ } blocks are not supported.
- Colors: Convert HSL to Hex does not read
turn and rad hues, none, numbers without % in the space-separated form (hsl(120 100 25)) or a trailing ; (they are errors). Hex to HSL rounds to integers, so converting back does not always give the same color.
- Remove console.log Statements: A call on the same line as other code (
b(); console.log(x);), a call that is the body of if (…), for (…), while (…), else or an arrow function, a chained call (console.log(x).then(…)), console.info and similar calls are kept. A call is also kept when removing it could join the lines around it into a different expression: when the next line starts with (, [, a template literal, a regular expression, an operator or in / instanceof (for safety also {, ! and ~) and the call or the code before it does not end with ; (or the code before it ends with }). The simple JavaScript reader treats a / after ) as division, so if (x) /re/.test(y) is misread.
- Sort Import Statements: Only JavaScript / TypeScript
import statements are sorted (not require or Python imports), and side-effect imports are never moved. An import line followed by other code on the same line, dynamic import(…), import.meta and import x = require(…) are treated as other code.
- Convert String Concatenation to Template Literal: An expression with an operator that binds as loosely as
+ or more loosely (-, comparisons, &&, ||, ??, ? :, assignments, ,) outside parentheses, a / or regular expression outside parentheses, a comment or an octal escape (\1) is refused; put that part in parentheses ('a' + (x ? 1 : 2) -> `a${(x ? 1 : 2)}`). With objects, + uses valueOf while a template literal uses toString, so the result can differ.
- Convert curl Command to fetch: Files are never read:
-d @file, --data-urlencode name@file, --json @file, -F name=@file, -H @file and a cookie file for -b become a // TODO: … reads the file '…' comment, and with -G, the data of -d @file is not added to the URL (only the TODO comment is written). Variables and command substitutions are not expanded ("Bearer $TOKEN" is written as is), and everything after an unquoted |, ;, &, <, >, ( or ) is ignored with a comment. These are errors: -G with --json or -F, -F with -d or --json, -d with --json, and a body with the GET or HEAD method (-X GET -d …, -I -d …; use -G to put the data in the URL). An ignored option whose name has characters other than letters, digits, - and . is listed as a JS string literal, and in combined short options everything after an unknown letter is ignored.
- Convert HTML to JSX: Tag names and attribute names must start with a letter (attribute names also with
_) and contain only letters, digits, -, _ and one :; anything else ({...x}, @click, x.y) is an error, and so is an unclosed tag, attribute value, comment or <script> and <![CDATA[…]]>. Event attribute values stay strings (onClick="go()"), so change them to functions yourself. An attribute without a value is kept without a value (<div class> -> <div className>), and checked, selected and value are kept as they are, so React can warn about uncontrolled or read-only inputs (use defaultChecked / defaultValue or add onChange). Several root elements are not wrapped in a fragment, and tags are not checked for balance.
- Bump Semantic Version: Build metadata (
+build.5) is removed, as npm does.
- Convert chmod Numeric / Symbolic: The file type letter of
ls -l (d, l …) and a trailing . + @ are dropped in the numeric form.
17. Multi Cursor & Selection
Thirty Selection - … commands work on the selections themselves (multi-cursor editing) and are added to a new Multi Cursor context submenu (after the Unicode submenu in the Selection Manipulator menu) and to the Command Palette. Most of them only change the selections; Align Cursors and the four text exchange commands edit the text. They run entirely in the extension, with no new dependencies and no network access. The existing multi-selection commands (Remove Cursor Above / Below, Separate Multi Selections, Select Matches, Extract URL, Remove Character from Each Side) are unchanged.
In the examples, […] is a selection, | is a cursor (an empty selection), · is a space, ⏎ is a line break, and a value in parentheses is the value you enter.
- Common rules:
- Order: The selections are always counted in document order (1-based), whatever order they were added in. The new selections are set in document order and the first one is scrolled into view.
- Nothing left: VS Code cannot have zero selections, so a command whose result would leave no selection changes nothing and shows a warning. A command whose result is the same as before changes nothing silently.
- Two or more selections: Keep Odd / Even / Every Nth, Remove First / Last, Deselect Duplicate Texts, Align Cursors, Rotate Texts Forward / Backward, Swap Two Selections and Copy First Selection to All need at least two selections; with one, they warn before asking anything.
- Characters: "One character" is one code point (a surrogate pair is never split), and a CRLF line break is one character.
- Menus: In the Command Palette, the commands that need several selections appear only with multiple selections; Keep Selections Matching Regex (MSEL-006), Remove Selections Matching Regex (MSEL-007) and Remove Empty Selections (MSEL-008) also appear only with multiple selections, although they do not need two selections to run. The splitting / selecting commands appear only when text is selected. Expand to Word / Quotes / Brackets, Cursors to First Non-whitespace, Show Selection Info and Select Leading Indentation also work with only a cursor from the Command Palette; like every command of the extension, the context menu is shown only when text is selected.
- Filtering the selections:
- Selection - Keep Odd Selections / Keep Even Selections:
[a] [b] [c] -> [a] b [c] / a [b] c.
- Selection - Keep Every Nth Selection: Asks for N (1 to 1,000,000) and keeps the Nth, 2Nth, 3Nth … selection:
[a] [b] [c] [d] (2) -> a [b] c [d].
- Selection - Remove First Selection / Remove Last Selection:
[a] [b] [c] -> a [b] [c] / [a] [b] c.
- Selection - Keep Selections Matching Regex / Remove Selections Matching Regex: Asks for a regular expression (JavaScript syntax with the
u flag, case-sensitive, up to 500 characters) and keeps / removes the selections whose text contains a match: [a1] [b] [c2] (\d) -> [a1] b [c2] / a1 [b] c2. An empty selection is tested as an empty text.
- Selection - Remove Empty Selections: Removes the cursors:
[a]·|·[b] -> [a]··[b].
- Selection - Deselect Duplicate Texts: Keeps only the first selection of every text (case-sensitive):
[a] [b] [a] -> [a] [b] a.
- Aligning, expanding and shrinking:
- Selection - Align Cursors: Inserts spaces before every selection so that all of them start at the same display column (the rightmost one; tabs count up to the next multiple of the editor's tab size):
a|=1⏎bbb|=2 -> a··|=1⏎bbb|=2. With several selections on one line, the first selections of all lines are aligned, then the second ones, and so on. The widths of the selections are kept, and one undo removes all inserted spaces.
- Selection - Expand to Word: A cursor becomes the word it is in, and each end of a selection moves to the start / end of the word it is in (the word definition of the language):
he|llo -> [hello].
- Selection - Expand to Inside Quotes: Selects the inside of the
"…", '…' or `…` around each selection on the same line (quotes are paired from left to right; a quote after a backslash is skipped): "he|llo" -> "[hello]".
- Selection - Expand to Inside Brackets: Selects the inside of the innermost
(), [] or {} around each selection (across lines); running it again goes one level out: f(a,|b) -> f([a,b]).
- Selection - Trim Whitespace from Selections: Removes spaces, tabs, line breaks and other white space (such as the full-width space) at both ends of every selection:
[··ab·] -> ··[ab]·. A selection of only white space becomes a cursor at its start.
- Selection - Shrink Selections by One Character: Moves both ends of every selection one character inward:
["ab"] -> "[ab]". Selections shorter than two characters do not change.
- Selection - Extend to Next Delimiter: Asks for a delimiter (literal text, 1 to 100 characters, no line breaks) and extends the end of every selection up to the next delimiter on the same line:
[a]bc,d (,) -> [abc],d. Selections without the delimiter after them do not change, and how many there were is shown. A selection that already ends right before a delimiter does not change either, so running the command again does not move on to the next delimiter.
- Splitting the selections:
- Selection - Split Selections by Delimiter: Asks for a delimiter (literal text, 1 to 100 characters, no line breaks) and splits every selection at it:
[a,b,c] (,) -> [a],[b],[c]. An empty part (a,,b) becomes a cursor, so the columns stay in place. A selection without the delimiter stays as it is; if no selection contains it, nothing changes and no message is shown.
- Selection - Split Selections by Regex: Asks for a regular expression (as above, run with the
g and u flags) and splits every selection at its matches: [a1b2c] (\d) -> [a]1[b]2[c]. Empty matches are not used for splitting. A selection without a match stays as it is; if no selection has a match, nothing changes and no message is shown.
- Selection - Split into Words: One selection per word (letters, marks, digits and
_): [foo bar] -> [foo] [bar]. Selections without words are dropped.
- Cursors on every line:
- Selection - Cursors to First Non-whitespace: Puts a cursor before the first character that is not a space or a tab on every line of the selections:
··a⏎····b -> ··|a⏎····|b. Empty lines and lines of only spaces and tabs are skipped. A selection that ends at the start of a line does not include that line.
- Selection - Select Column N: Asks for a delimiter (literal text,
, by default) and a column number N (1 to 1,000), and selects column N of every line of the selections (of the selected part of the line; of the whole line for a cursor): a,b⏎c,d (,, 2) -> a,[b]⏎c,[d]. Lines with fewer columns are skipped and an empty column becomes a cursor.
- Selection - Select Leading Indentation: Selects the spaces and tabs at the start of every line of the selections:
··a⏎····b -> [··]a⏎[····]b. Lines without indentation are skipped.
- Selecting inside the selections:
- Selection - Select All Numbers:
a1 b22 -> a[1] b[22]. Numbers are digits with an optional decimal part (1.5); a - right before a number is its sign unless it follows a letter, a digit, _, ) or ] (a-1 is a subtraction).
- Selection - Select All Quoted Strings: Selects the contents of
"…", '…' and `…` strings: f("a", 'b') -> f("[a]", '[b]'). A backslash escapes the next character, " and ' strings end at the end of the line, ` strings may span lines, unclosed quotes are ignored and an empty string becomes a cursor between its quotes.
- Selection - Select All URLs: Selects every
http:// and https:// URL (the same rule as Extract URL), without trailing .,;:!?'" and closing brackets that have no opening bracket in the URL: see https://a.example and https://b.example -> see [https://a.example] and [https://b.example].
- Exchanging the texts (these edit the text, select the new texts and are undone in one step):
- Selection - Rotate Texts Forward / Rotate Texts Backward:
[a] [b] [c] -> [c] [a] [b] / [b] [c] [a]. Empty selections take part as empty texts.
- Selection - Swap Two Selections: Exactly two selections:
[foo] = [bar] -> [bar] = [foo].
- Selection - Copy First Selection to All:
[x] [a] [b] -> [x] [x] [x].
- Information:
- Selection - Show Selection Info: Shows the number of selections and the start line and number of characters of each in a notification:
[ab]⏎⏎[c] -> 2 selections: L1 (2), L3 (1). At most 50 selections are listed (… (+M more)).
Limitations of the Multi Cursor commands
- Regular expressions: Keep / Remove Selections Matching Regex and Split Selections by Regex run the pattern in a worker thread and stop it after 2 seconds (for patterns with catastrophic backtracking); the pattern is up to 500 characters and the selections up to 10,000,000 characters in total. If the document is edited while the pattern is running, nothing is changed and a warning is shown.
- Number of selections: A command never makes more than 100,000 selections; a run that would make more changes nothing and shows a warning. VS Code itself keeps at most
editor.multiCursorLimit selections (10,000 by default), so with the default setting a result of 10,001 to 100,000 selections is cut down to that limit by VS Code (which shows its own message); raise the setting to keep them all.
- Merged selections: VS Code merges selections that overlap (for example, when Expand to Word expands two cursors in the same word), so the result can have fewer selections than expected.
- Expand to Inside Brackets: Brackets are matched by type without parsing the language, so brackets inside strings and comments are counted too. Only brackets within 1,000,000 characters before and after each selection are used. The brackets of the document are indexed once per run, so many cursors (for example after Select All Occurrences) do not make it slow.
- Expand to Inside Quotes / Select All Quoted Strings: The quotes are paired without parsing the language (an apostrophe in a word such as
it's starts a string).
- Select Column N: Quoted CSV fields are not parsed (a delimiter inside quotes still separates columns).
- Align Cursors: Full-width characters count as one column.
18. Markdown
Twenty-five Markdown: … commands (headings, lists and tasks, emphasis, code fences, quotes, images and links, tables, conversion to HTML and plain text, footnotes, reference links, details blocks and front matter) are added to the existing Markdown submenu of the Transform context submenu (after the existing Markdown Link command) and to the Command Palette. They run entirely in the extension: no network access, no files, no new dependencies (Front Matter to JSON uses js-yaml, which the YAML commands already use), and Convert to HTML is the extension's own subset implementation. The existing Markdown Link, CSV <-> Markdown Table, Enclose: Backtick Code (Auto Fence) and Escape Markdown Special Characters commands are unchanged.
In the examples, · is a space, ⏎ is a line break, […] is a selection, | is a cursor (an empty selection), and a value in parentheses is the value you enter.
- Common rules:
- Selections: Each selection is converted on its own (multiple cursors), in document order, and all changes are one undo step; afterwards each changed selection selects its new text. Empty selections are ignored by every command except Generate Table of Contents, so with only cursors nothing happens (and no input box is shown). A selection whose text would not change is not edited.
- Lines: LF, CRLF and CR line breaks are read, and every line break a command writes is the document's (LF or CRLF). The line commands do not count one line break at the end of a selection as a line and keep it. The heading and list commands (Increase / Decrease Heading Level, Generate Table of Contents, Renumber Ordered List, Convert Setext Headings to ATX, Strip Formatting, Heading to Anchor Link) leave the lines of fenced code blocks alone.
- Blocks on lines of their own: What Generate Table of Contents, Wrap in Code Fence, Wrap in Details Block and Inline Links to Reference Links write as a block never shares a line with other text, even when the selection starts or ends in the middle of a line: a line break is added before / after the block (and the spaces and tabs where the line is split are dropped):
say·[a=1]·now (js) -> say⏎```js⏎a=1⏎```⏎now. A cursor in the spaces after the selection keeps the spaces after it on the next line only when they are up to 3 columns; 4 columns or more, which would make the next line an indented code block, are dropped too, and the cursor moves to the start of the next line: [a]·|····b (empty language) -> ```⏎a⏎```⏎|b (the same for Wrap in Details Block and GitHub Alert Block). Generate Table of Contents does the same with a selection of nothing but spaces and tabs (without a heading) in those spaces, which becomes a cursor at the start of the next line: [#·A⏎foo][··]····bar -> -·[A](#a)⏎⏎|bar; up to 3 columns from it stay, a cursor there inserts a table of contents of its own and takes the spaces after it, and such a selection on a heading line also gets a table of contents of its own. The table of contents and the details block are also separated from the text after them (on the same line or on the next line) by a blank line, as the next line would otherwise become part of the list or the HTML block: [foo]⏎bar (S) -> <details><summary>S</summary>⏎⏎foo⏎⏎</details>⏎⏎bar; the table of contents also gets a blank line before it when text comes right before it. Only the indentation before a selection at the start of a line is kept as it is (no line break is added), except that Generate Table of Contents, Wrap in Code Fence and Wrap in Details Block drop indentation of 4 columns or more (a tab counts to the next multiple of 4), which would make the first line of the block (the list, the opening fence or <details>) an indented code block (Wrap in Code Fence and Wrap in Details Block also do this with shorter indentation that a later selected line does not start with, and keep the relative indentation of the lines in the block; see below): para⏎⏎····[foo] (S) -> para⏎⏎<details><summary>S</summary>⏎⏎foo⏎⏎</details>. The definitions of Inline Links to Reference Links always start at the start of a line, and the line break at the end of the document stays. The tables of contents that several cursors insert on the same line (or on nearby lines with nothing but spaces between them) are separated by a blank line, and the indentation before each one after the first is dropped, so that they never run together into one list or nest in each other: #·A⏎⏎···· with a cursor before and after the spaces -> #·A⏎⏎-·[A](#a)⏎⏎-·[A](#a). A selection of nothing but spaces, tabs and line breaks between (or before) them is treated as if it were not there, so this holds with it too.
- Input: A command that asks for a value asks once for all selections and does nothing if you cancel. The language of a code fence may be empty or up to 50 letters, digits and
_ + # . -; the alt text of an image and the summary of a details block are one line of up to 1,000 characters.
- Errors and size: If any selection cannot be converted, nothing is changed and a warning says why (
The text was not changed: …); YAML errors give the line and column but never quote the selected text. A run whose results would be longer than 10,000,000 characters in total is refused the same way.
- Menus: Generate Table of Contents is in the Command Palette also with only a cursor; the other commands appear there only when text is selected. Like every command of the extension, the context menu is shown only when text is selected.
- Headings:
- Markdown: Increase Heading Level / Decrease Heading Level: One
# more / less on every heading line: #·a⏎##·b -> ##·a⏎###·b. Increase turns a line that is not a heading into a level-1 heading and leaves ###### as it is; Decrease turns a level-1 heading into its text.
- Markdown: Generate Table of Contents: Has two modes:
- Selection: The selection is replaced with the table of contents of the headings in it:
#·A⏎##·B·C -> -·[A](#a)⏎··-·[B·C](#b-c). A selection without headings is left as it is.
- Cursor: The table of contents of the whole document is inserted at the cursor (with several cursors, at each of them).
- The anchors are GitHub-style slugs; repeated headings are numbered over the whole document (
#a, #a-1), also when only some of them are selected. An entry is nested one level (2 spaces) under the nearest earlier heading of a lower level, however many levels are skipped (#·A⏎####·D -> -·[A](#a)⏎··-·[D](#d)). If there are no headings, No headings were found. is shown. When the selection (or the cursor) reaches the end of a document that ends with a line break, that line break is kept after the table of contents.
- Markdown: Convert Setext Headings to ATX: A paragraph underlined with
=== becomes #·…, with --- ##·… (the lines of a multi-line paragraph are joined with a space): Title⏎=====⏎Sub⏎--- -> #·Title⏎##·Sub. A --- without a paragraph above it is a thematic break and stays.
- Markdown: Heading to Anchor Link: Every heading (or other non-blank) line becomes a link to its GitHub-style anchor:
##·Hello·World! -> [Hello·World!](#hello-world). [ and ] in the text are escaped with a backslash, and the slug is made from the text without its inline markup.
- Lists and tasks:
- Markdown: Convert Lines to Bullet List / Numbered List / Task List:
a⏎b -> -·a⏎-·b / 1.·a⏎2.·b / -·[·]·a⏎-·[·]·b. Blank lines are skipped (and not numbered), an existing list marker is replaced, and an existing checkbox keeps its state.
- Markdown: Toggle Task Checkbox:
[·] <-> [x] ([X] counts as done): -·[·]·a -> -·[x]·a. Other lines stay.
- Markdown: Remove List Markers: Removes bullets, numbers and checkboxes (the indentation stays):
-·[·]·a⏎2.·b -> a⏎b.
- Markdown: Renumber Ordered List: Numbers the ordered items from 1 again, for each nesting level:
1.·a⏎5.·b⏎2.·c -> 1.·a⏎2.·b⏎3.·c. A shallower item ends the deeper levels, and a line without indentation that is not a list item ends every list; blank lines end nothing.
- Markdown: Blockquote:
>· before every line (> on a blank line): a⏎b -> >·a⏎>·b.
- Inline formatting:
- Markdown: Bold / Italic / Strikethrough:
abc -> **abc** / _abc_ / ~~abc~~. Spaces at both ends of the selection stay outside the markers (·abc· -> ·**abc**·), as CommonMark does not emphasize text that starts or ends with a space; a selection of only spaces is left.
- Markdown: Wrap in Code Fence: Asks for the language (optional) and wraps the selection in a code fence:
a·=·1 (python) -> ```python⏎a·=·1⏎```. The fence is longer than any run of backticks in the selection. When only indentation comes before the selection on its line, the lines in the block keep their indentation relative to each other: indentation of up to 3 columns that every later line with text also starts with stays before both fences and the first line in the block (··[a⏎··b] -> ··```⏎··a⏎··b⏎··```, which also keeps the block inside a list item); otherwise (4 columns or more, or a later line without that indentation) the fences start the line and the indentation all lines share, counting the first line with the indentation before it, is removed, but no more than the indentation before the selection (····[a⏎······b] -> ```⏎a⏎··b⏎```).
- Markdown: Image: Asks for the alt text and turns the selected URL into an image:
https://example.com/a.png (alt) -> . \, [ and ] in the alt text are escaped, and a URL with spaces or unbalanced parentheses is written as <url>.
- Markdown: Linkify URLs: Every bare
http:// / https:// URL becomes an autolink: see·https://example.com. -> see·<https://example.com>. (without trailing punctuation and closing brackets that have no opening bracket, like Select All URLs). URLs in code, <…>, links, images and reference definitions are left.
- Markdown: Wrap in Details Block: Asks for the summary (empty:
Details; it is HTML-escaped) and wraps the selection in a collapsible block: 長い本文 (詳細) -> <details><summary>詳細</summary>⏎⏎長い本文⏎⏎</details>. When only indentation comes before the selection on its line, the lines in the block keep their indentation relative to each other as with Wrap in Code Fence: indentation of up to 3 columns that every later line with text also starts with stays before <details>, the first line in the block and </details> (··[a⏎····b] (S) -> ··<details><summary>S</summary>⏎⏎··a⏎····b⏎⏎··</details>); otherwise the tags start the line and the shared indentation is removed, but no more than the indentation before the selection.
- Tables:
- Markdown: Format Table: Pads every cell to the width of its column and rewrites the delimiter row, keeping the alignments:
|a|bb|⏎|-|-|⏎|ccc|d| -> |·a···|·bb·|⏎|·---·|·--·|⏎|·ccc·|·d··|. Missing cells become empty cells, and | in code spans or after a backslash does not split a cell. The selection must be a table (every line with a |, the second line a delimiter row).
- Conversion:
- Markdown: Convert to HTML:
#·a⏎**b** -> <h1>a</h1>⏎<p><strong>b</strong></p>. This is the extension's own subset of CommonMark, with no new dependency:
- Supported: ATX headings (
#), paragraphs, bold / italic / strikethrough (~~), inline code, fenced code blocks (the language as class="language-…"), bullet and ordered lists (nested by indentation, with start when the first number is not 1, tight and loose lists), block quotes, links, images, <https://…> autolinks, thematic breaks and backslash escapes.
- Not supported (written as paragraph text): setext headings, tables, reference links, footnotes, indented code blocks and HTML entities; task checkboxes stay text.
- Safety: All text is HTML-escaped, and raw HTML is escaped, never passed through (
<b>x</b> -> <b>x</b>). Links and images with a javascript:, vbscript:, data: or file: URL get # instead ([a](https://github.com/imahiro-t/selection-manipulator/blob/HEAD/javascript:…) -> <a href="#">a</a>).
- Markdown: Strip Formatting: Removes the Markdown markup:
#·A·**b**·[c](https://github.com/imahiro-t/selection-manipulator/blob/HEAD/d) -> A·b·c. Heading, quote and list markers, checkboxes, thematic breaks, setext underlines and fence lines are removed, links become their text and images their alt text, and backslash escapes are resolved; the lines of fenced code blocks are kept.
- Markdown: Front Matter to JSON: The front matter at the start of the selection (from a
--- line to the next --- or ... line) is replaced with one line of JSON: ---⏎title:·a⏎--- -> {"title":"a"}; the text after it stays. Unlike Convert YAML to JSON, which writes JSON indented with 2 spaces, the JSON is written without spaces. The YAML is read with js-yaml's YAML 1.2 Core schema: no code is run, !!js/function and other unknown tags are an error, and anchors and aliases that would make the JSON too large are refused like in Format YAML.
- Footnotes and reference links (these look at the whole document):
- Markdown: Convert to Footnote: Every selection becomes
[^n], and [^n]:·text is added at the end of the document after a blank line: 本文[補足] -> 本文[^1]⏎⏎[^1]:·補足. The numbers continue from the largest numbered footnote in the document; afterwards the new [^n] is selected.
- Markdown: Inline Links to Reference Links: The inline links of the selection become reference links, and the definitions are added after a blank line:
[a](https://x.example) -> [a][1]⏎⏎[1]:·https://x.example. The same URL and title get the same number (also across selections), and the numbers continue from the largest numbered definition in the document. When the selection ends in the middle of a line, the definitions go after the end of that line (see·[[a](http://b)]·here -> see·[a][1]·here⏎⏎[1]:·http://b) and only the converted links are selected afterwards. Images, links in images and links in code are left.
Limitations of the Markdown commands
- Convert to HTML: The subset is not fully CommonMark-compliant.
_ does not emphasize inside a word, emphasis does not continue over a blank line, --- right after a paragraph stays paragraph text (setext headings are not supported), an image inside the text of another image is not made, and block quotes and lists are nested at most 32 levels deep (deeper content is paragraph text). The same inline rules apply to Strip Formatting and to the slugs.
- Generate Table of Contents: Only ATX headings (
#) are used; setext headings are not in the table of contents and are not counted when repeated headings are numbered (convert them with Convert Setext Headings to ATX first). The slugs follow the main rules of GitHub (lower case, punctuation removed, spaces to -, -1, -2 … for repeated headings), not every detail of every renderer.
- Format Table: Column widths are counted in code points, so full-width characters count as one column.
- Wrap in Code Fence inside a list item: When only part of a list item's line is selected, the fence is written on lines without the item's indentation, so it ends the list instead of staying in the item (
-·item·[a=1] -> -·item⏎```js⏎a=1⏎```…). Select whole lines inside list items.
- Inline Links to Reference Links inside list items and block quotes: When the selection ends in the middle of a line in a list item or a block quote, the definitions are added after that line without the list indentation or
>, so the list or quote ends there (the links still work). Select up to the end of the item or quote to keep it together.
- Blank lines: Wrapping two selections on the same line with Wrap in Code Fence or Wrap in Details Block can leave two blank lines between the blocks; this does not change how the Markdown is rendered.
19. Text Transform
Twenty-three Text - … commands (repeat, truncate, pad, group, tr-like character sets, digits and punctuation, words and characters, frequency tables, URL removal, masking, Leetspeak and removing text between delimiters) are added to a new Text Transform context submenu (after the Multi Cursor submenu in the Selection Manipulator menu) and to the Command Palette (when there is a selection). They run entirely in the extension: no network access (Remove URLs never opens a URL), no files, no processes, no new dependencies, and no regular expression is ever built from what you enter. The existing text commands (Mask with Asterisk, Zero Padding, Generate - Repeat Character to Width, Extract URL and others) are unchanged.
In the examples, · is a space, ⇥ is a tab, ⏎ is a line break, and a value in parentheses is the value you enter.
- Common rules:
- Characters: "One character" is one grapheme cluster (what you see as one character: an emoji ZWJ sequence or a letter with combining marks counts as one), except for Translate / Delete / Squeeze Characters and Leetspeak, which work on code points.
- Selections: Every non-empty selection is used, in document order; with only cursors, the warning
Select the text to transform. is shown and no input box is opened. A selection of only spaces is used too (it can be padded, for example). The commands that replace the text convert each selection on its own and change all of them in one edit (one undo step); a selection whose text would not change is not edited.
- Input: A command that asks for values asks once for all selections and does nothing if you cancel. Numbers are whole numbers (digits only) in the range shown in the input box; separators, character sets and delimiters are one line of 1 to 100 characters (the separator of Repeat and the set of Squeeze may be empty); the pad character is exactly one character. A value out of range is shown as an error in the input box. The selections are read again after the input box closes.
- Limits and errors: The selections may be at most 1,000,000 characters in total, and a run whose results would be longer than 10,000,000 characters in total is refused; Repeat, Pad Start / End and Insert Separator Every N compute the length of their result before building it. If any selection fails, nothing is changed and no editor is opened, and a warning says why (
The selection was not changed: … or No result was shown: …, with selection 2 of 3: when there are several selections). Messages and logs never quote the selected text or the values you enter.
- Length and padding:
- Text - Repeat Selection N Times: Asks for N (1 to 10,000) and a separator (may be empty):
ab (3, -) -> ab-ab-ab. Generate - Repeat Character to Width fills a width with one character instead.
- Text - Truncate to N Characters: Asks for N (1 to 1,000,000); a longer selection keeps its first N − 1 characters followed by
… (N characters with the ellipsis): Hello·World (8) -> Hello·W…. A selection of N characters or fewer is not changed.
- Text - Shorten in the Middle: Asks for N (1 to 1,000,000) and replaces the middle with
…, keeping ceil((N − 1) / 2) characters at the start and floor((N − 1) / 2) at the end: very-long-file-name.txt (15) -> very-lo…ame.txt.
- Text - Pad Start to Width (Custom Character) / Pad End to Width (Custom Character): Ask for a width (1 to 10,000) and one character, and add the character before / after the whole selection until it is that wide:
42 (6, *) -> ****42, abc (6, .) -> abc.... A selection that is already as wide is not changed. Zero Padding always pads with 0.
- Text - Insert Separator Every N Characters: Asks for N (1 to 10,000) and a separator, inserted after every N characters but not after the last group:
1234567890 (4, -) -> 1234-5678-90.
- Character sets (plain characters, never ranges or regular expressions):
- Text - Translate Characters (tr): Asks for the characters to replace and their replacements, and replaces each character with the one at the same position, like
tr: hello (el, ip) -> hippo. Both sets must have the same number of characters, and a character may appear only once in the first set (the input box says so). Characters are compared exactly, so é does not match e.
- Text - Delete Characters in Set: Deletes every character of the set:
a-b_c (-_) -> abc.
- Text - Squeeze Repeated Characters: Squeezes runs of the same character to one, like
tr -s, for the characters of the set, or for every character when the set is empty: a---b--c (-) -> a-b-c, aaa··bb (empty) -> a·b.
- Digits and punctuation:
- Text - Remove Digits: Removes every decimal digit (Unicode
Nd, full-width and other scripts' digits too): abc123def -> abcdef.
- Text - Remove Punctuation: Removes punctuation (Unicode category
P: , . ! ? - ( " 、 。 …): Hello,·world! -> Hello·world. Symbols (category S, such as $ + = <) are kept.
- Text - Keep Digits Only: Keeps only the decimal digits and removes everything else, line breaks too:
TEL:·03-1234-5678 -> 0312345678.
- Words and characters (a word is a run of characters other than spaces, tabs and line breaks; sorting compares code points and does not depend on the locale):
- Text - Reverse Each Word: Reverses the characters of every word and keeps the spaces and line breaks where they are:
ab··cd⏎ef -> ba··dc⏎fe.
- Text - Sort Words in Selection: Sorts the words and joins them with one space, so a selection of several lines becomes one line:
pear·apple·fig -> apple·fig·pear.
- Text - Remove Duplicate Words: Keeps the first of each word (case-sensitive) and joins them with one space:
a·b·a·c·b -> a·b·c. A selection without words is not changed (also by Sort Words).
- Text - Sort Characters:
banana -> aaabnn.
- Text - Remove Duplicate Characters: Keeps the first of each character:
banana -> ban.
- Frequency tables (open one new editor for all selections together and never change the text; the lines are joined with the document's line ending):
- Text - Word Frequency Table:
word⇥count lines, the most frequent first (equal counts in the order the words first appear): b·a·b·a·c -> b⇥2⏎a⇥2⏎c⇥1. Without words, No words were found in the selection. is shown instead.
- Text - Character Frequency Table:
character⇥count lines in the same order: banana -> a⇥3⏎n⇥2⏎b⇥1. Spaces, tabs, line breaks and other invisible characters are written as code points, so they cannot break the table: a·b⇥b -> b⇥2⏎a⇥1⏎U+0020⇥1⏎U+0009⇥1 (a CRLF line break is U+000D·U+000A).
- Other:
- Text - Remove URLs: Removes the URLs and leaves one space between the words around each of them (no space at the start or end of a line):
see·https://a.example/x·now -> see·now. All white space around a URL counts, also the ideographic space (U+3000) and the no-break space (U+00A0), but line breaks are kept: x·https://a.example/ y -> x·y. Nothing is accessed. A URL starts with http:// or https:// in lower case, like Extract URL (HTTPS://…, ftp://… and www.… are not URLs here).
- Where a URL ends: before the first of these:
- a space, tab, line break or other whitespace;
- full-width punctuation (
。 、 , . ! ? : ; 。 、): 詳細は·https://example.com。続き -> 詳細は。続き;
- a closing bracket that the URL does not open, ASCII (
) ] } >) or full-width and quotation () ] } > 〉 》 」 』 】 〕 〗 〙 〛 ” ’), even without a space after it, so the text after it stays: foo(https://x.com)bar -> foo()bar, 「https://a.example」を参照 -> 「」を参照 (a bracket that the URL opens is part of it: see·https://en.wikipedia.org/wiki/Foo_(bar)·now -> see·now).
- Then:
- Punctuation at the end of a URL (
. , ; : ! ? ' ") is not part of it. The punctuation and closing brackets right after a URL are kept and joined to the word before it: Visit·https://example.com. -> Visit., (see·https://a.com)·ok -> (see)·ok. The spaces after them become one space (none at the end of a line, and none when a word follows without a space): a···https://x.example.··b -> a.·b.
- At the start of a line there is no word to join to, so the sentence punctuation right after the URL (
. , ; : ! ? and the full-width punctuation) is removed too, with the spaces after it; brackets and quotation marks stay: https://x.·Next -> Next, https://x.)·y -> )·y.
- A line that has only a URL becomes an empty line:
a⏎https://x.com⏎b -> a⏎⏎b.
- Text - Mask Except Last N Characters: Asks for N (0 to 1,000,000) and replaces every character but the last N with
*; line breaks stay and are not counted (spaces are masked): 4111111111111111 (4) -> ************1111, 1234⏎5678 (3) -> ****⏎*678. The original text is never shown or logged. Text: Mask with Asterisk (*) masks everything.
- Text - Leetspeak: A fixed table, a→4, e→3, i→1, o→0, s→5, t→7 (upper case too):
leet·speak -> l337·5p34k.
- Text - Remove Text Between Delimiters: Asks for a start and an end delimiter (plain text;
( and ) by default) and removes each start delimiter, the next end delimiter after it and the text between them, from left to right (no nesting): a·(note)·b -> a··b, a·(x·(y)·z)·b -> a··z)·b. A start delimiter without an end delimiter after it is kept.
20. Line & Selection (Extended)
Twenty-three more line and selection commands: fourteen Line: … commands (keep a range of lines, remove the first / last N lines, insert a blank line every N lines, cut characters, paste selections side by side, remove duplicates keeping the last, split by a regex, join as a natural-language list, line set operations on two selections, number non-blank lines and arrange lines into columns) are added to the existing Line submenu, and nine Selection - … commands (select all email addresses / IP addresses / hex colors / UUIDs / ISO dates, expand to the sentence or paragraph, keep only duplicate texts and join all selections into the first) are added to the existing Multi Cursor submenu; all of them are also in the Command Palette. They run entirely in the extension: no network access, no files, no processes, no new dependencies, and the IP addresses are checked without the net module. The existing commands (Line: Keep First / Last N Lines, Line: Add Line Numbers, Extract Email, Extract IP, Selection - Expand to Word and the others) are unchanged.
In the examples, […] is a selection, | is a cursor (an empty selection), · is a space, ⇥ is a tab, ⏎ is a line break, and a value in parentheses is the value you enter.
- Common rules:
- Blank lines: A "blank line" is the same for Add Numbers to Non-blank Lines, Join as Natural Language List, Expand to Sentence and Expand to Paragraph: an empty line, or a line of only white space other than line breaks, such as spaces, tabs, the full-width space (U+3000) or the no-break space (U+00A0). A line of only U+FEFF (BOM) or U+200B (zero-width space) is not blank.
- Line commands: They follow the rules of the line commands: one line break at the end of a selection is not a line and is kept, lines are joined with the document's line ending (LF or CRLF), every non-empty selection is converted on its own in one edit (one undo step), a value is asked once for all selections (and the selections are read again after the input box closes), and if any selection fails nothing is changed. Empty selections are ignored.
- Partial lines: Keep Lines N to M, Remove First / Last N Lines, Insert Blank Line Every N Lines, Remove Duplicate Lines (Keep Last) and Add Numbers to Non-blank Lines leave a partial first or last line of the selection unchanged, like Keep First / Last N Lines; Cut Character Range, Split into Lines by Regex, Join as Natural Language List and Arrange Lines into N Columns treat it as a line.
- Input: Line numbers, positions and N are whole numbers from 1 to 1,000,000 (the number of columns is 1 to 100); a value out of range is shown as an error in the input box. Cancelling an input box changes nothing.
- Two selections: Paste Selections Side by Side needs at least two non-empty selections, and the three set operations exactly two; cursors are not counted and stay as they are. With too few (or too many) selections, a warning is shown before any input box (
Select at least 2 … / Select exactly 2 …). The result replaces the first selection (in document order) and the other selections are not changed; it ends with a line break only when the first selection does.
- Where select-* looks: The five Select All … commands search inside the non-empty selections and ignore the cursors that are there too; only when every selection is empty (only cursors) do they search the whole document. A match must lie inside one selection. When nothing is found, a warning is shown (
No … were found in the selections. / … in the document.) and the selections do not change. The patterns are fixed and run in linear time.
- Limits: A run whose results would add more than 10,000,000 characters (counted over all selections) is refused; the commands whose result can be longer (Insert Blank Line Every N Lines, Paste Selections Side by Side, Split into Lines by Regex, Add Numbers to Non-blank Lines, Arrange Lines into N Columns) count the added characters before building the result. Join All Selections into First refuses a result longer than 10,000,000 characters. A command never makes more than 100,000 selections (see the Multi Cursor limitations).
- Menus: In the Command Palette, the Line commands appear when text is selected, the Select All … and Expand to … commands always (they also work with only a cursor), and Keep Only Duplicate Texts and Join All Selections into First only with multiple selections. In the context menu they are in the Line and Multi Cursor submenus.
- Choosing lines:
- Line: Keep Lines N to M: Asks for
N-M and keeps lines N to M of each selection, like sed -n 'N,Mp': 1⏎2⏎3⏎4⏎5 (2-3) -> 2⏎3. Lines after the end of the selection are ignored, so a range after the last line leaves nothing.
- Line: Remove First N Lines / Remove Last N Lines: N is 1 by default:
a⏎b⏎c (N=1) -> b⏎c / a⏎b. N at or above the number of lines leaves nothing. (Line: Keep Last N Lines keeps N lines instead.)
- Line: Remove Duplicate Lines (Keep Last): Keeps the last occurrence of each line, and the kept lines stay in their order:
a⏎b⏎a -> b⏎a. The other duplicate removals keep the first occurrence.
- Changing lines:
- Line: Insert Blank Line Every N Lines: N is 2 by default; no blank line is added after the last line:
1⏎2⏎3⏎4⏎5⏎6 (N=2) -> 1⏎2⏎⏎3⏎4⏎⏎5⏎6. It does not look at whether a line is blank, unlike Whitespace: Insert Blank Line Between Lines, which adds one only between two adjacent non-blank lines: a⏎⏎b (N=1) -> a⏎⏎⏎⏎b, which Insert Blank Line Between Lines leaves unchanged.
- Line: Cut Character Range of Each Line: Asks for
M-N or a single position N and keeps the Mth to Nth characters of every line, like cut -c: abcdefgh (3-5) -> cde. Characters are grapheme clusters (an emoji sequence or a letter with combining marks counts as one). A shorter line keeps what it has, possibly nothing.
- Line: Add Numbers to Non-blank Lines: Numbers only the non-blank lines as number, one space, line (
1 a, no colon and no padding, unlike Line: Add Line Numbers, which writes 1: a): a⏎⏎b -> 1 a⏎⏎2 b. Blank lines keep their content and do not use up a number. Unlike nl -b t, a line of only spaces, tabs or other white space is blank too and gets no number.
- Line: Arrange Lines into N Columns: Asks for N (1 to 100, default 2) and arranges the lines down N columns, filled column by column (ceil(lines / N) rows), like
column -c; each column is as wide as its widest line, two spaces separate the columns, and trailing spaces are removed: a⏎b⏎c⏎d (N=2) -> a··c⏎b··d. Widths are counted in code points, so a full-width character counts as one column.
- Splitting and joining:
- Line: Split into Lines by Regex: Asks for a regular expression (JavaScript syntax with the
u flag, case-sensitive, 1 to 500 characters) and replaces every match with a line break: a1b22c (\d+) -> a⏎b⏎c. Text - Split Lines (Custom Delimiter) splits at literal text. Against ReDoS, the pattern runs in a worker thread and is stopped after 2 seconds, the selections are limited to 10,000,000 characters in total, and more than 1,000,000 matches stop the command; if the document is edited while the pattern runs, nothing is changed. In all these cases a warning is shown.
- Line: Join as Natural Language List: Asks for a locale (
en by default) and joins the lines with Intl.ListFormat (a conjunction): a⏎b⏎c (en) -> a, b, and c, (ja) -> a、b、c. Blank lines are left out. An empty locale (or only spaces) and a locale that is not supported are rejected in the input box; the exact punctuation depends on the Node.js / ICU version of VS Code.
- Two selections (see the common rules):
- Line: Paste Selections Side by Side: Asks for a delimiter (literal text, up to 100 characters; empty uses a tab) and joins line i of every selection, like
paste: [a⏎b] [1⏎2] (empty) -> [a⇥1⏎b⇥2] [1⏎2]. A selection with fewer lines adds empty strings.
- Line: Lines Common to Two Selections:
[a⏎b⏎c] [b⏎c⏎d] -> [b⏎c] [b⏎c⏎d].
- Line: Lines Only in First Selection:
[a⏎b⏎c] [b] -> [a⏎c] [b].
- Line: Lines in Only One Selection: The lines only in the first selection, then the lines only in the second:
[a⏎b] [b⏎c] -> [a⏎c] [b⏎c].
- The set operations compare whole lines exactly (case-sensitive), write each line once and keep the order of the first selection.
- Selecting (see "Where select-* looks" above):
- Selection - Select All Email Addresses:
a·x@y.jp·b -> a·[x@y.jp]·b. It finds the same addresses as the pattern of Extract Email, but with a scanner that runs in linear time.
- Selection - Select All IP Addresses: Selects IPv4 addresses (each number 0 to 255) and IPv6 addresses (
:: and an embedded IPv4 address are allowed; zone IDs such as %eth0 are not): host·10.0.0.1·ok -> host·[10.0.0.1]·ok, a·2001:db8::1·b -> a·[2001:db8::1]·b. Trailing dots are not selected (ping·10.0.0.1. -> ping·[10.0.0.1].), an IPv4 address inside an IPv6 address is not selected separately (::ffff:192.0.2.1 is one selection), and an address after : is found (host:10.0.0.1, addr:fe80::1). Like Extract IP, IPv4 takes the first four numbers of a longer run of dotted numbers (1.2.3.4.5 -> [1.2.3.4].5).
- Selection - Select All Hex Colors:
#rgb, #rrggbb and #rrggbbaa not followed by a letter or digit: color:#fff;bg:#112233 -> color:[#fff];bg:[#112233] (#12345 and #fffg are not colors).
- Selection - Select All UUIDs: 8-4-4-4-12 hex digits not touching a letter or digit:
id=550e8400-e29b-41d4-a716-446655440000 -> id=[550e8400-e29b-41d4-a716-446655440000].
- Selection - Select All ISO Dates:
YYYY-MM-DD, optionally followed by T or a space, HH:MM, optional seconds with a fraction of any length, and a time zone (Z, +09:00 or +0900): from·2026-10-01·to·2026-10-31 -> from·[2026-10-01]·to·[2026-10-31], at·2026-10-01T12:34:56.789+09:00 -> the whole timestamp. Months and days are checked, leap years included (2024-02-29 yes, 2025-02-29 and 1900-02-29 no). When the time is not valid, only the date is selected after a space (2026-10-01·25:00 -> [2026-10-01]·25:00) and nothing after T.
- Expanding (both commands use the same paragraph boundary: a blank line as defined above):
- Selection - Expand to Sentence: Expands a cursor to its sentence, and the start / end of a selection to the start / end of its sentence:
Hi.·This·is|·a·pen.·Bye. -> Hi.·[This·is·a·pen.]·Bye.. A sentence ends at ., ! or ? followed by a space or a line break, or at 。, ! or ? (1.2 is not an end). Blank lines end a paragraph and stop the search. The spaces around a sentence are not selected; a cursor in the space between two sentences goes to the next one.
- Selection - Expand to Paragraph: Expands a cursor to its paragraph (from the start of its first line to the end of its last line), and the start / end of a selection to the start / end of its paragraph:
p1⏎⏎a|b⏎cd⏎⏎p3 -> p1⏎⏎[ab⏎cd]⏎⏎p3. Blank lines separate paragraphs.
- For both, a selection over several sentences / paragraphs covers all of them, an end of a selection on a blank line does not move (and a cursor on a blank line stays), and results that overlap are merged into one selection.
- Changing the selections:
- Selection - Keep Only Duplicate Texts: Keeps the selections whose text (case-sensitive) appears in two or more selections, the reverse of Selection - Deselect Duplicate Texts:
[a] [b] [a] -> [a] b [a]. When no two selections have the same text, only a notification is shown.
- Selection - Join All Selections into First: Asks for a delimiter (literal text,
, by default, up to 100 characters, no line breaks; it may be empty), writes the texts of all selections (document order, cursors as empty texts) joined with it into the first selection and deletes the texts of the other selections, in one edit (one undo step): [a]·[b]·[c] (default) -> [a,·b,·c]··, (empty) -> [abc]·· (the spaces that were between the selections stay). Afterwards the joined text is the only selection.
Limitations of the extended line and selection commands
- Sentences: Expand to Sentence does not know abbreviations, so
Mr. or e.g. followed by a space ends a sentence.
- ISO dates: When the fraction of a second is followed by a letter (
2026-10-01T12:34:56.123abc), only up to the seconds is selected (2026-10-01T12:34:56).
- Arrange Lines into N Columns: The output size is estimated before trailing spaces are removed, so a result very close to the limit can be refused although it would fit.
- Join as Natural Language List:
Intl.ListFormat can give slightly different punctuation in other VS Code (Node.js / ICU) versions.
21. Encoding, Escaping & Hashes (Extended)
Twenty-two more encoding, escaping, hash and checksum commands: nine encoders and decoders (Base32hex, Base45, Base62, uuencode and percent-encoding of every byte) are added to the existing Encode / Decode submenu, six escaping commands (CSS identifier, LDAP filter value, LDAP DN value, XPath string literal, C string literal and C / Java unescaping) to the existing Programmatic submenu, three hashes (SHA3-384, SHAKE256, HMAC-SHA3-512) to the existing Crypto submenu and four checksums and validations (CRC-16, CRC-32C, IBAN, ISBN) to the existing Checksum submenu, all under Transform; all of them are also in the Command Palette when text is selected. They run entirely in the extension: no network access (the LDAP and XPath commands only write text and never connect to or evaluate anything), no files (uuencode never reads or writes a file), no processes, no code evaluation and no new dependencies. The existing commands (Encode Base32, Encode Base58, Encode URI Component, Unescape, Convert to Java String Concatenation, Checksum: CRC-32 and the others) are unchanged.
In the examples, · is a space, ⏎ is a line break, a value in parentheses is the value you enter, and a long result is shortened with ….
- Common rules:
- Results: The commands never change the selected text. The encoders, decoders and escaping commands open the results in a new read-only editor (several selections: one editor, the results in document order joined with the document's line ending). The hash and checksum commands open a new read-only editor with the selected text (trimmed) as a heading followed by its result, like the existing Create Hash commands; the text is hashed exactly as it is selected (UTF-8 bytes, not trimmed). IBAN and ISBN Validate only show a notification.
- Selections and input: Empty selections are skipped, and with only cursors nothing happens (no input box is opened). A command that needs a value (the uuencode file name, the SHAKE256 length, the HMAC key) asks once for all selections and does nothing if you cancel; the selections are read again after the input box closes.
- Errors and limits: Text is read as UTF-8 bytes (a lone surrogate is an error), and decoded bytes that are not valid UTF-8 are an error instead of
�. If any selection fails, no editor is opened and an error says why (The selection was not changed: …, with selection 2 of 3: when there are several selections; a position is counted in the selection itself, from 1, spaces and line breaks included). A run whose results would exceed 10,000,000 characters in total (shared by all selections) is refused with a warning and nothing is opened; the length of each result is estimated before it is built. An unexpected failure is reported as the text could not be processed., and only the error name and stack frames are logged, never the selected text or the key.
- Encode / Decode (text is encoded as UTF-8 bytes):
- Encode Base32hex (RFC 4648 §7) / Decode Base32hex (RFC 4648 §7): The "extended hex" alphabet
0-9A-V with = padding (Encode Base32 uses A-Z2-7): foo <-> CPNMU===. The decoder ignores spaces, tabs and line breaks, accepts lower case and missing padding (cpnmu -> foo), and rejects other characters, wrong padding and non-zero unused bits.
- Encode Base45 (RFC 9285) / Decode Base45 (RFC 9285): The alphabet of QR code alphanumeric mode; every 2 bytes become 3 characters, a last single byte 2:
AB <-> BB8, Hello!! <-> %69·VD92EX0. The space is a Base45 character, so the decoder removes no space; it only removes the line breaks at the start and the end of the selection (a selected line with its line break works). A line break inside the selection (select one line per selection), a tab, a lower-case letter, a group above 65535 (a last pair above 255) and a length that leaves a remainder of 1 when divided by 3 are errors.
- Encode Base62 / Decode Base62:
0-9A-Za-z, the whole text as one big number, like Encode Base58: hi <-> 6x7. Each leading zero byte becomes one 0 (and back), so it survives a round trip: \0hi (a NUL and hi) <-> 06x7. The decoder ignores spaces, tabs and line breaks. As the conversion time grows with the square of the length, the encoder accepts at most 10,000 UTF-8 bytes and the decoder at most 13,500 characters (enough for any encoder output); a longer selection is refused before anything is computed.
- Encode uuencode: Asks for the file name of the
begin line (data by default; 1 to 64 ASCII letters, digits, ., _ and -, so no space, path separator or line break can get into the header) and writes begin·644·<name>, lines of 45 bytes (zero is written as a backquote), a backquote line and end, with the document's line ending: Cat (data) -> begin·644·data⏎#0V%T⏎`⏎end. The name is only written into the header; no file is created.
- Decode uuencode:
begin·644·data⏎#0V%T⏎`⏎end -> Cat. The begin and end lines may be left out or selected (their name and mode are never used and no file is created), and empty lines are ignored. Every data line must have exactly as many characters as its length character announces, so a data line whose trailing spaces were removed (by an editor or by e-mail), or an old format with an extra check character at the end of each line, is an error (line 2: the length character announces 3 bytes (4 characters), but the line has 3). Text after the end line and data after the terminating line are errors too.
- Encode All Characters as Percent-encoding: Every UTF-8 byte becomes
%XX (upper case), letters and digits included: a·b -> %61%20%62, あ -> %E3%81%82. Encode URI Component keeps the unreserved characters.
- Escaping (in the Programmatic submenu):
Escape CSS Identifier: The rules of CSS.escape (CSSOM): NUL becomes U+FFFD; control characters, a leading digit and a digit after a leading - become \<hex>·; a lone - becomes \-; other ASCII characters except letters, digits, - and _ get a backslash: 1foo·bar -> \31·foo\·bar, -1a -> -\31·a.
Escape LDAP Filter Value (RFC 4515): * ( ) \ and NUL become \2a \28 \29 \5c \00: a*b(c) -> a\2ab\28c\29.
Escape LDAP DN Value (RFC 4514): " + , ; < > \, a leading # or space and a trailing space get a backslash, and NUL becomes \00: Smith,·John -> Smith\,·John, #a· -> \#a\·.
Convert to XPath String Literal: An XPath 1.0 string literal: '…' when the text has no apostrophe, "…" when it has no quotation mark, otherwise concat() of the parts in apostrophes and the apostrophes in quotation marks: abc -> 'abc', It's -> "It's", It's·"x" -> concat('It',·"'",·'s·"x"').
Convert to C String Literal: One line in "…": \\ \" \n \r \t, and \xHH (lower case) for every UTF-8 byte of other control characters and non-ASCII characters: a"b⏎ -> "a\"b\n". A C compiler reads every hex digit after \x, so when a hex digit follows a \xHH, the literal is split with "" (adjacent literals are joined by the compiler): あa -> "\xe3\x81\x82""a". A ? right after a ? is written \?, so no trigraph (??= …) is left: ???= -> "?\?\?=". Convert to Java String Concatenation makes Java concatenations instead.
Unescape C / Java Style Escapes: Turns C / Java escapes back into characters with a hand-written scanner (no eval, no regular expression): a\x41\101 -> aAA. Unescape follows JSON.parse instead.
| Escape |
Meaning |
\a \b \f \n \r \t \v \\ \' \" \? |
The usual control characters and the character itself |
\o, \oo, \ooo |
Octal, greedy, at most 3 digits and at most \377 (\0 is the 1-digit case; \400 to \777 are errors) |
\x + hex digits |
Any number of hex digits, greedy as in C, at most \xff (\x100 is an error; \x041 is 0x41) |
\uXXXX / \UXXXXXXXX |
Exactly 4 / 8 hex digits; a high and a low surrogate in a row make one character, as in Java; at most U+10FFFF, no lone surrogate |
The \x and octal values are bytes, and the result is read as UTF-8: \xe3\x81\x82 -> あ (\xff alone is not valid UTF-8 and is an error). Any other character after a backslash (\q), a backslash at the end and a backslash before a line break (line continuation) are errors.
- Two modes: Only when the selection starts exactly with
" and ends with a " that is not escaped (2 or more characters), it is read as a sequence of C string literals: the bodies are unescaped and joined, like C's adjacent literal concatenation ("a"·"b" -> ab, "a\n"⏎"b" -> a⏎b, "\x4""1" -> 0x04 and 1). Only spaces, tabs and line breaks may be between the literals, a literal must not contain a raw line break, and every literal must be closed. Otherwise the whole selection is the body of one literal: an unescaped " and line breaks are kept as they are (say·"hi"! -> say·"hi"!).
- A selection that starts with
" in body text: Text such as "a"·and·"b" starts and ends with ", so it is read as literals and the text between them is an error (unexpected text between string literals at position 5). Text that starts with " but does not end with an unescaped " stays in body mode and keeps its quotation marks: "abc -> "abc, "a"·"b -> "a"·"b, "a\" -> "a".
- Whole lines: When you select a whole line with its line break, or with its indentation, the selection no longer starts or ends with
", so it is read in body mode and the quotation marks stay (··"a" -> ··"a", "a"⏎ -> "a"⏎). Select from the first " to the last " to read literals.
- Round trip: Unescape C / Java Style Escapes turns the output of Convert to C String Literal back into the original text.
- Hashes (in the Crypto submenu; the extension computes them itself, see below):
- Create Hash (SHA3-384): FIPS 202, 96 hex digits:
abc -> ec01498288516fc9….
- Create Hash (SHAKE256, Output Length N): Asks for the output length in bytes (1 to 1,024, default 32; up to 2,048 hex digits):
abc (32) -> 483366601360a877….
- Create HMAC (SHA3-512): Asks once for the key in a password input box and computes the HMAC-SHA3-512 (128 hex digits, block size 72 bytes):
abc (k) -> 7cc7ed9b9f44d32f…. The key must not be empty or contain a lone surrogate; it is not saved, logged or shown in the result or in a message.
- Why not
node:crypto: The extension host of VS Code (Electron, with BoringSSL) does not provide SHA-3, so these three run on the extension's own TypeScript implementation of Keccak (the one already used by SHA3-256 / SHA3-512 and HMAC-SHA3-256), checked against the FIPS 202 and NIST test vectors. Like the other SHA-3 commands, they are slower than the built-in hashes on very large selections.
- Checksums and validation (in the Checksum submenu). None of these are for cryptographic use: CRC-16 and CRC-32C detect accidental corruption only, not tampering (use a cryptographic hash or an HMAC for that), and the IBAN and ISBN check digits only catch typing mistakes; they prove nothing about where a value came from.
- Checksum: CRC-16/CCITT-FALSE: Polynomial 0x1021, initial value 0xFFFF, 4 lower-case hex digits:
123456789 -> 29b1.
- Checksum: CRC-32C (Castagnoli): The CRC of iSCSI and ext4, 8 lower-case hex digits:
123456789 -> e3069283. Checksum: CRC-32 uses the IEEE polynomial.
- Checksum: IBAN Validate: Checks the ISO 13616 mod-97 check digits and shows the result in a notification; the selection is not changed, and the IBAN is not shown in the notification:
GB82·WEST·1234·5698·7654·32 -> IBAN: valid. Spaces are ignored and lower case is accepted. Only the general structure is checked (a 2-letter country code, 2 check digits, 15 to 34 letters and digits in all), not the length or format of each country, so valid means only that the check digits match. Other text is IBAN: not an IBAN (…) with the reason.
- Checksum: ISBN-10 / ISBN-13 Validate: Checks the check digit and shows the result in a notification, with the right check digit when it is wrong:
978-4-00-310101-8 -> ISBN-13: valid, 978-4-00-310101-9 -> ISBN-13: invalid (the check digit should be 8), 0-8044-2957-X -> ISBN-10: valid. Spaces at both ends are ignored, and a single space or hyphen between two digits is a separator (a leading, trailing or doubled separator is not allowed); X is allowed only as the last digit of an ISBN-10. An ISBN-13 must start with 978 or 979: ISBN: not an ISBN (an ISBN-13 must start with 978 or 979) (it may still be a valid EAN-13); any other number of digits is ISBN: not an ISBN (10 or 13 digits are required).
- For both, the notification has the same form as Luhn Validate: with one selection, the result with its reason; with 2 to 10 selections, each selection by number without the reason (
ISBN: [#1](https://github.com/imahiro-t/selection-manipulator/issues/1) valid, [#2](https://github.com/imahiro-t/selection-manipulator/issues/2) invalid (should be 8), [#3](https://github.com/imahiro-t/selection-manipulator/issues/3) not an ISBN); with 11 or more, only the counts (IBAN: 12 selections: 5 valid, 4 invalid, 3 not an IBAN).
Limitations of the extended encoding, escaping and hash commands
- Base62 and many selections: The 10,000-byte / 13,500-character limits apply to each selection, so many selections near the limit can make VS Code wait for a while.
- IBAN: The length and format of each country are not checked (see above).
- uuencode: Only the traditional format with a length character and no check character is decoded; the file name and mode of the
begin line are ignored.
Twenty-four more data format commands: nineteen JSON, YAML, TOML, XML and LTSV commands (sort, filter and split JSON arrays, pick, omit and rename keys, remove empty values, JSON to a Markdown table, an array to an object by key and an object to key-value entries, set a value at a path, YAML to flow style, validate YAML, multi-document YAML to a JSON array, format TOML, validate XML, list XML element paths, and LTSV to and from JSON) are added to the end of the existing Data Format submenu, and five CSV - … column commands (reorder, merge two, split by a delimiter, count rows by value, fill empty cells) to the end of the existing CSV / TSV submenu, both under Transform; all of them are also in the Command Palette when text is selected. They run entirely in the extension: no network access, no files, no processes, no code evaluation and no new dependencies (YAML is read with the existing js-yaml, XML with the extension's own scanner). The existing commands (Pluck Field from JSON Array, Remove Null Values from JSON, Convert TOML to JSON, CSV - Swap Columns, CSV - Fill Empty Cells from Above and the others) are unchanged.
In the examples, · is a space, ⇥ is a tab, ⏎ is a line break, and a value in parentheses is the value you enter.
- Common rules:
- Results: The commands never change the selected text. They open the results in a new read-only editor (several selections: each selection is converted on its own and the results are joined in document order with the document's line ending, LF or CRLF). Validate YAML and Validate XML (Well-formedness) only show a notification. There are no (Replace) versions.
- JSON layout: A command that turns JSON into JSON keeps the layout of the selection like Sort JSON Keys: a selection on one line gives one line without spaces, and a selection on several lines gives JSON indented with 2 spaces. Convert LTSV to JSON and Convert Multi-document YAML to JSON Array always indent with 2 spaces.
- Selections and input: Empty selections are skipped, and with only cursors nothing happens (no input box is opened). A command that needs a value asks once for all selections and does nothing if you cancel; a wrong value is shown in the input box, and the selections are read again after it closes. Paths use the notation of Extract JSON Value by Path (
a.b[0], $["b-c"], $ for the whole value; up to 1,000 characters); key lists, key=value and key names can be up to 10,000 characters, the JSON value of Set JSON Value at Path up to 100,000, and the values of the CSV commands up to 1,000 characters without tabs, line breaks or other control characters.
- Errors and limits: If any selection fails, nothing is opened and an error says why (
The selection was not changed: …, with selection 2 of 3: when there are several). A selection can be up to 5,000,000 characters, and JSON can be nested up to 500 levels. A run whose results would exceed 10,000,000 characters in total (shared by all selections), or more than a command's own count limit (10,000 YAML documents, 100,000 XML paths, 1,000 added CSV columns), is refused with a warning and nothing is opened. An unexpected failure is reported as the text could not be converted, and only the error name and stack frames are logged, never the selected text or a typed value.
- Keys: Every object built from your keys or labels is an ordinary object without a prototype, so keys such as
__proto__, constructor and prototype stay ordinary keys in the result and never change anything else (Pick, Omit and Rename Keys, Remove Empty Values, Array to Object, Set JSON Value at Path, LTSV to JSON and Count Rows by Column Value).
- JSON arrays:
- Sort JSON Array: Asks for a key path (leave it empty to sort by the elements themselves) and sorts the top-level array by the elements or by the value at that path in each element:
[{"n":2},{"n":1}] (n) -> [{"n":1},{"n":2}]. The sort is stable (equal values keep their order).
- Order of types: number < string < boolean < array < object < null < missing (an element without the key path):
[null,{"a":1},"x",[2],true,1] -> [1,"x",true,[2],{"a":1},null].
- Within a type: numbers by value, strings by code point (not by locale, so
B comes before a), false before true; arrays and objects are compared by their JSON text (compact, keys sorted) by code point, not element by element, so [1,5] comes before [1] and [1] before [] (, < ]): [[],[1],[1,5]] -> [[1,5],[1],[]]. Objects with the same keys and values in another order are equal.
- Filter JSON Array by Field Value: Asks for
key=value (split at the first =; the key is a path, everything after the = is the value) and keeps the elements whose field matches; only equality is checked and nothing is evaluated: [{"s":"on"},{"s":"off"}] (s=on) -> [{"s":"on"}].
- Matching: The field matches when the value is JSON and equal to it (objects with keys in any order are equal), or when the field is a string equal to the value exactly as typed. So
status=200 keeps both 200 and "200", flag=true keeps true and "true", and status="200" keeps only the string "200" (quote the value to match strings only). A missing field never matches, and the value may be empty (s= keeps "").
- The value is used exactly as typed, spaces included: nothing is trimmed, so
status=·200 still keeps the number 200 (JSON ignores the space) but only the string "·200", not "200"; s=·on keeps only "·on".
- Split JSON Array into Chunks: Asks for N (1 to 1,000,000) and splits the array into arrays of N elements; the last one holds the rest:
[1,2,3] (2) -> [[1,2],[3]].
- Convert JSON Array to Markdown Table: An array of objects (not empty) to a table whose columns are all keys in order of first appearance:
[{"a":1,"b":2}] -> |·a·|·b·|⏎|·---·|·---·|⏎|·1·|·2·|. Strings are written as they are, other values (and nested objects and arrays) as compact JSON, and a missing key is an empty cell. In headers and cells, \ becomes \\, | becomes \| and every line break (LF, CRLF or CR) becomes <br>, so a cell never breaks the table.
- Convert JSON Array to Object by Key: Asks for a key (a path such as
id or user.id) and makes an object of the elements keyed by its value: [{"id":"a","v":1}] (id) -> {"a":{"id":"a","v":1}}. The value must be a string or a number (the number 1 and the string "1" are the same key); a missing value, another type or a key that two elements share is an error that names the element (element [1] repeats the key "1").
- JSON keys and values:
- Pick Keys from JSON Object: Asks for keys (separated by
,, spaces around each key removed, no empty key, up to 1,000) and keeps only those keys of an object, or of every object of an array, in their original order: {"a":1,"b":2,"c":3} (a,c) -> {"a":1,"c":3}. Pluck Field from JSON Array takes the value of one field instead.
- Omit Keys from JSON: Asks for keys in the same way and then for
Top level only or Recursive (every level, also inside arrays): {"a":1,"pw":"x"} (pw, Top level only) -> {"a":1}. With Top level only, the keys are removed from the object, or from each object of an array (other elements stay).
- Rename JSON Key: Asks for the key and then for its new name, and renames it in every object at every level, keeping the key order:
{"old":1} (old, new) -> {"new":1}. The same name twice is an error, and so is an object that already has the new key (the object at $ already has the key "b").
- Remove Empty Values from JSON: Removes
"", [], {} and null at every level, and a parent that becomes empty too: {"a":"","b":[],"c":1} -> {"c":1}, {"a":{"b":""}} -> {}. The top-level value itself stays. Remove Null Values from JSON removes only null and keeps empty parents.
- Convert JSON Object to Key-Value Array:
{"a":1} -> [{"key":"a","value":1}], one entry per key in order.
- Set JSON Value at Path: Asks for a path and then for a value as JSON (read with
JSON.parse only, never evaluated: 2, "text", true, null, {"a":1}) and replaces the value there: {"a":{"b":1}} (a.b, 2) -> {"a":{"b":2}}. Missing object keys on the way are created as objects ({"a":1} (x.y, 2) -> {"a":1,"x":{"y":2}}), and $ replaces the whole value. An array index must be an existing element (0 to length − 1), so no sparse array is made (a[1] is out of range (the array has 1 element; only existing elements can be set)); an index into a missing key, or a key into a value that is not an object, is an error.
- YAML (read with the YAML 1.2 Core schema, as in Format YAML; no type that runs code):
- Convert YAML to Flow Style: Writes one YAML document again in flow style with js-yaml:
a:·1⏎b:⏎··-·x -> {a:·1,·b:·[x]}. Anchors and aliases stay references and are never expanded: when a value is used more than once, it is written once with an anchor and then as an alias (a:·&x·{k:·1}⏎b:·*x -> {a:·&ref_0·{k:·1},·b:·*ref_0}, anchors renamed as in Format YAML), so YAML with nested aliases ("billion laughs") is not blown up; a value that is not shared gets no anchor. (js-yaml's noRefs option would write every shared value out again in full, so it is used only when nothing is shared.) As in Format YAML, "mappings and sequences × references to them" is limited to 300,000,000, and comments are lost. The result ends with a line break only if the selection does. Several documents (---) and a selection with only comments are errors.
- Validate YAML: Checks every document of the selection and shows
Valid YAML, or Invalid YAML: line L, column C: reason with js-yaml's reason and the line and column in the selection: a:·[1 -> Invalid YAML: line 2, column 1: unexpected end of the stream within a flow collection (js-yaml reports the end of the text on the next line), a:·1⏎··b:·2 -> Invalid YAML: line 2, column 4: bad indentation of a mapping entry. The values are thrown away as they are read, so aliases are never expanded. With several selections, one notification: Selection 1: Valid YAML; Selection 2: Invalid YAML: … (an error notification if any selection is not valid). The selected text is never shown.
- Convert Multi-document YAML to JSON Array: One element per document (
---), an empty document is null: a:·1⏎---⏎a:·2 -> [{"a":1},{"a":2}]. At most 10,000 documents. JSON has no aliases, so they are expanded here; the length of the JSON is checked before it is built, so nested aliases that would exceed 10,000,000 characters are refused at once with a warning. .inf and .nan are errors (JSON cannot hold them), and so is a selection with only comments or ---.
- TOML:
- Format TOML: Reads TOML with the parser of Convert TOML to JSON and writes it with the writer of Convert JSON to TOML: values first, then
[table] and [[array]] headers with a blank line before each: a=1⏎[b]⏎c="x" -> a·=·1⏎⏎[b]⏎c·=·"x". The values and types are kept, but their spelling is normalized:
- Floats stay floats and are written in a normal form with a decimal point or exponent (
1.0 stays 1.0, 1e3 becomes 1000.0, -0.0 stays), and dates and times are written as they are, without quotes.
- Integers are written in decimal:
0xff, 0o17 and 0b11 become 255, 15 and 3, and 0x7fffffffffffffff becomes 9223372036854775807. Integers beyond ±(2^53 − 1) are kept exactly (they are not written as floats as in Convert JSON to TOML), but an integer outside the 64-bit range of TOML (−2^63 to 2^63 − 1) is an error (the integer … is outside the 64-bit range TOML allows).
inf, nan (also +inf, -nan, …) and floats too large for a double (1e400) are kept as they are written. Convert TOML to JSON still refuses them, and integers beyond ±(2^53 − 1), as JSON cannot hold them.
- Comments, blank lines and the original quoting of keys are not kept, keys are written bare when they can be and in
"…" otherwise ("a"·=·1 -> a·=·1, 'b·c'·=·2 -> "b·c"·=·2), and an inline table may become a [table] (i·=·{x·=·1} -> [i]⏎x·=·1). A selection with no key is an error.
- XML (the extension's own scanner, which never reads, fetches or resolves anything):
- Validate XML (Well-formedness): Checks the main rules of well-formed XML 1.0 (matching tags, exactly one root element, no text outside it, quoted and unique attributes, comments without
--, CDATA sections, processing instructions, the XML declaration only at the start, character references and characters that XML allows) and shows Well-formed XML, or Invalid XML: line L, column C: reason without quoting the selection: <a><b></a> -> Invalid XML: line 1, column 7: mismatched end tag (expected the end tag of the element at line 1, column 4). Several selections give one notification, as in Validate YAML.
- DOCTYPE and entities: A DOCTYPE is read as syntax only: an external identifier (
SYSTEM "file:///…") is never fetched, and no entity declared in it is ever expanded, so only the five predefined entities (< > & ' ") and character references are accepted; any other entity, even one declared in the DOCTYPE, is an error (undefined entity (… entities are never resolved)). Elements can be nested up to 500 levels.
- Not checked: DTD validity, the encoding declaration, and the full Unicode ranges of names (a simplified rule is used: a name starts with an ASCII letter,
_, : or a character from U+00C0, and continues with those, digits, -, . and U+00B7).
- List XML Element Paths: Checks the XML in the same way and lists the paths of the leaf elements only (elements without child elements, also empty ones such as
<x/>) in document order, one per line: <r><i>1</i><i>2</i></r> -> /r/i[1]⏎/r/i[2], <r><a><b/></a><c>t</c></r> -> /r/a/b⏎/r/c. The root and other elements with children are not listed on their own lines (they appear inside the paths), so a root without children gives just /r. [n] (from 1) is added only to names that two or more siblings share. Attributes, text, comments and processing instructions are not listed. At most 100,000 lines.
- LTSV:
- Convert LTSV to JSON: One record per line (empty lines are skipped), fields separated by tabs, the label before the first
: of each field: host:a⇥status:200 -> [{"host":"a","status":"200"}]. Values stay strings. A field without :, an empty label and a label used twice in a record are errors (line 1, field 2: the label "a" is repeated).
- Escapes: Only four escapes in values are turned back (those that Convert JSON to LTSV writes):
\\ -> \, \t -> tab, \n -> LF and \r -> CR, read once from the left (\\t is \ and t). Any other backslash (\x, a backslash at the end) is kept, so C:\path stays C:\path. A log that contains a literal \n, \t, \r or \\ in a value (written by a program that does not escape) is changed: msg:a\nb becomes "a⏎b" (with a real line break) and \\ becomes one \.
- Convert JSON to LTSV: An object or an array of objects (not empty) to one record per line:
[{"a":"1"}] -> a:1. Strings are written as they are and other values as compact JSON; in values \ becomes \\, a tab \t, LF \n and CR \r, so a record stays on one line. Labels may contain only letters, digits, _, . and -; another key is an error. An object without keys ({}) becomes an empty line, which Convert LTSV to JSON skips: [{"a":"1"},{},{"b":"x"}] -> a:1⏎⏎b:x, read back as two records.
- Round trip: Converting to LTSV and back gives exactly the same string values (with tabs, line breaks and backslashes); numbers, booleans,
null, objects and arrays come back as strings of their JSON text (1 -> "1"), as LTSV has no types, and empty objects are lost.
- CSV columns (in the CSV / TSV submenu; they follow the rules of the table commands: RFC 4180 CSV with
,, a column is a number from 1 or the exact text of a header cell, short rows are filled with empty cells, minimal quoting, and the result ends with a line break only if the selection does):
- CSV - Reorder Columns: Asks for the new order of the column numbers and lists every column of the table exactly once:
a,b,c (3,1,2) -> c,a,b. A number used twice or a list that leaves a column out is an error (list every column of the table exactly once (the table has 3 columns, 2 given)). CSV - Swap Columns swaps two columns.
- CSV - Merge Two Columns: Asks for two different columns and a separator (0 to 100 characters, may be empty) and joins the two values into the place of the first column; the second column is removed, and the header row is joined too:
山田,太郎 (1, 2, ·) -> 山田·太郎.
- CSV - Split Column by Delimiter: Asks for a column and a delimiter (plain text, not a regular expression, 1 to 100 characters) and splits the cells of that column at every occurrence into as many columns as the row with the most parts needs; the header row is split too, and missing parts are empty cells:
2026-10-01 (1, -) -> 2026,10,01. At most 1,000 columns can be added (counted before anything is split), and the table must stay within 10,000,000 cells.
- CSV - Count Rows by Column Value: Asks for a column and counts the data rows (the first row is the header) for each value, in order of first appearance, under the header
<column name>,count: a⏎x⏎y⏎x (1) -> a,count⏎x,2⏎y,1. With only the header row it is an error.
- CSV - Fill Empty Cells with Value: Asks for a value (not empty) and puts it into every empty cell, also into the missing cells of short rows and into the header row; the value is quoted by the CSV rules when it holds a
, or ": a,,c⏎d (N/A) -> a,N/A,c⏎d,N/A,N/A. A cell with only spaces is not empty. If the result would be longer than 10,000,000 characters, a warning is shown and nothing is opened; this is checked before the result is built (from the number of empty cells × the length of the value). CSV - Fill Empty Cells from Above fills from the cell above instead.
Limitations of the extended data format commands
- Sort JSON Array: Arrays and objects are ordered by their JSON text, not element by element or by size (see above), and strings by code point, not by locale.
- Filter JSON Array by Field Value: The value is not trimmed (see above), and only equality is supported (no
!=, <, patterns or several conditions).
- Format TOML: Comments, blank lines, key quoting, inline tables and number spellings are not kept (see above); like Convert TOML to JSON, dates and times are checked for their format, not against the calendar.
- Validate XML and List XML Element Paths: Only well-formedness is checked (no DTD or schema validation); entities declared in a DOCTYPE are treated as undefined, so XML that uses them cannot be checked or listed.
- LTSV: Values with a literal
\n, \t, \r or \\ are unescaped (see above), and labels are not checked when reading, only when writing.
- YAML to Flow Style: Comments are lost and values are written in js-yaml's style, as in Format YAML.
- TOML error messages: An integer that is out of range is quoted in full in the error, so a very long integer gives a very long message.
23. Developer (Extended)
Twenty-three more developer commands (types for Rust, Kotlin, C#, Zod and Swift from sample JSON, lowercase SQL keywords, OKLCH, WCAG contrast ratios and inverted colors, three CSS declaration tools, removing JS / TS comments, C# verbatim strings, Rust raw strings and shell here-documents, HTTP status codes and MIME types from fixed tables, UUIDs, CIDR ranges, IPv6 addresses and IPv4 integers) are added to the end of the existing Programmatic submenu under Transform (after the escaping commands of section 21) and to the Command Palette when text is selected. They only write text: generated code is never compiled or run, no SQL or shell command is run, nothing is sent over the network, no file is read (the MIME lookup never opens the file), Node.js tables such as node:http are not used, and there are no new dependencies. The existing Developer commands (section 16, such as Convert JSON to TypeScript Interface, Uppercase SQL Keywords, Convert Hex to HSL and Convert to Go Raw String) are unchanged.
In the examples, · is a space, ⏎ is a line break, and ⇥ is a tab.
- Common rules:
- Output: The commands never change the selected text. The results always open in a new read-only editor (several selections: the results in document order, joined with the document's line ending); there are no (Replace) versions.
- Selections and errors: As in section 16: empty selections are skipped; selections of only spaces, tabs and line breaks are converted by Convert to C# Verbatim String, Convert to Rust Raw String and Convert to Shell Here-document and skipped by every other command, and if nothing is left the warning
Select the text to convert. is shown. The commands marked one value per line below convert each line on its own, keep empty lines and the spaces around each value, and fail as a whole if one line is wrong (No result was shown: line 2: …, with selection 2 of 3: when there are several selections). If any selection fails, nothing is opened. A selection can be up to 1,000,000 characters, JSON and CSS can be nested up to 200 levels, and a run whose results would exceed 10,000,000 characters in total is refused with a warning (…Select less text.). An unexpected failure is reported as the text could not be processed, and only the error name and stack frames are logged, never the selected text.
- Types from sample JSON (Convert JSON to Rust Struct (serde), Convert JSON to Kotlin Data Class, Convert JSON to C# Class, Convert JSON to Zod Schema, Convert JSON to Swift Codable):
- Like the types of section 16, the selection must be a JSON object or an array of objects (merged into one
Root type), read with JSON.parse only. Nested objects become their own types named after their keys, a key missing from some of the merged objects or a null value makes the type optional, integers and decimals are told apart by their value, and objects can be nested 200 levels deep.
- Identifiers: Names keep only ASCII letters, digits and
_ (an empty name becomes field, a name that starts with a digit gets a leading _, and names that collide are numbered: field, field2, …). Keywords are escaped in each language's way: Rust raw identifiers (r#type; self, super and crate, which cannot be raw, become self_ …), backquotes in Kotlin and Swift (`val`, `class`; in Swift, self and init become self_ and init_), and in C# a property with the name of its class gets a trailing _ (Root_). The original key is always kept in the rename attribute of the language (see below), written as an escaped string literal of that language.
- Rust (serde):
{"userId":1} -> use serde::{Deserialize, Serialize};⏎⏎#[derive(Serialize, Deserialize)]⏎struct Root {⏎····#[serde(rename·=·"userId")]⏎····user_id:·i64,⏎}. Fields are snake_case with #[serde(rename = "…")] when the name differs from the key; Option<…> for an optional key, i64, f64, bool, String, Vec<T>, and serde_json::Value for values of different types, a key that is only null and the elements of an empty array (this needs the serde_json crate). Structs and fields are not pub; add the visibility you need.
- Kotlin (kotlinx.serialization):
{"name":"a"} -> import kotlinx.serialization.Serializable⏎⏎@Serializable⏎data class Root(val name: String). Every class is @Serializable, properties are camelCase with @SerialName("…") when the name differs from the key (its import is written only then; $ in the key is escaped too). null makes T?, a key missing from some objects T? = null; Long, Double, Boolean, String, List<T>, and JsonElement for values of different types (with its import). An object without keys becomes a plain class (a data class needs a property). One property is written on the line of the class, more on their own lines with trailing commas.
- C# (System.Text.Json):
{"age":3} -> using System.Text.Json.Serialization;⏎⏎public class Root⏎{⏎····[JsonPropertyName("age")]⏎····public long Age { get; set; }⏎}. Properties are PascalCase and every property has [JsonPropertyName("…")] with the original key, so the class round-trips with the default options (case-sensitive, no naming policy) and with JsonSerializerDefaults.Web alike. null or a missing key makes T?; long, double, bool, string, List<T>, and JsonElement for values of different types. Only the needed using lines are written.
- Zod:
{"a":1} -> z.object({ a: z.number() }). Only the expression is written: add import { z } from 'zod' yourself (zod is not a dependency of this extension). z.number() (not .int()), z.string(), z.boolean(), z.null(), z.array(…), z.array(z.unknown()) for an empty array, z.union([…]) for values of different types, .nullable() and .optional(). Keys that are not identifiers are quoted ('a b'), and __proto__ is written as the computed key ['__proto__'] (in an object literal, even a quoted "__proto__": would set the prototype). An object that does not fit in 80 characters is written over several lines, indented by 2 spaces.
- Swift (Codable):
{"id":1} -> struct Root: Codable {⏎····let id: Int⏎}. Properties are camelCase; when one name differs from its key, an enum CodingKeys: String, CodingKey lists every property (Swift needs all of them there). null or a missing key makes T?; Int, Double, Bool, String, [T]. The standard library has no Codable type for any JSON value, so these are errors that name the key: an empty array ({"a":[]}: the key "a" has an empty array, whose element type is unknown, …), a key that is only null ({"a":null}) and values of different types ({"a":[1,"x"]}: the key "a" has values of different types (or only null) …). Rust, Kotlin, C# and Zod accept them.
- SQL: Lowercase SQL Keywords:
SELECT * FROM t -> select * from t. The same keywords that Uppercase SQL Keywords changes, with the same rules: strings, quoted identifiers and comments are not changed, and the forms that Uppercase SQL Keywords refuses are refused too (see the limitations of section 16). The SQL is never run.
- Colors (one value per line):
- Convert Hex Color to OKLCH:
#ff0000 -> oklch(62.8% 0.258 29.23). Reads #rgb, #rgba, #rrggbb and #rrggbbaa (the # is optional) and uses the OKLab matrices of CSS Color 4. L is rounded to 1 decimal (a percentage), C to 3 and H to 2, trailing zeros dropped; a gray (C below 0.0005) is written with chroma and hue 0 (#808080 -> oklch(60% 0 0)), and an alpha adds / a (#ff000080 -> oklch(62.8% 0.258 29.23 / 0.5)).
- Show WCAG Contrast Ratio: Two colors per line, separated by spaces or a comma (
#000000 #ffffff, #000, #fff; 3 or 6 digits, no alpha) -> 21:1 (AAA). The ratio follows WCAG 2.x relative luminance, and the level is AAA (7 or more), AA (4.5 or more), AA Large (3 or more, large text only) or Fail. The level is judged on the computed ratio, and the ratio is shown cut (not rounded) to 2 decimals, so the shown value never reaches a level that the color pair does not: #777 #fff -> 4.47:1 (AA Large), #767676 #fff -> 4.54:1 (AA).
- Invert Hex Color:
#112233 -> #eeddcc. Red, green and blue each become 255 minus their value; the number of digits, the # (or its absence) and the alpha are kept (fff8 -> 0008), and the result is upper case only when the input has upper-case letters and no lower-case ones (#ABC -> #543).
- CSS:
- Sort CSS Declarations:
{color:red;align-items:center} -> {align-items:center;color:red}. Sorts the declarations of each block (or a selected declaration list without braces) by property name (lower case, code point order, stable). Only the declarations move: the spaces, line breaks and ; around them stay, so the layout is kept. A comment right before a declaration moves with it, and so does a comment after its ; at the end of the same line ({⏎··b: 1; /* about b */⏎··a: 2;⏎} -> {⏎··a: 2;⏎··b: 1; /* about b */⏎}). The comment after the last declaration without a ; on the same line moves with it too, and goes after the ; when the declaration moves to a place that has one ({⏎··b: 1;⏎··a: 2 /* about a */⏎} -> {⏎··a: 2; /* about a */⏎··b: 1⏎}); a comment on a later line stays before the }. Nested rules (@media, CSS nesting) are sorted on their own, and declarations never move across them. Strings, comments and url(…) are not changed.
- Convert CSS Declarations to JS Style Object:
font-size: 12px; color: red -> { fontSize: '12px', color: 'red' } (one line; the outer braces are optional). Properties become camelCase (-webkit-box-flex -> WebkitBoxFlex, -ms-flex -> msFlex), custom properties stay quoted keys ('--main-color'), and every value becomes an escaped JavaScript string, never evaluated, !important included (color: 'red !important'). A property written twice becomes one key with the last value, in the place where it first appeared, as in a JS object literal (margin:0; margin:1px -> { margin: '1px' }). Comments are dropped, and a nested block is an error.
- Convert JS Style Object to CSS Declarations:
{ fontSize: '12px' } -> font-size: 12px;, one declaration per line. The object is read with the extension's literal parser (never evaluated) and must be flat, with string or number values. Keys become kebab-case (WebkitBoxFlex -> -webkit-box-flex, msFlex -> -ms-flex; --x and kebab-case keys stay), and numbers are written as they are, without a unit (width: 10 -> width: 10;; write '10px' for pixels). Nested objects, arrays, booleans, null, a __proto__ key and values that could break out of a declaration (;, {, }, a line break, comment markers, an unclosed string or bracket, or an odd number of \ at the end) are errors.
- JavaScript / TypeScript code: Remove JS / TS Comments:
a(); // x⏎/* y */b(); -> a();⏎b();. Removes // and /* */ comments with the JavaScript reader of section 16, so strings, the text of template literals and regular expressions are never changed; comments in the ${…} of a template literal are removed too (`a${x /* c */}b` -> `a${x}b`). A hashbang (#!…) at the start of the selection is kept.
- A block comment that spans lines keeps its line breaks (the same characters, LF, CRLF, U+2028 or U+2029), so automatic semicolon insertion reads the code as before:
return /*⏎*/ x -> return⏎ x (still return;), not return x.
- Only lines that had a comment and hold nothing but spaces afterwards are removed (with their line break, also a whole JSDoc block); lines that were empty or blank before stay. The spaces left at the end of a line after a removed comment are dropped too (
a = 1; // x -> a = 1;).
- Spaces around a removed comment: after a comment at the start of a line or right after
(, [, { or ${, the spaces after it are dropped (/* c */ a; -> a;, ··/* c */ a; -> ··a;, f(/* c */ a) -> f(a)); before a comment that comes right before ), ], }, , or ;, the spaces before it are dropped (f(a /* c */) -> f(a), g(a /* c */, b) -> g(a, b), ( /* c */ ) -> ()). Elsewhere in a line, the spaces on both sides stay (x = a /* c */ - b -> x = a··- b). The spaces after a block comment that spans lines always stay, as they may be the indent of the next line (x;⏎/* a⏎ */ b; -> x;⏎ b;). When removing a comment would join two tokens, one space is left (a/**/b -> a b). A comment on the last line removes that line but keeps the line break before it (a();⏎// end -> a();⏎).
- String literals (also for selections of only white space):
- Convert to C# Verbatim String:
a"b -> @"a""b"; every " is doubled and everything else, line breaks included, stays as it is.
- Convert to Rust Raw String:
a"#b -> r##"a"#b"##. Uses the fewest # that never appear after a " in the text (r"ab" when the text has no ").
- Convert to Shell Here-document:
echo $X -> cat <<'EOF'⏎echo $X⏎EOF. The delimiter is quoted, so nothing in the text ($X, `…`, \) is expanded, and it is a word that no line of the text equals (EOF, else EOF_1, EOF_2, …). A line break is added at the end of the text when it has none, and an empty text gives an empty here-document (cat <<'EOF'⏎EOF). Nothing is run.
- Fixed tables (one value per line; the tables are part of the extension, nothing is looked up elsewhere):
- Describe HTTP Status Code:
404 -> 404 Not Found. Three digits per line. The table holds the codes that have a reason phrase in the IANA HTTP Status Code Registry (61 codes: 100–103, 200–208, 226, 300–305, 307, 308, 400–417, 421–426, 428, 429, 431, 451, 500–508, 510, 511, with the phrases of RFC 9110 and the other current RFCs, such as 413 Content Too Large and 422 Unprocessable Content) and the customary 418 I'm a teapot, 62 codes in all. Unused and unassigned codes such as 104, 306 and 509 are errors.
- Look Up MIME Type by Extension:
report.pdf -> application/pdf. Takes an extension (pdf, .PDF), a file name or a path (the part after the last / or \, then after its last .: C:\x\a.tar.gz -> application/gzip), ignoring case, and looks it up in a fixed table of about 110 common extensions. The file is never opened. An unknown extension is an error.
- UUID and network addresses (one value per line; text only, no network access and no
net module):
- Normalize UUID Format:
{550E8400E29B41D4A716446655440000} -> 550e8400-e29b-41d4-a716-446655440000. Accepts braces, a urn:uuid: prefix, 32 hex digits without hyphens or with hyphens in the standard places, in any case; hyphens in other places are an error.
- Show CIDR Range Information:
192.168.1.0/24 -> network 192.168.1.0 / broadcast 192.168.1.255 / first 192.168.1.1 / last 192.168.1.254 / hosts 254. Host bits may be set (192.168.1.77/24 gives the same). A /31 has two hosts and no broadcast (RFC 3021), a /32 one host. IPv6 (/0 to /128) gives network 2001:db8:: / last 2001:db8::ffff:ffff:ffff:ffff / addresses 18446744073709551616. The range is only computed, never listed; an address with a zone ID is an error.
- Expand IPv6 Address:
2001:db8::1 -> 2001:0db8:0000:0000:0000:0000:0000:0001; an embedded IPv4 address becomes hex too (::ffff:1.2.3.4 -> 0000:0000:0000:0000:0000:ffff:0102:0304), and a zone ID (%eth0) and a prefix length (/64) are kept.
- Compress IPv6 Address:
2001:0db8:0000:0000:0000:0000:0000:0001 -> 2001:db8::1, as RFC 5952 recommends: lower case, leading zeros dropped, the longest run of two or more zero groups (the first of equal runs) as ::, and a single zero group stays 0. Only hex is written, also for an IPv4-mapped address (::ffff:102:304, not ::ffff:1.2.3.4). A zone ID and a prefix length are kept.
- Convert IPv4 to Integer and Back:
192.168.0.1 -> 3232235521 and 3232235521 -> 192.168.0.1, the direction recognized line by line (integers 0 to 4294967295 without leading zeros). An octet with a leading zero (192.168.01.1, octal in some tools) is an error.
Limitations of the extended Developer commands
- Output: The results always open in a new read-only editor; no command replaces the selection.
- Types from sample JSON: The types are guessed from one sample, so they are a starting point that you may need to edit. Keys with non-ASCII characters keep only their ASCII letters and digits in the names (
名前 -> field, café -> caf), but the original key is kept in #[serde(rename)], @SerialName, [JsonPropertyName] and CodingKeys (Zod quotes it as it is), so the JSON still round-trips. Keywords are renamed or escaped as described above (r#type, self_, `val`, init_, Root_). Swift Codable refuses empty arrays, keys that are only null and values of different types (see above). The Rust output uses serde_json::Value for such values and needs the serde_json crate; the Zod output needs import { z } from 'zod'. A lone surrogate in a key is an error for Rust and Swift (their strings cannot hold it) and written as \uXXXX for Kotlin and C#.
- Sort CSS Declarations: Declarations are sorted by property name only, so a shorthand and its longhands can change order and the cascade can change:
margin-top: 0; margin: 10px -> margin: 10px; margin-top: 0 sets the top margin to 0 instead of 10px. Check the result when a block mixes shorthands and longhands.
- CSS conversions: The CSS processing is simple: custom property values with
{ } blocks are not supported, and Convert JS Style Object to CSS Declarations does not add units or check property names and values (a value such as </style> is not refused, so do not put the result into HTML unchecked).
- Remove JS / TS Comments: The simple JavaScript reader treats
// inside JSX text as a comment, and a / after ) as division (if (x) /re/.test(y) is misread).
- String literals: Convert to Rust Raw String refuses text that would need more than 255
# and a carriage return without a line feed (a raw string cannot hold it). Convert to Shell Here-document always writes LF line breaks (CRLF becomes LF, because a shell reads a CR as part of the line), even in a CRLF document, and refuses a carriage return without a line feed.
- Describe HTTP Status Code: Only the 61 IANA codes with a reason phrase and 418 are known (see above); provisional, unused and unassigned codes (104, 306, 509, 600 …) are errors.
- Look Up MIME Type by Extension: Only the about 110 extensions of the fixed table are known; the type is chosen by the extension, never by the content.
- Network addresses: Compress IPv6 Address never writes the dotted IPv4 form; Show CIDR Range Information does not accept zone IDs and does not list addresses; Convert IPv4 to Integer and Back reads only the dotted decimal form (no
0x, octal or shortened forms such as 10.1).
24. Numbers & Math (Extended)
Twenty-three more number commands (significant figures, rounding to a multiple, clamping, Roman numerals, English number words, fractions, multiplication, IEEE 754 bits, two's complement, greatest common divisor and least common multiple, prime factors, differences, integer ranges, m / ft, m² / tsubo and degrees / radians) are added after the number commands of section 10: Math - Greatest Common Divisor and Math - Least Common Multiple to the end of the Calculate context submenu, the Unit: … commands to the end of the Unit Conversion submenu of Transform, and the other commands to the end of the Number submenu of Replace; all of them are also in the Command Palette when text is selected. They work only on the selected text and the values you enter: nothing is sent over the network, no file is read, nothing is evaluated, and there are no new dependencies. The commands of section 10 are unchanged.
In the examples, ⏎ is a line break and a value in parentheses is the value you enter.
- Common rules: The same as the Number Commands of section 10.
- Output: Math - Greatest Common Divisor and Math - Least Common Multiple never change the text: they open the result in a new read-only editor, one line for each selection. Every other command replaces each selection with its result (only the selections whose text changes, as one undo step).
- Selections and errors: Empty selections and selections of only spaces, tabs and line breaks are skipped (
Select the numbers to use. when nothing else is selected). The commands marked one value per line convert each line on its own, keep empty lines, the spaces around each value and LF / CRLF line breaks, and fail as a whole if one line is wrong (The selection was not changed: line 2: …, with selection 2 of 3: when there are several selections). If any selection fails, nothing is changed or opened. A command that asks for values asks once for all selections and does nothing if you cancel; the values are not saved.
- Rounding: Unless a command says otherwise, a result that is a safe integer is written as it is and any other result is rounded to 15 significant digits (rule A of section 10); the six Unit commands are rounded to 4 decimal places (half away from zero, without trailing zeros), like the Unit commands of section 10.
- Values you enter: Round to Nearest Multiple, Clamp to Range and Multiply by N take any finite number (
-2.5, 1e3; Enter a number. otherwise), and Round to Nearest Multiple refuses every spelling of 0 (0, -0, 0.0: Enter a number other than 0.). The bit widths are chosen by typing one of the listed numbers (Enter one of 64, 32.).
- Rounding and clamping (one value per line):
- Number - Round to Significant Figures: Asks for the number of significant figures (1 to 21):
123456 (2) -> 120000, 0.00123456 (3) -> 0.00123, -2.5 (1) -> -3. It rounds half away from zero on the number as written in decimal, like Number - Round, so a half written in decimal is never missed through floating-point error (1.45 (2) -> 1.5, -1.45 (2) -> -1.5, 2.675 (3) -> 2.68, 1.005 (3) -> 1.01). Unlike Number - Round, which counts the digits after the decimal point, it counts from the first non-zero digit. Very large and very small results are written in JavaScript's exponent notation (1.45e-7 (2) -> 1.5e-7).
- Number - Round to Nearest Multiple: Asks for N and rounds to the nearest multiple of N, half away from zero:
17 (5) -> 15, -2.5 (1) -> -3, 7 (0.3) -> 6.9; a negative N works the same way (-17 (-5) -> -15). The quotient is cleaned to 15 significant digits before it is rounded, so a boundary written in decimal is not missed through floating-point error (0.15 (0.1) -> 0.2, although 0.15 / 0.1 is 1.4999999999999998 in floating point; 1.005 (0.01) -> 1.01).
- Number - Clamp to Range: Asks for the minimum and then the maximum (if the minimum is greater, a warning says so and nothing is changed):
120⏎50⏎-5 (0, 100) -> 100⏎50⏎0. A value within the range is kept exactly as written (050.0 stays 050.0); a value outside becomes the bound.
- Number - Multiply by N:
12 (1.1) -> 13.2 (rule A, so 0.1 (3) -> 0.3). A result beyond the range of floating-point numbers is an error.
- Notations (one value per line):
- Number - To Roman Numeral:
2026 -> MMXXVI. Integers from 1 to 3999 without a sign; 0, 4000, decimals and signs are errors.
- Number - From Roman Numeral:
MMXXVI -> 2026, in any case (mcmxciv -> 1994). Only the standard subtractive form (I to MMMCMXCIX) is accepted: IIII, VX, IC and MMMM are errors.
- Number - From English Words: The reverse of Number - To English Words:
one hundred twenty-three -> 123, minus five -> -5, zero -> 0. Case, and and commas are ignored and the hyphen of the tens is optional (Two Million, Three Hundred and Five -> 2000305, twenty three -> 23). The scales (thousand to decillion) must come in descending order, each with a number from 1 to 999 before it (one thousand thousand and twelve hundred are errors). At most 100 words per line; the result is exact (BigInt).
- Number - Fraction to Decimal:
3/4 -> 0.75, 1 3/4 -> 1.75; a sign applies to the whole number (-1 3/4 -> -1.75), and spaces around / are allowed. Each integer can have up to 30 digits; a denominator of 0 is an error. The result follows rule A (1/3 -> 0.333333333333333). The reverse of Number - Decimal to Fraction.
- Bits (one value per line):
- Number - To IEEE 754 Bits: Asks for the width (
64 = double, 32 = single): 1.5 (64) -> 0x3FF8000000000000, 0.1 (32) -> 0x3DCCCCCD. Upper-case hex with 0x, 16 or 8 digits; -0 keeps its sign bit (0x8000000000000000). With 32, a number beyond the range of a single (1e39) is an error, and other numbers are rounded to the nearest single.
- Number - From IEEE 754 Hex:
0x3FF8000000000000 -> 1.5. The 0x is optional and case does not matter; 16 digits are read as a double, 8 digits as a single, and any other length is an error. The result is the shortest decimal that reads back to the same value (3dcccccd -> 0.1), so it is not rounded to 15 digits like the other commands; NaN, Infinity, -Infinity and -0 are written as such.
- Number - To Two's Complement Hex: Asks for the width (8, 16, 32 or 64):
-1 (32) -> 0xFFFFFFFF, -128 (8) -> 0x80. Upper-case hex with 0x, zero-padded to the width. Accepted values are −2^(w−1) to 2^w − 1, so a non-negative value up to 2^w − 1 is written as its unsigned bits (255 (8) -> 0xFF); anything else is an error that names the range (256 (8): out of the range of 8 bits (-128 to 255)). A value with more than 20 digits (not counting leading zeros) is refused before it is read.
- Integers:
- Math - Greatest Common Divisor (new editor):
12 18 24 -> 6. The integers are the number tokens of the selection, read as by Math - Median; negative integers count as their absolute value (-12 18 -> 6), gcd(0, a) = |a| (0 5 -> 5, all zeros -> 0), and one integer gives its absolute value (-7 -> 7). A decimal or exponent token is an error, and a selection without numbers is a warning (no numbers found). Each integer can have up to 1,000 digits and is computed exactly with BigInt.
- Math - Least Common Multiple (new editor):
4 6 -> 12, -4 6 -> 12; any 0 makes the result 0. The same input rules as Greatest Common Divisor; the calculation stops with an error as soon as the result has more than 1,000 digits.
- Math - Prime Factorization (one value per line):
360 -> 2^3 × 3^2 × 5, 97 -> 97. Integers from 2 to 9007199254740991 (2^53 − 1); others are errors. It divides by 2, 3 and the numbers 6k ± 1 up to the square root, so a large prime near 2^53 takes about 30 million trial divisions; one run (all lines and selections together) stops with an error after 100,000,000 trial divisions (about three primes near 2^53), and nothing is changed.
- Lists (the whole selection is replaced):
- Math - Differences Between Consecutive Numbers:
1 4 9 -> 3 5 (the reverse of Math - Cumulative Sum). The numbers are the number tokens of the selection (as in Math - Median); the differences are separated by the selection's line break (LF or CRLF) when it has one (1⏎4⏎9 -> 3⏎5), otherwise by a space. Fewer than 2 numbers is an error.
- Math - Collapse Integers to Ranges:
1 2 3 5 7 8 -> 1-3, 5, 7-8. The items are separated by spaces, tabs, commas or line breaks (several in a row count as one); each must be an integer from 0 to 9007199254740991. They are sorted, duplicates are removed, and the result is one line. Negative numbers, decimals and other text are errors.
- Math - Expand Ranges to Integers:
1-3, 5 -> 1, 2, 3, 5. The items are separated as for Collapse, and each is an integer or a range a-b (0 ≤ a ≤ b); spaces and tabs may surround the dash (1 - 3, 1 -3 and 1- 3 all mean 1-3), but not a line break. Since negative numbers are not accepted, a dash always means a range, and -3, 1-, 1--3, 1-3-5 and 3-1 are errors. The integers are written in the order of the ranges, duplicates included (5, 1-2, 2 -> 5, 1, 2, 2), as one line. If the ranges expand to more than 10,000 integers, a warning is shown and nothing is changed (counted before anything is generated, so 0-9007199254740991 is refused at once).
- Units (one value per line, rounded to 4 decimal places, without a unit symbol):
- Unit: m to ft / ft to m (1 ft = 0.3048 m):
1 -> 3.2808, 10 -> 3.048.
- Unit: m² to Tsubo (坪) / Tsubo (坪) to m² (1 tsubo = 400/121 m², about 3.3058 m²):
100 -> 30.25, 30.25 -> 100.
- Unit: Degrees to Radians / Radians to Degrees:
180 -> 3.1416, 3.14159265 -> 180.
Limitations of the extended number commands
- Size and limits: A selection can be up to 5,000,000 characters, and a run whose results would exceed 10,000,000 characters in total is refused with a warning, as in section 10. English words: 100 words per line. Fractions: 30 digits per integer. Two's complement: 20 digits. Greatest Common Divisor / Least Common Multiple: 1,000 digits per integer and a result of at most 1,000 digits. Prime Factorization: 2^53 − 1 and 100,000,000 trial divisions per run. Expand Ranges: 10,000 integers. The limits are checked before or while computing, so no input can make VS Code wait for long.
- Floating point: Round to Significant Figures, Round to Nearest Multiple, Clamp to Range, Multiply by N, Fraction to Decimal, Differences and the Unit commands use floating-point numbers, so input with more than 15 to 17 significant digits loses precision. Round to Nearest Multiple treats a quotient within about 15 significant digits of a half as exactly a half (that is how
0.15 (0.1) gives 0.2). Round to Significant Figures of a value next to the largest floating-point number that rounds up beyond it is an error and the text is left unchanged (1.7976931348623157e308 (1) -> line 1: the result is out of range).
- Number formats: From IEEE 754 Hex writes the shortest round-trip decimal (it can have 17 significant digits,
0.30000000000000004), unlike the other commands. To IEEE 754 Bits with 32 rounds to the nearest single, so From IEEE 754 Hex of the result can differ from the input (0.1 -> 0x3DCCCCCD -> 0.1 as a single, 0.10000000149011612 as a double).
- Number tokens: Greatest Common Divisor, Least Common Multiple and Differences read the numbers with the number-token rules of Math - Median (section 10), not as a list of items: a dash or comma between digits is not part of a number. So
12-18 is read as 12 alone (the -18 touches 12), and 1,000 10 as 1, 000 and 10 (Greatest Common Divisor gives 1). Remove thousands separators first (Number - Remove Thousands Separator) and separate the numbers with spaces or line breaks.
- Roman numerals and English words: Roman numerals are limited to 1 to 3999 in the standard form (no overlines, no
IIII). English words follow the American short scale of Number - To English Words (no a hundred, one and a half or British thousand million).
- Tsubo: 1 tsubo is defined as 400/121 m² (the legal definition, about 3.305785 m²); some tools use the rounded 3.3058 or 3.3 m², which gives slightly different results.
25. Dates, Generators & Random (Extended)
Twenty-four more commands: fifteen Date - … commands (ISO 8601 durations, start and end of the month, business days, RFC 3339 with the offset of a time zone, ISO weeks to dates, the sexagenary cycle (干支), 12-hour <-> 24-hour times, and the time in Snowflake IDs, ULIDs, UUID v7 and MongoDB ObjectIds) are added to the end of the Date Conversion context submenu, six Generate - … commands (brace expansion, multiplication table, Fibonacci numbers, prime numbers, time sequence and the Cartesian product of selections) to the end of the Generate submenu, and three Random - … commands (passphrase, string from your own characters and shuffle words) to the end of the Random submenu. In the Command Palette, the Date commands, Brace Expansion and Shuffle Words appear when text is selected, Cartesian Product of Selections with multiple selections, and the other generators always (they also work with only cursors). They work only on the selected text and the values you enter: nothing is sent over the network (the IDs are only read, never looked up), no file is read, no shell or process is run, nothing is evaluated, and there are no new dependencies (Date, Intl, BigInt and Node.js crypto only). The commands of sections 9 and 13 are unchanged.
In the examples, · is a space, ⏎ is a line break, and a value in parentheses is the value you enter.
- Common rules:
- Date commands: They follow the Date Commands of section 13: one value per line (spaces around it, empty lines and LF / CRLF kept; a line that cannot be read cancels the whole command with its line number), the dates of the new date commands (
YYYY-MM-DD / YYYY/MM/DD, an optional time and offset; years 0001 to 9999), and the same messages for empty selections, errors and cancelled input boxes. Add ISO 8601 Duration, Start of Month, End of Month, Add Business Days and the two time conversions replace each selection; the other date commands open the result in a new read-only editor.
- Generate and Random commands: They follow the Generator Commands of section 9 (document order, one edit and one undo step, a value asked once for all selections and cursors, not saved). Brace Expansion and Shuffle Words read every non-blank selection and ignore empty cursors; Multiplication Table, Fibonacci Sequence, Prime Numbers and Time Sequence read the number or time of a selection, and for empty cursors ask once for it; Passphrase and String from Custom Characters ignore the selected text and give each selection and cursor its own value.
- Limits: The counts and sizes are computed before anything is generated. A value over a limit (from a selection or a size computed from it) shows a warning (
The selection was not changed: …; for Cartesian Product of Selections, The text was not changed: …) and nothing is changed; a value out of range typed in an input box is shown as an error in the input box. A run whose results would exceed 10,000,000 characters in total is refused with a warning.
- Randomness: Passphrase, String from Custom Characters and Shuffle Words take every random number from Node.js
crypto.randomInt, which rejects values to avoid modulo bias; Math.random is not used.
- Durations and months:
- Date - Add ISO 8601 Duration: Asks for a duration (
P1DT2H, PT90M, P1Y2M, P1W; case is ignored; a leading - subtracts; each element is an integer of up to 9 digits, and only the seconds may have up to 3 decimals: PT1.5S; P1.5D is an error) and adds it to each date: 2026-10-01T00:00Z (P1DT2H) -> 2026-10-02T02:00:00Z, 2026-01-31 (P1M) -> 2026-02-28. Years and months move the calendar month first (a day past the end of the month becomes its last day, as Date - Add Months), then weeks and days move the calendar day, then hours, minutes and seconds move the time. The date and time are used as written (no time zone conversion). A date without a time and a duration of only Y / M / W / D stay a date; otherwise the time is rewritten as HH:MM:SS (.sss when the milliseconds are not 0; a date alone gets T and 00:00:00) and an offset as ±HH:MM (Z stays Z): 2026/10/01 10:00+0900 (-PT30M) -> 2026/10/01 09:30:00+09:00, 2026-10-01 (PT1H) -> 2026-10-01T01:00:00. The separator of the date and the T or space before the time are kept.
- Date - Seconds to ISO 8601 Duration (new editor):
5400 -> PT1H30M, 90061.250 -> P1DT1H1M1.25S, 0 -> PT0S. A number of seconds of 0 or more (a safe integer with up to 3 decimals) as days, hours, minutes and seconds; elements that are 0 are left out, and years and months are never used (their length is not fixed). A negative number is an error.
- Date - Start of Month / End of Month:
2026-10-15 -> 2026-10-01, 2026-02-10 -> 2026-02-28, 2024-02-10 -> 2024-02-29. The separator and the time part are kept as written.
- Business days (Monday to Friday; holidays are not taken into account):
- Date - Add Business Days: Asks for N (−100,000 to 100,000) and moves each date by N business days, as Excel's
WORKDAY: 2026-10-02 (Fri, 1) -> 2026-10-05. From a Saturday or Sunday, 1 is the next Monday and -1 the previous Friday; 0 leaves the date unchanged. The time part is kept.
- Date - Count Business Days Between (new editor):
2026-10-01 2026-10-08 -> 5. Two dates on each line, separated by spaces or as in Date - Difference Between Two Dates (a tab, /, .., ~, 〜, ~ or ,). The first date is counted and the last is not; a reversed pair gives a negative number (2026-10-08 / 2026-10-01 -> -5), and a time part is ignored.
- Both are computed in weeks and a remainder, not day by day, so a large N is as fast as a small one.
- Time zones, weeks and years:
- Date - Convert to RFC 3339 with Local Offset (new editor): Asks for an IANA time zone (as Date - Convert to Time Zone) and writes each point in time with the offset of that zone at that moment:
2026-10-01T00:00Z (Asia/Tokyo) -> 2026-10-01T09:00:00+09:00, 2026-07-01 (America/New_York) -> 2026-06-30T20:00:00-04:00; milliseconds are written when they are not 0. Points in time are read as in section 13 (a date without a time is 00:00 UTC, a date and time without an offset is local time, Unix timestamps are accepted). Date - Convert to ISO 8601, by contrast, always writes UTC with Z. An offset with seconds (the local mean time of many zones before about 1900, such as +09:18:59 for Asia/Tokyo in 1850) cannot be written in RFC 3339 and is an error, and so is a result outside the years 0001 to 9999 in that zone.
- Date - ISO Week to Date Range (new editor):
2026-W40 -> 2026-09-28 – 2026-10-04 (Monday to Sunday, joined with –, an en dash). YYYYWww and a lower-case w are also read. Week 53 is accepted only in a year that has one (2026-W53 -> 2026-12-28 – 2027-01-03; 2025-W53 is an error). The reverse of Date - ISO Week Number.
- Date - Sexagenary Cycle (Eto, 干支) (new editor):
2026 -> 丙午, 1984 -> 甲子. A year from 1 to 9999 (年 may follow: 2026年) or a date (its year). The calendar year is used; the start of spring (立春) is not taken into account, so January 2026 is also 丙午.
- 12-hour and 24-hour clocks:
- Date - Convert Time to 12-hour:
14:30 -> 2:30 PM, 0:05 -> 12:05 AM, 12:00 -> 12:00 PM, 23:59:30 -> 11:59:30 PM. Reads H:MM, HH:MM and HH:MM:SS (0:00 to 23:59:59); seconds are kept, and the hour is written without a leading zero.
- Date - Convert Time to 24-hour:
2:30 PM -> 14:30, 12:05 am -> 00:05, 11:59:30PM -> 23:59:30. Reads h:MM or h:MM:SS from 1 to 12 o'clock followed by AM or PM in any case, with one space or none. a.m. / p.m., 午前 / 午後 and hours 0 or 13 to 23 with AM / PM are errors.
- The time in IDs (new editor; the ID is only read):
- Date - Snowflake ID to Date: Asks for the epoch,
discord or twitter (Twitter / X), in any case, and writes the creation time of each ID as ISO 8601 with milliseconds: 175928847299117063 (discord) -> 2016-04-30T11:18:25.796Z. An ID is 1 to 20 decimal digits (checked before BigInt reads it) and at most 2^64 − 1. Which epoch an ID uses cannot be told from the ID: the wrong epoch gives a wrong time without an error.
- Date - ULID to Date:
01ARZ3NDEKTSV4RRFFQ69G5FAV -> 2016-07-30T23:54:10.259Z (26 Crockford Base32 characters in any case, the first 0 to 7; I, L, O and U are errors, not read as 1 and 0).
- Date - UUID v7 to Date:
0190163d-8694-739b-aea5-966c26f8ad91 -> 2024-06-14T10:14:09.300Z (36 characters with hyphens or 32 hexadecimal digits, any case). A UUID of another version (such as v4) or without the RFC 9562 variant is an error.
- Date - MongoDB ObjectId to Date:
507f1f77bcf86cd799439011 -> 2012-10-17T21:13:27Z (24 hexadecimal digits; seconds, so no milliseconds).
- A time after 9999-12-31 (possible for ULIDs and UUIDs) is an error.
- Generators:
- Generate - Brace Expansion: Expands the braces of every line of the selection like a shell, without running any shell:
file{1..3}.txt -> file1.txt⏎file2.txt⏎file3.txt, {a,b}{1,2} -> a1⏎a2⏎b1⏎b2. Supported: lists {a,b,c} (an empty item is kept: {,x}), integer ranges {1..3}, {3..1}, {-1..1} with up to 15 digits, zero-padded when an end has a leading zero ({01..10..3} -> 01⏎04⏎07⏎10), a step ({1..10..2}; its sign is ignored and a step of 0 counts as 1), single-letter ranges {a..e} (counted by character code, so {Z..b} includes the ASCII symbols between them, Z⏎[⏎\⏎]⏎^⏎_⏎`⏎a⏎b, as in bash), nesting, and the escapes \{, \}, \, and \\. Braces without a comma or a range ({a}, {}) and braces that are never closed stay as written, but what is inside them is still expanded ({a,b}{c} -> a{c}⏎b{c}). The strings of one line are joined with the document's line ending, and lines without braces are kept. Limits: braces nested more than 10 deep (literal braces such as {x} count toward the depth too), a range of more than 10,000 terms, more than 10,000 strings from one line or 100,000 from one selection warn and change nothing; they are counted while the line is read, before anything is expanded.
- Generate - Multiplication Table:
3 -> 1·2·3⏎2·4·6⏎3·6·9, 2x3 -> 1·2·3⏎2·4·6. The size is N (N × N), NxM, N×M, N*M or N M (N rows, M columns); each column is right-aligned to its widest number, with one space between columns. For empty cursors it asks for the size (default 9). N and M are 1 to 100: 0 is an error, larger sizes warn.
- Generate - Fibonacci Sequence:
7 -> 0⏎1⏎1⏎2⏎3⏎5⏎8, one per line from 0, exact with BigInt. For empty cursors it asks for N (default 10). N is 1 to 1,000; more warns.
- Generate - Prime Numbers:
20 -> 2·3·5·7·11·13·17·19, the primes up to N (not the first N primes), separated by spaces (a sieve of Eratosthenes of at most about 1 MB, shared by all selections of a run). For empty cursors it asks for N (default 100). N is 2 to 1,000,000; more warns.
- Generate - Time Sequence: Asks for the interval (1 to 1,440 minutes, default 30) and the number of times (1 to 10,000, default 3), then for empty cursors the first time (default
09:00), and writes the times one per line in the form of the first (H:MM, HH:MM or with seconds): 09:00 (30, 3) -> 09:00⏎09:30⏎10:00, 9:00:00 (45, 2) -> 9:00:00⏎9:45:00. Past 24:00 the times start again from 00:00 without a date: 23:30 (60, 3) -> 23:30⏎00:30⏎01:30.
- Generate - Cartesian Product of Selections: Needs two or more selections (with one, a warning is shown before the input box). Asks for a delimiter (literal text, up to 100 characters, no line breaks; empty by default, so the lines are joined directly) and writes every combination of one non-blank line of each selection, one per line, in document order with the last selection varying fastest:
[a⏎b] and [1⏎2] (empty) -> a1⏎a2⏎b1⏎b2, (-) -> a-1⏎a-2⏎b-1⏎b-2. Blank lines are skipped, and a selection or cursor without a non-blank line is a warning. As Selection - Join All Selections into First, the result replaces the first selection and the texts of the others are deleted, in one edit (one undo step), and the result is then the only selection; its lines use the document's line ending. More than 10,000 combinations, or a result over 10,000,000 characters, is computed by multiplication beforehand and warns without changing anything.
- Random (Node.js
crypto.randomInt):
- Random - Passphrase: Asks for the number of words (3 to 20, default 6) and a separator (0 to 10 characters, default
-; spaces are kept, tabs, line breaks and other control characters are errors), and writes that many words, each picked independently (a word can repeat), from a built-in list of 1,338 common English words (3 to 8 lower-case letters, written for this extension rather than copied from another list): (4, -) -> orbit-maple-quiet-lantern. Each word adds about 10.4 bits, so the default 6 words have about 62 bits of entropy (4 words about 41 bits); use more words for a stronger passphrase. The passphrase is written into the document only and is not saved or logged.
- Random - String from Custom Characters: Asks for the characters to use (default
A-Z and 0-9; spaces are kept as characters, repeats are ignored, 1 to 100 different characters (code points), no tabs, line breaks or other control characters) and the length (1 to 10,000 characters, default 16), and picks each character uniformly: (ABC123, 8) -> B3A1CC2A.
- Random - Shuffle Words: Shuffles the words of every line of the selection on its own (Fisher–Yates):
a·b·c·d -> c·a·d·b. Words are separated by spaces, tabs and ideographic spaces (U+3000), which stay where they are together with the indentation and the line breaks (LF / CRLF / CR); a line with one word or none is not changed.
Limitations of the extended date, generator and random commands
- Size and limits: A selection read by a Date command, or by Brace Expansion, Multiplication Table, Fibonacci Sequence, Prime Numbers, Time Sequence or Shuffle Words, can be up to 1,000,000 characters. Cartesian Product of Selections does not limit the length of the selections (only the 10,000 combinations and the 10,000,000 characters of the result below), and Passphrase and String from Custom Characters do not read the selected text. Add Business Days: ±100,000. Brace Expansion: 10 levels of nesting, 10,000 terms per range, 10,000 strings per line and 100,000 per selection. Multiplication Table: 100 × 100. Fibonacci Sequence: 1,000 terms. Prime Numbers: N up to 1,000,000. Time Sequence: 10,000 times, 1,440 minutes. Cartesian Product: 10,000 combinations. Passphrase: 20 words. String from Custom Characters: 100 characters to pick from, 10,000 long. Every command: 10,000,000 characters of results per run. Brace Expansion reads the braces of a selection in a few linear passes and writes the strings one by one without building intermediate lists, so even a run that is close to these limits (many selections of nearly 1,000,000 characters full of braces, or an expansion close to the output limit) usually finishes within about a second (well under one on a recent computer; it can take somewhat longer on a slower one).
- Business days: Only Saturdays and Sundays are skipped; public holidays and other days off are not known, so add or subtract them yourself.
- Brace Expansion: Only the forms above are supported: there is no
~, $var, glob or command substitution, and nothing is run. The result can differ from bash in edge cases (for example quoting with '…' or "…" is not understood; only the four backslash escapes are).
- RFC 3339 and time zones: Time zones and offsets come from the
Intl data of the VS Code you use. Historical offsets with seconds are refused rather than rounded.
- Sexagenary cycle: Only the stem and branch of the calendar year are given (no reading such as
ひのえうま, no month or day cycles).
- IDs: Only the time is read; the other parts (worker, random or counter bits) are not checked or shown, and a valid-looking ID is not checked to exist. A Snowflake ID is read with the epoch you choose, whichever service made it.
- Passphrases and random strings: They are as strong as their length allows: a passphrase from the 1,338-word list has about 10.4 bits per word (less than lists of 7,776 words such as Diceware), and a random string has log2(number of characters) bits per character. They are generated locally and never saved, but check them against the rules of the service you use them for.
26. Japanese, Unicode & Markdown (Extended)
Twenty-one more commands: seven Japanese - … commands (vertical text, gojuon rows, search keys, 万 / 億 notation, corporate numbers, decomposing dakuten and readings in parentheses to ruby) are added to the end of the Japanese context submenu (under Transform), seven Unicode commands (mathematical script, fraktur and double-struck letters, small capitals, Python escapes and flag emoji <-> country codes) to the end of the Unicode submenu, and seven Markdown: … commands (sorting and transposing tables, removing and extracting links, reference links to inline links, GitHub alerts and <kbd> keys) to the end of the Markdown submenu of Transform; all of them are also in the Command Palette when text is selected. They work only on the selected text and the values you choose: nothing is sent over the network (a corporate number is never looked up, a URL is never opened), no file is read, no shell or process is run, nothing is evaluated, and there are no new dependencies. The commands of sections 11, 15 and 18 are unchanged.
In the examples, · is a space, ⏎ is a line break, ⇥ is a tab, and a value in parentheses is the value you choose.
- Common rules:
- Japanese and Unicode commands: They follow the common rules of the Japanese Text Commands of section 11 and of section 15 (empty selections skipped,
Select the text to convert. when nothing else is selected, nothing changed when one selection fails, LF / CRLF kept, characters never cut apart). Convert to Vertical Text and Escape Unicode (Python) open the result in a new read-only editor, Validate Corporate Number shows a notification, and the other commands replace each selection. Gojuon Row and Number to Man/Oku Notation read one value per line as in section 11 (blank lines and the spaces around each value kept; a line that cannot be read cancels the whole command with its line number).
- Markdown commands: They follow the common rules of section 18 (each selection on its own, one undo step, the document's line ending,
The text was not changed: … when a selection cannot be converted). Extract Links opens its result in a new read-only editor; the others replace each selection. A choice (sort order, alert type) is made in a quick pick, once for all selections.
- Limits: A selection given to a Japanese or Unicode command can be up to 1,000,000 characters (a longer one is an error and nothing is changed); the Markdown commands have no limit of their own on the length of a selection, as in section 18. For all of them, a run whose results would exceed 10,000,000 characters in total is refused with a warning and nothing is changed. Convert to Vertical Text and Transpose Table compute the size of their result before building it.
- Japanese:
- Japanese - Convert to Vertical Text (new editor):
あい⏎う -> うあ⏎ い. Each line becomes a column read from top to bottom, the first line on the right. Short columns are filled with ideographic spaces (U+3000), a half-width space becomes one too, and ー, the brackets (){}〔〕【】《》〈〉「」『』[], 、。 and …‥ become their vertical presentation forms (ー -> |, 「 -> ﹁, 、 -> ︑, …). A line break at the end of the selection does not make an empty column; an empty line in the middle does.
- Japanese - Gojuon Row (Index Heading) (one value per line):
さとう⏎ガイド -> さ行⇥さとう⏎か行⇥ガイド. Puts the gojuon row of the first kana and a tab before each line. Katakana and half-width katakana count like hiragana; voiced, semi-voiced and small kana belong to the row of their plain kana, ゔ to あ行 and ん to わ行. A line that does not start with kana is an error.
- Japanese - Normalize for Search:
ガイドABC -> がいどabc. Makes a search key in one step: NFKC, katakana to hiragana, lower case, and the dashes and tildes right after kana (ー ‐ ‑ − — ― - ~ 〜 and the like) to ー. Because the dashes are judged after NFKC (which turns - into - and ~ into ~), an ASCII - or ~ right after kana becomes ー too: コード-A1 -> こーどーa1. This differs from Japanese - Normalize Hyphens and Long Vowel Marks of section 11, which never changes the ASCII -; compare keys made by this command only with keys made by this command.
- Japanese - Number to Man/Oku Notation (one value per line):
123456789 -> 1億2345万6789, 100000000 -> 1億. Writes each integer with the units 万, 億, 兆 and 京, keeping Arabic digits (unlike Japanese - Number to Kanji Numeral); groups of zeros are left out. A sign, full-width digits and , every three digits are accepted, the sign and the comma also in full width (-1,234 -> -1234). The digits are counted before the number is read: an absolute value above 10^20 − 1, a decimal or a misplaced comma is an error.
- Japanese - Validate Corporate Number (notification):
7000012050002 -> Corporate number: valid. Checks the check digit (the first digit) of each 13-digit Japanese corporate number (法人番号) and shows valid, invalid or not a corporate number; with several selections each one is listed (#1 valid, [#2](https://github.com/imahiro-t/selection-manipulator/issues/2) not a corporate number), and with more than 10 only the counts. Full-width digits are accepted, and spaces and hyphens (also -, ‐, ‑ and −) are ignored; ー is not a separator. The notification never contains the selected text.
- Japanese - Decompose Dakuten:
がぱヴ (゛ ゜) -> か゛は゜ウ゛. The reverse of Japanese - Compose Dakuten: splits full-width kana with a voiced or semi-voiced sound mark (including ゔ ヴ ヷ–ヺ and ゞ) into the plain kana and the mark, written as spacing marks ゛ ゜ or as combining marks U+3099 / U+309A (chosen in a quick pick). Half-width katakana and other characters are not changed.
- Japanese - Parenthesized Reading to Ruby Notation:
漢字(かんじ) / 漢字(かんじ) -> |漢字《かんじ》. A reading of only kana in full-width or ASCII parentheses right after a run of kanji becomes ruby notation; the base is the whole run of kanji before the parenthesis, and other parentheses are kept. A | or an ASCII | right before the base is taken as the start mark of the ruby and is not doubled: |漢字(かんじ) -> |漢字《かんじ》, |漢字(かんじ) -> |漢字《かんじ》. So in a Markdown table written without spaces, the cell |漢字(かんじ)| becomes |漢字《かんじ》|, the | of the table serving as the start mark (no character is lost; add a space after the | to keep them apart). When something else comes before the base, a | is added: |かな漢字(かんじ) -> |かな|漢字《かんじ》. Japanese - Remove Ruby Notation of section 11 does the opposite and already removes readings in parentheses.
- Unicode:
- Unicode - Mathematical Script / Mathematical Fraktur / Mathematical Double-struck:
Abc -> 𝒜𝒷𝒸 / 𝔄𝔟𝔠, Ab1 -> 𝔸𝕓𝟙. A–Z and a–z (and 0–9 for double-struck), like Unicode - Mathematical Bold of section 15; the letters Unicode encodes in the Letterlike Symbols block are used for them (ℬ ℰ ℱ ℋ ℐ ℒ ℳ ℛ ℯ ℊ ℴ, ℭ ℌ ℑ ℜ ℨ, ℂ ℍ ℕ ℙ ℚ ℝ ℤ). Other characters are kept.
- Unicode - Small Capitals:
abc -> ᴀʙᴄ. Lowercase a–z to small capitals; x has no small capital and is kept, as are uppercase letters and other characters.
- Escape Unicode (Python \U00XXXXXX) (new editor):
é😀 -> \xe9\U0001f600. Escapes every non-ASCII character as Python's ascii() does: U+0080–U+00FF as \xhh, the rest of the BMP as \uhhhh (lone surrogates too) and other code points as \Uhhhhhhhh, in lowercase hexadecimal; ASCII is kept. Escape Unicode (\uXXXX) writes the JavaScript form.
- Unicode - Country Code to Flag Emoji:
JP -> 🇯🇵. Every run of exactly two ASCII letters (either case) that is not next to another letter becomes two regional indicator symbols, which most systems show as the flag of that country code. The codes are not checked against ISO 3166-1, so ordinary two-letter words such as is, to or OK are converted too (It·is·OK -> 🇮🇹·🇮🇸·🇴🇰), and an unassigned code shows as two boxed letters; select only the codes. Runs of one letter or three or more letters are kept.
- Unicode - Flag Emoji to Country Code:
🇯🇵 -> JP. Regional indicator symbols become uppercase ASCII letters; a symbol without a partner becomes one letter.
- Markdown:
- Markdown: Sort Table by Column: Asks for the column number (1 to 1,000) and the order (ascending or descending, in a quick pick) and sorts the data rows:
|·k·|·v·|⏎|---|---|⏎|·b·|·2·|⏎|·a·|·1·| (1, ascending) -> |·k·|·v·|⏎|---|---|⏎|·a·|·1·|⏎|·b·|·2·|. Cells are compared in natural order (numbers by value); the header and delimiter rows stay on top, rows with equal cells keep their order, and a row without that cell sorts as empty. A column number beyond the header is a warning. Rows are moved as written, so escaped \| and code spans stay intact.
- Markdown: Transpose Table:
|·a·|·b·|⏎|---|---|⏎|·1·|·2·| -> |·a·|·1·|⏎|·---·|·---·|⏎|·b·|·2·|. The header row counts as a row and the first column becomes the new header; missing cells become empty cells, and the delimiter row is rewritten with --- (alignments are not carried over). Cells are written as they were, so \| stays escaped.
- Markdown: Remove Links (Keep Text):
[Docs](https://x.example) -> Docs. Each inline link becomes its text; images stay ([](https://github.com/imahiro-t/selection-manipulator/blob/HEAD/url) -> ), and links in code spans and fenced code blocks are left. Unlike Markdown: Strip Formatting, all other markup is kept.
- Markdown: Extract Links (new editor):
[a](https://github.com/imahiro-t/selection-manipulator/blob/HEAD/u1)· -> a⇥u1⏎b⇥u2. Lists the inline links and images of the selections in document order as text⇥url lines (links and images in code are skipped; a linked image keeps its  as the text; tabs and line breaks in a field become a space). With none, an information message is shown. The URLs are only copied, never opened.
- Markdown: Reference Links to Inline Links:
[a][1]⏎⏎[1]:·https://x.example -> [a](https://x.example). The reverse of Markdown: Inline Links to Reference Links: full [text][label] and collapsed [text][] references (images too) in the selections become inline links, using one-line definitions anywhere in the document (labels compare without case and with runs of whitespace as one space; the first definition wins). The destination and title are written as in the definition (<…>, quotes and escapes kept; a bare destination with unbalanced parentheses is written as <…>). Shortcut references [label] and definitions over several lines are not converted. Definitions inside the selections that are no longer referenced anywhere are removed (with the blank lines before them when they end the selection); definitions outside the selections are never changed. With nothing to convert, an information message is shown.
- Markdown: GitHub Alert Block:
text (NOTE) -> >·[!NOTE]⏎>·text. Wraps the selection in a GitHub alert: the type is chosen in a quick pick from a fixed list, NOTE, TIP, IMPORTANT, WARNING and CAUTION (no other type can be typed; the choice is checked again before it is written), and every line gets >· (> for a blank line). The block gets lines of its own, and a blank line after it when text follows.
- Markdown: Keyboard Key ():
Ctrl+C -> <kbd>Ctrl</kbd>+<kbd>C</kbd>. Wraps each key of a shortcut in <kbd> tags on every line: keys are separated by +, a + where a key is expected is the plus key (Ctrl++ -> <kbd>Ctrl</kbd>+<kbd>+</kbd>; a++b -> <kbd>a</kbd>+<kbd>+</kbd>+<kbd>b</kbd>), spaces around a key are dropped, and a key name with spaces (Page Up) is one key. Key names are HTML-escaped first (< > & " '), so <script> becomes <kbd><script></kbd> and no tag can be injected.
Limitations of the extended Japanese, Unicode and Markdown commands
- Size and limits: A selection can be up to 1,000,000 characters for the Japanese and Unicode commands; the Markdown commands only limit the results. The results of a run can be up to 10,000,000 characters in total for all three groups. Convert to Vertical Text: up to 1,000 lines and 1,000 characters (graphemes) per line; more warns and shows nothing. Sort Table by Column: column 1 to 1,000.
- Vertical text: The result is plain text laid out in a grid, not real vertical writing: only full-width characters line up, while half-width letters, digits and emoji are as wide as the font makes them. Only the characters listed above get vertical forms; other punctuation, half-width katakana and Latin letters are not rotated, and lines are never wrapped (one line is one column, so long lines make tall columns).
- Corporate numbers: The check digit is data validation that catches typing mistakes, not a cryptographic check: a number that passes may still not exist, and nothing is looked up (there is no external lookup of the National Tax Agency's corporate number database).
- Search keys: Normalize for Search is meant for comparing keys made by the same command; because of the ASCII
- / ~ rule above, コード-A1 and コードーA1 give the same key, which Normalize Hyphens and Long Vowel Marks would keep apart.
- Ruby: Only readings of kana right after kanji are converted (
ABC(えーびーしー) is kept), and an existing | or | right before the base text, including the | of a Markdown table cell, is used as the ruby start mark.
- Styled letters and flags: Mathematical alphanumerics and small capitals are meant for display; screen readers and search may not read them as letters, and some small capitals are missing from older fonts. Country Code to Flag Emoji converts every isolated pair of letters, words included.
- GitHub alerts: Only the five types above exist; other renderers may show the block as a plain quote.
Development
Node.js: Use Node.js 22 (22.13 or later), the same major version as CI. The version is declared in .nvmrc and .tool-versions, so nvm install && nvm use or asdf install picks it up (the accepted range is also in engines.node of package.json). Older versions such as Node.js 20.10 fail on npm run lint, because ESLint 10 needs a newer Node.js.
Build and test: Run the same steps as CI:
npm ci
npm run lint
npm run test-compile
npm run esbuild
npm test
npm run test:showcase
npm run showcase:check
Security
- Security Policy: How to report a vulnerability, and the implementation rules every new command must follow (local processing only, no code/shell execution, no network access, no remote resources in Webviews, no new dependencies by default).
| |