aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--rprt.md295
2 files changed, 200 insertions, 97 deletions
diff --git a/README.md b/README.md
index d47e0bd..61937db 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
> Finally, a text editor for your flying saucer.
-A text editor powered by a tacit programming language with selection rank polymorphic functions, (loosely) inspired by Sam.
+A text editor powered by a tacit language with rank polymorphic functions, (loosely) inspired by Sam and BQN.
[See rprt.md for details about the programming language](rprt.md).
diff --git a/rprt.md b/rprt.md
index 1ac92c4..e34e9cf 100644
--- a/rprt.md
+++ b/rprt.md
@@ -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