Skip to content

Commit

Permalink
docs: Update "Getting Started" documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
LeonMatthesKDAB committed Nov 15, 2024
1 parent 09440eb commit ba939a5
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 27 deletions.
12 changes: 12 additions & 0 deletions docs/API/knut/ribbon.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ import Knut
|string|**[id](#id)**|
|[RibbonMenu](../knut/ribbonmenu.md)|**[menu](#menu)**|

## Methods

| | Name |
|-|-|
|[RibbonElement](../knut/ribbonelement.md) |**[elementFromId](#elementFromId)**(string id)|

## Detailed Description

A ribbon is made of multiple items:
Expand Down Expand Up @@ -43,3 +49,9 @@ This property holds the id of the ribbon.
#### <a name="menu"></a>[RibbonMenu](../knut/ribbonmenu.md) **menu**

This property holds the menu of the ribbon.

## Method Documentation

#### <a name="elementFromId"></a>[RibbonElement](../knut/ribbonelement.md) **elementFromId**(string id)

This method returns RibbonElement from identifier `id`.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 16 additions & 10 deletions docs/getting-started/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@

## General overview

Knut allows to automate some code modifications on a codebase. This allows applying some modification on multiple files at once, for example the source and header files in a C++ project.
Knut is built to automate code modifications on a codebase.
For many repetitive tasks, Knut aims to automate around 90% of the work, with a bit of fix-up required afterwards.
Knut achieves this by providing high-level APIs to access and modify your code base, which can easily be scripted with JavaScript to run arbitrary transformations.
It is even possible to apply modifications on multiple files at once, for example the source and header files in a C++ project.

When running knut, the first thing is to open a project, a project being just the root directory for the codebase. Once a project is open, knut can open one or multiple files inside the project, and run transformations on those files. Transformations are defined in script files (see [writing scripts](script.md)).
When running Knut, the first thing is to open a project, which is just the root directory for the codebase.
Once a project is open, Knut can open one or multiple files inside the project, and run transformations on those files.
Transformations are defined in script files (see [writing scripts](script.md)).

Each file open provides different API usable by the scripts, depending on the type of file:
Each open file provides different API usable by the scripts, depending on the type of file:

- a text file has find/replace/navigation APIs (and more...)
- a C++ file adds block navigation, switch header/source or declaration/definition...
Expand All @@ -19,25 +24,26 @@ Each file open provides different API usable by the scripts, depending on the ty

### Setup

To run scripts you need to set it up accordingly:
To run scripts you need to set Knut up accordingly:

- start the knut user interface and go to `File`>`Options...`
- start the Knut user interface and go to `File`>`Options...`
- or start directly the settings dialog via the command line: `knut` --gui-setting`

This will display a dialog with the script knut general settings.
This will display a dialog with the script Knut general settings.
![Knut settings](overview-settings.png)

You need at least one script directory.
You need at least one script path.
Script paths contain .js or .qml files that can be run by Knut (see [writing scripts](script.md)).

### Running

Once done, you can run any scripts:
Once done, you can run a script inside your script paths:

- from the command line:

```
knut --run <path-to-script>
```

- from the user interface, using the `Script`>`Run Script...` menu

## Settings
Expand All @@ -49,7 +55,7 @@ Knut has 3 levels of settings:
- project settings: stored in `<project home>/knut.json`

Settings can be overridden, project settings have priority over user settings over internal settings. When a project is loaded, settings are saved in the project settings, otherwise in the user settings.
Script paths are merged between the user and project settings, allowing for some general scripts, and project-specific scripts.
Script paths are merged between the user and project settings, which allows accessing both general scripts, and project-specific scripts.

Some settings (like Text Editor Behavior) are only per project.

Expand Down
9 changes: 8 additions & 1 deletion docs/getting-started/script.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ If the first line is a comment, it will be used as the script description.
!!! Note ""
If you need to know more about QML, follow this link: [https://doc.qt.io/qt-6/qmlapplications.html](https://doc.qt.io/qt-6/qmlapplications.html)

Both Javascript and QML scripts use the same API, see the [Knut API reference](../API/knut/document.md).

For more advanced use cases, take a look at: [Syntax tree queries using Tree-sitter](./treesitter.md)

## Javascript script

Javascript scripts **must** contain a main function, the entry point for the script:

```js
// Script description
function main {
function main() {
message.log("Hello World!")
}
```
Expand Down Expand Up @@ -68,6 +72,9 @@ ScriptDialog {

The `QLineEdit` (named `lineEdit`) in the ui file is accessed both in reading and writing via `data.lineEdit`.

Note that the `init()` function in the root item (visual or not) will automatically be called at startup.
In a visual script, the `init()` function usually should not start the code transformation, but should wait for the dialog to be accepted, or a button to be clicked, etc.

### Supported widgets

Here is the list of supported widgets for your dialogs, and how to access them from the QML script.
Expand Down
45 changes: 29 additions & 16 deletions docs/getting-started/treesitter.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,45 +15,56 @@ From the [Tree-sitter website][treesitter]:
## Tree-sitter in Knut

Current support in user scripts is limited to:
Knut exposes Tree-sitter via high-level APIs that allow:

- Inspecting the concrete syntax tree generated by Tree-sitter using the "Tree-sitter Inspector".
- Running [Tree-sitter Queries][queries]
- Only available on C/C++ files

However, this already allows for some very easy & powerful analysis and modification of C++ source files.
While this doesn't give access to all of the details exposed by Tree-sitter, this already allows for some very easy & powerful analysis and modification of code files.

Knut also returns Tree-sitter query results in some of its high-level methods.
Knut also returns Tree-sitter query results in many of its high-level methods.
Usually in the form of the [QueryMatch][querymatch] class.

See the [QueryMatch documentation][querymatch] for more details of how to use this class.

Compared to the language server, Tree-sitter is a lot more resistant to errors and works well, even if the current code would not compile.
Compared to a language server, Tree-sitter is a lot more resistant to errors and works well, even if the current code would not compile.
For this reason many Knut functions internally rely on Tree-sitter instead of the language server.
This may result in false-positives though, as Tree-sitter only works on a syntax level and doesn't understand the high-level structures of the code.
Tree-sitter will especially struggle if symbols are overloaded, as all references may be picked up.

## Writing Tree-sitter queries
## Viewing the Tree-sitter state

Tree-sitter queries are a powerful tool, as the syntax tree parsed by Tree-sitter makes it easy to find functions, class definitions, etc.
For the exhaustive specification of the query syntax, see the [Tree-sitter website][queries].
Familiarizing yourself with Tree-sitters state is the first step to writing your own queries.
Knut includes the `Tree-sitter Inspector`, which displays the concrete syntax tree (CST) generated by Tree-sitter.

Knut supports prototyping queries with the `Tree-sitter Inspector`, which can be accessed in the Knut GUI under the `C++` menu.
To open it, click `Code`>`Tree-sitter Inspector`.

The Tree-sitter Inspector allows you to inspect the syntax tree of the current file.
Note that this does not include anonymous nodes (e.g. any symbols like -> * + - / ).
These are still in the syntax tree and can be queried.
For details, see the [query documentation][queries].
![Knut's Tree-sitter Inspector](./gui-treesitter-inspector.png)

The `Tree-sitter Inspector` displays the CST on the left.

As the syntax tree can become large very quickly, the Inspector provides a bi-directional mapping to the edited file.

1. Clicking any node in the inspector will select the corresponding text in the document
2. Any node that includes the cursor position is highlighted in green.

Additionally, you can test your queries in the bottom-left input field.
> Also note the `Show unnamed nodes` option in the bottom.
> The Tree-sitter CST is highly detailed and includes a lot of individual characters/keywords
> A lot of these nodes are hidden by default and won't be relevant for many queries.
> For the cases where these nodes may be relevant, the checkbox makes them visible.
On the right side, you can prototype a [Tree-sitter query](queries), the results of which will immediately be displayed at the bottom and in the CST.
The Tree-sitter Inspector will notify you of errors in your query and display the number of patterns, matches and captures as you type.
Any captured nodes will also display their captures in the syntax tree view.

> ⚠️ Because the query runs immediately, testing complex queries on large files can cause Knut to freeze when typing.
> If this is the case, extracting the relevant code into a smaller file can be a good remedy.
## Writing Tree-sitter queries

Tree-sitter queries are a powerful tool, as the syntax tree parsed by Tree-sitter makes it easy to find functions, class definitions, etc.
For the exhaustive specification of the query syntax, see the [Tree-sitter website][queries].

After prototyping a query, it can easily be included in a script by calling [`query`][codedocument-query] on any LSP capable document (e.g. C/C++).
Together with Javascripts [Destructuring Assignment][destructuring] and [Template Literals][template-literals] this makes queries very ergonomic to use in your own scripts.

Expand Down Expand Up @@ -85,8 +96,8 @@ if (!constructor) {
let old_body = constructor.get("body").text;

// Modify a capture
constructor.get("body").replace("body").replace(`{
std::log << "${className} Constructor" << std::endl;
constructor.get("body").replace(`{
std::cout << "${className} Constructor" << std::endl;
}`);
// Or remove it outright
Expand Down Expand Up @@ -176,6 +187,8 @@ E.g.: To check that the type of a parameter is `const std::string &`, you can si
(#eq_except? "const std::string &" @param "identifier"))))
```

Note that for this exact use-case, using `#like_except?` would be a better fit, to match `const std::string&`, as well as `const std::string &`.

### `(like_except? [pattern] [capture] [exclusion]+)`
Check if the pattern and capture are "alike", excluding any (sub-)nodes that have a type listed in `exclusion`.

Expand Down

0 comments on commit ba939a5

Please sign in to comment.