Skip to content

Commit e697716

Browse files
authored
Merge pull request #139 from vim-denops/imp-buffer
💥 Remove undocumented public exports and add some features on `buffer` module
2 parents b8579b8 + d295427 commit e697716

File tree

5 files changed

+366
-46
lines changed

5 files changed

+366
-46
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type-check: FORCE ## Type check
2020
@deno test --unstable --no-run ${TARGETS}
2121

2222
test: FORCE ## Test
23-
@deno test --unstable -A --no-check --jobs
23+
@deno test --unstable -A --no-check --jobs ${ARGS}
2424

2525
gen: FORCE ## Generate codes
2626
@deno run --unstable -A ./scripts/gen-function/gen-function.ts

denops_std/buffer/README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,48 @@ export async function main(denops: Denops): Promise<void> {
7878
It may temporary change a current buffer or a current window to properly reload
7979
the content of the `bufnr` buffer.
8080

81+
### decode
82+
83+
Use `decode()` to decode raw binary content for string array for the `bufnr`
84+
buffer like:
85+
86+
```typescript
87+
import { Denops } from "../mod.ts";
88+
import * as fn from "../function/mod.ts";
89+
import { decode, open, replace } from "../buffer/mod.ts";
90+
91+
export async function main(denops: Denops): Promise<void> {
92+
await open(denops, "README.md");
93+
const bufnr = await fn.bufnr(denops) as number;
94+
const data = await Deno.readFile("README.md");
95+
const { content } = await decode(denops, bufnr, data);
96+
await replace(denops, bufnr, content);
97+
}
98+
```
99+
100+
It follows Vim's rule to find a corresponding `fileformat` and `fileencoding` to
101+
decode the `data` if the one is not given by `options`.
102+
103+
### append
104+
105+
Use `append()` to append the content of the `bufnr` buffer like:
106+
107+
```typescript
108+
import { Denops } from "../mod.ts";
109+
import * as fn from "../function/mod.ts";
110+
import { append, open } from "../buffer/mod.ts";
111+
112+
export async function main(denops: Denops): Promise<void> {
113+
await open(denops, "README.md");
114+
const bufnr = await fn.bufnr(denops) as number;
115+
// Append the content under the cursor position of the `bufnr` buffer
116+
await append(denops, bufnr, ["Hello", "World"]);
117+
}
118+
```
119+
120+
It temporary change `modified`, `modifiable`, and `foldmethod` options to append
121+
the content of the `buffer` buffer without unmodifiable error or so on.
122+
81123
### replace
82124

83125
Use `replace()` to replace the content of the `bufnr` buffer like:
@@ -100,6 +142,8 @@ replace the content of the `buffer` buffer without unmodifiable error or so on.
100142

101143
### assign
102144

145+
**DEPRECATED: Use `decode()` and `replace()` individually**
146+
103147
Use `assign()` to assign raw binary content into the `bufnr` buffer like:
104148

105149
```typescript

denops_std/buffer/buffer.ts

Lines changed: 113 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { execute } from "../helper/mod.ts";
66
import * as unknownutil from "https://deno.land/x/unknownutil@v2.0.0/mod.ts";
77
import {
88
assertFileFormat,
9+
FileFormat,
910
findFileFormat,
1011
isFileFormat,
1112
maybeFileFormat,
@@ -54,6 +55,18 @@ async function ensurePrerequisites(denops: Denops): Promise<string> {
5455
endtry
5556
endfunction
5657
58+
function! DenopsStdBufferAppend_${suffix}(bufnr, lnum, repl) abort
59+
let modified = getbufvar(a:bufnr, '&modified')
60+
let modifiable = getbufvar(a:bufnr, '&modifiable')
61+
let foldmethod = getbufvar(a:bufnr, '&foldmethod')
62+
call setbufvar(a:bufnr, '&modifiable', 1)
63+
call setbufvar(a:bufnr, '&foldmethod', 'manual')
64+
call appendbufline(a:bufnr, a:lnum, a:repl)
65+
call setbufvar(a:bufnr, '&modified', modified)
66+
call setbufvar(a:bufnr, '&modifiable', modifiable)
67+
call setbufvar(a:bufnr, '&foldmethod', foldmethod)
68+
endfunction
69+
5770
function! DenopsStdBufferReplace_${suffix}(bufnr, repl, fileformat, fileencoding) abort
5871
let modified = getbufvar(a:bufnr, '&modified')
5972
let modifiable = getbufvar(a:bufnr, '&modifiable')
@@ -97,19 +110,6 @@ async function ensurePrerequisites(denops: Denops): Promise<string> {
97110
return suffix;
98111
}
99112

100-
export type OpenOptions = {
101-
mods?: string;
102-
cmdarg?: string;
103-
opener?: string;
104-
};
105-
106-
export type OpenResult = {
107-
winid: number;
108-
bufnr: number;
109-
winnr: number;
110-
tabpagenr: number;
111-
};
112-
113113
/**
114114
* Open a buffer
115115
*/
@@ -131,6 +131,19 @@ export async function open(
131131
) as OpenResult;
132132
}
133133

134+
export type OpenOptions = {
135+
mods?: string;
136+
cmdarg?: string;
137+
opener?: string;
138+
};
139+
140+
export type OpenResult = {
141+
winid: number;
142+
bufnr: number;
143+
winnr: number;
144+
tabpagenr: number;
145+
};
146+
134147
/**
135148
* Edit a buffer
136149
*/
@@ -142,11 +155,82 @@ export async function reload(denops: Denops, bufnr: number): Promise<void> {
142155
);
143156
}
144157

145-
export type ReplaceOptions = {
158+
/**
159+
* Decode content for the buffer with given format and encoding.
160+
*/
161+
export async function decode(
162+
denops: Denops,
163+
bufnr: number,
164+
data: Uint8Array,
165+
options: DecodeOptions = {},
166+
): Promise<DecodeResult> {
167+
const [fileformat, fileformatsStr, fileencodingsStr] = await batch.gather(
168+
denops,
169+
async (denops) => {
170+
await fn.getbufvar(denops, bufnr, "&fileformat");
171+
await fn.getbufvar(denops, bufnr, "&fileformats");
172+
await fn.getbufvar(denops, bufnr, "&fileencodings");
173+
},
174+
);
175+
assertFileFormat(fileformat);
176+
unknownutil.assertString(fileformatsStr);
177+
unknownutil.assertString(fileencodingsStr);
178+
const fileformats = fileformatsStr.split(",");
179+
const fileencodings = fileencodingsStr.split(",");
180+
unknownutil.assertArray(fileformats, isFileFormat);
181+
unknownutil.assertArray(fileencodings, unknownutil.isString);
182+
let enc: string;
183+
let text: string;
184+
if (options.fileencoding) {
185+
enc = options.fileencoding;
186+
text = (new TextDecoder(enc)).decode(data);
187+
} else {
188+
[enc, text] = tryDecode(data, fileencodings);
189+
}
190+
const ff = maybeFileFormat(options.fileformat) ??
191+
findFileFormat(text, fileformats) ?? fileformat;
192+
return {
193+
content: splitText(text, ff),
194+
fileformat: ff,
195+
fileencoding: enc,
196+
};
197+
}
198+
199+
export type DecodeOptions = {
146200
fileformat?: string;
147201
fileencoding?: string;
148202
};
149203

204+
export type DecodeResult = {
205+
content: string[];
206+
fileformat: FileFormat;
207+
fileencoding: string;
208+
};
209+
210+
/**
211+
* Append content under the current cursor position or given lnum of the buffer
212+
*/
213+
export async function append(
214+
denops: Denops,
215+
bufnr: number,
216+
repl: string[],
217+
options: AppendOptions = {},
218+
): Promise<void> {
219+
const suffix = await ensurePrerequisites(denops);
220+
const lnum = options.lnum ??
221+
await ensure(denops, bufnr, () => fn.line(denops, "."));
222+
await denops.call(
223+
`DenopsStdBufferAppend_${suffix}`,
224+
bufnr,
225+
lnum,
226+
repl,
227+
);
228+
}
229+
230+
export type AppendOptions = {
231+
lnum?: number;
232+
};
233+
150234
/**
151235
* Replace the buffer content
152236
*/
@@ -166,54 +250,40 @@ export async function replace(
166250
);
167251
}
168252

169-
export type AssignOptions = {
253+
export type ReplaceOptions = {
170254
fileformat?: string;
171255
fileencoding?: string;
172-
preprocessor?: (repl: string[]) => string[];
173256
};
174257

175258
/**
176259
* Assign content to the buffer with given format and encoding.
260+
*
261+
* @deprecated Use `decode()` and `replace()` individually instead.
177262
*/
178263
export async function assign(
179264
denops: Denops,
180265
bufnr: number,
181-
content: Uint8Array,
266+
data: Uint8Array,
182267
options: AssignOptions = {},
183268
): Promise<void> {
184-
const [fileformat, fileformatsStr, fileencodingsStr] = await batch.gather(
269+
const { content, fileformat, fileencoding } = await decode(
185270
denops,
186-
async (denops) => {
187-
await fn.getbufvar(denops, bufnr, "&fileformat");
188-
await fn.getbufvar(denops, bufnr, "&fileformats");
189-
await fn.getbufvar(denops, bufnr, "&fileencodings");
190-
},
271+
bufnr,
272+
data,
273+
options,
191274
);
192-
assertFileFormat(fileformat);
193-
unknownutil.assertString(fileformatsStr);
194-
unknownutil.assertString(fileencodingsStr);
195-
const fileformats = fileformatsStr.split(",");
196-
const fileencodings = fileencodingsStr.split(",");
197-
unknownutil.assertArray(fileformats, isFileFormat);
198-
unknownutil.assertArray(fileencodings, unknownutil.isString);
199-
let enc: string;
200-
let text: string;
201-
if (options.fileencoding) {
202-
enc = options.fileencoding;
203-
text = (new TextDecoder(enc)).decode(content);
204-
} else {
205-
[enc, text] = tryDecode(content, fileencodings);
206-
}
207-
const ff = maybeFileFormat(options.fileformat) ??
208-
findFileFormat(text, fileformats) ?? fileformat;
209275
const preprocessor = options.preprocessor ?? ((v: string[]) => v);
210-
const repl = preprocessor(splitText(text, ff));
276+
const repl = preprocessor(content);
211277
await replace(denops, bufnr, repl, {
212-
fileformat: ff,
213-
fileencoding: enc,
278+
fileformat,
279+
fileencoding,
214280
});
215281
}
216282

283+
export type AssignOptions = DecodeOptions & {
284+
preprocessor?: (repl: string[]) => string[];
285+
};
286+
217287
/**
218288
* Concrete the buffer.
219289
*

0 commit comments

Comments
 (0)