Skip to content

Commit cba03e1

Browse files
committed
πŸ“ Rewrite documentation for denops v6
1 parent d804221 commit cba03e1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+5199
-435
lines changed

β€Žbook.toml

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,4 @@ multilingual = false
55
src = "src"
66
title = "Denops Documentation"
77

8-
[preprocessor.plantuml]
9-
plantuml-cmd="http://www.plantuml.com/plantuml"
8+
[preprocessor.alerts]

β€Žsrc/SUMMARY.md

+15-10
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@
33
[Introduction](./introduction.md)
44

55
- [Install](./install.md)
6-
- [Tutorial](./tutorial.md)
7-
- [Preparing Deno and Denops](./tutorial/preparing-deno-and-denops.md)
8-
- [Developing Your First Plugin](./tutorial/developing-your-first-plugin.md)
9-
- [Vim/Neovim Configuration](./tutorial/vimneovim-configuration.md)
10-
- [Making a Plugin Directory Tree](./tutorial/making-a-directory-tree.md)
11-
- [Adding a Skelton of Denops Plugin](./tutorial/adding-a-skelton-of-denops-plugin.md)
12-
- [Adding an API](./tutorial/adding-an-api.md)
13-
- [Calling Vim/Neovim Features](./tutorial/calling-vimneovim-features.md)
14-
- [Developing More Applicative Plugin](./tutorial/developing-more-applicative-plugin.md)
15-
- [Developing Your Next Plugins](./tutorial/developing-your-next-plugins.md)
6+
- [Getting Started](./getting-started/README.md)
7+
- [Explanation of the Getting started](./getting-started/explanation.md)
8+
- [Tutorial (Hello world)](./tutorial/helloworld/README.md)
9+
- [Creating a minimal Vim plugin](./tutorial/helloworld/creating-a-minimal-vim-plugin.md)
10+
- [Creating a minimal Denops plugin](./tutorial/helloworld/creating-a-minimal-denops-plugin.md)
11+
- [Adding Denops APIs](./tutorial/helloworld/adding-an-api.md)
12+
- [Calling Vim features](./tutorial/helloworld/calling-vim-features.md)
13+
- [Tutorial (Maze)](./tutorial/maze/README.md)
14+
- [Utilizing third-party library](./tutorial/maze/utilizing-third-party-library.md)
15+
- [Outputting content to buffer](./tutorial/maze/outputting-content-to-buffer.md)
16+
- [Adjusting maze size to fit the window](./tutorial/maze/adjusting-maze-size-to-fit-the-window.md)
17+
- [Properly create a virtual buffer](./tutorial/maze/properly-create-a-virtual-buffer.md)
18+
- [Properly configured the buffer](./tutorial/maze/properly-configured-the-buffer.md)
19+
- [Reduce the number of RPC calls](./tutorial/maze/reduce-the-number-of-rpc-calls.md)
20+
- [FAQ](./faq.md)

β€Žsrc/faq.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# FAQ
2+
3+
## How to Check Denops Startup Time
4+
5+
To check the startup time of Denops or Denops plugins, utilize
6+
[denops-startup-recorder]. This plugin visualizes the timing of events related
7+
to Denops and Denops plugin startup.
8+
9+
[denops-startup-recorder]: https://github.com/vim-denops/denops-startup-recorder.vim
10+
11+
It shows the result in echo area like:
12+
13+
![](./img/faq-1.png)
14+
15+
## How to Check Denops Performance
16+
17+
To assess Denops performance, employ [denops-benchmark]. This plugin measures
18+
the number of operations or characters that can be processed in milliseconds.
19+
20+
[denops-benchmark]: https://github.com/vim-denops/denops-benchmark.vim
21+
22+
It shows the result in a buffer like:
23+
24+
![](./img/faq-2.png)

