Skip to content

Commit 915fbee

Browse files
authored
Merge pull request #15 from vim-denops/load-scriptfile
Add `load()` to source local/remote Vim script
2 parents 72abe82 + 2930cbd commit 915fbee

File tree

4 files changed

+81
-0
lines changed

4 files changed

+81
-0
lines changed

deps.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
export * as path from "https://deno.land/std@0.95.0/path/mod.ts";
2+
export * as hash from "https://deno.land/std@0.95.0/hash/mod.ts";
3+
export * as fs from "https://deno.land/std@0.95.0/fs/mod.ts";
4+
15
export type {
26
Context,
37
Dispatcher,

vim/load.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { Denops, fs, hash, path } from "../deps.ts";
2+
import { execute } from "./execute.ts";
3+
4+
/**
5+
* Load Vim script in local/remote URL
6+
*/
7+
export async function load(
8+
denops: Denops,
9+
url: URL,
10+
): Promise<void> {
11+
const scriptPath = await ensureLocalFile(url);
12+
await execute(
13+
denops,
14+
"execute printf('source %s', fnameescape(scriptPath)) ",
15+
{ scriptPath },
16+
);
17+
}
18+
19+
async function ensureLocalFile(url: URL): Promise<string> {
20+
if (url.protocol === "file:") {
21+
return path.fromFileUrl(url);
22+
}
23+
const cacheDir = await getOrCreateCacheDir();
24+
const filename = getLocalFilename(url);
25+
const filepath = path.join(cacheDir, filename);
26+
if (await fs.exists(filepath)) {
27+
return filepath;
28+
}
29+
const response = await fetch(url);
30+
if (response.status !== 200) {
31+
throw new Error(`Failed to fetch '${url}'`);
32+
}
33+
const content = await response.arrayBuffer();
34+
await Deno.writeFile(
35+
filepath,
36+
new Uint8Array(content),
37+
{ mode: 0o700 }, // Do NOT allow groups/others to read the file
38+
);
39+
return filepath;
40+
}
41+
42+
function getLocalFilename(url: URL): string {
43+
const h = hash.createHash("sha256");
44+
h.update(url.href);
45+
const basename = path.basename(url.pathname);
46+
return `${h.digest()}-${basename}`;
47+
}
48+
49+
async function getOrCreateCacheDir(): Promise<string> {
50+
const cacheDir = Deno.build.os === "windows"
51+
? getCacheDirWindows()
52+
: getCacheDirUnix();
53+
await Deno.mkdir(cacheDir, { recursive: true });
54+
return cacheDir;
55+
}
56+
57+
function getCacheDirUnix(): string {
58+
const root = Deno.env.get("HOME");
59+
if (!root) {
60+
throw new Error("`HOME` environment variable is not defined.");
61+
}
62+
return path.join(root, ".cache", "denops_std", "load");
63+
}
64+
65+
function getCacheDirWindows(): string {
66+
const root = Deno.env.get("LOCALAPPDATA");
67+
if (!root) {
68+
throw new Error("`LOCALAPPDATA` environment variable is not defined.");
69+
}
70+
return path.join(root, "denops_std", "load");
71+
}

vim/mod.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from "./autocmd.ts";
22
export * from "./execute.ts";
33
export * from "./variable.ts";
4+
export * from "./load.ts";
45
export * from "./vim.ts";

vim/vim.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Context, Denops, Dispatcher } from "../deps.ts";
22
import { execute } from "./execute.ts";
33
import { autocmd, AutocmdHelper } from "./autocmd.ts";
44
import { VariableHelper } from "./variable.ts";
5+
import { load } from "./load.ts";
56

67
export class Vim {
78
private static instance?: Vim;
@@ -60,6 +61,10 @@ export class Vim {
6061
await autocmd(this.#denops, group, main);
6162
}
6263

64+
async load(url: URL): Promise<void> {
65+
await load(this.#denops, url);
66+
}
67+
6368
register(dispatcher: Dispatcher): void {
6469
this.#denops.extendDispatcher(dispatcher);
6570
}

0 commit comments

Comments
 (0)