Support carets in matchregex snippets
parent
0cf36a0acf
commit
d5f1ba6583
|
@ -110,6 +110,7 @@ export async function insertSnippetTemplate(slashCompletion: SlashCompletion) {
|
||||||
|
|
||||||
if (snippetTemplate.match || snippetTemplate.matchRegex) {
|
if (snippetTemplate.match || snippetTemplate.matchRegex) {
|
||||||
const pageText = await editor.getText();
|
const pageText = await editor.getText();
|
||||||
|
|
||||||
// Regex matching mode
|
// Regex matching mode
|
||||||
const matchRegex = new RegExp(
|
const matchRegex = new RegExp(
|
||||||
(snippetTemplate.match || snippetTemplate.matchRegex)!,
|
(snippetTemplate.match || snippetTemplate.matchRegex)!,
|
||||||
|
@ -119,21 +120,41 @@ export async function insertSnippetTemplate(slashCompletion: SlashCompletion) {
|
||||||
while (startOfLine > 0 && pageText[startOfLine - 1] !== "\n") {
|
while (startOfLine > 0 && pageText[startOfLine - 1] !== "\n") {
|
||||||
startOfLine--;
|
startOfLine--;
|
||||||
}
|
}
|
||||||
let currentLine = pageText.slice(startOfLine, cursorPos);
|
let endOfLine = cursorPos;
|
||||||
|
while (endOfLine < pageText.length && pageText[endOfLine] !== "\n") {
|
||||||
|
endOfLine++;
|
||||||
|
}
|
||||||
|
let currentLine = pageText.slice(startOfLine, endOfLine);
|
||||||
|
const caretParts = replacementText.split("|^|");
|
||||||
const emptyLine = !currentLine;
|
const emptyLine = !currentLine;
|
||||||
currentLine = currentLine.replace(matchRegex, replacementText);
|
currentLine = currentLine.replace(matchRegex, caretParts[0]);
|
||||||
|
|
||||||
|
let newSelection = emptyLine
|
||||||
|
? {
|
||||||
|
anchor: startOfLine + currentLine.length,
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
if (caretParts.length === 2) {
|
||||||
|
// The semantics of a caret in a replacement are:
|
||||||
|
// 1. It's a caret, so we need to move the cursor there
|
||||||
|
// 2. It's a placeholder, so we need to remove it
|
||||||
|
// 3. Any text after the caret should be inserted after the caret
|
||||||
|
const caretPos = currentLine.length;
|
||||||
|
// Now add the text after the caret
|
||||||
|
currentLine += caretParts[1];
|
||||||
|
newSelection = {
|
||||||
|
anchor: startOfLine + caretPos,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
await editor.dispatch({
|
await editor.dispatch({
|
||||||
changes: {
|
changes: {
|
||||||
from: startOfLine,
|
from: startOfLine,
|
||||||
to: cursorPos,
|
to: endOfLine,
|
||||||
insert: currentLine,
|
insert: currentLine,
|
||||||
},
|
},
|
||||||
selection: emptyLine
|
selection: newSelection,
|
||||||
? {
|
|
||||||
anchor: startOfLine + currentLine.length,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const carretPos = replacementText.indexOf("|^|");
|
const carretPos = replacementText.indexOf("|^|");
|
||||||
|
|
|
@ -20,6 +20,7 @@ _These features are not yet properly released, you need to use [the edge builds]
|
||||||
* There are also two very notable new plugs you may be interested in trying:
|
* There are also two very notable new plugs you may be interested in trying:
|
||||||
* [[Plugs/TreeView]]: a sidebar showing (and allowing you to manipulate) your space’s folder tree (at long last)
|
* [[Plugs/TreeView]]: a sidebar showing (and allowing you to manipulate) your space’s folder tree (at long last)
|
||||||
* [[Plugs/AI]]: various clever AI integrations (supporting many different LLMs, including locally hosted ones)
|
* [[Plugs/AI]]: various clever AI integrations (supporting many different LLMs, including locally hosted ones)
|
||||||
|
* [[Snippets]] using `matchRegex` can now use the `|^|` caret to wrap text around the replacement, see the [[Snippets#Examples]]
|
||||||
* [[Space Script]] is now indexed in templates too (so you can put space script in template tagged pages)
|
* [[Space Script]] is now indexed in templates too (so you can put space script in template tagged pages)
|
||||||
* Changed the signature of `silverbullet.registerFunction` to make the first argument an object, see [[Space Script#Custom functions]]. Old string-based scripts still work, for backwards compatibility.
|
* Changed the signature of `silverbullet.registerFunction` to make the first argument an object, see [[Space Script#Custom functions]]. Old string-based scripts still work, for backwards compatibility.
|
||||||
* The [[Functions#replace(str, match, replacement)]] function now supports multiple replacements
|
* The [[Functions#replace(str, match, replacement)]] function now supports multiple replacements
|
||||||
|
|
|
@ -8,45 +8,64 @@ You define a snippet by creating a [[Templates|template]] with a `hooks.snippet`
|
||||||
* `command`: expose the snippet as a [[Commands|command]].
|
* `command`: expose the snippet as a [[Commands|command]].
|
||||||
* `key`: Bind the snippet to a keyboard shortcut (note: this requires to _also_ specify the `command` configuration).
|
* `key`: Bind the snippet to a keyboard shortcut (note: this requires to _also_ specify the `command` configuration).
|
||||||
* `mac`: Bind the snippet to a Mac-specific keyboard shortcut.
|
* `mac`: Bind the snippet to a Mac-specific keyboard shortcut.
|
||||||
* `matchRegex` (advanced use only): match the current line against a regular expression, and replace the match with the template’s body.
|
* `matchRegex` (advanced use only): match the _current line_ against a regular expression, and replace the match with the template’s body. If a caret placeholder (`|^|`) appears in the template’s body, the replacement body _before_ the caret will be the replacement of the matchRegex match, and the part _after_ that carret will be appended to the end of the line. This enables text wrapping behavior, see the example below.
|
||||||
* `insertAt`: by default a snippet is inserted at the cursor position, but alternatively it can be inserted at: `line-start`, `line-end`, `page-start` or `page-end`.
|
* `insertAt`: by default a snippet is inserted at the cursor position, but alternatively it can be inserted at: `line-start`, `line-end`, `page-start` or `page-end`.
|
||||||
|
|
||||||
Minimal example:
|
# Frontmatter
|
||||||
|
|
||||||
---
|
|
||||||
tags: template
|
|
||||||
hooks.snippet:
|
|
||||||
slashCommand: meeting-notes
|
|
||||||
---
|
|
||||||
## Meeting notes for {{today}}!
|
|
||||||
|
|
||||||
|^|
|
|
||||||
|
|
||||||
## Frontmatter
|
|
||||||
A template’s [[Frontmatter]] is interpreted by SilverBullet’s [[Templates|template]] engine and removed when instantiated. However, to inject frontmatter after instantiation, you can use the `frontmatter` attribute.
|
A template’s [[Frontmatter]] is interpreted by SilverBullet’s [[Templates|template]] engine and removed when instantiated. However, to inject frontmatter after instantiation, you can use the `frontmatter` attribute.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
---
|
```
|
||||||
tags: template
|
---
|
||||||
hooks.snippet.slashCommand: meeting-notes
|
tags: template
|
||||||
frontmatter: |
|
hooks.snippet.slashCommand: meeting-notes
|
||||||
date: {{today}}
|
frontmatter: |
|
||||||
---
|
date: {{today}}
|
||||||
## Meeting notes for {{today}}!
|
---
|
||||||
|
## Meeting notes for {{today}}!
|
||||||
|
|
||||||
|^|
|
|^|
|
||||||
|
```
|
||||||
|
|
||||||
Which will expand into e.g.
|
Which will expand into e.g.
|
||||||
|
|
||||||
---
|
```
|
||||||
date: 2023-11-11
|
---
|
||||||
---
|
date: 2023-11-11
|
||||||
## Meeting notes for 2023-11-11
|
---
|
||||||
|
## Meeting notes for 2023-11-11
|
||||||
|
|
||||||
.
|
.
|
||||||
|
```
|
||||||
|
|
||||||
When the page already contained frontmatter before inserting the snippet, it will be augmented with the additional frontmatter specified by the template.
|
When the page already contained frontmatter before inserting the snippet, it will be augmented with the additional frontmatter specified by the template.
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
A minimal example using a caret placeholder (to position the cursor after snippet insertion):
|
||||||
|
|
||||||
|
```
|
||||||
|
---
|
||||||
|
tags: template
|
||||||
|
hooks.snippet.slashCommand: meeting-notes
|
||||||
|
---
|
||||||
|
## Meeting notes for {{today}}!
|
||||||
|
|
||||||
|
|^|
|
||||||
|
```
|
||||||
|
|
||||||
|
A more advanced example using `matchRegex`: a variant of the [[Library/Core/Snippet/Task]] template which adds a `creationDate` [[Attributes|attribute]] at the end:
|
||||||
|
|
||||||
|
```
|
||||||
|
---
|
||||||
|
tags: template
|
||||||
|
description: Make this a task with a creation date
|
||||||
|
hooks.snippet:
|
||||||
|
slashCommand: task-created
|
||||||
|
matchRegex: "^(\\s*)[\\-\\*]?\\s*(\\[[ xX]\\])?\\s*"
|
||||||
|
---
|
||||||
|
$1* [ ] |^| [creationDate: {{today}}]
|
||||||
|
```
|
||||||
|
|
||||||
# Use
|
# Use
|
||||||
A snippet can be _triggered_ via the specified `slashCommand` via `/slashCommand` or via {[Open Command Palette]} and/or its associate key bindings when `command`, `key`/`mac` are specified.
|
A snippet can be _triggered_ via the specified `slashCommand` via `/slashCommand` or via {[Open Command Palette]} and/or its associate key bindings when `command`, `key`/`mac` are specified.
|
||||||
|
|
Loading…
Reference in New Issue