β€Žsrc/getting-started/README.md

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Getting Started
2+
3+
[Denops] ([/ˈdiːnoʊps/](http://ipa-reader.xyz/?text=%CB%88di%CB%90no%CA%8Aps),
4+
pronounced `dee-nops`) is an ecosystem for [Vim] / [Neovim] that empowers
5+
developers to write plugins in [TypeScript] / [JavaScript] powered by [Deno].
6+
7+
Let's start by creating a simple plugin to learn how to develop Denops plugins.
8+
9+
## Create a Plugin
10+
11+
Create a directory named `denops-getting-started` in your home directory and a
12+
file named `main.ts` within it, under `denops/denops-getting-started/`:
13+
14+
```
15+
$HOME
16+
└── denops-getting-started
17+
└── denops
18+
└── denops-getting-started
19+
└── main.ts
20+
```
21+
22+
Next, write the following TypeScript code in `main.ts`:
23+
24+
```typescript
25+
import type { Denops } from "https://deno.land/x/[email protected]/mod.ts";
26+
27+
export function main(denops: Denops): void {
28+
denops.dispatcher = {
29+
async hello() {
30+
await denops.cmd(`echo "Hello, Denops!"`);
31+
},
32+
};
33+
}
34+
```
35+
36+
## Activate the Plugin
37+
38+
Add the following line to your Vim or Neovim configuration file (e.g.,
39+
`~/.vimrc` or `~/.config/nvim/init.vim`):
40+
41+
```vim
42+
set runtimepath+=~/denops-getting-started
43+
```
44+
45+
Or Neovim Lua configuration file (e.g., `~/.config/nvim/init.lua`):
46+
47+
```lua
48+
vim.opt.runtimepath:append("~/denops-getting-started")
49+
```
50+
51+
## Try the Plugin
52+
53+
Restart Vim/Neovim and execute the following command:
54+
55+
```vim
56+
:call denops#request('denops-getting-started', 'hello', [])
57+
```
58+
59+
You should see "Hello, Denops!" displayed on the screen like:
60+
61+
![](./img/README-01.png)
62+
63+
[Denops]: https://github.com/vim-denops/denops.vim
64+
[Vim]: https://www.vim.org/
65+
[Neovim]: https://neovim.io/
66+
[TypeScript]: https://www.typescriptlang.org/
67+
[JavaScript]: https://developer.mozilla.org/en-US/docs/Web/JavaScript
68+
[Deno]: https://deno.land/

β€Žsrc/getting-started/explanation.md

+241
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
# Explanation of the Getting Started
2+
3+
In this section, we'll provide detailed information about the Getting Started.
4+
If you find it too detailed, feel free to skip this section and move on to the
5+
next chapter, especially if your goal is to start developing a Denops plugin
6+
promptly.
7+
8+
## What is Denops?
9+
10+
Denops claims to be an ecosystem for developing Vim / Neovim (hereafter, when we
11+
refer to Vim without restriction, we also include Neovim) plugins using Deno,
12+
but, in reality, it is a Vim plugin with the following features:
13+
14+
- Detection and registration of Denops plugins
15+
- Launching and connecting to Deno processes
16+
- Calling Deno process-side functions from Vim via RPC (Remote Procedure Call)
17+
- Calling Vim features from Deno process-side via RPC
18+
19+
By utilizing this plugin, you can control Vim from code written in TypeScript
20+
(Denops plugins).
21+
22+
> [!NOTE]
23+
>
24+
> [RPC (Remote Procedure Call)](https://en.wikipedia.org/wiki/Remote_procedure_call)
25+
> is used, and while Vim uses a
26+
> [JSON-based custom specification](https://vim-jp.org/vimdoc-en/channel.html#channel-use),
27+
> Neovim uses [MessagePack-RPC](https://github.com/msgpack-rpc/msgpack-rpc) (a
28+
> slightly modified specification). However, Denops abstracts away these
29+
> differences, so Denops plugin developers don't need to be aware of the RPC
30+
> specification differences between Vim and Neovim.
31+
32+
## What is a Vim Plugin?
33+
34+
When Vim starts, it searches for files named `plugin/*.vim` in directories
35+
specified in `runtimepath`. Additionally, if a function like `foo#bar#hoge()` is
36+
called, it searches for files named `autoload/foo/bar.vim` in the `runtimepath`
37+
and reads the file, calling the `foo#bar#hoge()` function defined within.
38+
39+
A Vim plugin is a set of predefined features provided to users, utilizing the
40+
functionality mentioned above. Typically, an entry point is defined in
41+
`plugin/{plugin_name}.vim`, and detailed features are implemented in
42+
`autoload/{plugin_name}.vim` or `autoload/{plugin_name}/*.vim`. For example,
43+
here is the directory structure for a Vim plugin named `hello`:
44+
45+
```
46+
vim-hello
47+
β”œβ”€β”€ autoload
48+
β”‚ └── hello.vim # Defines the function `hello#hello()`
49+
└── plugin
50+
└── hello.vim # Defines the `Hello` command
51+
```
52+
53+
> [!NOTE]
54+
>
55+
> For more detailed information on creating Vim plugins, refer to
56+
> `:help write-plugin`.
57+
58+
## What is a Denops Plugin?
59+
60+
When Denops is installed, in addition to Vim plugins, files named
61+
`denops/*/main.ts` are also searched when Vim starts. If a corresponding file is
62+
found, Denops registers the parent directory name (`foo` in the case of
63+
`denops/foo/main.ts`) as the plugin name. Then, it imports the corresponding
64+
file as a TypeScript module and calls the function named `main`.
65+
66+
A Denops plugin, similar to a Vim plugin, provides a set of features written in
67+
TypeScript to users. Since Denops plugins typically include both TypeScript and
68+
Vim script code, the directory structure looks like an extension of the Vim
69+
plugin structure with an added `denops` directory. For example, here is the
70+
directory structure for a Denops plugin named `hello`:
71+
72+
```
73+
denops-hello
74+
β”œβ”€β”€ autoload
75+
β”‚ └── hello.vim # Tasks better written in Vim script (may not exist)
76+
β”œβ”€β”€ denops
77+
β”‚ └── hello
78+
β”‚ └── main.ts # Entry point for the Denops plugin (mandatory)
79+
└── plugin
80+
└── hello.vim # Entry point written in Vim script (optional)
81+
```
82+
83+
In the Getting Started, we created a file named
84+
`denops/denops-getting-started/main.ts` and added its parent directory
85+
(`denops-getting-started`) to `runtimepath`. There were no `autoload` or
86+
`plugin` directories because we didn't provide an entry point that Vim could
87+
easily call.
88+
89+
## Understanding the Code in Getting Started
90+
91+
In the Getting Started, we wrote the following code in the `main.ts` file:
92+
93+
```typescript
94+
import type { Denops } from "https://deno.land/x/[email protected]/mod.ts";
95+
96+
export function main(denops: Denops): void {
97+
denops.dispatcher = {
98+
async hello() {
99+
await denops.cmd(`echo "Hello, Denops!"`);
100+
},
101+
};
102+
}
103+
```
104+
105+
Let's break down this code step by step.
106+
107+
### About Imports
108+
109+
```typescript
110+
import type { Denops } from "https://deno.land/x/[email protected]/mod.ts";
111+
```
112+
113+
The first line imports the `Denops` type from the [denops_std] standard library.
114+
You can find detailed information about the library by checking the URL:
115+
`https://deno.land/x/[email protected]` (remove `/mod.ts`). We fixed the version
116+
in the import URL, so it's recommended to check for details and update to the
117+
latest version URL.
118+
119+
Note that we use `import type` syntax, which is part of TypeScript's
120+
[Type-Only Imports and Export](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html).
121+
This syntax can be written as `import { type Denops }` with the same meaning.
122+
Using `import { Denops }` for a type-only import is also valid.
123+
124+
> [!NOTE]
125+
>
126+
> Denops plugins are dynamically imported, so there might be differences in
127+
> Denops versions between development and usage. Therefore, to minimize
128+
> differences between Denops versions, only the `Denops` type information is
129+
> exposed. The implementation can be found in
130+
> [`denops/@denops-private/denops.ts`](https://github.com/vim-denops/denops.vim/blob/main/denops/%40denops-private/denops.ts),
131+
> but it is not publicly exposed for the reasons mentioned above.
132+
>
133+
> This type information is provided by [denops_core], and [denops_std] simply
134+
> re-exports the type information from [denops_core]. However, [denops_core] is
135+
> intended to be referenced only by [denops.vim] and [denops_std], so Denops
136+
> plugin developers don't need to use it directly.
137+
138+
### About Entry Point
139+
140+
```typescript
141+
export function main(denops: Denops): void {
142+
// Omitted...
143+
}
144+
```
145+
146+
The above code exports the `main` function. The `main` function is called by
147+
Denops, and it takes the
148+
[Denops instance](https://deno.land/x/denops_std/mod.ts?s=Denops) (`denops`) as
149+
an argument. Denops plugins use this `denops` to add user-defined APIs or call
150+
Vim's features.
151+
152+
### About User-Defined APIs
153+
154+
```typescript
155+
denops.dispatcher = {
156+
async hello() {
157+
// Omitted...
158+
},
159+
};
160+
```
161+
162+
The code above adds a user-defined API named `hello` to `denops.dispatcher`.
163+
`denops.dispatcher` is defined as follows, and each method takes `unknown` types
164+
for both arguments and return values:
165+
166+
```typescript
167+
interface Dispatcher {
168+
[key: string]: (...args: unknown[]) => unknown;
169+
}
170+
```
171+
172+
By defining methods in `denops.dispatcher`, you can freely define APIs. Since
173+
the methods registered in `denops.dispatcher` are always called with `await`,
174+
you can make them asynchronous by returning a `Promise`.
175+
176+
The methods defined in `denops.dispatcher` can be called from Vim using the
177+
following functions:
178+
179+
| Function | Description |
180+
| ---------------------- | -------------------------------------------------------------------------------- |
181+
| `denops#request` | Synchronously calls a user-defined API and returns the result. |
182+
| `denops#request_async` | Asynchronously calls a user-defined API and passes the result to callbacks. |
183+
| `denops#notify` | Calls a user-defined API without waiting for completion and discards the result. |
184+
185+
At the end of the Getting Started, we used
186+
`denops#request('denops-getting-started', 'hello', [])` to call the user-defined
187+
API named `hello` in `denops-getting-started` plugin.
188+
189+
### About Calling Vim's features
190+
191+
```typescript
192+
await denops.cmd(`echo "Hello, Denops!"`);
193+
```
194+
195+
With the received `denops`, you can call Vim functions, execute Vim commands, or
196+
evaluate Vim expressions. In the example above, the `hello` API internally uses
197+
`denops.cmd` to execute the `echo` command in Vim. The `denops` object provides
198+
several methods:
199+
200+
| Method | Description |
201+
| ---------- | ---------------------------------------------------------------------------------------------------------- |
202+
| `call` | Calls a Vim function and returns the result. |
203+
| `batch` | Calls multiple Vim functions in bulk and returns the results in bulk. |
204+
| `cmd` | Executes a Vim command. If `ctx` is provided, it is expanded as local variables. |
205+
| `eval` | Evaluate a Vim expression and returns the result. If `ctx` is provided, it is expanded as local variables. |
206+
| `dispatch` | Calls a user-defined API of another Denops plugin and returns the result. |
207+
208+
Although `denops` provides low-level interfaces, [denops_std] combines these
209+
low-level interfaces to offer higher-level interfaces. Therefore, it's
210+
recommended to use [denops_std] to call Vim's features in actual plugin
211+
development.
212+
213+
For example, use
214+
[`function` module](https://deno.land/x/[email protected]/function/mod.ts) to
215+
call Vim's function instead of `denops.call` like:
216+
217+
```typescript
218+
import * as fn from "https://deno.land/x/[email protected]/function/mod.ts";
219+
220+
// Bad (result1 is `unknown`)
221+
const result1 = await denops.call("expand", "%");
222+
223+
// Good (result2 is `string`)
224+
const result2 = await fn.expand(denops, "%");
225+
```
226+
227+
If developers use `function` module instead, they can benefit from features like
228+
auto-completion and type checking provided by LSP (Language Server Protocol).
229+
230+
## Next Steps
231+
232+
In the next step, follow the tutorial to learn how to develop a minimum Denops
233+
plugin.
234+
235+
- [Tutorial (Hello World)](../tutorial/helloworld/README.md)
236+
- [Tutorial (Maze)](../tutorial/maze/README.md)
237+
- [API reference](https://deno.land/x/denops_std/mod.ts)
238+
239+
[denops.vim]: https://github.com/vim-denops/denops.vim
240+
[denops_std]: https://deno.land/x/denops_std
241+
[denops_core]: https://deno.land/x/denops_core
12.7 KB
Loading
Binary file not shown.

β€Žsrc/img/adding-an-api-1.png

-20.1 KB
Binary file not shown.

β€Žsrc/img/adding-an-api-2.png

-104 KB
Binary file not shown.
-20.2 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.

β€Žsrc/img/faq-1.png

54 KB
Loading

β€Žsrc/img/faq-2.png

31.6 KB
Loading

0 commit comments

Comments
Β (0)