Этот проект — экспериментальная ветка [редактора Vim][] от @rhysd для компиляции
его в WebAssembly с использованием emscripten и binaryen. Vim работает на Web Worker
и взаимодействует с основным потоком через SharedArrayBuffer
.
Цель этого проекта — запуск редактора Vim в браузерах без утраты мощных функций Vim, скомпилировав исходные коды C в WebAssembly.
:write
записывает файл только в память. Скачайте текущий буфер с помощью :export
или
конкретный файл с помощью :export {file}
."*
поддерживается. Например, вставьте текст из системного буфера в Vim с помощью "*p
или :put *
, и скопируйте текст из Vim в системный буфер с помощью
"*y
или :yank *
.
Если вы хотите синхронизировать буфер Clipboard Vim с системным буфером,
команда :set clipboard=unnamed
должна работать как в обычном Vim.~/.vim
сохраняются персистентно в Indexed DB.
Пожалуйста, напишите вашу любимую конфигурацию в ~/.vim/vimrc
(НЕ ~/.vimrc
).file={filepath}={url}
загружает файл с {url}
в {filepath}
. Любые
удалённые файлы могут быть открыты (учтите CORS).:! /path/to/file.js
выполняет JavaScript-код в браузере. :! %
выполняет
текущий буфер.:e tutor
.arg=
(например, ?arg=~%2f.vim%2fvimrc&arg=hello.txt
) для
добавления аргументов командной строки Vim.monokai: https://github.com/sjl/greyshade.vimmd) для более подробной информации.onedark: https://github.com/dimonomid/onedark.vim monokai: https://github.com/sjl/gxv/tree/master/scripts/vim-monokai idb: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API [vim editor]: https://www.vim.org/ @rhysd: https://github.com/rhysd webassembly: https://webassembly.org/ emscripten: https://emscripten.org/ binaryen: https://github.com/WebAssembly/binaryen web worker: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API shared-array-buffer: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer try it: https://rhysd.github.io/vim-wasm/ travis-ci-badge: https://img.shields.io/travis/rhysd/vim-wasm npm-badge: https://img.shields.io/npm/v/vim-wasm travis-ci: https://travis-ci.org/rhysd/vim-wasm npm-package: https://www.npmjs.com/package/vim-wasm
Уведомление
SharedArrayBuffer
и Atomics
. В Firefox или Safari для текущего времени необходимо включить флаги функций (javascript.options.shared_memory
для Firefox).vim.wasm
принимает клавишные вводы из события keydown
DOM. Пожалуйста, отключите расширения вашего браузера, которые перехватывают клавишные события (режим инкогнито будет наилучшим вариантом).:quit
, но это не закрывает вкладку браузера. Пожалуйста, закройте её вручную.Этот проект упакован в виде npm пакета vim-wasm
для удобного использования в веб-приложениях. Пожалуйста, ознакомьтесь с документацией для получения дополнительной информации.Текущая версия Vim, перенесенная в WebAssembly, — это 8.2.0055 с наборами функций 'normal' и 'small'. Пожалуйста, проверьте журнал изменений для истории обновлений.
Следующие проекты связаны с этим npm пакетом и могут быть более подходящими для вашего случая использования.
vim.wasm
. Редактор Vim можно встроить в ваше веб-приложение на основе React.vim.wasm
, включающего указанный плагин Vim, сразу. Вы можете попробовать плагин Vim без его установки!vim.wasm
. Попробуйте онлайн!
В рабочем потоке запускается скомпилированный в Wasm Vim. Рабочий поток запускается как отдельный Web Worker от главного потока при открытии страницы.
Предположим, вы вводите что-то с клавиатуры. Браузер принимает это как KeyboardEvent
на событии keydown
. JavaScript в главном потоке ловит событие и сохраняет информацию о нажатии клавиши в буфер общей памяти.
Буфер общей памяти делится между рабочим потоком. Vim ждет и получает информацию о нажатии клавиш, опрашивая буфер общей памяти с помощью API Atomics
JavaScript. Когда информация о нажатии клавиш обнаруживается в буфере, она загружается и вычисляется последовательность нажатий. С помощью API JS to Wasm, благодаря emscripten, последовательность добавляется в буфер ввода Vim в Wasm.
Последовательность в буфере ввода обрабатывается ядром редактора (обновление буфера, экрана, ...). Из-за этих обновлений происходят события отрисовки, такие как отрисовка текста, отрисовка прямоугольников, прокрутка областей, ...
Эти события отрисовки отправляются JavaScript в рабочем потоке из Wasm благодаря API JS to C emscripten. Учитывая соотношение пикселей устройства и API <canvas/>
, вычисляется способ рендеринга этих событий, и вычисленные события рендеринга передаются из рабочего потока в главный поток с помощью передачи сообщений с помощью postMessage()
.JavaScript в главном потоке получает и помещает эти события рендеринга в очередь. На каждом кадре анимации они рендерятся на <canvas/>
.
В итоге вы видите отрендеренный экран на странице.
WebAssembly-интерфейс для Vim реализован как новый графический интерфейс пользователя для Vim, подобно другим графическим интерфейсам, таким как GTK-интерфейс. Исходные коды C компилируются в отдельные файлы LLVM-биткода, а затем они объединяются в один файл биткода vim.bc
с помощью emcc
. emcc
в конечном итоге компилирует vim.bc
в двоичный файл vim.wasm
с помощью binaryen и генерирует HTML/JavaScript-временную среду выполнения.
Первое, с чем я столкнулся, это отсутствие библиотеки терминалов, такой как ncurses. Я изменил скрипт configure
, чтобы игнорировать проверку библиотеки терминалов. Это нормально, так как графический интерфейс пользователя для Wasm всегда используется вместо консольного интерфейса пользователя. Мне пришлось использовать множество обходных путей, чтобы пройти проверки configure
.Emscripten предоставляет Unix-подобную среду. Поэтому os_unix.c
может поддерживать Wasm. Однако некоторые функции не поддерживаются emscripten. Я добавил множество #ifdef FEAT_GUI_WASM
для отключения функций, которые не могут быть поддерживаемы Wasm (например, поддержка fork(2)
, поддержка PTY, обработчики сигналов являются заглушками, ...). Я создал gui_wasm.c
, heavily опираясь на gui_mac.c
и gui_w32.c
. Цикл событий (gui_mch_update()
и gui_mch_wait_for_chars()
) реализован с использованием блокирующего ожидания. И почти все события отрисовки UI передаются на JavaScript-уровень путем вызова функций JavaScript из C благодаря emscripten.Исходные коды C скомпилированы (с множеством оптимизаций) в LLVM bitcode с Clang, который интегрирован в emscripten. Затем все файлы bitcode (.o
) связываются в один файл bitcode vim.bc
с помощью llvm-link
(также интегрированного в emscripten).
Я также создал JavaScript-таймайнт на TypeScript для отрисовки событий отрисовки, отправленных из C. JavaScript-таймайнт разделен на две части: основной поток и поток рабочего процесса. wasm/main.ts
предназначен для основного потока. Он запускает Vim в потоке рабочего процесса и отрисовывает экран Vim на <canvas>
, получая события отрисовки от Vim. wasm/runtime.ts
и wasm/pre.ts
предназначены для потока рабочего процесса. Они написаны с использованием API emscripten.
emcc
(C-компилятор emscripten) компилирует vim.bc
и runtime.js
в vim.wasm
, vim.js
и vim.data
с заранее загруженными файлами runtime Vim (например, схемами цветов) с помощью binaryen. Файлы runtime загружаются на виртуальную файловую систему, предоставленную браузером emscripten. Здесь эти файлы компилируются для потока рабочего процесса. wasm/main.js
запускает отдельного Web Worker, загружающего vim.js
.
Наконец, я создал небольшой wasm/index.html
, который содержит <canvas/>
для отрисовки экрана Vim и загрузки wasm/main.js
.
Теперь, размещая wasm/index.html
с помощью веб-сервера и доступ к нему с помощью браузера, можно запустить Vim. Он работает.### Как реализовать sleep()
на JavaScript
Самая сложная часть этого переноса заключалась в том, как реализовать блокирующее ожидание (обычно выполняемое с помощью sleep()
).
Так как блокировка основного потока на веб-странице означает блокировку взаимодействия пользователя, это, в основном, запрещено. Почти все операции, требующие времени, реализованы как асинхронные API на JavaScript. Wasm, работающий в основном потоке, не может блокировать поток, кроме как с помощью busy loop.Но C-программы часто используют функцию sleep()
, поэтому это проблема при переносе программ. GUI-фронтенд Vim также ожидает ввод пользователя с использованием блокирующего ожидания. Emscripten предлагает обходной путь для решения этой проблемы, Emterpreter. С использованием Emterpreter, Emscripten предоставляет (псевдо) блокирующие функции ожидания, такие как emscripten_sleep()
. Когда они используются в C-функции, emcc
компилирует функцию в Emterpreter-байт-код вместо Wasm. И во время выполнения байт-код выполняется интерпретатором (на Wasm). Когда интерпретатор достигает точки вызова emscripten_sleep()
, он приостанавливает выполнение байт-кода и устанавливает таймер (с помощью функции setTimeout
на JavaScript). После истечения времени интерпретатор возобновляет состояние и продолжает выполнение. С этой механикой асинхронное ожидание на JavaScript выглядит как синхронное ожидание из мира C. Вначале я использовал Emterpreter, и это работало. Однако были несколько проблем.- Он разделяет исходные файлы Vim на две части: чистый Wasm-код, который выполняется напрямую, и Emterpreter-байт-код, который выполняется на интерпретаторе. Мне приходилось поддерживать длинный список функций, которые должны быть скомпилированы в Emterpreter-байт-код. Когда список неверен, Vim падает.
Я искал альтернативу и нашел Atomics.wait()
. Atomics.wait()
— это низкоуровневая синхронная примитивная функция. Она ожидает, пока определенный байт в буфере совместного доступа к памяти не будет обновлен. Это блокирующее ожидание. Конечно, оно недоступно на основном потоке. Его следует использовать на потоке рабочего процесса.
Я перенес базу Wasm-кода в Web Worker, выполняющийся на рабочем потоке, хотя рендеринг <canvas/>
все еще выполняется в основном потоке.
Vim использует
Atomics.wait()
для ожидания ввода пользователя, наблюдая за буфером совместного доступа к памяти. Когда происходит событие клавиши, основной поток сохраняет данные события клавиши в буфер совместного доступа к памяти и уведомляет о новом событии клавиши с помощью Atomics.notify()
. Рабочий поток обнаруживает, что буфер был обновлен с помощью Atomics.wait()
, и загружает данные события клавиши из буфера. Vim вычисляет последовательность клавиш из данных и добавляет её в буфер ввода. Наконец, Vim обрабатывает событие и отправляет события рисования в основной поток через JavaScript.В качестве бонуса взаимодействие пользователя больше не блокируется, так как почти вся логика, включая весь Vim, выполняется в рабочем потоке.
Пожалуйста, убедитесь, что установлены Emscripten (я использую 1.38.37) и binaryen (я использую v84). Если вы используете macOS, они могут быть установлены с помощью brew install emscripten binaryen
.
Пожалуйста, используйте скрипт build.sh
для работы над этим проектом. Просто после клонирования этого репозитория запустите ./build.sh
. Он собирает vim.wasm в директории wasm/
. Это требует времени и мощности процессора. Наконец, разместите wasm/
напрямую на localhost
с помощью веб-сервера, такого как
python -m http.server 1234
. Доступ к localhost:1234?debug
запустит Vim с отладочными логами. Обратите внимание, что это намного медленнее, чем выпускная сборка, так как включены многие отладочные возможности. Пожалуйста, прочитайте wasm/README.md для получения дополнительной информации.
Пожалуйста, обратите внимание, что ветка wasm
этого репозитория часто объединяет последнюю версию vim/vim master ветки. Если вы хотите работать над этим проектом, убедитесь, что вы создали свою собственную ветку и объединили ветку wasm
в вашу ветку с помощью git merge
.
sleep()
. По умолчанию, emscriptenкомпилирует sleep()
в бесконечный цикл. Поэтому vim.wasm использует Emterpreter
который предоставляет emscripten_sleep()
. Некоторые функции, разрешенные в белом списке, выполняются с использованием Emterpreter. Однако эта функция не так стабильна. Она увеличивает размер сборки и затягивает процесс компиляции.~~ Это было исправлено в #30
string
, не работает.SharedArrayBuffer
отключен из-за уязвимости Spectre. Это можно исправить с помощью Asyncify. Работа ведется и отслеживается в PR #35.## TODOРазработка управляется в GitHub Projects.
<canvas/>
в рабочем потоке с использованием Offscreen CanvasЭтот проект был вдохновлен впечатляющим проектом vim.js от Lu Wang.
:help license
для получения дополнительной информации. [Vim editor]: https://www.vim.org/
Для переводов этого README смотрите конец файла.
Vim — это значительно улучшенная версия хорошего старого UNIX-редактора Vi. В нём добавлено множество новых функций: многоуровневое отмену действий, синтаксическое выделение, историю командной строки, онлайн-справку, проверку орфографии, автозавершение имен файлов, операции с блоками, языки сценариев и т.д. Также доступен графический интерфейс пользователя (GUI). При этом сохранена совместимость с Vi, поэтому те, кто привык к Vi, будут чувствовать себя как дома. Различия между Vim и Vi можно найти в файле runtime/doc/vi_diff.txt
.Этот редактор очень полезен для редактирования программ и других текстовых файлов. Все команды вводятся с помощью обычных символов клавиатуры, поэтому те, кто умеет печатать двумя руками, могут работать очень быстро. Кроме того, пользователь может назначить функциональным клавишам команды, а также использовать мышь.
Vim работает под MS-Windows (NT, 2000, XP, Vista, 7, 8, 10), Macintosh, VMS и почти всех версиях UNIX. Портация на другие системы не должна быть слишком сложной. Старые версии Vim работают под MS-DOS, MS-Windows 95/98/Me, Amiga DOS, Atari MiNT, BeOS, RISC OS и OS/2. Эти версии больше не поддерживаются.
Часто вы можете использовать свой любимый менеджер пакетов для установки Vim. На Mac и Linux предустановлен небольшой вариант Vim, но если вам нужны дополнительные функции, вам всё равно потребуется установить Vim.
Существуют отдельные дистрибутивы для Unix, PC, Amiga и некоторых других систем. Этот файл README.md
прилагается к архиву runtime. В него входят документация, файлы синтаксического анализа и другие файлы, используемые во время работы. Чтобы запустить Vim, вам нужно получить либо один из двоичных архивов, либо архив исходного кода. Какой именно вам нужен, зависит от системы, на которой вы хотите его запустить, и от того, хотите ли вы или должны сами скомпилировать его. Проверьте http://www.vim.org/download.php для обзора доступных дистрибутивов.Некоторые популярные места для получения последней версии Vim:
Если вы получили двоичный дистрибутив, вам не нужно компилировать Vim. Если вы получили дистрибутив исходного кода, все необходимые файлы для компиляции Vim находятся в директории src
. Инструкции по компиляции можно найти в файле src/INSTALL
.
Для получения системно-специфических инструкций обратитесь к одному из этих файлов. Или в директории READMEdir
(в репозитории), или в корневой директории (если вы распаковали архив):
README_ami.txt Amiga
README_unix.txt Unix
README_dos.txt MS-DOS и MS-Windows
README_mac.txt Macintosh
README_vms.txt VMS
Есть и другие файлы README_*.txt
, в зависимости от используемой версии дистрибутива.
Уроки Vim для начинающих представляют собой учебный курс продолжительностью один час. Часто его можно запустить как vimtutor
. Для получения дополнительной информации увидьте :help tutor
.
Лучше всего использовать :help
в Vim. Если у вас ещё нет исполняемого файла, прочитайте runtime/doc/help.txt
. В этом файле содержатся ссылки на другие документы. Пользовательский справочник написан в виде книги и рекомендуется для изучения использования Vim. Увидьте :help user-manual
.## Копирование ##
Vim — это программа с благотворительной лицензией. Вы можете использовать и копировать её столько, сколько вам угодно, но вы поощряетесь сделать пожертвование, чтобы помочь сиротам в Уганде. Пожалуйста, прочитайте файл runtime/doc/uganda.txt
для получения подробностей (выполните :help uganda
внутри Vim).
Краткое содержание лицензии: нет никаких ограничений на использование или распространение неизменённой копии Vim. Части Vim также могут быть распространены, но текст лицензии всегда должен быть включён. Для изменённых версий применяются некоторые ограничения. Лицензия совместима с GPL, вы можете скомпилировать Vim с библиотеками GPL и распространять его.
Исправление ошибок и добавление новых функций требует много времени и усилий. Чтобы выразить свою благодарность за выполненную работу и мотивировать Брама и других продолжать работу над Vim, пожалуйста, отправьте пожертвование.
Так как Брам вернулся к оплачиваемой работе, деньги теперь будут использованы для помощи детям в Уганде. Увидьте runtime/doc/uganda.txt
. Но при этом пожертвования увеличивают мотивацию Брама продолжать работу над Vim!
Для получения самой последней информации о спонсорстве посмотрите на веб-сайте Vim: http://www.vim.org/sponsor/
Последние новости о Vim можно найти на домашней странице Vim: http://www.vim.org/
Если у вас возникли проблемы, посмотрите документацию или советы: http://www.vim.org/docs.php http://vim.wikia.com/wiki/Vim_Tips_Wiki
Если у вас все еще возникают проблемы или у вас есть другие вопросы, используйте одну из рассылок, чтобы обсудить их с пользователями и разработчиками Vim: http://www.vim.org/maillist.php
Если ничего больше не помогает, сообщите об ошибках напрямую: Bram Moolenaar Bram@vim.org
Отправьте любые другие комментарии, патчи, цветы и предложения на: Bram Moolenaar Bram@vim.org
Это README.md
для версии 8.2 Vim: Vi IMproved.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )