├── .npmrc ├── test ├── mocha.opts ├── lib.d.ts ├── tsconfig.json ├── helper │ └── nyaovim.ts └── smoke │ └── startup.ts ├── resources ├── title-bar.png ├── icon │ ├── nyaovim-logo.icns │ ├── nyaovim-logo.ico │ ├── nyaovim-logo.png │ └── nyaovim-logo.svg └── osx_plist │ └── file_associations.plist ├── .npmignore ├── .gitignore ├── bower.json ├── renderer ├── lib.d.ts ├── tsconfig.json ├── main.html ├── main.ts └── nyaovim-app.ts ├── .github ├── CONTRIBUTING.md ├── PULL_REQUEST_TEMPLATE.md └── ISSUE_TEMPLATE.md ├── .travis.yml ├── main ├── lib.d.ts ├── tsconfig.json ├── browser-config.ts ├── main.ts └── menu.ts ├── runtime ├── plugin │ └── nyaovim.vim └── autoload │ └── nyaovim.vim ├── scripts ├── travis-before-install.sh └── make-release.sh ├── Guardfile ├── bin └── cli.js ├── LICENSE.txt ├── docs ├── browser-config.md ├── faq.md ├── runtime-api.md ├── tips.md └── make-ui-plugin.md ├── package.json ├── tslint.json └── README.md /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --ui bdd 2 | --timeout 30000 3 | -------------------------------------------------------------------------------- /resources/title-bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rhysd/NyaoVim/HEAD/resources/title-bar.png -------------------------------------------------------------------------------- /test/lib.d.ts: -------------------------------------------------------------------------------- 1 | interface ObjectConstructor { 2 | assign(x: object, ...xs: object[]): object; 3 | } 4 | -------------------------------------------------------------------------------- /resources/icon/nyaovim-logo.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rhysd/NyaoVim/HEAD/resources/icon/nyaovim-logo.icns -------------------------------------------------------------------------------- /resources/icon/nyaovim-logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rhysd/NyaoVim/HEAD/resources/icon/nyaovim-logo.ico -------------------------------------------------------------------------------- /resources/icon/nyaovim-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rhysd/NyaoVim/HEAD/resources/icon/nyaovim-logo.png -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | /app.asar 3 | /.git 4 | /test 5 | /Guardfile 6 | /tslint.json 7 | /scripts 8 | /app 9 | /dist 10 | /.npmrc 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | npm-debug.log 3 | /app.asar 4 | /bower_components 5 | /main/**/*.js 6 | /main/**/*.js.map 7 | /renderer/**/*.js 8 | /renderer/**/*.js.map 9 | /test/**/*.js 10 | /app 11 | /dist 12 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nyaovim", 3 | "version": "0.0.0", 4 | "homepage": "https://github.com/rhysd/NyaoVim", 5 | "authors": [ 6 | "rhysd " 7 | ], 8 | "license": "MIT", 9 | "dependencies": { 10 | "polymer": "^2.5.0", 11 | "webcomponentsjs": "^1.1.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /renderer/lib.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare namespace NodeJS { 4 | interface Global { 5 | require: NodeRequireFunction; 6 | } 7 | } 8 | 9 | interface String { 10 | endsWith(search: string, position?: number): boolean; 11 | } 12 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Thank you for contributing NyaoVim! 2 | ========================================= 3 | 4 | ## Language 5 | 6 | I'm Japanese and not good English user. So Japanese is the best language to communicate, but of course English is also OK. 7 | 8 | ## Templates 9 | 10 | Please use issue/PR templates which are inserted automatically. 11 | 12 | -------------------------------------------------------------------------------- /test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "removeComments": true, 5 | "preserveConstEnums": true, 6 | "noImplicitAny": true, 7 | "noImplicitReturns": true, 8 | "noUnusedLocals": true, 9 | "noEmitOnError": true, 10 | "strictNullChecks": true, 11 | "target": "es2015" 12 | }, 13 | "include": [ 14 | "**/*.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: "6" 3 | os: 4 | # - osx 5 | - linux 6 | osx_image: xcode9 7 | dist: trusty 8 | sudo: required 9 | before_install: 10 | - source ./scripts/travis-before-install.sh 11 | install: 12 | - npm run dep 13 | script: 14 | - nvim --version 15 | - npm run build 16 | - npm run lint 17 | - npm run smoke-test 18 | notifications: 19 | email: 20 | on_success: never 21 | on_failure: change 22 | -------------------------------------------------------------------------------- /renderer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "removeComments": true, 5 | "preserveConstEnums": true, 6 | "outDir": ".", 7 | "noImplicitAny": true, 8 | "noImplicitReturns": true, 9 | "noUnusedLocals": true, 10 | "noUnusedParameters": true, 11 | "noEmitOnError": true, 12 | "target": "es2015", 13 | "sourceMap": true 14 | }, 15 | "files": [ 16 | "nyaovim-app.ts", 17 | "main.ts", 18 | "lib.d.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /main/lib.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace NodeJS { 2 | interface Global { 3 | config_dir_path: string; 4 | nyaovimrc_path: string; 5 | } 6 | } 7 | 8 | declare namespace ElectronWindowState { 9 | interface WindowState { 10 | x: number; 11 | y: number; 12 | width: number; 13 | height: number; 14 | isMaximized: boolean; 15 | isFullScreen: boolean; 16 | manage(win: Electron.BrowserWindow): void; 17 | saveState(win: Electron.BrowserWindow): void; 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /main/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "removeComments": true, 5 | "preserveConstEnums": true, 6 | "outDir": ".", 7 | "noImplicitAny": true, 8 | "noImplicitReturns": true, 9 | "noImplicitThis": true, 10 | "noUnusedLocals": true, 11 | "noUnusedParameters": true, 12 | "noEmitOnError": true, 13 | "target": "es2015", 14 | "sourceMap": true 15 | }, 16 | "files": [ 17 | "browser-config.ts", 18 | "menu.ts", 19 | "main.ts", 20 | "lib.d.ts" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /runtime/plugin/nyaovim.vim: -------------------------------------------------------------------------------- 1 | if (exists('g:loaded_nyaovim_runtime') && g:loaded_nyaovim_runtime) 2 | finish 3 | endif 4 | 5 | function! s:send_current_path(method) abort 6 | let p = expand('%:p') 7 | if filereadable(p) 8 | call rpcnotify(0, a:method, p) 9 | endif 10 | endfunction 11 | 12 | augroup nyaovim 13 | autocmd! 14 | autocmd BufReadPost,BufNewFile * call send_current_path('nyaovim:edit-start') 15 | augroup END 16 | 17 | call s:send_current_path('nyaovim:edit-start') 18 | 19 | let g:loaded_nyaovim_runtime = 1 20 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### What was a problem? 4 | 5 | {Please write here} 6 | 7 | ### How this PR fixes the problem? 8 | 9 | {Please write here} 10 | 11 | ### Check lists (check `x` in `[ ]` of list items) 12 | 13 | - [ ] Coding style (if any code was modified) 14 | - [ ] Confirmed 15 | - OS: {Please write here} 16 | - `nvim` version: {Please write here} 17 | 18 | ### Additional Comments (if any) 19 | 20 | {Please write here} 21 | 22 | -------------------------------------------------------------------------------- /scripts/travis-before-install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then 6 | sudo add-apt-repository ppa:neovim-ppa/unstable -y 7 | sudo apt-get -qq update 8 | sudo apt-get install -y software-properties-common python-software-properties 9 | sudo apt-get install -y neovim 10 | export DISPLAY=:99.0 11 | sh -e /etc/init.d/xvfb start 12 | sleep 3 13 | elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then 14 | brew update 15 | brew install neovim 16 | else 17 | echo "Unknown platform: ${TRAVIS_OS_NAME}" 18 | exit 1 19 | fi 20 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | ignore /^node_modules/, /^build/, /^typings/ 2 | 3 | def build(kind, path) 4 | suffix = 5 | if kind.empty? 6 | '' 7 | else 8 | "-#{kind}" 9 | end 10 | puts "\033[93m#{Time.now}: #{File.basename path}\033[0m" 11 | success = system "npm run build#{suffix}" 12 | if success 13 | puts "\033[92mOK\033[0m\n\n" 14 | else 15 | puts "\033[91mFAIL\033[0m\n\n" 16 | end 17 | end 18 | 19 | guard :shell do 20 | watch %r[^main/.+\.ts$] do |m| 21 | build(:main, m[0]) 22 | end 23 | 24 | watch %r[^renderer/.+\.ts$] do |m| 25 | build(:renderer, m[0]) 26 | end 27 | 28 | watch %r[^test/.+\.ts$] do |m| 29 | build(:test, m[0]) 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### Expected Behavior 4 | 5 | {Please write here} 6 | 7 | ### Actual Behavior 8 | 9 | {Please write here} 10 | 11 | ### Steps to Reproduce (including precondition) 12 | 13 | {Please write here} 14 | 15 | ### Screenshot on This Problem (if possible) 16 | 17 | {Please write here} 18 | 19 | ### Your Environment 20 | 21 | - OS: {Please write here} 22 | - NyaoVim version: {Please write here} 23 | - `nvim` version: {Please write here} 24 | - Keyboard layout: {Please write here} 25 | - Linux: Window manager: {Please write here} 26 | 27 | ### Additional Comments (if any) 28 | 29 | {Please write here} 30 | 31 | -------------------------------------------------------------------------------- /bin/cli.js: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | 3 | const spawn = require('child_process').spawn; 4 | const electron = require('electron'); 5 | const join = require('path').join; 6 | 7 | const argv = process.argv.slice(2); 8 | const no_detach_idx = argv.indexOf('--no-detach'); 9 | const detached = 10 | no_detach_idx === -1 && 11 | argv.indexOf('--help') === -1 && 12 | argv.indexOf('--version') === -1; 13 | 14 | if (no_detach_idx !== -1) { 15 | argv.splice(no_detach_idx, 1); 16 | } 17 | argv.unshift(join(__dirname, '..')); 18 | 19 | if (!process.env.NODE_ENV) { 20 | process.env.NODE_ENV = 'production'; 21 | } 22 | 23 | if (detached) { 24 | spawn(electron, argv, { 25 | stdio: 'inherit', 26 | detached: true 27 | }).unref(); 28 | } else { 29 | spawn(electron, argv, { stdio: 'inherit' }); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /renderer/main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | NyaoVim 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /renderer/main.ts: -------------------------------------------------------------------------------- 1 | if (process.env.PATH.indexOf('/usr/local/bin') === -1 && process.platform !== 'win32') { 2 | // Note: 3 | // This solves the problem that $PATH is not set up when app is 4 | // started via clicking NyaoVim.app. 5 | // 6 | // XXX: 7 | // This is just a workaround. 8 | // If nvim is installed to other directory, we can't know that. 9 | process.env.PATH += ':/usr/local/bin'; 10 | } 11 | 12 | // Note: 13 | // import {remote} from 'electron'; causes an error because both main.js and nyaovim-app.js are 14 | // loaded with 63 | ``` 64 | 65 | It ensures that the script is loaded after loading ``. 66 | 67 | -------------------------------------------------------------------------------- /main/browser-config.ts: -------------------------------------------------------------------------------- 1 | import {join} from 'path'; 2 | import {readFileSync} from 'fs'; 3 | import {app} from 'electron'; 4 | import extend = require('deep-extend'); 5 | import windowStateKeeper = require('electron-window-state'); 6 | 7 | export interface BrowserConfigJson { 8 | remember_window_state: boolean; 9 | window_options: Electron.BrowserWindowConstructorOptions; 10 | single_instance: boolean; 11 | show_menubar: boolean; 12 | } 13 | 14 | export default class BrowserConfig { 15 | loaded_config: BrowserConfigJson; 16 | window_state: ElectronWindowState.WindowState; 17 | 18 | constructor() { 19 | this.loaded_config = null; 20 | this.window_state = null; 21 | } 22 | 23 | loadFrom(config_dir: string) { 24 | return new Promise(resolve => { 25 | try { 26 | const config_file = join(config_dir, 'browser-config.json'); 27 | const content = readFileSync(config_file, 'utf8'); 28 | this.loaded_config = JSON.parse(content); 29 | } catch (e) { 30 | // Do nothing 31 | } 32 | resolve(); 33 | }); 34 | } 35 | 36 | applyToOptions(opt: Electron.BrowserWindowConstructorOptions): Electron.BrowserWindowConstructorOptions { 37 | if (typeof this.loaded_config !== 'object' || this.loaded_config === null) { 38 | return opt; 39 | } 40 | 41 | if (typeof this.loaded_config.window_options === 'object') { 42 | extend(opt, this.loaded_config.window_options); 43 | } 44 | 45 | if (this.loaded_config.remember_window_state) { 46 | const s = windowStateKeeper({ 47 | defaultWidth: 1000, 48 | defaultHeight: 800, 49 | path: global.config_dir_path, 50 | }); 51 | if (typeof s.x === 'number') { 52 | opt.x = s.x; 53 | } 54 | if (typeof s.y === 'number') { 55 | opt.y = s.y; 56 | } 57 | opt.width = s.width; 58 | opt.height = s.height; 59 | if (typeof s.isFullScreen === 'boolean') { 60 | opt.fullscreen = s.isFullScreen; 61 | } 62 | 63 | this.window_state = s; 64 | } 65 | 66 | return opt; 67 | } 68 | 69 | setupWindowState(win: Electron.BrowserWindow) { 70 | if (this.window_state === null) { 71 | return null; 72 | } 73 | // Note: 74 | // Using 'resize' event instead of 'close' event because of 75 | // 'Object has been destroyed' error. 76 | // See https://github.com/rhysd/NyaoVim/pull/63 77 | win.on('resize', () => { 78 | this.window_state.saveState(win); 79 | }); 80 | 81 | if (this.window_state.isMaximized) { 82 | win.maximize(); 83 | } 84 | return this.window_state; 85 | } 86 | 87 | configSingletonWindow(win: Electron.BrowserWindow) { 88 | if (this.loaded_config === null || !this.loaded_config.single_instance) { 89 | return false; 90 | } 91 | return app.makeSingleInstance((argv, cwd) => { 92 | if (win.isMinimized()) { 93 | win.restore(); 94 | } 95 | win.focus(); 96 | 97 | // Note: Omit Electron binary and NyaoVim directory 98 | const args = argv.slice(2); 99 | if (args.length !== 0) { 100 | win.webContents.send('nyaovim:exec-commands', [ 101 | 'cd ' + cwd, 102 | 'args ' + args.join(' '), 103 | ]); 104 | } 105 | return true; 106 | }); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint:recommended" 4 | ], 5 | "rules": { 6 | "align": [ 7 | true, 8 | "parameters", 9 | "statements" 10 | ], 11 | "ban": false, 12 | "class-name": true, 13 | "comment-format": [ 14 | true, 15 | "check-space" 16 | ], 17 | "curly": true, 18 | "eofline": true, 19 | "forin": false, 20 | "indent": [ 21 | true, 22 | "spaces" 23 | ], 24 | "interface-name": false, 25 | "jsdoc-format": true, 26 | "label-position": true, 27 | "max-line-length": false, 28 | "member-access": false, 29 | "member-ordering": [ 30 | true, 31 | "public-before-private", 32 | "static-before-instance", 33 | "variables-before-functions" 34 | ], 35 | "no-any": false, 36 | "no-arg": true, 37 | "no-bitwise": false, 38 | "no-conditional-assignment": true, 39 | "no-consecutive-blank-lines": false, 40 | "no-console": [ 41 | true, 42 | "debug", 43 | "info", 44 | "time", 45 | "timeEnd", 46 | "trace" 47 | ], 48 | "no-construct": true, 49 | "no-debugger": true, 50 | "no-duplicate-variable": true, 51 | "no-empty": true, 52 | "no-eval": true, 53 | "no-inferrable-types": false, 54 | "no-internal-module": true, 55 | "no-require-imports": false, 56 | "no-shadowed-variable": true, 57 | "no-string-literal": true, 58 | "no-switch-case-fall-through": false, 59 | "no-trailing-whitespace": true, 60 | "no-unused-expression": true, 61 | "no-unsafe-finally": true, 62 | "no-use-before-declare": true, 63 | "no-var-keyword": true, 64 | "no-var-requires": true, 65 | "object-literal-sort-keys": false, 66 | "object-literal-key-quotes": [ 67 | true, 68 | "as-needed" 69 | ], 70 | "one-line": [ 71 | true, 72 | "check-open-brace", 73 | "check-catch", 74 | "check-else", 75 | "check-whitespace" 76 | ], 77 | "quotemark": [ 78 | true, 79 | "single", 80 | "avoid-escape", 81 | "jsx-double" 82 | ], 83 | "radix": true, 84 | "semicolon": true, 85 | "switch-default": true, 86 | "trailing-comma": [ 87 | true, 88 | { 89 | "multiline": "always", 90 | "singleline": "never" 91 | } 92 | ], 93 | "triple-equals": [ 94 | true, 95 | "allow-null-check" 96 | ], 97 | "typedef": [ 98 | false 99 | ], 100 | "typedef-whitespace": [ 101 | true, 102 | { 103 | "call-signature": "nospace", 104 | "index-signature": "nospace", 105 | "parameter": "nospace", 106 | "property-declaration": "nospace", 107 | "variable-declaration": "nospace" 108 | } 109 | ], 110 | "variable-name": [ 111 | false, 112 | "check-format", 113 | "allow-leading-underscore", 114 | "ban-keywords" 115 | ], 116 | "whitespace": [ 117 | true, 118 | "check-branch", 119 | "check-decl", 120 | "check-operator", 121 | "check-separator", 122 | "check-type" 123 | ], 124 | "no-unnecessary-type-assertion": true, 125 | "no-for-in-array": true, 126 | "no-void-expression": [ 127 | true, 128 | "ignore-arrow-function-shorthand" 129 | ], 130 | "return-undefined": true, 131 | "deprecation": true, 132 | "no-unnecessary-qualifier": true, 133 | "no-return-await": true, 134 | "no-duplicate-switch-case": true, 135 | "no-implicit-dependencies": [ 136 | true, 137 | "dev" 138 | ], 139 | "ban-comma-operator": true, 140 | "no-duplicate-imports": true, 141 | "no-this-assignment": true, 142 | "use-default-type-parameter": true, 143 | "no-unbound-method": [ 144 | true, 145 | "ignore-static" 146 | ], 147 | "prefer-object-spread": true, 148 | "encoding": true, 149 | "prefer-switch": true, 150 | "interface-over-type-literal": true, 151 | "callable-types": true, 152 | "no-floating-promises": false, 153 | "number-literal-format": false, 154 | "no-parameter-reassignment": false, 155 | "no-namespace": false, 156 | "ordered-imports": false, 157 | "arrow-parens": false, 158 | "only-arrow-functions": false, 159 | "no-reference": false, 160 | "max-classes-per-file": false, 161 | "prefer-readonly": true 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /docs/make-ui-plugin.md: -------------------------------------------------------------------------------- 1 | How to Make UI Plugin 2 | ===================== 3 | 4 | I created [nyaovim-popup-tooltip](https://github.com/rhysd/nyaovim-popup-tooltip) as sample UI plugin. It will help you understand how to make UI plugin. 5 | 6 | - [Directory Structure](#structure) 7 | - [Getting Started](#tutorial) 8 | - [Debug Your Plugin](#debug) 9 | - [Handle Resizing Neovim Window](#window-resize) 10 | 11 | ## Directory Structure 12 | 13 | NyaoVim UI plugin is a normal Neovim plugin except for `nyaovim-plugin` directory as below. 14 | 15 | ``` 16 | plugin-root-dir 17 | ├── README.md 18 | ├── autoload 19 | ├── nyaovim-plugin 20 | └── plugin 21 | ``` 22 | 23 | - `autoload` is the same as normal Neovim plugin's autoload directory. 24 | - `plugin` is the same as normal Neovim plugin's plugin directory. 25 | - `nyaovim-plugin` is a place for HTML file which contains Web Component of UI. NyaoVim searches this directory and loads Web Components in it automatically. 26 | - UI should be created as a custom element of WebComponents v1 in the HTML file. And you can use [Polymer v2](https://www.polymer-project.org/) framework to 27 | utilize data binding from `nyaovimrc.html` (mainly for user configuration). 28 | 29 | 30 | ## Getting Started 31 | 32 | Let's make your `nyaovim-plugin/first-component.html`. 33 | 34 | ```html 35 | 36 | 37 | 47 | 48 | ``` 49 | 50 | And you need to get an editor instance from `nayovim-app` element. It is a custom element and it contains [``](https://github.com/rhysd/neovim-component) in it. You can access powerful [``'s APIs](https://github.com/rhysd/neovim-component#neovim-editor-apis) via `editor` property. 51 | 52 | You can write JavaScript for it. 53 | 54 | ```html 55 | 56 | 62 | ``` 63 | 64 | Let's change the content of `
` from Neovim. You can call [Neovim msgpack-rpc APIs](https://neovim.io/doc/user/msgpack_rpc.html) through [client instance](https://github.com/rhysd/neovim-component#call-neovim-apis). 65 | Subscribe notification from Neovim as following. 66 | 67 | ```html 68 | 69 | 82 | ``` 83 | 84 | If you created your component as [Polymer v2](https://github.com/Polymer/polymer) element, you can receive editor instance as `editor` property of it. 85 | 86 | You've finished creating UI. 87 | Note that you can also use [Electron APIs](https://github.com/atom/electron/tree/master/docs/api) and [Node.js APIs](https://nodejs.org/en/) (e.g. `require()`) here. 88 | 89 | Next, write small Vim script code in `plugin/hello-world.vim`. `rpcnotify()` is available to send Vim script values to component via msgpack-rpc. 90 | 91 | ```vim 92 | " Send notification to your UI 93 | command! -nargs=+ HelloWorld call rpcnotify(0, 'hello-world:content', ) 94 | ``` 95 | 96 | All has been done. 97 | Put `` in your `nyaovimrc.html` and start NyaoVim, then execute the command. 98 | 99 | ```vim 100 | :HelloWorld Hello world from NyaoVim! 101 | ``` 102 | 103 | Congrats! Now you can start to make your UI with HTML, CSS, Polymer, Electron and Node.js! When you want to ask a question, please feel free to make an issue for question. 104 | 105 | ## Debug Your Plugin 106 | 107 | If you want to debug your plugin or NyaoVim, you can start NyaoVim in debug mode with `$NODE_ENV` environment variable. 108 | 109 | ```sh 110 | $ NODE_ENV=debug nyaovim 111 | ``` 112 | 113 | Chrome DevTools will be launched in detached window and you can debug your UI plugin like general web applications; showing console, checking DOM elements, profiling and so on. Even if you start NyaoVim normally, you can also open Chrome DevTools by clicking menu item 'Toggle DevTools'. 114 | 115 | ## Handle Resizing Neovim Window 116 | 117 | As [described in neovim-component document](https://github.com/rhysd/neovim-component#view-apis), when `` **may** need to resize, you **must** call `editor.screen.checkShouldResize()` in order to notify it to ``. Please note that the notification is not needed when window is resized. And it is OK that nothing happens to the size of `` as result. 118 | This is needed because Neovim is rendered on `` and it can't know the timing when itself is resized. 119 | 120 | For example, when your component appears in window, the area of `` may change. 121 | 122 | ```javascript 123 | function showUpSomeElementInNyaoVimWindow() { 124 | const e = document.getElementById('some-elem'); 125 | 126 | // Element appears in window! Screen might be resized by the change. 127 | // 'none' -> 'block' 128 | e.style.display = 'block'; 129 | 130 | // You need to call this to say to that 'You may be resized. Check it out!'. 131 | editor.screen.checkShouldResize(); 132 | } 133 | ``` 134 | 135 | -------------------------------------------------------------------------------- /main/main.ts: -------------------------------------------------------------------------------- 1 | import {join} from 'path'; 2 | import {stat, writeFileSync} from 'fs'; 3 | import {app, BrowserWindow, shell, nativeImage} from 'electron'; 4 | import {sync as mkdirpSync} from 'mkdirp'; 5 | import setMenu from './menu'; 6 | import BrowserConfig from './browser-config'; 7 | 8 | if (process.argv.indexOf('--help') !== -1) { 9 | console.log(`OVERVIEW: NyaoVim; Web-enhanced Extensible Neovim Frontend 10 | 11 | USAGE: nyaovim [options] [neovim args...] 12 | 13 | OPTIONS: 14 | --no-detach : Don't detach the editor process 15 | --help : Show this help 16 | --version : Show versions of NyaoVim, Electron, Chrome, Node.js, and V8 17 | `); 18 | app.exit(); 19 | } 20 | 21 | if (process.argv.indexOf('--version') !== -1) { 22 | const vs: {[n: string]: string} = process.versions as any; 23 | const versions = ['electron', 'chrome', 'node', 'v8'].map((n: string) => ` ${n} : ${vs[n]}`).join('\n'); 24 | console.log(`${app.getName()} version ${app.getVersion()} 25 | ${versions} 26 | `); 27 | app.exit(); 28 | } 29 | 30 | process.on('unhandledRejection', (reason: string, p: Promise) => { 31 | console.error('Fatal: Unhandled rejection at: Promise', p, 'Reason:', reason); 32 | }); 33 | 34 | const is_run_from_npm_package_on_darwin = 35 | app.getAppPath().indexOf('/NyaoVim.app/') === -1; 36 | 37 | const config_dir_name = 38 | process.platform !== 'darwin' ? 39 | app.getPath('appData') : 40 | process.env.XDG_CONFIG_HOME || join(process.env.HOME, '.config'); 41 | 42 | global.config_dir_path = join(config_dir_name, 'nyaovim'); 43 | global.nyaovimrc_path = join(global.config_dir_path, 'nyaovimrc.html'); 44 | 45 | function exists(path: string) { 46 | return new Promise(resolve => { 47 | stat(path, (err, stats) => { 48 | if (err) { 49 | resolve(false); 50 | return; 51 | } 52 | resolve(stats.isFile() || stats.isDirectory()); 53 | }); 54 | }); 55 | } 56 | 57 | function prepareDefaultNyaovimrc() { 58 | console.log('Generate default nyaovimrc at ' + global.nyaovimrc_path); 59 | 60 | return exists(global.config_dir_path).then(e => { 61 | if (!e) { 62 | mkdirpSync(global.config_dir_path); 63 | } 64 | }).then(() => { 65 | const contents = 66 | ` 67 | 75 | 76 | `; 77 | writeFileSync(global.nyaovimrc_path, contents, 'utf8'); 78 | }); 79 | } 80 | 81 | const ensure_nyaovimrc = exists(global.nyaovimrc_path).then((e: boolean) => { 82 | if (!e) { 83 | return prepareDefaultNyaovimrc(); 84 | } else { 85 | // Note: This line needs because of TS7030 error 86 | return undefined; 87 | } 88 | }).catch(err => console.error(err)); 89 | 90 | const browser_config = new BrowserConfig(); 91 | const prepare_browser_config 92 | = browser_config.loadFrom(global.config_dir_path) 93 | .catch(err => console.error(err)); 94 | 95 | function startMainWindow() { 96 | const index_html = 'file://' + join(__dirname, '..', 'renderer', 'main.html'); 97 | 98 | const default_config = { 99 | width: 800, 100 | height: 600, 101 | useContentSize: true, 102 | webPreferences: { 103 | blinkFeatures: 'KeyboardEventKey,Accelerated2dCanvas,Canvas2dFixedRenderingMode', 104 | }, 105 | icon: nativeImage.createFromPath(join(__dirname, '..', 'resources', 'icon', 'nyaovim-logo.png')), 106 | } as Electron.BrowserWindowConstructorOptions; 107 | 108 | const user_config = browser_config.applyToOptions(default_config); 109 | 110 | let win = new BrowserWindow(user_config); 111 | 112 | const already_exists = browser_config.configSingletonWindow(win); 113 | if (already_exists) { 114 | app.quit(); 115 | return null; 116 | } 117 | 118 | browser_config.setupWindowState(win); 119 | if (browser_config.loaded_config !== null && browser_config.loaded_config.show_menubar === false) { 120 | win.setMenuBarVisibility(false); 121 | } 122 | 123 | win.once('closed', function() { 124 | win = null; 125 | }); 126 | 127 | win.loadURL(index_html); 128 | if (process.env.NODE_ENV !== 'production' && is_run_from_npm_package_on_darwin) { 129 | win.webContents.openDevTools({mode: 'detach'}); 130 | } 131 | 132 | return win; 133 | } 134 | 135 | app.once('window-all-closed', () => app.quit()); 136 | app.on('open-url', (e: Event, u: string) => { 137 | e.preventDefault(); 138 | shell.openExternal(u); 139 | }); 140 | app.once('will-finish-launching', function() { 141 | // we use once here because only the first open-file event might be missed by nyaovim-app 142 | app.once('open-file', (e: Event, p: string) => { 143 | // open-file event might be sent before ready event is emitted 144 | // put it in argv to let nyaovim-app to pick it up later 145 | process.argv.push(p); 146 | e.preventDefault(); 147 | }); 148 | }); 149 | 150 | app.once( 151 | 'ready', 152 | () => { 153 | if (process.platform === 'darwin' && is_run_from_npm_package_on_darwin) { 154 | // XXX: 155 | // app.dock.setIcon() is not defined in github-electron.d.ts yet. 156 | (app.dock as any).setIcon(join(__dirname, '..', 'resources', 'icon', 'nyaovim-logo.png')); 157 | } 158 | 159 | Promise.all([ 160 | ensure_nyaovimrc, 161 | prepare_browser_config, 162 | ]).then(() => { 163 | const w = startMainWindow(); 164 | if (w !== null) { 165 | setMenu(w); 166 | } 167 | }); 168 | }, 169 | ); 170 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![NyaoVim](resources/title-bar.png) 2 | =================================== 3 | 4 | This is a [Neovim](https://neovim.io/) frontend built on [Electron](https://electronjs.org/). 5 | The Neovim editor is [composed as a Web Component](https://github.com/rhysd/neovim-component) and users 6 | can extend the UI with reusable Web Components, HTML, CSS and JavaScript. 7 | 8 | `:help design-not` says: 9 | 10 | > Use Vim as a component from a shell or in an IDE. 11 | 12 | NyaoVim is built in the same spirit. NyaoVim contains the Neovim editor as a Web Component and extends 13 | its UI with web technology, as in other modern editors and IDEs (e.g. [Atom](http://atom.io/), 14 | [VS Code](https://github.com/Microsoft/vscode), [LightTable](http://lighttable.com/)). 15 | 16 | 17 | ## Goals 18 | 19 | - **NyaoVim bundles no extended UI by default.** It only provides the nice UI plugin architecture. 20 | Users can compose their favorite UI with Web Components, HTML and CSS. It is also easy to make a NyaoVim 21 | distribution where useful components are bundled. 22 | - **Do not introduce another plugin manager.** HTML for Web Components should be bundled with Vim plugins. 23 | Therefore, a Vim plugin manager can handle UI components, letting us bundle JS and Vim script code. 24 | - **Do not lose Vim's comfortability by default.** It should be aware of performance. 25 | - **UI component creators can use powerful APIs, packages and tools**; [Node.js APIs](https://nodejs.org/en/docs/), 26 | [Electron APIs](https://github.com/atom/electron/tree/master/docs/api), [Neovim msgpack-rpc APIs](https://neovim.io/doc/user/msgpack_rpc.html)), 27 | so many [npm packages](https://www.npmjs.com/) and [Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/). 28 | - **Cross Platform** (Linux, OS X, Windows) 29 | 30 | Memo: 'nyao' is 'meow' in Japanese and its pronounce resembles 'neo'. 31 | It is also an acronym for 'Not Yet Another Original'. 32 | 33 | 34 | ## App Structure 35 | 36 | NyaoVim consists of Web Components on Electron as shown in the following figure. At first there is 37 | only `` and you can add/remove additional components. 38 | 39 | ![structure](https://raw.githubusercontent.com/rhysd/ss/master/NyaoVim/structure.png) 40 | 41 | 42 | ## UI Plugin Examples 43 | 44 | UI plugins are installable as easily as regular plugins. Each of them is written within 100~300 lines. 45 | You can also create reusable Web Components and integrate them into NyaoVim. 46 | 47 | - [nyaovim-markdown-preview](https://github.com/rhysd/nyaovim-markdown-preview) 48 | 49 | ![nyaovim-markdown-preview screenshot](https://raw.githubusercontent.com/rhysd/ss/master/nyaovim-markdown-preview/main.gif) 50 | 51 | - [nyaovim-popup-tooltip](https://github.com/rhysd/nyaovim-popup-tooltip) 52 | 53 | ![nyaovim-popup-tooltip screenshot](https://raw.githubusercontent.com/rhysd/ss/master/nyaovim-popup-tooltip/main.gif) 54 | 55 | - [nyaovim-mini-browser](https://github.com/rhysd/nyaovim-mini-browser) 56 | 57 | ![nyaovim-mini-browser screenshot](https://raw.githubusercontent.com/rhysd/ss/master/nyaovim-mini-browser/main.gif) 58 | 59 | 60 | ## Usage 61 | 62 | ### Getting Started 63 | 64 | You can install NyaoVim as an [npm package](https://www.npmjs.com/package/nyaovim). Currently no packaging 65 | release is available yet. If you use Windows and haven't installed Neovim yet, please read [first tips](docs/tips.md) first. 66 | 67 | ```sh 68 | $ npm install -g nyaovim 69 | ``` 70 | 71 | `npm` may require `sudo` if you installed `node` pacakge via system package manager. 72 | 73 | If you haven't installed Neovim yet, please install it following [Neovim's instructions](https://github.com/neovim/neovim/wiki/Installing-Neovim) 74 | because NyaoVim internally uses the `nvim` command. **Note that `nvim` v0.1.6 or later is needed.** 75 | 76 | You can start NyaoVim with the `nyaovim` command if you install this app with npm. 77 | 78 | ```sh 79 | $ nyaovim [files...] 80 | ``` 81 | 82 | You would see a minimal Neovim GUI editor (like gVim). This is an Electron app and Neovim is drawn 83 | on ``. You can see the DevTools of this app with the 'Developer Tools' menu item. 84 | 85 | On first start up of NyaoVim, it creates `~/.config/nyaovim/nyaovimrc.html` for UI configuration 86 | (`%AppData%` instead of `.config` in Windows). Yes, you can extend and configure UI components with 87 | HTML and CSS! 88 | 89 | ### Configure Editor Options 90 | 91 | I guess you're now thinking 'Hmm, font is not good and too small...'. You can configure some editor 92 | options by properties of [`` properties](https://github.com/rhysd/neovim-component#neovim-editor-properties). 93 | For example, below configures font face and font size by `font` and `font-size` properties. Then set 94 | line-height to 1.5 (for example, Atom adopts 1.5 as line-height). 95 | 96 | ```html 97 | 104 | ``` 105 | 106 | And you can also configure browser window options with `browser-config.json` (e.g. Preserving window 107 | state, Single instance app, and so on). See [tips](docs/tips.md) for more detail. 108 | 109 | ### Install UI Plugin 110 | 111 | For example, let's install [nyaovim-popup-tooltip](https://github.com/rhysd/nyaovim-popup-tooltip). 112 | 113 | As described in the Goals section, a UI plugin is a normal Neovim plugin. You can install it like 114 | any other Neovim plugin. If you use [vim-plug](https://github.com/junegunn/vim-plug), all you need 115 | is adding below line to your `init.vim`. 116 | 117 | ```vim 118 | Plug 'rhysd/nyaovim-popup-tooltip' 119 | ``` 120 | 121 | Then you need to put the popup tooltip UI on your NyaoVim interface. Please open `~/.config/nyaovim/nyaovimrc.html` 122 | (`%AppData%` instead of `.config` in Windows). As described in the Goals section, a user can build 123 | a UI with HTML and CSS with high customization. 124 | 125 | Please add `` tag under `` tag as below 126 | 127 | ```html 128 | 129 | 130 | ``` 131 | 132 | `` is a [Polymer](https://github.com/Polymer/polymer) component. 133 | `editor="[[editor]]"` is a data binding in Polymer framework to pass editor instance to ``. It means 134 | unidirectional data flow from parent to child. 135 | 136 | After installing nyaovim-popup-tooltip as a Neovim plugin and adding UI to HTML, you're all done! 137 | Open NyaoVim, move the cursor to any image path, and enter `gi`. NyaoVim will load the image and show 138 | it in a popup tooltip as below. 139 | 140 | ![nyaovim-popup-tooltip screenshot](https://raw.githubusercontent.com/rhysd/ss/master/nyaovim-popup-tooltip/main.gif) 141 | 142 | 143 | ## Documents 144 | 145 | There is more in documentation in the [docs directory](docs). 146 | 147 | - [How to Make UI Plugin](docs/make-ui-plugin.md) 148 | - [Tips](docs/tips.md) 149 | - [FAQ](docs/faq.md) 150 | - [Runtime API](docs/runtime-api.md) 151 | - [Browser Config](docs/browser-config.md) 152 | 153 | 154 | ## Versioning 155 | 156 | NyaoVim is now under beta phase. Major version is fixed to 0 until it gets stable release. 157 | 158 | Updating minor version means it contains breaking changes. And updating patch version means it contains 159 | no breaking change, so you can update version easily. 160 | 161 | 162 | ## License 163 | 164 | [MIT License](/LICENSE.txt). 165 | 166 | Logo of this app is created based on [Neovim logo](https://neovim.io/) licensed under [CCA 3.0 Unported](https://creativecommons.org/licenses/by/3.0/legalcode). 167 | 168 | > The Neovim logo by Jason Long is licensed under the Creative Commons Attribution 3.0 Unported License. 169 | 170 | -------------------------------------------------------------------------------- /main/menu.ts: -------------------------------------------------------------------------------- 1 | import {Menu, app, webContents} from 'electron'; 2 | import {join} from 'path'; 3 | import openAboutWindow from 'about-window'; 4 | 5 | function startAboutWindow() { 6 | openAboutWindow({ 7 | icon_path: join(__dirname, '..', 'resources', 'icon', 'nyaovim-logo.png'), 8 | copyright: 'Copyright (c) 2015 rhysd', 9 | }); 10 | } 11 | 12 | export default function setMenu(win: Electron.BrowserWindow) { 13 | const template = [ 14 | { 15 | label: 'Edit', 16 | submenu: [ 17 | { 18 | label: 'Undo', 19 | accelerator: 'CmdOrCtrl+Z', 20 | click: () => { 21 | if ((win.webContents as any).isFocused()) { 22 | // send the command to the nyaovim-app 23 | win.webContents.send('nyaovim:exec-commands', ['undo']); 24 | } else { 25 | // execute the default command 26 | webContents.getFocusedWebContents().undo(); 27 | } 28 | }, 29 | }, 30 | { 31 | label: 'Redo', 32 | accelerator: 'Shift+CmdOrCtrl+Z', 33 | click: () => { 34 | if ((win.webContents as any).isFocused()) { 35 | // send the command to the nyaovim-app 36 | win.webContents.send('nyaovim:exec-commands', ['redo']); 37 | } else { 38 | // execute the default command 39 | webContents.getFocusedWebContents().redo(); 40 | } 41 | }, 42 | }, 43 | { 44 | type: 'separator', 45 | }, 46 | { 47 | label: 'Cut', 48 | accelerator: 'CmdOrCtrl+X', 49 | click: () => { 50 | if ((win.webContents as any).isFocused()) { 51 | // send the command to the nyaovim-app 52 | win.webContents.send('nyaovim:cut'); 53 | } else { 54 | // execute the default command 55 | webContents.getFocusedWebContents().cut(); 56 | } 57 | }, 58 | }, 59 | { 60 | label: 'Copy', 61 | accelerator: 'CmdOrCtrl+C', 62 | click: () => { 63 | if ((win.webContents as any).isFocused()) { 64 | // send the command to the nyaovim-app 65 | win.webContents.send('nyaovim:copy'); 66 | } else { 67 | // execute the default command 68 | webContents.getFocusedWebContents().copy(); 69 | } 70 | }, 71 | }, 72 | { 73 | label: 'Paste', 74 | accelerator: 'CmdOrCtrl+V', 75 | click: () => { 76 | if ((win.webContents as any).isFocused()) { 77 | // send the command to the nyaovim-app 78 | win.webContents.send('nyaovim:paste'); 79 | } else { 80 | // execute the default command 81 | webContents.getFocusedWebContents().paste(); 82 | } 83 | }, 84 | }, 85 | { 86 | label: 'Select All', 87 | accelerator: 'CmdOrCtrl+A', 88 | click: () => { 89 | if ((win.webContents as any).isFocused()) { 90 | // send the command to the nyaovim-app 91 | win.webContents.send('nyaovim:select-all'); 92 | } else { 93 | // execute the default command 94 | webContents.getFocusedWebContents().selectAll(); 95 | } 96 | }, 97 | }, 98 | ], 99 | }, 100 | 101 | { 102 | label: 'View', 103 | submenu: [ 104 | { 105 | label: 'Reload', 106 | accelerator: 'CmdOrCtrl+R', 107 | click: () => win.reload(), 108 | }, 109 | { 110 | label: 'Toggle Full Screen', 111 | accelerator: process.platform === 'darwin' ? 'Ctrl+Command+F' : 'F11', 112 | click: () => win.setFullScreen(!win.isFullScreen()), 113 | }, 114 | { 115 | label: 'Open Developer Tools', 116 | accelerator: process.platform === 'darwin' ? 'Alt+Command+I' : 'Ctrl+Shift+I', 117 | click: () => win.webContents.openDevTools({mode: 'detach'}), 118 | }, 119 | ], 120 | }, 121 | 122 | { 123 | label: 'Window', 124 | role: 'window', 125 | submenu: [ 126 | { 127 | label: 'Minimize', 128 | accelerator: 'CmdOrCtrl+M', 129 | role: 'minimize', 130 | }, 131 | { 132 | label: 'Close', 133 | accelerator: 'CmdOrCtrl+W', 134 | role: 'close', 135 | }, 136 | ], 137 | }, 138 | 139 | { 140 | label: 'Help', 141 | role: 'help', 142 | submenu: [ 143 | { 144 | label: 'About NyaoVim', 145 | click: () => startAboutWindow(), 146 | }, 147 | ], 148 | }, 149 | ] as Electron.MenuItemConstructorOptions[]; 150 | 151 | if (process.platform === 'darwin') { 152 | template.unshift({ 153 | label: 'NyaoVim', 154 | submenu: [ 155 | { 156 | label: 'About NyaoVim', 157 | click: () => startAboutWindow(), 158 | }, 159 | { 160 | type: 'separator', 161 | }, 162 | { 163 | label: 'Services', 164 | role: 'services', 165 | }, 166 | { 167 | type: 'separator', 168 | }, 169 | { 170 | label: 'Hide NyaoVim', 171 | accelerator: 'Command+H', 172 | role: 'hide', 173 | }, 174 | { 175 | label: 'Hide Others', 176 | accelerator: 'Command+Shift+H', 177 | role: 'hideothers', 178 | }, 179 | { 180 | label: 'Show All', 181 | role: 'unhide', 182 | }, 183 | { 184 | type: 'separator', 185 | }, 186 | { 187 | label: 'Quit', 188 | accelerator: 'Command+Q', 189 | click: () => { app.quit(); }, 190 | }, 191 | ], 192 | } as Electron.MenuItemConstructorOptions); 193 | 194 | (template[3].submenu as Electron.MenuItemConstructorOptions[]).push( 195 | { 196 | type: 'separator', 197 | }, 198 | { 199 | label: 'Bring All to Front', 200 | role: 'front', 201 | }, 202 | ); 203 | } 204 | 205 | const menu = Menu.buildFromTemplate(template); 206 | Menu.setApplicationMenu(menu); 207 | return menu; 208 | } 209 | -------------------------------------------------------------------------------- /resources/icon/nyaovim-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | neovim-mark@2x 27 | 28 | 29 | 30 | 51 | neovim-mark@2x 53 | Created with Sketch (http://www.bohemiancoding.com/sketch) 55 | 57 | 59 | 63 | 67 | 68 | 70 | 74 | 78 | 79 | 81 | 85 | 89 | 90 | 98 | 103 | 108 | 109 | 117 | 121 | 125 | 126 | 134 | 139 | 144 | 145 | 146 | 150 | 154 | 160 | 167 | 173 | 179 | 180 | 198 | 216 | 222 | 227 | 232 | 237 | 243 | 248 | 255 | 262 | 263 | 264 | -------------------------------------------------------------------------------- /renderer/nyaovim-app.ts: -------------------------------------------------------------------------------- 1 | import {NeovimElement, Neovim} from 'neovim-component'; 2 | import {remote, shell, ipcRenderer as ipc} from 'electron'; 3 | import {join, basename} from 'path'; 4 | import {readdirSync} from 'fs'; 5 | import {Nvim, RPCValue} from 'promised-neovim-client'; 6 | 7 | class ComponentLoader { 8 | initially_loaded: boolean; 9 | component_paths: string[]; 10 | nyaovim_plugin_paths: string[]; 11 | 12 | constructor() { 13 | this.initially_loaded = false; 14 | this.component_paths = []; 15 | } 16 | 17 | loadComponent(path: string) { 18 | const link: HTMLLinkElement = document.createElement('link'); 19 | link.rel = 'import'; 20 | link.href = path; 21 | document.head.appendChild(link); 22 | this.component_paths.push(path); 23 | } 24 | 25 | loadPluginDir(dir: string) { 26 | const nyaovim_plugin_dir = join(dir, 'nyaovim-plugin'); 27 | try { 28 | for (const entry of readdirSync(nyaovim_plugin_dir)) { 29 | if (entry.endsWith('.html')) { 30 | this.loadComponent(join(nyaovim_plugin_dir, entry)); 31 | } 32 | } 33 | this.nyaovim_plugin_paths.push(dir); 34 | } catch (err) { 35 | // 'nyaovim-plugin' doesn't exist 36 | } 37 | } 38 | 39 | loadFromRTP(runtimepaths: string[]) { 40 | for (const rtp of runtimepaths) { 41 | this.loadPluginDir(rtp); 42 | } 43 | } 44 | } 45 | 46 | class RuntimeApi { 47 | private client: Nvim; 48 | 49 | constructor(private readonly definitions: {[name: string]: (...args: any[]) => void}) { 50 | this.client = null; 51 | } 52 | 53 | subscribe(client: Nvim) { 54 | client.on('notification', this.call.bind(this)); 55 | for (const name in this.definitions) { 56 | client.subscribe(name).catch(); 57 | } 58 | this.client = client; 59 | } 60 | 61 | unsubscribe() { 62 | if (this.client) { 63 | for (const name in this.definitions) { 64 | this.client.unsubscribe(name); 65 | } 66 | } 67 | } 68 | 69 | call(func_name: string, args: RPCValue[]) { 70 | const func = this.definitions[func_name]; 71 | if (!func) { 72 | return null; 73 | } 74 | return func.apply(func, args); 75 | } 76 | } 77 | 78 | const component_loader = new ComponentLoader(); 79 | const ThisBrowserWindow = remote.getCurrentWindow(); 80 | const runtime_api = new RuntimeApi({ 81 | 'nyaovim:load-path': (html_path: string) => { 82 | component_loader.loadComponent(html_path); 83 | }, 84 | 'nyaovim:load-plugin-dir': (dir_path: string) => { 85 | component_loader.loadPluginDir(dir_path); 86 | }, 87 | 'nyaovim:edit-start': (file_path: string) => { 88 | ThisBrowserWindow.setRepresentedFilename(file_path); 89 | remote.app.addRecentDocument(file_path); 90 | }, 91 | 'nyaovim:require-script-file': (script_path: string) => { 92 | require(script_path); 93 | }, 94 | 'nyaovim:call-global-function': (func_name: string, args: RPCValue[]) => { 95 | const func = (window as any)[func_name]; 96 | if (func /*&& func is Function*/) { 97 | func.apply(window, args); 98 | } 99 | }, 100 | 'nyaovim:open-devtools': (mode: 'right' | 'bottom' | 'undocked' | 'detach') => { 101 | const contents = remote.getCurrentWebContents(); 102 | contents.openDevTools({mode}); 103 | }, 104 | 'nyaovim:execute-javascript': (code: string) => { 105 | if (typeof code !== 'string') { 106 | console.error('nyaovim:execute-javascript: Not a string', code); 107 | return; 108 | } 109 | try { 110 | /* tslint:disable */ 111 | eval(code); 112 | /* tslint:enable */ 113 | } catch (e) { 114 | console.error('While executing javascript:', e, ' Code:', code); 115 | } 116 | }, 117 | 'nyaovim:browser-window': (method: string, args: RPCValue[]) => { 118 | try { 119 | (ThisBrowserWindow as any)[method].apply(ThisBrowserWindow, args); 120 | } catch (e) { 121 | console.error("Error while executing 'nyaovim:browser-window':", e, ' Method:', method, ' Args:', args); 122 | } 123 | }, 124 | }); 125 | 126 | function prepareIpc(client: Nvim) { 127 | ipc.on('nyaovim:exec-commands', (_: any, cmds: string[]) => { 128 | for (const c of cmds) { 129 | client.command(c); 130 | } 131 | }); 132 | 133 | ipc.on('nyaovim:copy', () => { 134 | // get current vim mode 135 | client.eval('mode()').then((value: string) => { 136 | if (value.length === 0) { 137 | return undefined; 138 | } 139 | const ch = value[0]; 140 | const code = value.charCodeAt(0); 141 | if (ch === 'v' // visual mode 142 | || ch === 'V' // visual line mode 143 | || code === 22 // visual block mode. 22 is returned by ':echo char2nr("\")' 144 | ) { 145 | client.input('"+y'); 146 | } 147 | }); 148 | }); 149 | 150 | ipc.on('nyaovim:select-all', () => { 151 | // get current vim mode. 152 | client.eval('mode()').then((value: string) => { 153 | if (value.length === 0) { 154 | return undefined; 155 | } 156 | 157 | const command = value[0] === 'n' ? 'ggVG' : 'ggVG'; 158 | client.input(command); 159 | }); 160 | }); 161 | 162 | ipc.on('nyaovim:cut', () => { 163 | // get current vim mode 164 | client.eval('mode()').then((value: string) => { 165 | if (value.length === 0) { 166 | return undefined; 167 | } 168 | 169 | const ch = value[0]; 170 | const num = value.charCodeAt(0); 171 | if (ch === 'v' // visual mode 172 | || ch === 'V' // visual line mode 173 | || num === 22 // visual block mode 174 | ) { 175 | client.input('"+x'); 176 | } 177 | }); 178 | }); 179 | 180 | ipc.on('nyaovim:paste', () => { 181 | // get current vim mode 182 | client.eval('mode()').then((value: string) => { 183 | if (value.length === 0) { 184 | return undefined; 185 | } 186 | 187 | let command: string; 188 | 189 | const ch = value[0]; 190 | const code = value.charCodeAt(0); 191 | if (ch === 'v') { 192 | // visual mode 193 | // deleting the highlighted area 194 | // to prevent vim from copying the area to the pasteboard 195 | command = '"_d"+P'; 196 | } else if (ch === 'V') { 197 | // visual line mode 198 | command = '"_d"+p'; 199 | } else if (code === 22 || ch === 'n') { 200 | // visual block mode 201 | // the "_d trick doesn't work here 202 | // because the visual selection will disappear after "_d command 203 | // or normal mode 204 | command = '"+p'; 205 | } else if (ch === 'i') { 206 | // insert mode 207 | // gp will move cursor to the last of pasted content 208 | command = '"+gp'; 209 | } else if (ch === 'c') { 210 | // command line mode 211 | command = '+'; 212 | } 213 | 214 | if (command) { 215 | client.command(`normal! ${command}`); 216 | } 217 | }); 218 | }); 219 | } 220 | 221 | class NyaoVimApp extends Polymer.Element { 222 | static get is() { 223 | return 'nyaovim-app'; 224 | } 225 | 226 | static get properties() { 227 | return { 228 | argv: { 229 | type: Array, 230 | value() { 231 | 232 | // Handle the arguments of the standalone Nyaovim.app 233 | // The first argument of standalone distribution is the binary path 234 | let electron_argc = 1; 235 | 236 | // When application is executed via 'electron' ('Electron' on darwin) executable. 237 | if ('electron' === basename(remote.process.argv[0]).toLowerCase()) { 238 | // Note: 239 | // The first argument is a path to Electron executable. 240 | // The second argument is the path to main.js 241 | electron_argc = 2; 242 | } 243 | 244 | // Note: 245 | // First and second arguments are related to Electron 246 | // XXX: 247 | // Spectron additionally passes many specific arguments to process and 'nvim' process 248 | // will fail because of them. As a workaround, we stupidly ignore arguments on E2E tests. 249 | const a = process.env.NYAOVIM_E2E_TEST_RUNNING ? [] : remote.process.argv.slice(electron_argc); 250 | 251 | a.unshift( 252 | '--cmd', `let\ g:nyaovim_version="${remote.app.getVersion()}"`, 253 | '--cmd', `set\ rtp+=${join(__dirname, '..', 'runtime').replace(' ', '\ ')}`, 254 | ); 255 | 256 | // XXX: 257 | // Swap files are disabled because it shows message window on start up but frontend can't detect it. 258 | a.unshift('-n'); 259 | 260 | return a; 261 | }, 262 | }, 263 | editor: Object, 264 | }; 265 | } 266 | 267 | argv: string[]; 268 | editor: Neovim; 269 | 270 | ready() { 271 | super.ready(); 272 | (global as any).hello = this; 273 | const element = this.$['nyaovim-editor'] as NeovimElement; 274 | const editor = element.editor; 275 | editor.on('error', (err: Error) => alert(err.message)); 276 | editor.on('quit', () => ThisBrowserWindow.close()); 277 | this.editor = editor; 278 | 279 | editor.store.on('beep', () => shell.beep()); 280 | editor.store.on('title-changed', () => { 281 | document.title = editor.store.title; 282 | }); 283 | 284 | editor.on('process-attached', () => { 285 | const client = editor.getClient(); 286 | 287 | client.listRuntimePaths() 288 | .then((rtp: string[]) => { 289 | component_loader.loadFromRTP(rtp); 290 | component_loader.initially_loaded = true; 291 | }); 292 | 293 | runtime_api.subscribe(client); 294 | 295 | element.addEventListener('drop', e => { 296 | e.preventDefault(); 297 | const f = e.dataTransfer.files[0]; 298 | if (f) { 299 | client.command('edit! ' + f.path); 300 | } 301 | }); 302 | 303 | remote.app.on('open-file', (e: Event, p: string) => { 304 | e.preventDefault(); 305 | client.command('edit! ' + p); 306 | }); 307 | 308 | prepareIpc(client); 309 | }); 310 | 311 | element.addEventListener('dragover', e => e.preventDefault()); 312 | 313 | window.addEventListener('keydown', e => { 314 | if (e.keyCode === 0x1b && !editor.store.focused) { 315 | // Note: Global shortcut to make focus back to screen 316 | editor.focus(); 317 | } 318 | }); 319 | } 320 | 321 | // TODO: Remove all listeners when detached 322 | } 323 | 324 | customElements.define(NyaoVimApp.is, NyaoVimApp); 325 | -------------------------------------------------------------------------------- /resources/osx_plist/file_associations.plist: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | 26 | 27 | CFBundleDocumentTypes 28 | 29 | 30 | CFBundleTypeExtensions 31 | 32 | adb 33 | ads 34 | 35 | CFBundleTypeIconFile 36 | file.icns 37 | CFBundleTypeName 38 | ADA source 39 | CFBundleTypeRole 40 | Editor 41 | LSHandlerRank 42 | Alternate 43 | 44 | 45 | CFBundleTypeExtensions 46 | 47 | scpt 48 | 49 | CFBundleTypeIconFile 50 | file.icns 51 | CFBundleTypeName 52 | Compiled AppleScript 53 | CFBundleTypeRole 54 | Editor 55 | LSHandlerRank 56 | Alternate 57 | 58 | 59 | CFBundleTypeExtensions 60 | 61 | applescript 62 | 63 | CFBundleTypeIconFile 64 | file.icns 65 | CFBundleTypeName 66 | AppleScript source 67 | CFBundleTypeRole 68 | Editor 69 | LSHandlerRank 70 | Alternate 71 | 72 | 73 | CFBundleTypeExtensions 74 | 75 | as 76 | 77 | CFBundleTypeIconFile 78 | file.icns 79 | CFBundleTypeName 80 | ActionScript source 81 | CFBundleTypeRole 82 | Editor 83 | LSHandlerRank 84 | Alternate 85 | 86 | 87 | CFBundleTypeExtensions 88 | 89 | asp 90 | asa 91 | 92 | CFBundleTypeIconFile 93 | file.icns 94 | CFBundleTypeName 95 | ASP document 96 | CFBundleTypeRole 97 | Editor 98 | LSHandlerRank 99 | Alternate 100 | 101 | 102 | CFBundleTypeExtensions 103 | 104 | aspx 105 | ascx 106 | asmx 107 | ashx 108 | 109 | CFBundleTypeIconFile 110 | file.icns 111 | CFBundleTypeName 112 | ASP.NET document 113 | CFBundleTypeRole 114 | Editor 115 | LSHandlerRank 116 | Alternate 117 | 118 | 119 | CFBundleTypeExtensions 120 | 121 | bib 122 | 123 | CFBundleTypeIconFile 124 | file.icns 125 | CFBundleTypeName 126 | BibTeX bibliography 127 | CFBundleTypeRole 128 | Editor 129 | LSHandlerRank 130 | Alternate 131 | 132 | 133 | CFBundleTypeExtensions 134 | 135 | c 136 | 137 | CFBundleTypeIconFile 138 | file.icns 139 | CFBundleTypeName 140 | C source 141 | CFBundleTypeRole 142 | Editor 143 | LSHandlerRank 144 | Alternate 145 | 146 | 147 | CFBundleTypeExtensions 148 | 149 | cc 150 | cp 151 | cpp 152 | cxx 153 | c++ 154 | 155 | CFBundleTypeIconFile 156 | file.icns 157 | CFBundleTypeName 158 | C++ source 159 | CFBundleTypeRole 160 | Editor 161 | LSHandlerRank 162 | Alternate 163 | 164 | 165 | CFBundleTypeExtensions 166 | 167 | cs 168 | 169 | CFBundleTypeIconFile 170 | file.icns 171 | CFBundleTypeName 172 | C# source 173 | CFBundleTypeRole 174 | Editor 175 | LSHandlerRank 176 | Alternate 177 | 178 | 179 | CFBundleTypeExtensions 180 | 181 | coffee 182 | 183 | CFBundleTypeIconFile 184 | file.icns 185 | CFBundleTypeName 186 | CoffeeScript source 187 | CFBundleTypeRole 188 | Editor 189 | LSHandlerRank 190 | Alternate 191 | 192 | 193 | CFBundleTypeExtensions 194 | 195 | COMMIT_EDITMSG 196 | 197 | CFBundleTypeIconFile 198 | file.icns 199 | CFBundleTypeName 200 | Commit message 201 | CFBundleTypeRole 202 | Editor 203 | LSHandlerRank 204 | Alternate 205 | 206 | 207 | CFBundleTypeExtensions 208 | 209 | cfdg 210 | 211 | CFBundleTypeIconFile 212 | file.icns 213 | CFBundleTypeName 214 | Context Free Design Grammar 215 | CFBundleTypeRole 216 | Editor 217 | LSHandlerRank 218 | Alternate 219 | 220 | 221 | CFBundleTypeExtensions 222 | 223 | clj 224 | cljs 225 | 226 | CFBundleTypeIconFile 227 | file.icns 228 | CFBundleTypeName 229 | Clojure source 230 | CFBundleTypeRole 231 | Editor 232 | LSHandlerRank 233 | Alternate 234 | 235 | 236 | CFBundleTypeExtensions 237 | 238 | csv 239 | 240 | CFBundleTypeIconFile 241 | file.icns 242 | CFBundleTypeName 243 | Comma separated values 244 | CFBundleTypeRole 245 | Editor 246 | LSHandlerRank 247 | Alternate 248 | 249 | 250 | CFBundleTypeExtensions 251 | 252 | tsv 253 | 254 | CFBundleTypeIconFile 255 | file.icns 256 | CFBundleTypeName 257 | Tab separated values 258 | CFBundleTypeRole 259 | Editor 260 | LSHandlerRank 261 | Alternate 262 | 263 | 264 | CFBundleTypeExtensions 265 | 266 | cgi 267 | fcgi 268 | 269 | CFBundleTypeIconFile 270 | file.icns 271 | CFBundleTypeName 272 | CGI script 273 | CFBundleTypeRole 274 | Editor 275 | 276 | 277 | CFBundleTypeExtensions 278 | 279 | cfg 280 | conf 281 | config 282 | htaccess 283 | 284 | CFBundleTypeIconFile 285 | file.icns 286 | CFBundleTypeName 287 | Configuration file 288 | CFBundleTypeRole 289 | Editor 290 | LSHandlerRank 291 | Alternate 292 | 293 | 294 | CFBundleTypeExtensions 295 | 296 | css 297 | 298 | CFBundleTypeIconFile 299 | file.icns 300 | CFBundleTypeName 301 | Cascading style sheet 302 | CFBundleTypeRole 303 | Editor 304 | LSHandlerRank 305 | Alternate 306 | 307 | 308 | CFBundleTypeExtensions 309 | 310 | diff 311 | 312 | CFBundleTypeIconFile 313 | file.icns 314 | CFBundleTypeName 315 | Differences file 316 | CFBundleTypeRole 317 | Editor 318 | LSHandlerRank 319 | Alternate 320 | 321 | 322 | CFBundleTypeExtensions 323 | 324 | dtd 325 | 326 | CFBundleTypeIconFile 327 | file.icns 328 | CFBundleTypeName 329 | Document Type Definition 330 | CFBundleTypeRole 331 | Editor 332 | LSHandlerRank 333 | Alternate 334 | 335 | 336 | CFBundleTypeExtensions 337 | 338 | dylan 339 | 340 | CFBundleTypeIconFile 341 | file.icns 342 | CFBundleTypeName 343 | Dylan source 344 | CFBundleTypeRole 345 | Editor 346 | LSHandlerRank 347 | Alternate 348 | 349 | 350 | CFBundleTypeExtensions 351 | 352 | erl 353 | hrl 354 | 355 | CFBundleTypeIconFile 356 | file.icns 357 | CFBundleTypeName 358 | Erlang source 359 | CFBundleTypeRole 360 | Editor 361 | LSHandlerRank 362 | Alternate 363 | 364 | 365 | CFBundleTypeExtensions 366 | 367 | fscript 368 | 369 | CFBundleTypeIconFile 370 | file.icns 371 | CFBundleTypeName 372 | F-Script source 373 | CFBundleTypeRole 374 | Editor 375 | LSHandlerRank 376 | Alternate 377 | 378 | 379 | CFBundleTypeExtensions 380 | 381 | f 382 | for 383 | fpp 384 | f77 385 | f90 386 | f95 387 | 388 | CFBundleTypeIconFile 389 | file.icns 390 | CFBundleTypeName 391 | Fortran source 392 | CFBundleTypeRole 393 | Editor 394 | LSHandlerRank 395 | Alternate 396 | 397 | 398 | CFBundleTypeExtensions 399 | 400 | h 401 | pch 402 | 403 | CFBundleTypeIconFile 404 | file.icns 405 | CFBundleTypeName 406 | Header 407 | CFBundleTypeRole 408 | Editor 409 | LSHandlerRank 410 | Alternate 411 | 412 | 413 | CFBundleTypeExtensions 414 | 415 | hh 416 | hpp 417 | hxx 418 | h++ 419 | 420 | CFBundleTypeIconFile 421 | file.icns 422 | CFBundleTypeName 423 | C++ header 424 | CFBundleTypeRole 425 | Editor 426 | LSHandlerRank 427 | Alternate 428 | 429 | 430 | CFBundleTypeExtensions 431 | 432 | go 433 | 434 | CFBundleTypeIconFile 435 | file.icns 436 | CFBundleTypeName 437 | Go source 438 | CFBundleTypeRole 439 | Editor 440 | LSHandlerRank 441 | Alternate 442 | 443 | 444 | CFBundleTypeExtensions 445 | 446 | gtd 447 | gtdlog 448 | 449 | CFBundleTypeIconFile 450 | file.icns 451 | CFBundleTypeName 452 | GTD document 453 | CFBundleTypeRole 454 | Editor 455 | LSHandlerRank 456 | Alternate 457 | 458 | 459 | CFBundleTypeExtensions 460 | 461 | hs 462 | lhs 463 | 464 | CFBundleTypeIconFile 465 | file.icns 466 | CFBundleTypeName 467 | Haskell source 468 | CFBundleTypeRole 469 | Editor 470 | LSHandlerRank 471 | Alternate 472 | 473 | 474 | CFBundleTypeExtensions 475 | 476 | htm 477 | html 478 | phtml 479 | shtml 480 | 481 | CFBundleTypeIconFile 482 | file.icns 483 | CFBundleTypeName 484 | HTML document 485 | CFBundleTypeRole 486 | Editor 487 | LSHandlerRank 488 | Alternate 489 | 490 | 491 | CFBundleTypeExtensions 492 | 493 | inc 494 | 495 | CFBundleTypeIconFile 496 | file.icns 497 | CFBundleTypeName 498 | Include file 499 | CFBundleTypeRole 500 | Editor 501 | LSHandlerRank 502 | Alternate 503 | 504 | 505 | CFBundleTypeExtensions 506 | 507 | ics 508 | 509 | CFBundleTypeIconFile 510 | file.icns 511 | CFBundleTypeName 512 | iCalendar schedule 513 | CFBundleTypeRole 514 | Editor 515 | LSHandlerRank 516 | Alternate 517 | 518 | 519 | CFBundleTypeExtensions 520 | 521 | ini 522 | 523 | CFBundleTypeIconFile 524 | file.icns 525 | CFBundleTypeName 526 | MS Windows initialization file 527 | CFBundleTypeRole 528 | Editor 529 | LSHandlerRank 530 | Alternate 531 | 532 | 533 | CFBundleTypeExtensions 534 | 535 | io 536 | 537 | CFBundleTypeIconFile 538 | file.icns 539 | CFBundleTypeName 540 | Io source 541 | CFBundleTypeRole 542 | Editor 543 | LSHandlerRank 544 | Alternate 545 | 546 | 547 | CFBundleTypeExtensions 548 | 549 | java 550 | 551 | CFBundleTypeIconFile 552 | file.icns 553 | CFBundleTypeName 554 | Java source 555 | CFBundleTypeRole 556 | Editor 557 | LSHandlerRank 558 | Alternate 559 | 560 | 561 | CFBundleTypeExtensions 562 | 563 | bsh 564 | 565 | CFBundleTypeIconFile 566 | file.icns 567 | CFBundleTypeName 568 | BeanShell script 569 | CFBundleTypeRole 570 | Editor 571 | LSHandlerRank 572 | Alternate 573 | 574 | 575 | CFBundleTypeExtensions 576 | 577 | properties 578 | 579 | CFBundleTypeIconFile 580 | file.icns 581 | CFBundleTypeName 582 | Java properties file 583 | CFBundleTypeRole 584 | Editor 585 | LSHandlerRank 586 | Alternate 587 | 588 | 589 | CFBundleTypeExtensions 590 | 591 | js 592 | htc 593 | 594 | CFBundleTypeIconFile 595 | file.icns 596 | CFBundleTypeName 597 | JavaScript source 598 | CFBundleTypeRole 599 | Editor 600 | LSHandlerRank 601 | Alternate 602 | 603 | 604 | CFBundleTypeExtensions 605 | 606 | jsp 607 | 608 | CFBundleTypeIconFile 609 | file.icns 610 | CFBundleTypeName 611 | Java Server Page 612 | CFBundleTypeRole 613 | Editor 614 | LSHandlerRank 615 | Alternate 616 | 617 | 618 | CFBundleTypeExtensions 619 | 620 | json 621 | 622 | CFBundleTypeIconFile 623 | file.icns 624 | CFBundleTypeName 625 | JSON file 626 | CFBundleTypeRole 627 | Editor 628 | LSHandlerRank 629 | Alternate 630 | 631 | 632 | CFBundleTypeExtensions 633 | 634 | ldif 635 | 636 | CFBundleTypeIconFile 637 | file.icns 638 | CFBundleTypeName 639 | LDAP Data Interchange Format 640 | CFBundleTypeRole 641 | Editor 642 | LSHandlerRank 643 | Alternate 644 | 645 | 646 | CFBundleTypeExtensions 647 | 648 | less 649 | 650 | CFBundleTypeIconFile 651 | file.icns 652 | CFBundleTypeName 653 | Less source 654 | CFBundleTypeRole 655 | Editor 656 | LSHandlerRank 657 | Alternate 658 | 659 | 660 | CFBundleTypeExtensions 661 | 662 | lisp 663 | cl 664 | l 665 | lsp 666 | mud 667 | el 668 | 669 | CFBundleTypeIconFile 670 | file.icns 671 | CFBundleTypeName 672 | Lisp source 673 | CFBundleTypeRole 674 | Editor 675 | LSHandlerRank 676 | Alternate 677 | 678 | 679 | CFBundleTypeExtensions 680 | 681 | log 682 | 683 | CFBundleTypeIconFile 684 | file.icns 685 | CFBundleTypeName 686 | Log file 687 | CFBundleTypeRole 688 | Editor 689 | LSHandlerRank 690 | Alternate 691 | 692 | 693 | CFBundleTypeExtensions 694 | 695 | logo 696 | 697 | CFBundleTypeIconFile 698 | file.icns 699 | CFBundleTypeName 700 | Logo source 701 | CFBundleTypeRole 702 | Editor 703 | LSHandlerRank 704 | Alternate 705 | 706 | 707 | CFBundleTypeExtensions 708 | 709 | lua 710 | 711 | CFBundleTypeIconFile 712 | file.icns 713 | CFBundleTypeName 714 | Lua source 715 | CFBundleTypeRole 716 | Editor 717 | LSHandlerRank 718 | Alternate 719 | 720 | 721 | CFBundleTypeExtensions 722 | 723 | markdown 724 | mdown 725 | markdn 726 | md 727 | 728 | CFBundleTypeIconFile 729 | file.icns 730 | CFBundleTypeName 731 | Markdown document 732 | CFBundleTypeRole 733 | Editor 734 | LSHandlerRank 735 | Alternate 736 | 737 | 738 | CFBundleTypeExtensions 739 | 740 | mk 741 | 742 | CFBundleTypeIconFile 743 | file.icns 744 | CFBundleTypeName 745 | Makefile source 746 | CFBundleTypeRole 747 | Editor 748 | LSHandlerRank 749 | Alternate 750 | 751 | 752 | CFBundleTypeExtensions 753 | 754 | wiki 755 | wikipedia 756 | mediawiki 757 | 758 | CFBundleTypeIconFile 759 | file.icns 760 | CFBundleTypeName 761 | Mediawiki document 762 | CFBundleTypeRole 763 | Editor 764 | LSHandlerRank 765 | Alternate 766 | 767 | 768 | CFBundleTypeExtensions 769 | 770 | s 771 | mips 772 | spim 773 | asm 774 | 775 | CFBundleTypeIconFile 776 | file.icns 777 | CFBundleTypeName 778 | MIPS assembler source 779 | CFBundleTypeRole 780 | Editor 781 | LSHandlerRank 782 | Alternate 783 | 784 | 785 | CFBundleTypeExtensions 786 | 787 | m3 788 | cm3 789 | 790 | CFBundleTypeIconFile 791 | file.icns 792 | CFBundleTypeName 793 | Modula-3 source 794 | CFBundleTypeRole 795 | Editor 796 | LSHandlerRank 797 | Alternate 798 | 799 | 800 | CFBundleTypeExtensions 801 | 802 | moinmoin 803 | 804 | CFBundleTypeIconFile 805 | file.icns 806 | CFBundleTypeName 807 | MoinMoin document 808 | CFBundleTypeRole 809 | Editor 810 | LSHandlerRank 811 | Alternate 812 | 813 | 814 | CFBundleTypeExtensions 815 | 816 | m 817 | 818 | CFBundleTypeIconFile 819 | file.icns 820 | CFBundleTypeName 821 | Objective-C source 822 | CFBundleTypeRole 823 | Editor 824 | LSHandlerRank 825 | Alternate 826 | 827 | 828 | CFBundleTypeExtensions 829 | 830 | mm 831 | 832 | CFBundleTypeIconFile 833 | file.icns 834 | CFBundleTypeName 835 | Objective-C++ source 836 | CFBundleTypeRole 837 | Editor 838 | LSHandlerRank 839 | Alternate 840 | 841 | 842 | CFBundleTypeExtensions 843 | 844 | ml 845 | mli 846 | mll 847 | mly 848 | 849 | CFBundleTypeIconFile 850 | file.icns 851 | CFBundleTypeName 852 | OCaml source 853 | CFBundleTypeRole 854 | Editor 855 | LSHandlerRank 856 | Alternate 857 | 858 | 859 | CFBundleTypeExtensions 860 | 861 | mustache 862 | hbs 863 | 864 | CFBundleTypeIconFile 865 | file.icns 866 | CFBundleTypeName 867 | Mustache document 868 | CFBundleTypeRole 869 | Editor 870 | LSHandlerRank 871 | Alternate 872 | 873 | 874 | CFBundleTypeExtensions 875 | 876 | pas 877 | p 878 | 879 | CFBundleTypeIconFile 880 | file.icns 881 | CFBundleTypeName 882 | Pascal source 883 | CFBundleTypeRole 884 | Editor 885 | LSHandlerRank 886 | Alternate 887 | 888 | 889 | CFBundleTypeExtensions 890 | 891 | patch 892 | 893 | CFBundleTypeIconFile 894 | file.icns 895 | CFBundleTypeName 896 | Patch file 897 | CFBundleTypeRole 898 | Editor 899 | LSHandlerRank 900 | Alternate 901 | 902 | 903 | CFBundleTypeExtensions 904 | 905 | pl 906 | pod 907 | perl 908 | 909 | CFBundleTypeIconFile 910 | file.icns 911 | CFBundleTypeName 912 | Perl source 913 | CFBundleTypeRole 914 | Editor 915 | LSHandlerRank 916 | Alternate 917 | 918 | 919 | CFBundleTypeExtensions 920 | 921 | pm 922 | 923 | CFBundleTypeIconFile 924 | file.icns 925 | CFBundleTypeName 926 | Perl module 927 | CFBundleTypeRole 928 | Editor 929 | LSHandlerRank 930 | Alternate 931 | 932 | 933 | CFBundleTypeExtensions 934 | 935 | php 936 | php3 937 | php4 938 | php5 939 | 940 | CFBundleTypeIconFile 941 | file.icns 942 | CFBundleTypeName 943 | PHP source 944 | CFBundleTypeRole 945 | Editor 946 | LSHandlerRank 947 | Alternate 948 | 949 | 950 | CFBundleTypeExtensions 951 | 952 | ps 953 | eps 954 | 955 | CFBundleTypeIconFile 956 | file.icns 957 | CFBundleTypeName 958 | PostScript source 959 | CFBundleTypeRole 960 | Editor 961 | LSHandlerRank 962 | Alternate 963 | 964 | 965 | CFBundleTypeExtensions 966 | 967 | dict 968 | plist 969 | scriptSuite 970 | scriptTerminology 971 | 972 | CFBundleTypeIconFile 973 | file.icns 974 | CFBundleTypeName 975 | Property list 976 | CFBundleTypeRole 977 | Editor 978 | LSHandlerRank 979 | Alternate 980 | 981 | 982 | CFBundleTypeExtensions 983 | 984 | py 985 | rpy 986 | cpy 987 | python 988 | 989 | CFBundleTypeIconFile 990 | file.icns 991 | CFBundleTypeName 992 | Python source 993 | CFBundleTypeRole 994 | Editor 995 | LSHandlerRank 996 | Alternate 997 | 998 | 999 | CFBundleTypeExtensions 1000 | 1001 | r 1002 | s 1003 | 1004 | CFBundleTypeIconFile 1005 | file.icns 1006 | CFBundleTypeName 1007 | R source 1008 | CFBundleTypeRole 1009 | Editor 1010 | LSHandlerRank 1011 | Alternate 1012 | 1013 | 1014 | CFBundleTypeExtensions 1015 | 1016 | rl 1017 | ragel 1018 | 1019 | CFBundleTypeIconFile 1020 | file.icns 1021 | CFBundleTypeName 1022 | Ragel source 1023 | CFBundleTypeRole 1024 | Editor 1025 | LSHandlerRank 1026 | Alternate 1027 | 1028 | 1029 | CFBundleTypeExtensions 1030 | 1031 | rem 1032 | remind 1033 | 1034 | CFBundleTypeIconFile 1035 | file.icns 1036 | CFBundleTypeName 1037 | Remind document 1038 | CFBundleTypeRole 1039 | Editor 1040 | LSHandlerRank 1041 | Alternate 1042 | 1043 | 1044 | CFBundleTypeExtensions 1045 | 1046 | rst 1047 | rest 1048 | 1049 | CFBundleTypeIconFile 1050 | file.icns 1051 | CFBundleTypeName 1052 | reStructuredText document 1053 | CFBundleTypeRole 1054 | Editor 1055 | LSHandlerRank 1056 | Alternate 1057 | 1058 | 1059 | CFBundleTypeExtensions 1060 | 1061 | rhtml 1062 | erb 1063 | 1064 | CFBundleTypeIconFile 1065 | file.icns 1066 | CFBundleTypeName 1067 | HTML with embedded Ruby 1068 | CFBundleTypeRole 1069 | Editor 1070 | LSHandlerRank 1071 | Alternate 1072 | 1073 | 1074 | CFBundleTypeExtensions 1075 | 1076 | erbsql 1077 | 1078 | CFBundleTypeIconFile 1079 | file.icns 1080 | CFBundleTypeName 1081 | SQL with embedded Ruby 1082 | CFBundleTypeRole 1083 | Editor 1084 | LSHandlerRank 1085 | Alternate 1086 | 1087 | 1088 | CFBundleTypeExtensions 1089 | 1090 | rb 1091 | rbx 1092 | rjs 1093 | rxml 1094 | 1095 | CFBundleTypeIconFile 1096 | file.icns 1097 | CFBundleTypeName 1098 | Ruby source 1099 | CFBundleTypeRole 1100 | Editor 1101 | LSHandlerRank 1102 | Alternate 1103 | 1104 | 1105 | CFBundleTypeExtensions 1106 | 1107 | sass 1108 | scss 1109 | 1110 | CFBundleTypeIconFile 1111 | file.icns 1112 | CFBundleTypeName 1113 | Sass source 1114 | CFBundleTypeRole 1115 | Editor 1116 | LSHandlerRank 1117 | Alternate 1118 | 1119 | 1120 | CFBundleTypeExtensions 1121 | 1122 | scm 1123 | sch 1124 | 1125 | CFBundleTypeIconFile 1126 | file.icns 1127 | CFBundleTypeName 1128 | Scheme source 1129 | CFBundleTypeRole 1130 | Editor 1131 | LSHandlerRank 1132 | Alternate 1133 | 1134 | 1135 | CFBundleTypeExtensions 1136 | 1137 | ext 1138 | 1139 | CFBundleTypeIconFile 1140 | file.icns 1141 | CFBundleTypeName 1142 | Setext document 1143 | CFBundleTypeRole 1144 | Editor 1145 | LSHandlerRank 1146 | Alternate 1147 | 1148 | 1149 | CFBundleTypeExtensions 1150 | 1151 | sh 1152 | ss 1153 | bashrc 1154 | bash_profile 1155 | bash_login 1156 | profile 1157 | bash_logout 1158 | 1159 | CFBundleTypeIconFile 1160 | file.icns 1161 | CFBundleTypeName 1162 | Shell script 1163 | CFBundleTypeRole 1164 | Editor 1165 | LSHandlerRank 1166 | Alternate 1167 | 1168 | 1169 | CFBundleTypeExtensions 1170 | 1171 | slate 1172 | 1173 | CFBundleTypeIconFile 1174 | file.icns 1175 | CFBundleTypeName 1176 | Slate source 1177 | CFBundleTypeRole 1178 | Editor 1179 | LSHandlerRank 1180 | Alternate 1181 | 1182 | 1183 | CFBundleTypeExtensions 1184 | 1185 | sql 1186 | 1187 | CFBundleTypeIconFile 1188 | file.icns 1189 | CFBundleTypeName 1190 | SQL source 1191 | CFBundleTypeRole 1192 | Editor 1193 | LSHandlerRank 1194 | Alternate 1195 | 1196 | 1197 | CFBundleTypeExtensions 1198 | 1199 | sml 1200 | 1201 | CFBundleTypeIconFile 1202 | file.icns 1203 | CFBundleTypeName 1204 | Standard ML source 1205 | CFBundleTypeRole 1206 | Editor 1207 | LSHandlerRank 1208 | Alternate 1209 | 1210 | 1211 | CFBundleTypeExtensions 1212 | 1213 | strings 1214 | 1215 | CFBundleTypeIconFile 1216 | file.icns 1217 | CFBundleTypeName 1218 | Strings document 1219 | CFBundleTypeRole 1220 | Editor 1221 | LSHandlerRank 1222 | Alternate 1223 | 1224 | 1225 | CFBundleTypeExtensions 1226 | 1227 | svg 1228 | 1229 | CFBundleTypeIconFile 1230 | file.icns 1231 | CFBundleTypeName 1232 | Scalable vector graphics 1233 | CFBundleTypeRole 1234 | Editor 1235 | LSHandlerRank 1236 | Alternate 1237 | 1238 | 1239 | CFBundleTypeExtensions 1240 | 1241 | i 1242 | swg 1243 | 1244 | CFBundleTypeIconFile 1245 | file.icns 1246 | CFBundleTypeName 1247 | SWIG source 1248 | CFBundleTypeRole 1249 | Editor 1250 | LSHandlerRank 1251 | Alternate 1252 | 1253 | 1254 | CFBundleTypeExtensions 1255 | 1256 | tcl 1257 | 1258 | CFBundleTypeIconFile 1259 | file.icns 1260 | CFBundleTypeName 1261 | Tcl source 1262 | CFBundleTypeRole 1263 | Editor 1264 | LSHandlerRank 1265 | Alternate 1266 | 1267 | 1268 | CFBundleTypeExtensions 1269 | 1270 | tex 1271 | sty 1272 | cls 1273 | 1274 | CFBundleTypeIconFile 1275 | file.icns 1276 | CFBundleTypeName 1277 | TeX document 1278 | CFBundleTypeRole 1279 | Editor 1280 | LSHandlerRank 1281 | Alternate 1282 | 1283 | 1284 | CFBundleTypeExtensions 1285 | 1286 | text 1287 | txt 1288 | utf8 1289 | 1290 | CFBundleTypeIconFile 1291 | file.icns 1292 | CFBundleTypeMIMETypes 1293 | 1294 | text/plain 1295 | 1296 | CFBundleTypeName 1297 | Plain text document 1298 | CFBundleTypeOSTypes 1299 | 1300 | TEXT 1301 | sEXT 1302 | ttro 1303 | 1304 | CFBundleTypeRole 1305 | Editor 1306 | LSHandlerRank 1307 | Alternate 1308 | 1309 | 1310 | CFBundleTypeExtensions 1311 | 1312 | textile 1313 | 1314 | CFBundleTypeIconFile 1315 | file.icns 1316 | CFBundleTypeName 1317 | Textile document 1318 | CFBundleTypeRole 1319 | Editor 1320 | LSHandlerRank 1321 | Alternate 1322 | 1323 | 1324 | CFBundleTypeExtensions 1325 | 1326 | toml 1327 | 1328 | CFBundleTypeIconFile 1329 | file.icns 1330 | CFBundleTypeName 1331 | TOML file 1332 | CFBundleTypeRole 1333 | Editor 1334 | LSHandlerRank 1335 | Alternate 1336 | 1337 | 1338 | CFBundleTypeExtensions 1339 | 1340 | xhtml 1341 | 1342 | CFBundleTypeIconFile 1343 | file.icns 1344 | CFBundleTypeName 1345 | XHTML document 1346 | CFBundleTypeRole 1347 | Editor 1348 | LSHandlerRank 1349 | Alternate 1350 | 1351 | 1352 | CFBundleTypeExtensions 1353 | 1354 | xml 1355 | xsd 1356 | xib 1357 | rss 1358 | tld 1359 | pt 1360 | cpt 1361 | dtml 1362 | 1363 | CFBundleTypeIconFile 1364 | file.icns 1365 | CFBundleTypeName 1366 | XML document 1367 | CFBundleTypeRole 1368 | Editor 1369 | LSHandlerRank 1370 | Alternate 1371 | 1372 | 1373 | CFBundleTypeExtensions 1374 | 1375 | xsl 1376 | xslt 1377 | 1378 | CFBundleTypeIconFile 1379 | file.icns 1380 | CFBundleTypeName 1381 | XSL stylesheet 1382 | CFBundleTypeRole 1383 | Editor 1384 | LSHandlerRank 1385 | Alternate 1386 | 1387 | 1388 | CFBundleTypeExtensions 1389 | 1390 | vcf 1391 | vcard 1392 | 1393 | CFBundleTypeIconFile 1394 | file.icns 1395 | CFBundleTypeName 1396 | Electronic business card 1397 | CFBundleTypeRole 1398 | Editor 1399 | LSHandlerRank 1400 | Alternate 1401 | 1402 | 1403 | CFBundleTypeExtensions 1404 | 1405 | vb 1406 | 1407 | CFBundleTypeIconFile 1408 | file.icns 1409 | CFBundleTypeName 1410 | Visual Basic source 1411 | CFBundleTypeRole 1412 | Editor 1413 | LSHandlerRank 1414 | Alternate 1415 | 1416 | 1417 | CFBundleTypeExtensions 1418 | 1419 | yaml 1420 | yml 1421 | 1422 | CFBundleTypeIconFile 1423 | file.icns 1424 | CFBundleTypeName 1425 | YAML document 1426 | CFBundleTypeRole 1427 | Editor 1428 | LSHandlerRank 1429 | Alternate 1430 | 1431 | 1432 | CFBundleTypeExtensions 1433 | 1434 | nfo 1435 | 1436 | CFBundleTypeIconFile 1437 | file.icns 1438 | CFBundleTypeName 1439 | Text document 1440 | CFBundleTypeRole 1441 | Editor 1442 | LSHandlerRank 1443 | Alternate 1444 | 1445 | 1446 | CFBundleTypeExtensions 1447 | 1448 | g 1449 | vss 1450 | d 1451 | e 1452 | gri 1453 | inf 1454 | mel 1455 | build 1456 | re 1457 | textmate 1458 | fxscript 1459 | lgt 1460 | 1461 | CFBundleTypeIconFile 1462 | file.icns 1463 | CFBundleTypeName 1464 | Source 1465 | CFBundleTypeRole 1466 | Editor 1467 | LSHandlerRank 1468 | Alternate 1469 | 1470 | 1471 | CFBundleTypeExtensions 1472 | 1473 | cfm 1474 | cfml 1475 | dbm 1476 | dbml 1477 | dist 1478 | dot 1479 | ics 1480 | ifb 1481 | dwt 1482 | g 1483 | in 1484 | l 1485 | m4 1486 | mp 1487 | mtml 1488 | orig 1489 | pde 1490 | rej 1491 | servlet 1492 | s5 1493 | tmp 1494 | tpl 1495 | tt 1496 | xql 1497 | yy 1498 | * 1499 | 1500 | CFBundleTypeIconFile 1501 | file.icns 1502 | CFBundleTypeName 1503 | Document 1504 | CFBundleTypeRole 1505 | Editor 1506 | LSHandlerRank 1507 | Alternate 1508 | 1509 | 1510 | CFBundleTypeIconFile 1511 | file.icns 1512 | CFBundleTypeName 1513 | Document 1514 | CFBundleTypeOSTypes 1515 | 1516 | **** 1517 | 1518 | CFBundleTypeRole 1519 | Editor 1520 | LSHandlerRank 1521 | Alternate 1522 | LSItemContentTypes 1523 | 1524 | public.data 1525 | 1526 | 1527 | 1528 | CFBundleTypeRole 1529 | Editor 1530 | LSHandlerRank 1531 | Alternate 1532 | LSItemContentTypes 1533 | 1534 | public.directory 1535 | com.apple.bundle 1536 | com.apple.resolvable 1537 | 1538 | 1539 | 1540 | 1541 | 1542 | --------------------------------------------------------------------------------