[utilities/kate] /: Update documentation for script type snippets
Thomas Friedrichsmeier
null at kde.org
Tue Jun 10 13:42:34 BST 2025
Git commit 3466f6dc98583254ea87c341a3289daf007ccca5 by Thomas Friedrichsmeier.
Committed on 10/06/2025 at 12:37.
Pushed by tfry into branch 'master'.
Update documentation for script type snippets
M +11 -35 addons/snippets/editsnippet.cpp
M +3 -5 addons/snippets/snippet.cpp
M +65 -39 doc/kate/plugins.docbook
M +8 -0 doc/katepart/development.docbook
https://invent.kde.org/utilities/kate/-/commit/3466f6dc98583254ea87c341a3289daf007ccca5
diff --git a/addons/snippets/editsnippet.cpp b/addons/snippets/editsnippet.cpp
index e42e6e261e..cc48a71774 100644
--- a/addons/snippets/editsnippet.cpp
+++ b/addons/snippets/editsnippet.cpp
@@ -72,28 +72,20 @@ EditSnippet::EditSnippet(SnippetRepository *repository, Snippet *snippet, QWidge
connect(m_ui->modeComboBox, &QComboBox::currentIndexChanged, this, [this]() {
if (m_ui->modeComboBox->currentData().toInt() == Snippet::TextTemplate) {
m_ui->snippetLabel->setText(
- i18n("The text your snippet will insert into the document. "
- "<a href=\"A template snippet can contain editable fields. They can be "
- "cycled by pressing Tab. The following expressions can be used "
- "in the template text to create fields: <br><tt>${field_name}</tt> "
- "creates a simple, editable field. All subsequent occurrences of the "
- "same field_name will mirror the contents of the first "
- "during editing.<br><tt>${field_name=default}</tt> can be used to "
- "specify a default value for the field, where <tt>default</tt> can be any "
- "JavaScript expression (use quotatio marks to specify "
- "a fixed string as default value).<br><tt>${func(other_field1, "
- "other_field2, ...)</tt> evaluates a JavaScript function defined in the "
- "'Scripts Library' tab on each edit, and is replaced by the value returned "
- "by that function.<br><tt>${cursor}</tt> "
- "can be used to mark the end position of the cursor after everything "
- "else was filled in.\">More...</a>"));
- m_snippetView->document()->setMode(QStringLiteral("None")); // TODO
+ i18n("Text to insert into the document (see "
+ "<a href=\"help:/kate/kate-application-plugin-snippets.html\">handbook</a> "
+ "for special fields)."));
+ m_snippetView->document()->setMode(QStringLiteral("Normal"));
} else {
// TODO
- m_ui->snippetLabel->setText(i18n("Explanation for script. Individual portion vs Script Library"));
+ m_ui->snippetLabel->setText(
+ i18n("Javascript code to evaluate (see "
+ "<a href=\"help:/kate/kate-application-plugin-snippets.html\">handbook</a> "
+ "for details)."));
m_snippetView->document()->setMode(QStringLiteral("JavaScript"));
}
});
+ m_ui->snippetLabel->setOpenExternalLinks(true);
m_ui->modeComboBox->addItem(i18n("Text template"), QVariant(Snippet::TextTemplate));
m_ui->modeComboBox->addItem(i18n("Script"), QVariant(Snippet::Script));
@@ -102,19 +94,9 @@ EditSnippet::EditSnippet(SnippetRepository *repository, Snippet *snippet, QWidge
m_scriptsView->document()->setText(m_repo->script());
m_scriptsView->document()->setModified(false);
- // TODO: link to handbook
m_ui->scriptLabel->setText(
- i18n("Write down JavaScript helper functions to use in your snippets here. "
- "<a href=\"Editable template fields are accessible as local variables. "
- "For example in a template snippet containing <tt>${field}</tt>, a "
- "variable called <tt>field</tt> will be present which contains the "
- "up-to-date contents of the template field. Those variables can either "
- "be used in the function statically or passed as arguments, by using the "
- "<tt>${func(field)}</tt> or <tt>${field2=func(field)}</tt> syntax in the "
- "snippet string.<br>You can use the kate scripting API to get the "
- "selected text, full text, file name and more by using the appropriate "
- "methods of the <tt>document</tt> and <tt>view</tt> objects. Refer to "
- "the scripting API documentation for more information.\">More...</a>"));
+ i18n("JavaScript functions shared between all snippets in this repository (see "
+ "<a href=\"help:/kate/kate-application-plugin-snippets.html\">handbook</a>)."));
m_ui->descriptionLabel->setText(i18n("(Optional) description to show in tooltips. May contain HTML formatting."));
m_descriptionView = createView(m_ui->descriptionTab);
@@ -134,12 +116,6 @@ EditSnippet::EditSnippet(SnippetRepository *repository, Snippet *snippet, QWidge
connect(m_ui->snippetShortcut, &KKeySequenceWidget::keySequenceChanged, this, &EditSnippet::topBoxModified);
connect(m_snippetView->document(), &KTextEditor::Document::textChanged, this, &EditSnippet::validate);
- auto showHelp = [](const QString &text) {
- QWhatsThis::showText(QCursor::pos(), text);
- };
- connect(m_ui->snippetLabel, &QLabel::linkActivated, showHelp);
- connect(m_ui->scriptLabel, &QLabel::linkActivated, showHelp);
-
// if we edit a snippet, add all existing data
if (m_snippet) {
setWindowTitle(i18n("Edit Snippet %1 in %2", m_snippet->text(), m_repo->text()));
diff --git a/addons/snippets/snippet.cpp b/addons/snippets/snippet.cpp
index 51d0ba135b..422f502c96 100644
--- a/addons/snippets/snippet.cpp
+++ b/addons/snippets/snippet.cpp
@@ -98,11 +98,9 @@ void Snippet::apply(KTextEditor::View *view, const QString &repoScript) const
view->insertTemplate(view->cursorPosition(), snippet(), repoScript);
} else {
QVariant res;
- auto ok = view->evaluateScript(repoScript + u'\n' + snippet(), &res);
- if (!ok) {
- // show error message, by simply inserting it
- view->document()->insertText(view->cursorPosition(), res.toString());
- }
+ view->evaluateScript(repoScript + u'\n' + snippet(), &res);
+ // for convenience, insert result (or error message) at cursor position
+ view->document()->insertText(view->cursorPosition(), res.toString());
}
}
diff --git a/doc/kate/plugins.docbook b/doc/kate/plugins.docbook
index d673beab72..a61fdf50a6 100644
--- a/doc/kate/plugins.docbook
+++ b/doc/kate/plugins.docbook
@@ -3355,7 +3355,7 @@ that are for the currently opened file type.</para></listitem>
</menuchoice></term>
<listitem>
<para>Create a new snippet, which is a reusable chunk of text you
-may insert in any part of any document.</para>
+may insert in any part of any document, or a small script.</para>
</listitem>
</varlistentry>
@@ -3463,16 +3463,24 @@ than one file type pressing the &Shift; while adding types.</para></listitem>
<varlistentry>
<term><guilabel>Name</guilabel></term>
-<listitem><para>The name will be shown in the completion list.</para></listitem>
+<listitem><para>The name as shown in the list of snippets, and in the completion list (required).</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><guilabel>Type</guilabel></term>
+<listitem><para>Snippets may either be defined as text templates or scripts. Both types allow to use &javascript; functions
+(see below, for details), and can thus be used to similar effect. However, as a rule of thumb, text templates will be more
+suiteable, if you mostly want to <emphasis>insert</emphasis> text, while scripts are often an easier solution, if you want to
+<emphasis>modify</emphasis> text).</para></listitem>
</varlistentry>
<varlistentry>
<term>Shortcut</term>
-<listitem><para>Pressing this shortcut will insert the snippet into the document.</para></listitem>
+<listitem><para>Pressing this shortcut will insert (or run) the snippet into the current document.</para></listitem>
</varlistentry>
<varlistentry>
-<term><guilabel>Snippets</guilabel></term>
+<term><guilabel>Snippet</guilabel> (type <userinput>Text Template</userinput>)</term>
<listitem><para>The text your snippet will insert into the document.</para>
<para>A snippet can contain editable fields. They can be cycled by
pressing 	. The following expressions can be used in the template
@@ -3484,64 +3492,81 @@ of the first during editing.</para>
<para><userinput>${<replaceable>field_name=default</replaceable>}</userinput>
can be used to specify a default value for the field.
<replaceable>default</replaceable> can be any &javascript; expression.</para>
-<para>Use <userinput>${<replaceable>field_name</replaceable>=<replaceable>text</replaceable>}</userinput>
+<para>Use quotes (<userinput>${<replaceable>field_name</replaceable>=<replaceable>"text"</replaceable>}</userinput>)
to specify a fixed string as default value.</para>
<para><userinput>${func(<replaceable>other_field1</replaceable>,
<replaceable>other_field2</replaceable>, ...)}</userinput> can be used to create a
-field which evaluates a &javascript; function on each edit and contains its
-contents. See the <guilabel>Scripts</guilabel> tab for more information.</para>
+field which evaluates a &javascript; function on each edit and is replaced by that
+function's return value. See the <guilabel>Script Library</guilabel> tab for more information.</para>
<para><userinput>${cursor}</userinput> can be used to mark the end position
of the cursor after everything else was filled in.</para>
</listitem>
</varlistentry>
<varlistentry>
-<term><guilabel>Scripts</guilabel></term>
-<listitem><para>&javascript; helper functions to use in your snippets.</para>
-<para>All &javascript; functions should return the contents you want to place in a
-template field as a string.</para>
-<para>Functions are called in a scope which contains the contents of all
-editable template fields as local variables. For example in a snippet
+<term><guilabel>Snippet</guilabel> (type <userinput>Script</userinput>)</term>
+<listitem><para>The &javascript; code to evaluate for this snippet</para>
+<para>If this code contains a <userinput>return</userinput>, the returned string will be inserted at the current
+cursor position, but you can also use the <ulink url="help:/katepart/dev-scripting.html#dev-scripting-api">&kate;
+scripting API</ulink> to modify the document, directly.</para>
+<para>Additionally, your code may use functions defined in the <guilabel>Script Library</guilabel> tab, which
+are shared between all snippets in a repository.</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term><guilabel>Script Library</guilabel></term>
+<listitem><para>&javascript; helper functions to use in your snippets. These functions are shared between all snippets in a repository.</para>
+<para>You can use the <ulink url="help:/katepart/dev-scripting.html#dev-scripting-api">&kate; scripting API</ulink>
+to get the selected text, full text, file name and more by using the appropriate methods of the <userinput>document</userinput>
+and <userinput>view</userinput> objects. Refer to the scripting API
+documentation for more information.</para>
+
+<para>When scripting in conjuction with <userinput>Text Template</userinput> snippets, you should keep the
+following details/hints in mind:</para>
+<itemizedlist>
+<listitem><para>Remember that only the <emphasis>return value</emphasis> of a function is inserted in a field.</para></listitem>
+<listitem><para>The contents of all editable template fields are available as variables in this scope. For example in a snippet
containing <userinput>${<replaceable>field</replaceable>}</userinput>,
a variable called <userinput>field</userinput> will be present which contains
the up-to-date contents of the template field. Those variables can either
be used in the function statically or passed as arguments, by using the
<userinput>${func(field)}</userinput> or <userinput>${<replaceable>field2=func(field)</replaceable>}</userinput>
-syntax in the snippet string.</para>
-<para>You can use
-the <ulink url="help:/katepart/dev-scripting.html#dev-scripting-api">&kate; scripting API</ulink>
-to get the selected text, full text, file name and
-more by using the appropriate methods of the <userinput>document</userinput>
-and <userinput>view</userinput> objects. Refer to the scripting API
-documentation for more information.</para>
-<para>For more complex scripts it may be important to understand that
+syntax in the snippet string.</para></listitem>
+<listitem><para>For more complex scripts it may be important to understand that
<emphasis>first</emphasis>, the raw snippet is inserted into the document, and <emphasis>then</emphasis>
functions are being evaluated. E.g., if a function retrieves the text on the
line where the snippet is being inserted, that text will also contain
-<userinput>${functionCall()}</userinput>.</para>
-<para>As an example of working with selections using the scripting API, a simple way
-to wrap selected text inside tags is this snippet:
-<userinput><strong>${view.selectedText()}</strong></userinput>
-</para>
-<para>The following example invokes a script that inserts a default text in case
-there is no selection. Snippet:</para>
+<userinput>${functionCall()}</userinput>. Where this causes complications, consider using a
+<userinput>Script</userinput>-type snippet, instead.</para></listitem>
+<listitem><para>To simply wrap the currently selected text into tags, use: <userinput><strong>${view.selectedText()}</strong></userinput></para></listitem>
+</itemizedlist>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term><guilabel>Description</guilabel></term>
+<listitem><para>An optional description of what this snippet does. This will be shown in tooltips. The description
+may contain basic HTML formatting.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term>Usage example</term>
+<listitem><para>The following example invokes a script that wraps the selected text, or - if
+there is no selection - a default text, into tags (Snippet type <userinput>Script</userinput>):</para>
<para>
-<userinput>${rangeCommand("<strong>%%1</strong>", "Bold")}</userinput></para>
-<para>Script:
<programlisting>
-function rangeCommand(command, def) {
- if (view.selectedText().length > 0) {
- return command.replace("%%1", view.selectedText());
- } else {
- return command.replace("%%1", def);
- }
-}
+let range = view.hasSelection() ? view.selection() : new Range(view.cursorPosition(), view.cursorPosition());
+let innertext = range.isEmpty() ? "Bold" : document.text(range);
+document.removeText(range);
+document.insertText(range.start, "<strong>" + innertext + "</strong>");
</programlisting>
</para>
</listitem>
</varlistentry>
</variablelist>
+
</sect3>
</sect2>
@@ -3557,10 +3582,11 @@ function rangeCommand(command, def) {
</mediaobject>
</screenshot>
-<para>You can call snippets in two ways:</para>
+<para>You can call snippets in several ways:</para>
<itemizedlist>
-<listitem><para>By choosing the snippet from the tool view.</para></listitem>
+<listitem><para>By clicking on the snippet from the tool view.</para></listitem>
+<listitem><para>Using a keyboard shortcut, if you have assigned one.</para></listitem>
<listitem><para>While writing, you can press <keycombo action="simul">&Ctrl;
&Space;</keycombo>, which will display all the snippets in a
convenient window from which you can choose. This key combination provides
diff --git a/doc/katepart/development.docbook b/doc/katepart/development.docbook
index a9bc121605..86fbd50148 100644
--- a/doc/katepart/development.docbook
+++ b/doc/katepart/development.docbook
@@ -2584,6 +2584,8 @@ a theme.</para>
The &kappname; editor component is easily extensible by writing scripts.
The scripting language is ECMAScript (widely known as &javascript;).
&kappname; supports two kinds of scripts: indentation and command line scripts.
+A functionality similar to command line scripts is also provided in the
+<ulink url="help:/kate/kate-application-plugin-snippets.html">snippets plugin</ulink>
</para>
<sect2 id="dev-scripting-indentation">
@@ -2742,6 +2744,12 @@ by <ulink url="mailto:kwrite-devel at kde.org">contacting the mailing list</ulink>.
<sect2 id="dev-scripting-command-line">
<title>Command Line Scripts</title>
+<note>
+<para>A functionality similar the command line scripts, detailed here, is also provided in the
+<ulink url="help:/kate/kate-application-plugin-snippets.html">snippets plugin</ulink>.
+This plugin may provide an easier starting point, especially for small custom scripts.</para>
+</note>
+
<para>
As it is hard to satisfy everyone's needs, &kappname; supports little helper tools
for quick text manipulation through the
More information about the kde-doc-english
mailing list