Skip to content

Commit ae69293

Browse files
committed
feat(snippets): make automatic cursor placement an optional feature
This is ostensibly a reversion of v6.2.0, as that version's only change was the (non-optional) removal of auto-cursor, where this version makes it an optional feature Refs: 5e57a39
1 parent 5e57a39 commit ae69293

File tree

3 files changed

+51
-13
lines changed

3 files changed

+51
-13
lines changed

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const view = new EditorView({
3131

3232
<dl>
3333
<dt id="user-content-bibtex">
34-
<code><strong><a href="#user-content-bibtex">bibtex</a></strong>(<a id="user-content-bibtex^config" href="#user-content-bibtex^config">config</a>&#8288;?: {biblatex&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a>, smartSuggest&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a>, snippetRecs&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a>, syntaxLinter&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a>, keywords&#8288;?: readonly <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">string</a>[]} = {}) → <a href="https://codemirror.net/docs/ref#language.LanguageSupport">LanguageSupport</a></code></dt>
34+
<code><strong><a href="#user-content-bibtex">bibtex</a></strong>(<a id="user-content-bibtex^config" href="#user-content-bibtex^config">config</a>&#8288;?: {biblatex&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a>, smartSuggest&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a>, snippetRecs&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a>, autoCursor&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a>, syntaxLinter&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a>, keywords&#8288;?: readonly <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">string</a>[]} = {}) → <a href="https://codemirror.net/docs/ref#language.LanguageSupport">LanguageSupport</a></code></dt>
3535

3636
<dd><p><a href="#user-content-bibtexlanguage">BibTeX</a> language support with <a href="#user-content-biblatexlanguage">BibLaTeX</a> dialect support, autocompletion <a href="#user-content-bibtexcompletion">configuration</a>, and <a href="https://codemirror.net/docs/ref/#autocomplete.snippet">snippets</a> for both BibTeX and BibLaTeX that are suggested based on the editor <a href="https://codemirror.net/docs/ref/#autocomplete.CompletionContext">context</a>.</p>
3737
<p>There are configuration options for the following:</p>
@@ -54,6 +54,15 @@ const view = new EditorView({
5454
<li>Snippets have been scaffolded as per the current <a href="https://ctan.org/ctan-ann/id/mailman.3109.1292253131.2307.ctan-ann@dante.de">BibTeX</a>/<a href="https://ctan.org/ctan-ann/id/mailman.404.1656879977.32352.ctan-ann@ctan.org">BibLaTeX</a> specs. The snippet <a href="https://codemirror.net/docs/ref/#autocomplete.CompletionSection">render config</a>, exclusion of certain snippets, and entry snippets' suggestion of recommendation/optional fields are done in an <a href="https://www.citedrive.com/en/blog/codemirror-bibtex-plugin">opinionated</a> manner (<a href="https://github.com/citedrive/codemirror-lang-bibtex/issues">suggestions</a> are welcome!).</li>
5555
</ul>
5656
</li>
57+
<li><strong>Automatic Cursor Placement</strong>:
58+
<ul>
59+
<li>default: <code>autoCursor: true</code></li>
60+
<li>Automatically place the cursor in ideal location(s) when expanding a snippet. This, as well, is <a href="https://www.citedrive.com/en/blog/codemirror-bibtex-plugin">opinionated</a>.</li>
61+
<li>Please note that this feature relies on the cursor state (which is tracked by <a href="https://codemirror.net/docs/ref/#state.EditorState">EditorState</a>). When overwriting the EditorState (in a non user-input related manner, i.e. via a formatting plugin), the future cursor locations do not always persist, leading to a clunky (or sometimes fully inoperable) experience.</li>
62+
<li>Thus, if your CodeMirror implementation relies heavily on modifying/overwriting EditorState, I would recommend testing both with and without this feature, to see which works best for your use-case.</li>
63+
<li><em>(As an aside: I have some ideas on how to fix this issue, but I have just started a new semester at uni and will likely not have much time to work on the plugin for the next few months. - Vai)</em></li>
64+
</ul>
65+
</li>
5766
<li><strong>Syntax Linting</strong>:
5867
<ul>
5968
<li>default: <code>syntaxLinter: true</code></li>

src/bibtex.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ export const biblatexLanguage = bibtexLanguage.configure(
9292
/// - **Opinionated Snippets**:
9393
/// - default: `snippetRecs: true`
9494
/// - Snippets have been scaffolded as per the current [BibTeX](https://ctan.org/ctan-ann/id/mailman.3109.1292253131.2307.ctan-ann@dante.de)/[BibLaTeX](https://ctan.org/ctan-ann/id/mailman.404.1656879977.32352.ctan-ann@ctan.org) specs. The snippet [render config](#autocomplete.CompletionSection), exclusion of certain snippets, and entry snippets' suggestion of recommendation/optional fields are done in an [opinionated](https://www.citedrive.com/en/blog/codemirror-bibtex-plugin) manner ([suggestions](https://github.com/citedrive/codemirror-lang-bibtex/issues) are welcome!).
95+
/// - **Automatic Cursor Placement**:
96+
/// - default: `autoCursor: true`
97+
/// - Automatically place the cursor in ideal location(s) when expanding a snippet. This, as well, is [opinionated](https://www.citedrive.com/en/blog/codemirror-bibtex-plugin).
98+
/// - Please note that this feature relies on the cursor state (which is tracked by [EditorState](#state.EditorState)). When overwriting the EditorState (in a non user-input related manner, i.e. via a formatting plugin), the future cursor locations do not always persist, leading to a clunky (or sometimes fully inoperable) experience.
99+
/// - Thus, if your CodeMirror implementation relies heavily on modifying/overwriting EditorState, I would recommend testing both with and without this feature, to see which works best for your use-case.
100+
/// - _(As an aside: I have some ideas on how to fix this issue, but I have just started a new semester at uni and will likely not have much time to work on the plugin for the next few months. - Vai)_
95101
/// - **Syntax Linting**:
96102
/// - default: `syntaxLinter: true`
97103
/// - Invalid BibTeX (and BibLaTeX) syntax is underlined in red and a warning is issued, thanks to [bibtex-tidy](https://github.com/flamingtempura/bibtex-tidy).
@@ -103,6 +109,7 @@ export function bibtex(
103109
biblatex?: boolean;
104110
smartSuggest?: boolean;
105111
snippetRecs?: boolean;
112+
autoCursor?: boolean;
106113
syntaxLinter?: boolean;
107114
keywords?: readonly string[];
108115
} = {},
@@ -112,6 +119,7 @@ export function bibtex(
112119
biblatex: false,
113120
smartSuggest: true,
114121
snippetRecs: true,
122+
autoCursor: true,
115123
syntaxLinter: true,
116124
keywords: [],
117125
...config,
@@ -125,10 +133,16 @@ export function bibtex(
125133
entry.description,
126134
entry.fields,
127135
userConfig.snippetRecs,
136+
userConfig.autoCursor,
128137
),
129138
);
130139
const bibtexFieldSnippets = bibtexFields.map((field) =>
131-
createField(field.name, field.type, field.description),
140+
createField(
141+
field.name,
142+
field.type,
143+
field.description,
144+
userConfig.autoCursor,
145+
),
132146
);
133147
const biblatexEntrySnippets = biblatexEntries.map((entry) =>
134148
createEntry(
@@ -137,10 +151,16 @@ export function bibtex(
137151
entry.description,
138152
entry.fields,
139153
userConfig.snippetRecs,
154+
userConfig.autoCursor,
140155
),
141156
);
142157
const biblatexFieldSnippets = biblatexFields.map((field) =>
143-
createField(field.name, field.type, field.description),
158+
createField(
159+
field.name,
160+
field.type,
161+
field.description,
162+
userConfig.autoCursor,
163+
),
144164
);
145165
const userKeywordSnippets = userConfig.keywords.map((keyword) =>
146166
createKeyword(keyword),

src/snippets/snippets.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,23 @@ export const createEntry = (
1818
detail: string,
1919
fields: { recommended: string[]; optional: string[]; required: string[] },
2020
snipRecs: boolean,
21+
autoCursor: boolean,
2122
) => {
2223
let applySnip = snipRecs
23-
? snippet(
24-
// `@${label}{#{<citationkey>},\n\t% Recommended Fields:${fields.recommended.map((f) => `\n\t${f} = {#{<${f}>}}`)},\n\n\t% Optional Fields:${fields.optional.map((f) => `\n\t${f} = {#{<${f}>}}`)}\n}`,
25-
`@${label}{citationkey,\n\t% Recommended Fields:${fields.recommended.map((f) => `\n\t${f} = {${f}}`)},\n\n\t% Optional Fields:${fields.optional.map((f) => `\n\t${f} = {${f}}`)}\n}`,
26-
)
27-
: snippet(
28-
// `@${label}{#{<citationkey>},${fields.required.map((f) => `\n\t${f} = {#{<${f}>}}`)}\n}`,
29-
`@${label}{citationkey,${fields.required.map((f) => `\n\t${f} = {${f}}`)}\n}`,
30-
);
24+
? autoCursor
25+
? snippet(
26+
`@${label}{#{<citationkey>},\n\t% Recommended Fields:${fields.recommended.map((f) => `\n\t${f} = {#{<${f}>}}`)},\n\n\t% Optional Fields:${fields.optional.map((f) => `\n\t${f} = {#{<${f}>}}`)}\n}`,
27+
)
28+
: snippet(
29+
`@${label}{#{citationkey},\n\t% Recommended Fields:${fields.recommended.map((f) => `\n\t${f} = {${f}}`)},\n\n\t% Optional Fields:${fields.optional.map((f) => `\n\t${f} = {${f}}`)}\n}`,
30+
)
31+
: autoCursor
32+
? snippet(
33+
`@${label}{#{<citationkey>},${fields.required.map((f) => `\n\t${f} = {#{<${f}>}}`)}\n}`,
34+
)
35+
: snippet(
36+
`@${label}{#{citationkey},${fields.required.map((f) => `\n\t${f} = {${f}}`)}\n}`,
37+
);
3138
return {
3239
// matching options
3340
label: `@${label}`,
@@ -44,15 +51,17 @@ export const createField = (
4451
label: string,
4552
section: CompletionSection,
4653
detail: string,
54+
autoCursor: boolean,
4755
) => {
4856
return {
4957
// matching options
5058
label: label,
5159
detail: detail,
5260

5361
// expansion
54-
// apply: snippet(`${label} = {#{<${label}>}}#{,}\n#{}`),
55-
apply: snippet(`${label} = {${label}}`),
62+
apply: autoCursor
63+
? snippet(`${label} = {#{<${label}>}}#{,}\n#{}`)
64+
: snippet(`${label} = {#{}}`),
5665

5766
// render options
5867
section: section,

0 commit comments

Comments
 (0)