diff options
Diffstat (limited to 'rprt.md')
| -rw-r--r-- | rprt.md | 295 |
1 files changed, 199 insertions, 96 deletions
@@ -8,71 +8,72 @@ A compositional, point-free language for text manipulation. All functions work with two core types: -1. **Selection** — addresses and regions in files - - Rank 0: Position (integer offset) - - Rank 1: Range is a pair of positions [start,end) with capture groups - - Rank 2: A list of ranges with capture groups - - Rank 3: Indexed selection is a mapping of files -> list of ranges with capture groups +1. **Selection** — addresses and regions in buffers + + Every selection exists within one or more buffers. Selections have a rank: + + - **Rank 0**: Position — a natural number offset within a single buffer + - **Rank 1**: Range — a pair of positions [start,end) with capture groups, within a single buffer + - **Rank 2**: Ranges — a list of ranges with capture groups, within a single buffer + - **Rank 3**: Multi-buffer selection — a mapping from buffer identifiers to rank 2 selections + + Ranks 0-2 operate within a single buffer (typically the current buffer). Rank 3 is distinguished by spanning multiple buffers simultaneously. 2. **Text** — string data # 2. Selection Functions -Selection functions produce Selection outputs and take zero or more Selection inputs. They come in nullary, unary (monadic), and binary (dyadic) forms. +Selection functions produce Selection outputs and take zero (nullary functions), one (monadic functions), or two (dyadic functions) inputs of type Selection. ## 2.1 Core Selection Functions -There are ten core selection functions in RPRT. Nine of them have nullary and unary (monadic) forms. The tenth, `,` (span), additionally has binary (dyadic) semantics - it is the only selection function that takes two arguments. - -In the nullary case there are no rank semantics. In the unary case we provide their semantics as a function of the input rank below. - -| Function | Nullary | Rank | -|----------|----------------------------------------------------|---------| -| `.` | Current selection | matched | -| `$` | End of file | 0 | -| `#n` | Character n in file | 0 | -| `n` | Line n in file | 1 | -| `/re/` | First match forward in file from start | 1 | -| `x/re/` | All matches within file | 2 | -| `+n` | Line n in file | 1 | -| `X/re/` | All files and their contents whose name matches re | 3 | -| `,` | Entire file (0,$) | 2 | - -In the unary case, all defined functions are rank preserving. Their action on ranks > 1 are given by broadcasting, that is, `α F` where `α` has rank 2 is computed by applying `F` to each rank 1 range in `α` and collecting the results into a list of ranges, mutatis mutandis for rank 3. - -**Note:** The functions `.` and `X` have no unary or higher arity semantics. To use them as such is erroneous. - -**Note:** When the input has rank 0 (position), all defined unary functions are the identity since positions have no internal structure within which to search or operate. - -| Function | α Rank 1 | -|-----------|-------------------| -| `α /re/` | First re within α | -| `α x/re/` | All re within α | -| `α $` | End position of α | -| `α #n` | Char n within α | -| `α n` | Line n within α | -| `α +n` | Line n within α | -| `α ,` | Identity | - -The span function `,` is the only selection function with binary (dyadic) semantics. It creates ranges by spanning from one selection to another. - -**Semantics by rank:** - -| Rank of α | Rank of ω | Rank of result | Semantics | -|-----------|-----------|----------------|-------------------------------------------------------| -| 0 | 0 | 1 | Range from α to ω | -| 0 | 1 | 1 | Range from α to end of ω | -| 1 | 0 | 1 | Range from start of α to ω | -| 1 | 1 | 1 | Range from start of α to end of ω | -| 0/1 | 2 | 2 | α to each range in ω (broadcast) | -| 2 | 0/1 | 2 | Each range in α to ω (broadcast) | -| 2 | 2 | 2 | Pairwise ranges (zip shortest) | -| 0 | 3 | 3 | α to each range in ω (broadcast) | -| 3 | 0 | 3 | Each range in α to ω (broadcast) | -| 3 | 1/2 | - | Erroneous (TODO: maybe makes sense if indices align?) | -| 1/2 | 3 | - | Erroneous (TODO: maybe makes sense if indices align?) | - -## 2.2 Operators +There are ten core selection functions in RPRT. Seven have nullary and monadic forms. Two (`e`, `B`) have nullary form only. The function `-` additionally has dyadic semantics---it is the only selection function that may take two arguments. + +| Function | Nullary semantics | Output rank | +|------------|------------------------------------------------------------|-------------| +| `e` | Empty selection | 2 | +| `$` | End of buffer | 0 | +| `#n` (n∈ℕ) | Character n in buffer | 0 | +| `n` (n∈ℕ) | Line n in buffer | 1 | +| `/re/` | First match forward in buffer from start | 1 | +| `x/re/` | All matches within buffer | 2 | +| `+n` | Line n in buffer | 1 | +| `B/re/` | All buffers whose name match re, mapping to their contents | 3 | +| `-` | Entire buffer (0-$) | 2 | + +In the monadic case, all defined functions are rank preserving. Their action on ranks > 1 are given by broadcasting, that is, `α F` where `α` has rank 2 is computed by applying `F` to each rank 1 range in `α` and collecting the results into a list of ranges, mutatis mutandis for rank 3. + +**Note:** The functions `eB` have no monadic or dyadic forms. To use them as such is an error condition. + +**Note:** When the input has rank 0 (position), all defined monadic functions are the identity since positions have no internal structure within which to search or operate. + +| Function | Semantics for rank 1 `α` | +|-----------|--------------------------| +| `α /re/` | First re within `α` | +| `α x/re/` | All re within`α` | +| `α $` | End position of`α` | +| `α #n` | Char n within`α` | +| `α n` | Line n within`α` | +| `α +n` | Line n within`α` | +| `α -` | Identity | + +The span function `-` is the only selection function with dyadic semantics. It creates ranges by spanning from one selection to another. + +| Rank of `α` | Rank of `ω` | Rank of `α-ω` | Semantics | +|-------------|-------------|---------------|-------------------------------------------------------| +| 0 | 0 | 1 | Range from `α` to `ω` | +| 0 | 1 | 1 | Range from `α` to end of `ω` | +| 1 | 0 | 1 | Range from start of `α` to `ω` | +| 1 | 1 | 1 | Range from start of `α` to end of `ω` | +| 0/1 | 2 | 2 | `α` to each range in `ω` (broadcast) | +| 2 | 0/1 | 2 | Each range in `α` to `ω` (broadcast) | +| 2 | 2 | 2 | Pairwise ranges (zip shortest) | +| 0 | 3 | 3 | `α` to each range in `ω` (broadcast) | +| 3 | 0 | 3 | Each range in `α` to `ω` (broadcast) | +| 3 | 1/2 | - | Erroneous (TODO: maybe makes sense if indices align?) | +| 1/2 | 3 | - | Erroneous (TODO: maybe makes sense if indices align?) | + +## 2.2 Selection Function Operators Operators take functions as arguments and return new functions. @@ -80,29 +81,29 @@ Operators take functions as arguments and return new functions. The reverse operator `'` takes a selection function and reverses its direction. -**Note:** `'F` is not defined when `F` is one of the functions `.X,` . +**Note:** `'F` is not defined when `F` is one of the functions `e-B` . -| Function | Nullary | Rank | -|----------|-------------------------------|------| -| `'$` | Start of file (position 0) | 0 | -| `'#n` | Character n from end of file | 0 | -| `'n` | Line n from end of file | 1 | -| `'/re/` | First match backward from end | 1 | -| `'x/re/` | All matches, right-to-left | 2 | -| `'+n` | Line -n in file | 1 | +| Function | Nullary | Rank | +|----------|--------------------------------|------| +| `'$` | Start of buffer (position 0) | 0 | +| `'#n` | Character n from end of buffer | 0 | +| `'n` | Line n from end of buffer | 1 | +| `'/re/` | First match backward from end | 1 | +| `'x/re/` | All matches, right-to-left | 2 | +| `'+n` | Line -n in buffer | 1 | -In the unary case, all functions are rank preserving, and all of the above functions are the identity on rank 0 inputs. Their action on ranks > 1 is by broadcasting. +In the monadic case, all functions are rank preserving, and all of the above functions are the identity on rank 0 inputs. Their action on ranks > 1 is by broadcasting. -| Function | α Rank 1 | -|------------|--------------------------------| -| `α '$` | Start position of α | -| `α '#n` | Char n from end of α | -| `α 'n` | Line n from end of α | -| `α '/re/` | First match backward within α | -| `α 'x/re/` | All matches right-to-left in α | -| `α '+n` | Line -n within α | +| Function | Semantics for rank 1 `α` | +|------------|----------------------------------| +| `α '$` | Start position of `α` | +| `α '#n` | Char n from end of `α` | +| `α 'n` | Line n from end of `α` | +| `α '/re/` | First match backward within `α` | +| `α 'x/re/` | All matches right-to-left in `α` | +| `α '+n` | Line -n within `α` | -**Note:** When the input has rank 0 (position), all defined reversed unary functions are the identity since positions have no internal structure within which to search or operate. +**Note:** When the input has rank 0 (position), all defined reversed monadic functions are the identity since positions have no internal structure within which to search or operate. ### 2.2.2 The Sequential Operator `;` @@ -110,16 +111,16 @@ The sequential operator `;` transforms a selection function from operating "with **Note:** It is erroneous to use `;F` in the nullary case. TODO: or are there interesting semantics? -**Note:** `;F` is not defined when `F` is one of `.X,` . +**Note:** `;F` is not defined when `F` is one of `e-B` . -| Function | α Rank 0 | α Rank 1 | -|------------|----------------------------|-----------------------------------| -| `α ;$` | End of file | End of file (ignores α) | -| `α ;#n` | Character n after α | Character n after end of α | -| `α ;n` | Line n after α | Line n after end of α | -| `α ;/re/` | First match forward from α | First match forward from end of α | -| `α ;x/re/` | All matches forward from α | All matches forward from end of α | -| `α ;+n` | Line n after α | Line n after end of α | +| Function | Semantics for rank 0 `α` | Semantics for rank 1 `α` | +|------------|------------------------------|-------------------------------------| +| `α ;$` | End of buffer | End of buffer (ignores `α`) | +| `α ;#n` | Character n after `α` | Character n after end of `α` | +| `α ;n` | Line n after `α` | Line n after end of `α` | +| `α ;/re/` | First match forward from `α` | First match forward from end of `α` | +| `α ;x/re/` | All matches forward from `α` | All matches forward from end of `α` | +| `α ;+n` | Line n after `α` | Line n after end of `α` | ### 2.2.3 The Complement Operator `~` @@ -127,20 +128,122 @@ The complement operator `~` takes a selection function and produces a new select | Rank of output of `F` | Rank of output of `~F` | Semantics | |-----------------------|------------------------|------------------------------------------------------------------| -| 0 | 2 | The complement of the position its file as a selection | -| 1 | 2 | The complement of the range in its file as a selection | +| 0 | 2 | The complement of the position its buffer as a selection | +| 1 | 2 | The complement of the range in its buffer as a selection | | 2 | 2 | The selection corresponding to the ranges between the selections | -| 3 | 3 | The broadcast of `~` to each file | +| 3 | 3 | The broadcast of `~` to each buffer | -## 2.3 Composition and Parsing +# 3. Text Functions and Editor State -**Operator application:** Functions are modified by operators. All operators commute: `';F` = `;'F`. +## 3.1 The Editor State Monad -**Precedence:** Following BQN rules: -- Operators bind tighter than functions -- Functions apply left-to-right -- Binary functions are infix +All RPRT expressions evaluate within an implicit `EditorState` monad containing: +- Buffer contents (for all open buffers) +- Current buffer +- Current selection +- File/buffer mappings + +Selection and Text functions have signatures `EditorState Selection` and `EditorState Text` respectively. + +## 3.2 Type Coercion + +When a Text argument is required, a Selection is implicitly coerced to Text by extracting its contents. This coercion has no side effects. + +| Input rank | Coerced Text | +|------------|------------------------------------------------------------------| +| 0 | Empty string (position has no extent) | +| 1 | Contents of the range | +| 2 | Contents of each range (text function broadcasts per range) | +| 3 | Contents per buffer per range (broadcasts per buffer then range) | + +For ranks 2 and 3, the selection provides multiple text values. Text operations broadcast accordingly: if `α F β` where β is rank 2, the operation applies once per range in β, using the contents of each range as the text argument. + + +## 3.3 Text Operations + +Text operations have signature `Selection × Text → Selection`. They modify the editor state (buffer contents) and return the affected Selection. + +TODO: unfortunately `.` and `d` ignore opposite arguments so we're stuck with not being able to give monadic text funcions? + +| Function | Semantics | +|----------|------------------------------------------------------------------------| +| `α . τ` | Current selection in buffer(s) named by `τ` (`α` ignored) | +| `α c τ` | Change (replace) `α` with text `τ` | +| `α i τ` | Insert text `τ` before `α` | +| `α a τ` | Append text `τ` after `α` | +| `α d τ` | Delete `α` (`τ` ignored) | +| `α w τ` | Write buffers associated with `α` (`τ` ignored) | +| `α \| τ` | Pipe `α` through command `τ`, return rank 3 selection of output buffer | + +**Note:** The text argument `τ` may be a string literal or a Selection (which coerces to Text). + +**Note:** The `.` function unifies multiple use cases: +- `.` (nullary) — current selection in current buffer +- `e . "name"` — current selection in buffer "name" +- `e . β` where β is rank 2 or 3 — current selections in buffers named by β's contents (returns rank 3) + +## 3.4 Evaluation Contexts + +**Top-level Selection:** Sets the editor's current selection. +``` +α # Finds pattern AND sets editor selection to it +``` -## 3. Text Functions +**All text operations:** Modify editor content. Note that `F` returns a selection, so at the top level this also changes the current selection. +``` +α F τ # F modifies contents, sets selection to changed region. +α F (β G τ) # Inner G modifies contents but doesn't set selection. F modifies contents and sets the new selection. +``` -Text functions modify selections, and consume zero or one selections, and one Text value. +**Buffer switching statement:** The `b` statement changes the current buffer in the EditorState. +``` +b "name" # Switch current buffer to "name" +/pattern/ # Searches in "name" +``` + +The `b` statement is not a function and cannot be composed. It only appears as a top-level statement. + +## 3.5 The Grouping Operator `{}` + +The grouping operator `{}` provides transactional semantics: all operations within see the same input editor state, and their modifications are merged with position tracking where possible. Any error aborts the entire evaluation. + +**Syntax:** `{ op₁ , op₂ , ... , opₙ }` + +**Semantics:** +- Captures editor state on entry +- All operations execute with the original positions +- Returns the union of all resulting Selections + +**Example:** + +Where `α` and `β` are selections +``` +α {swap i , d} β +``` + +Evaluates in parallel +* `α (swap i) β` which is `β i α` which means "insert at (the start of) β the content from α" +* `α d β` which means "delete α" + +The net result of this is to _move_ the content of α to (the start of) the selection given by β. + +## 3.6 Shell Integration + +The `|` text function pipes selections through shell commands, returning rank 3 selections for ephemeral buffers containing command output. Use the empty selection `e` to run commands with no stdin. + +**Examples:** + +TODO: throw some combinators in to make this example nicer. + +``` +e | "date" # Run date with no input, returns selection to output +/pattern/ c (e | "date") # Replace pattern with date command output +selection c (selection | "sort") # Pipe selection through sort, replace with result +``` + +# 4 Composition and Parsing + +**Precedence:** Following BQN rules: +- Operators bind tighter than functions +- Functions and operators apply left-to-right +- Dyadic functions are infix |
