Skip to content

Commit

Permalink
Merge branch 'export-cmd' into wasm
Browse files Browse the repository at this point in the history
  • Loading branch information
rhysd committed Jun 20, 2019
2 parents 39a3537 + 3b5fe09 commit 4c81d4c
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 30 deletions.
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,24 @@ and interacts with the main thread via [`SharedArrayBuffer`][shared-array-buffer

### [Try it with your browser][try it]

- **NOTICES**
- **USAGE**
- Drag&Drop file to browser tab opens it in Vim
- `:write` only writes file on memory. Download current buffer by `:export` or
specific file by `:export {file}`.
- You can try vimtutor by `:e tutor`.

- **NOTICE**
- Please access from desktop Chrome, Firefox, Safari or Chromium based browsers
since this project uses `SharedArrayBuffer` and `Atomics`. On Firefox or Safari,
feature flags (`javascript.options.shared_memory` for Firefox) must be enabled
for now.
- Drag&Drop file to browser tab opens the file in Vim
- vim.wasm takes key inputs from DOM `keydown` event. Please disable your browser
extensions which affect key inputs (incognito mode would be the best).
extensions which intercept key events (incognito mode would be the best).
- This project is very early phase of experiment. Only tiny features
are supported for now (please see TODO section). And you may notice soon on
trying it... it's buggy :)
- If inputting something does not change anything, please try to click somewhere
in the page. Vim may have lost the focus.
- You can try vimtutor by `:e tutor`.
- Vim exits on `:quit`, but it does not close a browser tab. Please close it
manually :)

Expand Down
44 changes: 22 additions & 22 deletions src/ex_cmdidxs.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,27 @@ static const unsigned short cmdidxs1[26] =
/* c */ 42,
/* d */ 103,
/* e */ 125,
/* f */ 145,
/* g */ 161,
/* h */ 167,
/* i */ 176,
/* j */ 194,
/* k */ 196,
/* l */ 201,
/* m */ 259,
/* n */ 277,
/* o */ 297,
/* p */ 309,
/* q */ 348,
/* r */ 351,
/* s */ 370,
/* t */ 437,
/* u */ 477,
/* v */ 488,
/* w */ 506,
/* x */ 521,
/* y */ 530,
/* z */ 531
/* f */ 146,
/* g */ 162,
/* h */ 168,
/* i */ 177,
/* j */ 195,
/* k */ 197,
/* l */ 202,
/* m */ 260,
/* n */ 278,
/* o */ 298,
/* p */ 310,
/* q */ 349,
/* r */ 352,
/* s */ 371,
/* t */ 438,
/* u */ 478,
/* v */ 489,
/* w */ 507,
/* x */ 522,
/* y */ 531,
/* z */ 532
};

/*
Expand Down Expand Up @@ -69,4 +69,4 @@ static const unsigned char cmdidxs2[26][26] =
/* z */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

static const int command_count = 544;
static const int command_count = 545;
50 changes: 50 additions & 0 deletions src/ex_cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -8563,3 +8563,53 @@ ex_oldfiles(exarg_T *eap UNUSED)
}
}
#endif


void
ex_export(exarg_T *eap)
{
#ifndef FEAT_GUI_WASM
EMSG(_("E9999: This command is available only for Wasm build"));
#else
int other;
char_u *ffname = eap->arg;
int free_ffname = FALSE;

// Note: This implementation referred implementation of do_write()
// Note: ffname means full-fname

if (curbufIsChanged() && do_write(eap) == FAIL)
{
// Could not write the buffer. Do not export file
return;
}

if (*ffname == NUL)
{
ffname = curbuf->b_ffname;
}
else
{
ffname = fix_fname(ffname);
if (ffname == NULL)
{
EMSG(_("E9999: Could not export this file"));
return;
}
free_ffname = TRUE;
}

if (ffname == NULL)
EMSG(_("E9999: Cannot export file due to OOM"));
else
{
if (!vimwasm_export_file(ffname))
{
EMSG(_("E9999: Could not export file in JavaScript runtime"));
}
}

if (free_ffname)
vim_free(ffname);
#endif // FEAT_GUI_WASM
}
3 changes: 3 additions & 0 deletions src/ex_cmds.h
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,9 @@ EX(CMD_execute, "execute", ex_execute,
EX(CMD_exit, "exit", ex_exit,
RANGE|WHOLEFOLD|BANG|FILE1|ARGOPT|DFLALL|TRLBAR|CMDWIN,
ADDR_LINES),
EX(CMD_export, "export", ex_export,
FILE1|ARGOPT|TRLBAR,
ADDR_LINES),
EX(CMD_exusage, "exusage", ex_exusage,
TRLBAR,
ADDR_LINES),
Expand Down
1 change: 1 addition & 0 deletions src/proto/ex_cmds.pro
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,5 @@ void ex_smile(exarg_T *eap);
void ex_drop(exarg_T *eap);
char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags);
void ex_oldfiles(exarg_T *eap);
void ex_export(exarg_T *eap);
/* vim: set ft=c : */
1 change: 1 addition & 0 deletions src/wasm_runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ int vimwasm_get_mouse_y(void);
void vimwasm_resize(int, int);
int vimwasm_call_shell(char *);
int vimwasm_wait_for_event(int timeout);
int vimwasm_export_file(char *fullpath);

