Skip to content

sim 0.2.0

Latest

Choose a tag to compare

@nagamine-git nagamine-git released this 21 Oct 00:40
· 1 commit to main since this release

Added

  • <C-w> moves the focus between the text and the tree and leaves the tree open: <C-w>w (and W, p, <C-w>) goes to the other one, <C-w>h or <C-w><Left> to the tree (opening it), <C-w>t to the tree if it is open, <C-w>l, <C-w><Right> or <C-w>b to the text. Ctrl-n is as it was. Insert mode, the command line and the picker keep their Ctrl-w, and the rest of Neovim's <C-w> keys are not taken: sim has no split windows (TREE-2).
  • The tree's folder keys are Neo-tree's: Enter opens a closed folder and closes an open one, C closes the folder (or, on a file, the folder that holds it), z closes them all, and Z opens the folder under the cursor and every folder below it, never a git-ignored folder or a link, at most 200 a press (TREE-4).
  • The bar says colors stopped among its state words, for as long as it is so, for a file whose parse the highlighter gave up after 5 s (it was said once on the status line, where a key ended it) (SYN-3).
  • The changes view: <Space>ge opens the panel with only the files that differ from HEAD, staged and unstaged together and untracked ones too, in their folders. Each file shows its status letter and +n −n from git diff --numstat HEAD (an untracked file its line count) and each folder the sums. Deleted files are listed, and Enter opens HEAD's version of one read-only, as a buffer named HEAD:path whose tab says so; a rename is one row, old → new, with a cut that keeps the new name whole and marks every cut with …. <Space>ge again, or q, goes back to the tree. In sim --plain the key is refused, naming plain mode (DIFF-1 to DIFF-6).
  • The editor's title is a breadcrumb, src › sim.rs › leader_key: the file's path below the root and the section the cursor is in, the nearest Markdown heading or the function, impl, class, struct, trait or module it is inside (found by a few string tests over the lines above it, not a parse). In depth it is the title of the editor's box, in flat it is at the right of the tab bar, and long ones are cut from the left with … (UI-18).
  • The Markdown read view: in a Markdown file every line but the cursor's (and, in Visual mode, the selected ones) is drawn as it reads, in place and in the one pane: the markers of emphasis (**, *, _) and of inline code are not drawn, and tables are aligned by display width (a Japanese cell counts two columns a char, :--, :-: and --: align the text, the delimiter row is ├─┼─┤). Only those markers are ever hidden, never a #, a bracket, a URL or a char of text, and a char shown in another form (^[, <U+202E>) is still the alert's block wherever it is: in a span, a link, a URL, a cell or code (MD-2). A table that does not fit the pane, or has a cell too many, stays raw, whole. <Space>um turns the read view off and on, the choice is remembered in the state directory and the first run is on; sim --plain has none; a click in a read line puts the cursor on the char of the file under the pointer; and the window draws it too (MD-1 to MD-9)
  • sim-gui, a window for sim, in gui/ (a third workspace member, publish = false: it is not on crates.io, Homebrew or the AUR yet, and the sim binary and the sim-editor and sim-editor-core crates do not depend on it). It draws the depth look on the GPU (boxes raised from a floor with soft shadows, a chip for the shown tab, a window that floats over a dimmed page, a char shown in another form as a rounded pill) from the editor's own screen: the keys, the modes, the colors and the jobs are sim's, and the window keeps no rule of its own (GUI-1 to GUI-17). It is built with cargo run -p sim-gui -- <file>; the text is set in the first common coding font the system has (JetBrains Mono, Fira Code, Cascadia Mono, Source Code Pro, Noto Sans Mono, DejaVu Sans Mono, Liberation Mono, Menlo, Monaco, then the system's monospace; SIM_GUI_FONT names another, sim-gui --help lists everything it reads from the environment), the input method works where a key is text, and SIM_GUI_REDUCED_MOTION turns the motion off. It starts through the same function as the terminal, so it is plain as root and as the editor of sudoedit (PLAIN-1: no git, no ripgrep, no filter, no hook), and a hangup or a termination snapshots what is unsaved as in the terminal. Its dependency list is closed and has no webview and nothing that speaks to a network. Not seen on a real display yet.
  • The frame says what the guard did to a repository: where git is not run for the repository's config the tree's box says git not run in the alert's block (in flat, the tree's header does) and the lines of both boxes are the alert's, and where git runs with settings of the repository's own turned off (the monitor, the hooks path, an external diff, a text conversion, a filter) it says n git settings off; a narrow panel gets a shorter form. The status line names the first setting once, and <Space>gi says again why git was not run or which settings were turned off (GIT-5).
  • The lines another process has just written into the open file are lit for 400 ms, the whole text of each in the change's green as a solid block, bold (bold on inverse with no color), and are then marked as they were (UI-19). The core lists the lines a merge marked (App::wrote, one field).
  • A Markdown link whose text looks like an address that its target is not ([https://good.example](https://evil.example), a host that differs, a path that differs from a target with no host, or a javascript:, data: or vbscript: target) has its target drawn on the alert's block in the raw line and in the read view, which hides no bracket, text or URL of a link (MD-10).
  • :tutor: about fifteen minutes of short lessons in a scratch buffer, in the language of LC_ALL, LC_MESSAGES or LANG (English, 日本語, 简体中文, 繁體中文, 한국어, Español, Português, Français, Deutsch, Русский; English for any other), with exercises that are graded as you type: a row [ ] 1.1 … shows ✗ and shows ✓ as soon as the lines under it are right (and ✗ again if you undo). Nine lessons in the editor (movement, typing, deleting and changing, undo, copy and paste, searching, saving and quitting, what sim shows that other editors hide, and the finder, the tree, the looks and <Space>bk, whose exercises are marked done when you do them) and eight with --plain. Nothing typed there writes a file or a snapshot: :w, :wq, :x, ZZ and :w name all say the tutor is a scratch copy, the status line calls it [tutor], and :q! leaves it (TUTOR-1 to TUTOR-4).
  • Markdown callouts (GitHub's alerts): > [!NOTE], [!TIP], [!IMPORTANT], [!WARNING] and [!CAUTION], in any case, on a quote's first line with a body after it, are drawn in the read view as the kind's word (Note) in bold, with GitHub's octicon before it where zi has the icons on; no kind has a hue (the word, always, and the icon tell it; in flat and depth the bar is the primary gray where a plain quote's is the secondary; calm and NO_COLOR have the word in bold), and the line the cursor is on shows [!NOTE] as typed, in bold. Which quotes are callouts was measured against GitHub's renderer (24 forms in a test); other [!KIND]s stay quotes (MD-11).
  • Calm lights a yank too, for the same 150 ms: the text it took is in the gray of a Visual selection (lightness alone, |Lc| >= 15 against the page, SYN-5), and underlined where the selection is (no truecolor, NO_COLOR). It showed nothing; the flash in flat and depth is as it was (UI-13).
  • <Space>bk says again where the version that :w! or :e! gave up was copied, alone on the status line (a path wider than the line is cut from the left, so the file's name stays), as <Space>gi does for the guard (SAFE-7).
  • Every char that is invisible is shown (SAFE-10, SAFE-11): format chars (Cf), unassigned code points, tag characters (the way an instruction is smuggled to a language model), variation selectors (the way code was hidden in packages), Hangul fillers, soft hyphens, word joiners, line separators and the other chars named in the SPEC are drawn as <U+E0041>, in the text, the status line, the messages, the command line and every name and line that comes from a file (the tree, the tabs, the breadcrumb, the search, the picker). A zero-width joiner joins nothing, so it is a form too; emoji sequences, a keycap, the three flags of England, Scotland and Wales, a selector after a pictograph and the icons of a Nerd Font stay as they are. A kanji followed by an ideographic variation selector shows the selector: the price of closing a channel that hid bytes, which falls on Japanese. One table in the core (core/src/core/hidden.tbl, Unicode 18.0.0) says which chars; the editor asks it. Measured against Neovim 0.12.5 in NOTES.
  • Marks (VI-17): ma to mz set a mark in the file; 'a goes to the first non-blank of its line and `a to its place, with an operator (d'a, y`a) and in Visual mode; '' and `` go back to where the cursor was before the last jump (G, gg, /, n, N, *, #, %, a mark, :s, u), as Neovim's do. A mark follows its text through edits and undo (it goes with its line when the line is deleted), and through a change that comes from the disk (DISK-6); a mark that is not set says mark not set: a and nothing moves. :marks lists them on one line. In memory only, one set for each file. core/tests/oracle.rs compares them with Neovim (SIM_ORACLE_MODE=mark).
  • :registers shows each register whole where there is room, and a long one takes what the short ones leave (cut with …).
  • Registers (VI-15): "a to "z hold text and "A to "Z add to it, "" is the unnamed one, "0 the last yank, "1 to "9 the last deletes of a line or more, "- the small deletes, "_ takes anything and holds nothing; the name goes before a command or between its count and it ("ayw, "Ayy, "ap, 2"ayy), in Visual mode too, and . after "1p puts "2p. :registers (:reg) says what they hold, with a line break as ⏎ and a control character as ^[. They live in memory only (nothing is written, not in a snapshot either) and every open file shares them. A yank with a name stays in sim, even over ssh and in tmux; "+ and "* are one register that writes the system clipboard (also a cut: "+dd) and holds what was sent ("0 is the plain yank's alone); it is never read, "+p says to paste with the terminal. A register is a rope that shares its text with the buffer and the undo steps: nine deletes of a 10 MB file add nothing (87 MB as strings), and core/tests/oracle.rs with SIM_ORACLE_MODE=reg compares them with Neovim.

Changed

  • A name that holds a control char or a bidirectional control is its form (^[, <U+202E>) in the tree, the tabs, the breadcrumb, the results and the picker, where it was the replacement char (U+FFFD); a zero-width joiner that joins no emoji takes the 8 columns of its form where it took none.
  • sim's git is built in one function, and what a command line can stop is neutralized instead of making sim skip the repository: a file system monitor, hooks (core.hooksPath points to an empty private directory), a filter (emptied by name, except git-lfs's own filter as git lfs install writes it, with only git-lfs's harmless settings beside it), an external diff and a text conversion run nothing, and git answers. A repository whose config still could run a command that nothing stops, such as core.sshCommand or an include, is skipped as before, with the key named (GIT-1 to GIT-3).
  • The status line says each fact once. The file's name, which the tab and the breadcrumb say, and Top, Bot and NN%, which the scrollbar shows, are gone from it (they stay where there is no tab bar or no scrollbar); utf-8 and LF are said only when they are not so: not utf-8, CRLF and BOM show at its right when they apply, and the file type only for a script whose name does not tell it (#!/usr/bin/env python3). The core's own line, which sim --plain shows, says CRLF and BOM among its words too (UI-10, VIS-9).
  • The tree is not in fog: its rows no longer fade by their distance from the open file or the cursor. Only the rows that are no match of a / search fade (LOOK-7).
  • Markdown is no longer drawn with every marker on the screen by default: the first run is the read view (<Space>um shows the raw text, and the line the cursor is on is always the file's own text). UI-8's looks are what the raw lines and --plain show.
  • A submodule is one entry with its status and no child git runs in it: git status sees its commit and not its work tree, and every diff of sim's takes no submodule (GIT-4).
  • Without color the scrollbar's handle is a ║ rail at the weight of the text and no longer an inverse block, the brightest thing on the screen even when the file fits (UI-11, COLOR-3). The colors of the handle are as they were.
  • The paints of a yank's flash, a search's matches and a write from outside come before the tint and the words of a changed row, as UI-13 and UI-14 say (they came after, and a changed row hid them).
  • There is no longer one register: a yank without a name still reaches the clipboard through OSC 52 and a delete still does not (VI-8), and " no longer says registers: there is only one.

Fixed

  • A change that the watcher read just before a save was done could be taken in after the save had started, though it was older than the save's answer: App merged it into the buffer over the text that the save was writing, and a later ZZ or :w wrote the merged text over the file, so a line of the user's and of the outside process's was in no place any more (found by the model: the file was deleted and made again, Ctrl-s was typed, and the file was deleted again; DISK-1, a very old race, not new in the marks round). A read that comes in while a save is in flight now waits for the save's answer and is taken in, or dropped as older, by its number.
  • The highlighter no longer spins on a core for ever on JavaScript in a Markdown fence, in an HTML <script> and in the other syntaxes that embed it (a statement without a semicolon that ends in a block comment, a JSDoc comment after return start): syntect's parser went round in a circle on matches that consume nothing, and now goes on one char after 128 of them (a copy of syntect 5.3.0 with that guard is in vendor/, SYN-3). A parse that is only slow is still given up after 5 s.
  • The mark of a link that lies (MD-10) no longer judges a path in the text against a target that has a host: [/r/rust](https://www.reddit.com/r/rust) and [`/dev/urandom`][14] were 46 of the 128 marks in 6,000 real files and all honest, and the browser shows the host. A path whose first segment is a host ([/good.com/login](https://evil.com/login)) is read as that host and is still marked.
  • sim died with a panic when it opened a file whose name starts with digits that read as a line number (h264.rs, e1000.c) and when 123 was typed after a : or / in a file with fewer lines, once the interface was drawn: the status line and the command line were read as numbered lines of the text (UI-6).
  • The message after :w! or :e! ended in the copy's absolute path, which a long state directory or a macOS $TMPDIR pushed off the line: it is now told as a shell takes it, ~/.local/state/sim/a.rs.1.disk below the home directory, and <Space>bk says it again (SAFE-7).
  • The breadcrumb in flat's tab bar was drawn as it was given, so a directory named with an escape sequence, or a Markdown heading with one, could reach the terminal (SAFE-8). The parts are now made fit to be drawn like every other row text (U+FFFD for a control, bidirectional or zero-width char) and both places that draw them draw what fit gives (UI-18).
  • With the cursor on a Markdown fence line the breadcrumb could name the wrong heading for a frame; the line above now says which fence it is (UI-18).
  • The status line said a non-UTF-8 file's encoding twice (read-only: not valid UTF-8 in the middle and not utf-8 at the right); the middle says read-only and the right the format (UI-10).
  • sim --plain no longer shows the icons hint (zi: icons (needs a Nerd Font)) or uses up its one-time marker: zi is refused in plain mode, and the editor's first run after plain ones still gives the hint once (ICON-1, PLAIN-1).
  • The mark of a link that lies (MD-10) could be got around by the form of the link. The target is now read as a browser reads a URL: a \ ends the authority (https://evil.com\@good.com/ goes to evil.com), https:evil.com and https:/\evil.com too, tab and newline are dropped, and an authority with a %, a control char, a blank, an entity or a char that is not ASCII is never taken for another host. The text is found with its brackets nested and escaped ([good.com [x]](…)) and judged word by word after its escapes and entities are decoded ([Visit good.com](…), good&#46;com); a <…> target with blanks, blanks after the (, and a link that goes over lines are judged whole. Reference links are judged by their definitions ([good.com][1] with [1]: https://evil.com: the target is marked on the definition and the text on the use), any two letters are a country code unless they end the name of a source file (paypal.com.mx), and calm marks the link too, as it marks a hidden char.
  • The mark of a link that lies (MD-10) was reviewed again, and a differential fuzz against two renderers (markdown-it and md4c, about 130,000 generated documents) and 6,000 Markdown files of one machine were looked at for what got by and what cried wolf. A line made of brackets could freeze sim for minutes (a walk that was quadratic in the line); the work is now linear and bounded for a line, a frame and a document, and what is past a bound is marked and not trusted. A definition in a block quote or a list item (> - > [1]: …), a reference whose text goes over lines or is written with escapes, entities or emphasis, an image in the text of a reference, and a use that no definition resolves where one may have been missed are judged or marked. A link written in raw HTML (<a href="…">) is judged like the rest, with the tags that a browser reads and CommonMark does not. Code is judged like the rest: a stray backtick, or a fence that a renderer does not open, made a live link look like code to the highlighter. A bracket in a comment, a tag, an autolink or a code span no longer pairs with the wrong one, an escaped \! is no image, the \ of a target is read as the %5C that a renderer writes, a word after a label (site:good.com, url=good.com) or a full stop of another script (good。com) is an address, and strikethrough, a processing instruction, CDATA and a mark of direction no longer hide one. What it no longer marks, because the real files showed it was no lie: a badge (an image in a link), a raw-HTML link around an image, the definitions of a long CHANGELOG, an array or a shell test in code, a version (HTTP/1.1), ~30, a name with underscores, a dot directory, an emoji and a full stop, a subdomain of the host in the text, and Japanese labels. A file is Markdown for this by the highlighter's own table of names (.md, .mdown, .markdown, .markdn), and a line that the highlighter gives a link is looked at in any file.
  • The mark of a link that lies (MD-10) no longer passes a target that has a scheme as a relative path (search-ms: opens a share of the host in the text, tel:, ms-msdt:, https:evil.com): only a target with no scheme is relative, a scheme that is not special and has no // goes to no host a text can name, and mailto: is judged by the host of each recipient, to, cc and bcc. A subdomain is trusted only when the host in the text is not a suffix that many share ([github.io](https://evil.github.io), co.uk, amazonaws.com), and a host with letters that are not ASCII (a Cyrillic о, google.com, google.cоm) is an address that is judged, honest only as the same string or as its punycode. SPEC has a table of the forms of a URL and of a host.

Install: brew install efg-technologies/tap/sim (or brew upgrade sim). Source: sim-0.2.0.tar.gz below; cargo install --locked --path sim in it builds the vendored syntect with its guard.

Full changelog: v0.1.0...v0.2.0