#endif /* FEAT_GUI_WASM */

Expand Down
8 changes: 7 additions & 1 deletion wasm/common.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,13 @@ declare type MessageFromWorker =
readonly status: number;
timestamp?: number;
}
| FileBufferMessageFromWorker;
| FileBufferMessageFromWorker
| {
readonly kind: 'export';
readonly path: string;
readonly contents: ArrayBuffer;
timestamp?: number;
};
declare type MessageKindFromWorker = MessageFromWorker['kind'];

declare type EventStatusFromMain = 0 | 1 | 2 | 3 | 4;
30 changes: 29 additions & 1 deletion wasm/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,7 @@ interface StartOptions {
class VimWasm {
public onVimInit?: () => void;
public onVimExit?: (status: number) => void;
public onFileExport?: (fullpath: string, contents: ArrayBuffer) => void;
private readonly worker: VimWorker;
private readonly screen: ScreenCanvas;
private readonly resizer: ResizeHandler;
Expand Down Expand Up @@ -652,6 +653,19 @@ class VimWasm {
this.screen.enqueue(msg.event);
debug('draw event', msg.event);
break;
case 'export':
debug(
'Exporting file',
msg.path,
'with size',
msg.contents.byteLength,
'bytes with',
this.onFileExport,
);
if (this.onFileExport !== undefined) {
this.onFileExport(msg.path, msg.contents);
}
break;
case 'started':
this.screen.onVimInit();
this.resizer.onVimInit();
Expand Down Expand Up @@ -679,7 +693,7 @@ class VimWasm {
debug('Vim exited with status', msg.status);
break;
default:
throw new Error(`FATAL: Unexpected message from worker: ${msg}`);
throw new Error(`FATAL: Unexpected message from worker: ${JSON.stringify(msg)}`);
}
}

Expand Down Expand Up @@ -796,4 +810,18 @@ if (!perf) {
};
}

vim.onFileExport = (fullpath: string, contents: ArrayBuffer) => {
const slashIdx = fullpath.lastIndexOf('/');
const filename = slashIdx !== -1 ? fullpath.slice(slashIdx + 1) : fullpath;
const blob = new Blob([contents], { type: 'application/octet-stream' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};

vim.start({ debug: debugging, perf });
2 changes: 2 additions & 0 deletions wasm/runtime.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ declare const FS: {
stderr: ((...args: any[]) => void) | null,
): void;
writeFile(name: string, contents: Uint8Array): void;
readFile(path: string, opts?: { encoding?: string; flags?: string }): Uint8Array;
};
declare interface VimWasmRuntime {
domWidth: number;
Expand All @@ -33,6 +34,7 @@ declare interface VimWasmRuntime {
vimStarted(): void;
vimExit(status: number): void;
waitForEventFromMain(timeout: number | undefined): number;
exportFile(fullpath: string): number;
}
declare const VW: {
runtime: VimWasmRuntime;
Expand Down
16 changes: 14 additions & 2 deletions wasm/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,13 @@ const VimWasmLibrary = {
}
}

exportFile(fullpath: string) {
const contents = FS.readFile(fullpath).buffer; // encoding = binary
debug('Read', contents.byteLength, 'bytes contents from', fullpath);
this.sendMessage({ kind: 'export', path: fullpath, contents }, [contents]);
return 1;
}

private eventStatus() {
return Atomics.load(this.buffer, 0) as EventStatusFromMain;
}
Expand Down Expand Up @@ -264,13 +271,13 @@ const VimWasmLibrary = {
return [idx, s];
}

private sendMessage(msg: MessageFromWorker) {
private sendMessage(msg: MessageFromWorker, transfer?: ArrayBuffer[]) {
if (this.perf) {
// performance.now() is not available because time origin is different between
// Window and Worker
msg.timestamp = Date.now();
}
postMessage(msg);
postMessage(msg, transfer as any);
}
}

Expand Down Expand Up @@ -441,6 +448,11 @@ const VimWasmLibrary = {
vimwasm_wait_for_event(timeout: number): number {
return VW.runtime.waitForEventFromMain(timeout > 0 ? timeout : undefined);
},

// int vimwasm_export_file(char *);
vimwasm_export_file(fullpath: CharPtr) {
return VW.runtime.exportFile(UTF8ToString(fullpath));
},
};

autoAddDeps(VimWasmLibrary, '$VW');
Expand Down

0 comments on commit 4c81d4c

Please sign in to comment.