├── .gitignore ├── .travis.yml ├── CHANGES.txt ├── Default.sublime-keymap ├── Default.sublime-mousemap ├── Development └── Default.sublime-keymap ├── LICENSE.txt ├── Preferences.sublime-settings ├── README.md ├── Vintageous.sublime-build ├── Vintageous.sublime-commands ├── Vintageous.sublime-project ├── VintageousEx Cmdline.JSON-tmLanguage ├── VintageousEx Cmdline.sublime-settings ├── VintageousEx Cmdline.tmLanguage ├── __init__.py ├── appveyor.yml ├── bin ├── Build.ps1 ├── Config.ps1 ├── Publish.ps1 ├── Push.ps1 ├── Stats.ps1 ├── build.sh ├── builder.py ├── check.py ├── make_version.py └── toplist.py ├── dev_cmds.py ├── ex ├── __init__.py ├── completions.py ├── ex_error.py ├── ex_location.py ├── parser │ ├── __init__.py │ ├── nodes.py │ ├── parser.py │ ├── scanner.py │ ├── scanner_command_abbreviate.py │ ├── scanner_command_browse.py │ ├── scanner_command_buffers.py │ ├── scanner_command_cd_command.py │ ├── scanner_command_cdd_command.py │ ├── scanner_command_copy.py │ ├── scanner_command_cquit.py │ ├── scanner_command_delete.py │ ├── scanner_command_double_ampersand.py │ ├── scanner_command_edit.py │ ├── scanner_command_exit.py │ ├── scanner_command_file.py │ ├── scanner_command_global.py │ ├── scanner_command_goto.py │ ├── scanner_command_let.py │ ├── scanner_command_map.py │ ├── scanner_command_move.py │ ├── scanner_command_new.py │ ├── scanner_command_nmap.py │ ├── scanner_command_nunmap.py │ ├── scanner_command_omap.py │ ├── scanner_command_only.py │ ├── scanner_command_ounmap.py │ ├── scanner_command_print.py │ ├── scanner_command_print_working_dir.py │ ├── scanner_command_quit_all_command.py │ ├── scanner_command_quit_command.py │ ├── scanner_command_read_shell_out.py │ ├── scanner_command_register.py │ ├── scanner_command_set.py │ ├── scanner_command_set_local.py │ ├── scanner_command_shell.py │ ├── scanner_command_shell_out.py │ ├── scanner_command_substitute.py │ ├── scanner_command_tab_first_command.py │ ├── scanner_command_tab_last_command.py │ ├── scanner_command_tab_next_command.py │ ├── scanner_command_tab_only_command.py │ ├── scanner_command_tab_open_command.py │ ├── scanner_command_tab_prev_command.py │ ├── scanner_command_unabbreviate.py │ ├── scanner_command_unmap.py │ ├── scanner_command_unvsplit.py │ ├── scanner_command_vmap.py │ ├── scanner_command_vsplit.py │ ├── scanner_command_vunmap.py │ ├── scanner_command_write.py │ ├── scanner_command_write_all.py │ ├── scanner_command_write_and_quit_all.py │ ├── scanner_command_write_and_quit_command.py │ ├── scanner_command_yank.py │ ├── state.py │ ├── subscanners.py │ ├── tokens.py │ └── tokens_base.py ├── plat │ ├── __init__.py │ ├── linux.py │ ├── osx.py │ └── windows.py └── shell.py ├── ex_commands.py ├── ex_main.py ├── ex_motions.py ├── jump_list_cmds.py ├── manifest.json ├── messages.json ├── messages ├── 2.9.1.txt ├── 2.9.10.txt ├── 2.9.11.txt ├── 2.9.2.txt ├── 2.9.3.txt ├── 2.9.4.txt ├── 2.9.5.txt ├── 2.9.6.txt ├── 2.9.7.txt ├── 2.9.8.txt ├── 2.9.9.txt ├── 3.0.0.txt ├── 3.0.1.txt ├── 3.0.2.txt ├── 3.5.0.txt ├── 3.5.1.txt ├── 3.5.10.txt ├── 3.5.11.txt ├── 3.5.12.txt ├── 3.5.13.txt ├── 3.5.14.txt ├── 3.5.2.txt ├── 3.5.3.txt ├── 3.5.4.txt ├── 3.5.5.txt ├── 3.5.6.txt ├── 3.5.7.txt ├── 3.5.8.txt ├── 3.5.9.txt ├── 3.6.0.txt ├── 3.6.1.txt ├── 3.6.2.txt ├── 3.6.3.txt ├── 3.6.4.txt ├── 3.6.6.txt ├── 3.6.7.txt ├── 3.6.8.txt ├── 3.8.0.txt ├── 3.8.1.txt ├── 3.8.10.txt ├── 3.8.2.txt ├── 3.8.3.txt ├── 3.8.4.txt ├── 3.8.5.txt ├── 3.8.6.txt ├── 3.8.7.txt ├── 3.8.8.txt ├── 3.8.9.txt ├── 4.0.0.txt ├── 4.0.1.txt ├── 4.0.2.txt ├── 4.0.3.txt ├── 4.0.4.txt ├── 4.0.5.txt ├── 4.0.6.txt ├── 4.0.7.txt └── install.txt ├── modelines.py ├── plugins ├── __init__.py └── plugins.py ├── state.py ├── test_runner.py ├── tests ├── __init__.py ├── cmd_tester.py ├── commands │ ├── __init__.py │ ├── test__ctrl_x_and__ctrl_a.py │ ├── test__vi_antilambda.py │ ├── test__vi_b.py │ ├── test__vi_big_a.py │ ├── test__vi_big_e.py │ ├── test__vi_big_f.py │ ├── test__vi_big_g.py │ ├── test__vi_big_i.py │ ├── test__vi_big_j.py │ ├── test__vi_big_s.py │ ├── test__vi_big_t.py │ ├── test__vi_cc.py │ ├── test__vi_ctrl_r.py │ ├── test__vi_dd.py │ ├── test__vi_dollar.py │ ├── test__vi_e.py │ ├── test__vi_f.py │ ├── test__vi_g_g.py │ ├── test__vi_h.py │ ├── test__vi_hat.py │ ├── test__vi_j.py │ ├── test__vi_k.py │ ├── test__vi_l.py │ ├── test__vi_octothorp.py │ ├── test__vi_percent.py │ ├── test__vi_repeat_search.py │ ├── test__vi_s.py │ ├── test__vi_search.py │ ├── test__vi_star.py │ ├── test__vi_t.py │ ├── test__vi_underscore.py │ ├── test__vi_visual_o.py │ ├── test__vi_zero.py │ ├── test_all_cmds.py │ ├── test_vi_big_b.py │ ├── test_vi_big_p.py │ ├── vi_big_x-internal-normal-mode.cmd-test │ ├── vi_cc-internal-normal-mode.cmd-test │ ├── vi_dd-internal-normal-mode.cmd-test │ ├── vi_dd-internal-normal.cmd-test │ ├── vi_gm-normal-mode.cmd-test │ ├── vi_l-normal-mode.cmd-test │ ├── vi_right_brace-normal-mode.cmd-test │ └── vi_x-internal-normal-mode.cmd-test ├── data │ └── Default.sublime-keymap_ ├── ex │ ├── __init__.py │ ├── parsers │ │ ├── __init__.py │ │ └── new │ │ │ ├── __init__.py │ │ │ ├── test_nodes.py │ │ │ ├── test_parser.py │ │ │ ├── test_parser_state.py │ │ │ ├── test_scanner.py │ │ │ └── test_scanner_state.py │ ├── test_commands.py │ ├── test_copy.py │ ├── test_delete.py │ ├── test_location.py │ ├── test_move.py │ └── test_shell_out.py ├── test_entering_normal_mode.py ├── test_state.py └── vi │ ├── __init__.py │ ├── test_a_word.py │ ├── test_big_word.py │ ├── test_big_word_reverse.py │ ├── test_find_paragraph_text_object.py │ ├── test_keys.py │ ├── test_mappings.py │ ├── test_marks.py │ ├── test_move_by_word_ends.py │ ├── test_registers.py │ ├── test_search.py │ ├── test_settings.py │ ├── test_tag_text_object.py │ ├── test_text_objects.py │ ├── test_variables.py │ ├── test_word.py │ ├── test_word_reverse.py │ └── test_word_start_reverse.py ├── vi ├── __init__.py ├── abbrev.py ├── cmd_base.py ├── cmd_defs.py ├── constants.py ├── contexts.py ├── core.py ├── dot_file.py ├── extend.py ├── inputs.py ├── jump_list.py ├── keys.py ├── macros.py ├── mappings.py ├── marks.py ├── registers.py ├── search.py ├── settings.py ├── sublime.py ├── text_objects.py ├── units.py ├── utils.py └── variables.py ├── xactions.py ├── xmotions.py ├── xsupport.py └── xsupport_mouse.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | 6 | # Distribution / packaging 7 | dist/ 8 | 9 | 10 | # Editors 11 | *.sublime-workspace 12 | *.sublime-package 13 | 14 | *~ 15 | *.TMP 16 | *.swp 17 | *.swo 18 | *.swm 19 | *.swn 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | - osx 4 | 5 | env: 6 | global: 7 | - PACKAGE="Vintageous" 8 | matrix: 9 | - SUBLIME_TEXT_VERSION="3" 10 | 11 | before_install: 12 | - curl -OL https://raw.githubusercontent.com/randy3k/UnitTesting/master/sbin/travis.sh 13 | 14 | install: 15 | - sh travis.sh bootstrap 16 | 17 | script: 18 | - sh travis.sh run_tests 19 | 20 | notifications: 21 | email: false 22 | -------------------------------------------------------------------------------- /Default.sublime-mousemap: -------------------------------------------------------------------------------- 1 | [ 2 | ] 3 | -------------------------------------------------------------------------------- /Development/Default.sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["f5"], "command": "run_tests_for_active_view", "context": [{ "key": "vi_command_mode_aware"}]}, 3 | { "keys": ["ctrl+f5"], "command": "run_all_tests", "context": [{ "key": "vi_command_mode_aware"}]} 4 | ] 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | License 2 | ======= 3 | 4 | Vintageous is made available under the MIT license: 5 | 6 | Copyright (c) 2010 Guillermo López-Anglada (SublimeModelines) 7 | Copyright (c) 2011 Sublime HQ Pty Ltd (Vintage) 8 | Copyright (c) 2011 Guillermo López-Anglada (VintageEx) 9 | Copyright (c) 2013 Guillermo López-Anglada (Vintageous) 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Preferences.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | // If true, debug information will be printed to the console. 3 | "vintageous_verbose": false, 4 | 5 | // If true, some key bindings prefaced by the CTRL modifier will override default Sublime Text 6 | // key bindings. 7 | "vintageous_use_ctrl_keys": false, 8 | 9 | // If true, search occurrences will be highlighted in '/', '?', etc. 10 | // (Disabled.) 11 | "vintageous_hlsearch": true, 12 | 13 | // If true, search patterns will be applied incrementally as they are typed in. 14 | // (Disabled.) 15 | "vintageous_incsearch": true, 16 | 17 | // If true, ':' and ex commands will be available. 18 | "vintageous_enable_cmdline_mode": true, 19 | 20 | // If true, the current mode will be reset to normal mode when a tab gets activated. 21 | "vintageous_reset_mode_when_switching_tabs": true, 22 | 23 | // If true, some commands will take the current indentation level into account. 24 | // (Disabled.) 25 | "vintageous_autoindent": true, 26 | 27 | // If true, copy actions will always propagate to the system clipboard. 28 | "vintageous_use_sys_clipboard": false, 29 | 30 | // If true, / and ? will use regular expressions. 31 | // If false, smart case will be used instead: the pattern will be interpreted literally and, if 32 | // it's either all lowercase or all uppercase, case will be ignored too. 33 | "vintageous_magic": true, 34 | 35 | // If true, /, ?, * and # will always ignore case. 36 | "vintageous_ignorecase": true, 37 | 38 | // Logging level. Used for diagnostics and troubleshooting. Common valid 39 | // values are 'debug', 'info', 'error', 'critical'. Most users should 40 | // not need to modify the default value. 41 | "vintageous_log_level": "error" 42 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/guillermooo/Vintageous.svg?branch=master)](https://travis-ci.org/guillermooo/Vintageous) [![Build status](https://ci.appveyor.com/api/projects/status/pvea8jg8bdoq2rmn/branch/master)](https://ci.appveyor.com/project/guillermooo/vintageous/branch/master) 2 | 3 | ## Vintageous 4 | 5 | Click here to lend your support to: Vintageous and make a donation at www.pledgie.com ! 6 | 7 | 8 | **Vintageous** is a comprehensive vi/Vim emulation layer for Sublime Text 3. 9 | 10 | Vintageous has been discontinued. 11 | 12 | The successor to Vintageous is Sublime Six. 13 | 14 | See you in Sublime Six. 15 | 16 | https://github.com/guillermooo/Six 17 | 18 | http://sublimesix.com/ 19 | 20 | 21 | ### Installing 22 | 23 | **Make sure that Vintage 24 | is in the `ignored_packages` list 25 | in your user preferences.** 26 | 27 | You can install Vintageous in multiple ways: 28 | 29 | 30 | ##### Using Package Control 31 | 32 | Search for 'Vintageous' and install. 33 | 34 | 35 | ##### Using a Pre-built Version 36 | 37 | 1. Download the [current build](https://bitbucket.org/guillermooo/vintageous/downloads/Vintageous.sublime-package) 38 | 2. Copy *Vintageous.sublime-package* to the *Installed Packages* folder located under the data directory. 39 | 40 | 41 | ##### Building from Source 42 | 43 | 1. Clone this repository 44 | 2. Optionally, update to a specific tag 45 | 3. Run `./bin/build.sh` (OS X/Linux) or `bin/Publish.ps1` (Windows). 46 | 47 | Refer to the [wiki](https://github.com/guillermooo/Vintageous/wiki) for more information. 48 | 49 | 50 | ### Documentation 51 | 52 | Refer to the [wiki](https://github.com/guillermooo/Vintageous/wiki). 53 | 54 | 55 | ### Settings 56 | 57 | See [Vintageous/Preferences.sublime-settings](https://github.com/guillermooo/Vintageous/blob/master/Preferences.sublime-settings) for a comprehensive list of settings. 58 | -------------------------------------------------------------------------------- /Vintageous.sublime-build: -------------------------------------------------------------------------------- 1 | { 2 | "shell_cmd": "./build.sh", 3 | "windows": 4 | { 5 | "shell_cmd": "powershell -noninteractive -file \"$project_path\\bin\\Build.ps1\"" 6 | }, 7 | "working_dir": "${project_path}", 8 | 9 | "variants": [ 10 | { 11 | "name": "Vintageous - Test (All)", 12 | "target": "run_vintageous_tests", 13 | }, 14 | 15 | { 16 | "name": "Vintageous - Test (This File Only)", 17 | "target": "run_vintageous_tests", 18 | "active_file_only": true 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /Vintageous.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { "caption": "Vintageous: Reset", "command": "reset_vintageous" }, 3 | { "caption": "Vintageous: Toggle Vim Ctrl Keys", "command": "vintageous_toggle_ctrl_keys" }, 4 | { "caption": "Vintageous: Exit from command mode", "command": "force_exit_from_command_mode" }, 5 | { "caption": "Vintageous: Open .vintageousrc", "command": "vintageous_open_config_file" } 6 | ] -------------------------------------------------------------------------------- /Vintageous.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "follow_symlinks": true, 6 | "path": "." 7 | } 8 | ], 9 | 10 | "settings": 11 | { 12 | "ensure_new_line_at_eof_on_save": true, 13 | "trim_trailing_white_space_on_save": true, 14 | "default_line_ending": "unix", 15 | "translate_tabs_to_spaces": false 16 | }, 17 | 18 | "SublimeLinter": 19 | { 20 | "@python": 3.4 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /VintageousEx Cmdline.JSON-tmLanguage: -------------------------------------------------------------------------------- 1 | { "name": "Vintageous Command Line", 2 | "scopeName": "text.excmdline", 3 | "uuid": "eb9bb9a2-ab05-4edf-aee1-22d79cc9d9b0", 4 | 5 | "patterns": [ 6 | {"match": "^(:)(?:(\\d+)|(cd(?:d)?|w(?:rite|q|all)?|e(?:dit|new|xit)?|pw(?:d)?|buffers|files|ls|reg(?:isters)?|map|ab(?:breviate)?|q(:?uit|all)?|r(?:ead)?|as(?:cii)?|f(?:ile)?|move|co(?:py)?|t(?:abfirst|abprev|abedit|abe|abnext|abn|ablast|abl|abonly|abo)?|setl(:?ocal)?|se(?:t)?|s(?:ubstitute|hell|h)?|&&|d(?:elete)?|g(?:lobal)?|p(?:rint)?|P(?:rint)?|bro(?:owse)?|cq(?:uit)?|x(?:it)?|on(?:ly)?|new|y(?:ank)?|(?:un)?vs(?:plit)?)(!)?)?", 7 | "captures": { 8 | "1": {"name": "keyword.excmdline"}, 9 | "2": {"name": "constant.numeric.excmdline"}, 10 | "3": {"name": "support.function.excmdline"}, 11 | "4": {"name": "keyword.excmdline"} 12 | } 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /VintageousEx Cmdline.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "auto_match_enabled": false 3 | } 4 | -------------------------------------------------------------------------------- /VintageousEx Cmdline.tmLanguage: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Vintageous Command Line 7 | patterns 8 | 9 | 10 | captures 11 | 12 | 1 13 | 14 | name 15 | keyword.excmdline 16 | 17 | 2 18 | 19 | name 20 | constant.numeric.excmdline 21 | 22 | 3 23 | 24 | name 25 | support.function.excmdline 26 | 27 | 4 28 | 29 | name 30 | keyword.excmdline 31 | 32 | 33 | match 34 | ^(:)(?:(\d+)|(cd(?:d)?|w(?:rite|q|all)?|e(?:dit|new|xit)?|pw(?:d)?|buffers|files|ls|reg(?:isters)?|map|ab(?:breviate)?|q(:?uit|all)?|r(?:ead)?|as(?:cii)?|f(?:ile)?|move|co(?:py)?|t(?:abfirst|abprev|abedit|abe|abnext|abn|ablast|abl|abonly|abo)?|setl(:?ocal)?|se(?:t)?|s(?:ubstitute|hell|h)?|&&|d(?:elete)?|g(?:lobal)?|p(?:rint)?|P(?:rint)?|bro(?:owse)?|cq(?:uit)?|x(?:it)?|on(?:ly)?|new|y(?:ank)?|(?:un)?vs(?:plit)?)(!)?)? 35 | 36 | 37 | scopeName 38 | text.excmdline 39 | uuid 40 | eb9bb9a2-ab05-4edf-aee1-22d79cc9d9b0 41 | 42 | 43 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | global: 3 | PACKAGE: "Vintageous" 4 | 5 | matrix: 6 | - SUBLIME_TEXT_VERSION: "3" 7 | 8 | clone_depth: 1 9 | 10 | install: 11 | - ps: start-filedownload "https://raw.githubusercontent.com/randy3k/UnitTesting/master/sbin/appveyor.ps1" 12 | - ps: .\appveyor.ps1 "bootstrap" -verbose 13 | 14 | build: off 15 | 16 | test_script: 17 | - ps: .\appveyor.ps1 "run_tests" -verbose 18 | -------------------------------------------------------------------------------- /bin/Build.ps1: -------------------------------------------------------------------------------- 1 | param([switch]$Release, [switch]$NoRestartEditor=$False) 2 | 3 | push-location $PSScriptRoot 4 | . '.\Config.ps1' 5 | if(!$?){ 6 | write-error "Could not read config." 7 | exit 1 8 | } 9 | pop-location 10 | 11 | push-location "$PSScriptRoot\.." 12 | & (join-path $PSScriptRoot '.\Publish.ps1') @PSBoundParameters 13 | if ($LASTEXITCODE -ne 0) { 14 | write-error "Could not publish package." 15 | pop-location 16 | exit 1 17 | } 18 | pop-location 19 | 20 | if ($NoRestartEditor) { exit 0 } 21 | 22 | get-process "sublime_text" -ea silentlycontinue | stop-process 23 | write-output "Trying to restart Sublime Text..." 24 | start-sleep -milliseconds 250 25 | 26 | $editor = (GetConfigValue 'global-win' 'editor') 27 | if(!$?){ 28 | write-error "Could not locate editor command." 29 | exit 1 30 | } 31 | 32 | &$editor 33 | -------------------------------------------------------------------------------- /bin/Config.ps1: -------------------------------------------------------------------------------- 1 | # Helpers to read files in this format: 2 | # 3 | # global-win editor path/to/some/bin 4 | # project-foo deploy-url http://some/url/here 5 | # ... 6 | 7 | function GetConfig { 8 | $path = "~/.sublime-package-dev" 9 | 10 | if(!(test-path $path)){ 11 | write-error "Could not find personal configuration in $path." 12 | exit 1 13 | } 14 | get-content $path 15 | } 16 | 17 | $script:configData = GetConfig 18 | 19 | function GetConfigValue { 20 | param($section, $key) 21 | $section = $section.ToLower() 22 | $key = $key.ToLower() 23 | foreach($item in $configData){ 24 | if(!$item.Trim()){ 25 | continue 26 | } 27 | $s, $k, $v = $item.ToLower() -split ' ',3 28 | if(($s -eq $section) -and ($k -eq $key)){ 29 | if(!$v){ 30 | throw "No value found for '${section}:$key'." 31 | } 32 | return $v 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /bin/Publish.ps1: -------------------------------------------------------------------------------- 1 | param([switch]$Release, [switch]$DontUpload) 2 | 3 | $script:thisDir = split-path $MyInvocation.MyCommand.Path -parent 4 | # Don't resolve-path because it may not exist yet. 5 | $script:distDir = join-path $thisDir "../dist" 6 | 7 | . (join-path $script:thisDir "Config.ps1") 8 | if(!$?){ 9 | write-error "Could not read config." 10 | exit 1 11 | } 12 | 13 | & "py.exe" "-3" (join-path $script:thisDir "check.py") $typeOfBuild 14 | if ($LASTEXITCODE -ne 0) { 15 | "publish aborted" 16 | exit 1 17 | } 18 | 19 | $typeOfBuild = if ($Release) {"release"} else {"dev"} 20 | # Run with the required Python version. 21 | & "py.exe" "-3" (join-path $script:thisDir "builder.py") "--release" $typeOfBuild 22 | 23 | if ($LASTEXITCODE -ne 0) { 24 | write-error "could not run builder.py" 25 | exit 1 26 | } 27 | 28 | $installedPackages = (GetConfigValue 'global-win' 'installed-packages') 29 | if(!$?){ 30 | throw "Could not retrieve Installed Packages location from confige" 31 | exit 1 32 | } 33 | $targetDir = resolve-path ($installedPackages) 34 | 35 | copy-item (join-path $distDir "Vintageous.sublime-package") $targetDir -force 36 | 37 | if ($Release -and (!$DontUpload)) { 38 | $deployUrl = (GetConfigValue 'project-vintageous' 'deploy-url') 39 | if(!$?){ 40 | throw "Could not retrieve deploy url from config." 41 | exit 1 42 | } 43 | start-process $deployUrl 44 | (resolve-path $distDir).path | clip.exe 45 | } 46 | -------------------------------------------------------------------------------- /bin/Push.ps1: -------------------------------------------------------------------------------- 1 | # This script ensures that we abort pushing if we have unfinzalied Mercurial patches. 2 | # 3 | # hg-git has bug that will break the local repository if we do all the following things: 4 | # 1. we push changes in A.patch to Github without finalizing the patch first 5 | # 2. we make further changes to the patch locally and refresh 6 | # 3. we finalize and push A.patch to Github again 7 | 8 | if (& hg qseries) { 9 | write-host "Cannot push: unfinalized patches!" -foregroundcolor RED 10 | exit 11 | } 12 | 13 | # Override .hg/hgrc 14 | & hg --config "alias.push=push" push bb 15 | & hg --config "alias.push=push" push git 16 | -------------------------------------------------------------------------------- /bin/Stats.ps1: -------------------------------------------------------------------------------- 1 | # Gather some metrics about this project. 2 | 3 | push-location $PSSCriptRoot\.. 4 | $code = get-content ( 5 | get-childitem . *.py -recurse | 6 | select-object -expandproperty fullname) | 7 | select-string -notmatch "^\s*#" | 8 | measure-object -line 9 | 10 | 11 | $comments = get-content ( 12 | get-childitem . *.py -recurse | 13 | select-object -expandproperty fullname) | 14 | select-string "^\s*#" | 15 | measure-object -line 16 | 17 | 18 | $tests = get-content ( 19 | get-childitem .\tests *.py -recurse | 20 | select-object -expandproperty fullname) | 21 | select-string -notmatch "^\s*#" | 22 | measure-object -line 23 | 24 | pop-location 25 | 26 | write-output "-----------------------------------------------" 27 | write-output "SLOC (Application): $($code.lines - $tests.lines)" 28 | write-output "SLOC (Tests): $($tests.lines)" 29 | write-output "SLOC (Comments): $($comments.lines)" 30 | write-output "SLOC (Total): $($code.lines + $comments.lines)" 31 | -------------------------------------------------------------------------------- /bin/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 3 | 4 | e=1 5 | if python "$DIR/builder.py"; then 6 | case "$(uname)" in 7 | Linux) 8 | cp -f "$DIR/../dist/Vintageous.sublime-package"\ 9 | "${HOME}/.config/sublime-text-3/Installed Packages" 10 | e=$? 11 | ;; 12 | Darwin) 13 | cp -f "$DIR/../dist/Vintageous.sublime-package"\ 14 | "${HOME}/Library/Application Support/Sublime Text 3/Installed Packages/" 15 | e=$? 16 | ;; 17 | *) 18 | echo "Vintageous: no build script for $(uname) :_(" 19 | ;; 20 | esac 21 | else 22 | echo "Failed to execute $DIR/builder.py" 23 | e=2 24 | fi 25 | 26 | exit $e 27 | -------------------------------------------------------------------------------- /bin/builder.py: -------------------------------------------------------------------------------- 1 | from fnmatch import fnmatch 2 | from itertools import chain 3 | from zipfile import ZipFile 4 | from zipfile import ZIP_DEFLATED 5 | import argparse 6 | import glob 7 | import json 8 | import os 9 | 10 | 11 | THIS_DIR = os.path.abspath(os.path.dirname(__file__)) 12 | PROJECT_ROOT = os.path.dirname(THIS_DIR) 13 | RESERVED = ['manifest.json', 'dist'] 14 | 15 | 16 | parser = argparse.ArgumentParser( 17 | description="Builds .sublime-package archives.") 18 | parser.add_argument('-d', dest='target_dir', default='./dist', 19 | help="output directory") 20 | parser.add_argument('--release', dest='release', default='dev', 21 | help="type of build (e.g. 'dev', 'release'...)") 22 | 23 | 24 | def get_manifest(): 25 | path = os.path.join(PROJECT_ROOT, 'manifest.json') 26 | with open(path) as f: 27 | return json.load(f) 28 | 29 | 30 | def unwanted(fn, pats): 31 | return any(fnmatch(fn, pat) for pat in pats + RESERVED) 32 | 33 | 34 | def ifind_files(patterns): 35 | for fn in (fn for (pat, exclude) in patterns 36 | for fn in glob.iglob(pat) 37 | if not unwanted(fn, exclude)): 38 | yield fn 39 | 40 | 41 | def build(target_dir="dist", release="dev"): 42 | os.chdir(PROJECT_ROOT) 43 | manifest = get_manifest() 44 | name = manifest['name'] + '.sublime-package' 45 | 46 | target_dir = os.path.join(PROJECT_ROOT, target_dir) 47 | if not os.path.exists(target_dir): 48 | os.mkdir(target_dir) 49 | 50 | target_file = os.path.join(target_dir, name) 51 | if os.path.exists(target_file): 52 | os.unlink(target_file) 53 | 54 | with ZipFile(target_file, 'a', compression=ZIP_DEFLATED) as package: 55 | for fn in ifind_files(manifest['include'][release]): 56 | package.write(fn) 57 | 58 | 59 | if __name__ == '__main__': 60 | args = parser.parse_args() 61 | build(args.target_dir, args.release) 62 | -------------------------------------------------------------------------------- /bin/check.py: -------------------------------------------------------------------------------- 1 | """ 2 | check for common build errors 3 | """ 4 | 5 | import json 6 | import os 7 | import sys 8 | 9 | 10 | _this_dir = os.path.dirname(__file__) 11 | _parent = os.path.realpath(os.path.join(_this_dir, '..')) 12 | 13 | 14 | def check_messages(): 15 | _messages = os.path.realpath(os.path.join(_parent, 'messages.json')) 16 | _messages_dir = os.path.realpath(os.path.join(_parent, 'messages')) 17 | 18 | msg_paths = None 19 | try: 20 | with open(_messages, 'r') as f: 21 | msg_paths = json.load(f) 22 | except Exception as e: 23 | print('syntax error in messages.json') 24 | print('=' * 80) 25 | print(e) 26 | print('=' * 80) 27 | sys.exit(1) 28 | 29 | def exists(path): 30 | if os.path.exists(os.path.join(_parent, path)): 31 | return True 32 | 33 | def is_name_correct(key, path): 34 | name = os.path.basename(path) 35 | return (key == os.path.splitext(name)[0]) 36 | 37 | # is there a file for each message? 38 | for (key, rel_path) in msg_paths.items(): 39 | if not is_name_correct(key, rel_path): 40 | print('file name not correct: {0} ==> {1}'.format(key, rel_path)) 41 | sys.exit(1) 42 | 43 | if not exists(rel_path): 44 | print('message file not found: {0}'.format(rel_path)) 45 | sys.exit(1) 46 | 47 | 48 | if __name__ == '__main__': 49 | check_messages() 50 | -------------------------------------------------------------------------------- /bin/toplist.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import json 3 | import os 4 | import plistlib 5 | 6 | 7 | THIS_DIR = os.path.abspath(os.path.dirname(__file__)) 8 | 9 | 10 | parser = argparse.ArgumentParser( 11 | description="Builds .tmLanguage files out of .JSON-tmLanguage files.") 12 | parser.add_argument('-s', dest='source', 13 | help="source .JSON-tmLanguage file") 14 | 15 | def build(source): 16 | with open(source, 'r') as f: 17 | json_data = json.load(f) 18 | plistlib.writePlist(json_data, os.path.splitext(source)[0] + '.tmLanguage') 19 | 20 | 21 | if __name__ == '__main__': 22 | args = parser.parse_args() 23 | if args.source: 24 | build(args.source) 25 | -------------------------------------------------------------------------------- /ex/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Misc stuff needed for ex commands. 3 | ''' 4 | 5 | # Used to provide completions on the ex command line. 6 | command_names = [] 7 | 8 | 9 | def command(name, abbrev): 10 | """ 11 | Registers the name of an ex command with `command_names`. 12 | 13 | Meant to be imported like this: 14 | 15 | from Vintageous import ex 16 | 17 | ... 18 | 19 | @ex.command('foo', 'f') 20 | class ExFooCommand(...): 21 | ... 22 | """ 23 | command_names.append((name, abbrev)) 24 | def inner(f): 25 | return f 26 | return inner 27 | -------------------------------------------------------------------------------- /ex/parser/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guillermooo/Vintageous/f958207009902052aed5fcac09745f1742648604/ex/parser/__init__.py -------------------------------------------------------------------------------- /ex/parser/scanner_command_abbreviate.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_ABBREVIATE 4 | from .tokens_base import TokenOfCommand 5 | 6 | from Vintageous.ex.ex_error import ERR_INVALID_ARGUMENT 7 | from Vintageous.ex.ex_error import VimError 8 | from Vintageous import ex 9 | 10 | 11 | @ex.command('abbreviate', 'ab') 12 | class TokenCommandAbbreviate(TokenOfCommand): 13 | def __init__(self, params, *args, **kwargs): 14 | super().__init__(params, 15 | TOKEN_COMMAND_ABBREVIATE, 16 | 'write', *args, **kwargs) 17 | self.target_command = 'ex_abbreviate' 18 | 19 | @property 20 | def short(self): 21 | return self.params['short'] 22 | 23 | @property 24 | def full(self): 25 | return self.params['full'] 26 | 27 | 28 | def scan_command_abbreviate(state): 29 | params = { 30 | 'short': None, 31 | 'full': None, 32 | } 33 | 34 | state.expect(' ') 35 | state.skip(' ') 36 | state.ignore() 37 | 38 | if state.consume() == EOF: 39 | return None, [TokenCommandAbbreviate({}), TokenEof()] 40 | 41 | state.backup() 42 | 43 | m = state.match(r'(?P.+?)(?: +(?P.+))?$') 44 | params.update(m.groupdict()) 45 | 46 | return None, [TokenCommandAbbreviate(params), TokenEof()] 47 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_browse.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_BROWSE 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('browse', 'bro') 9 | class TokenBrowse(TokenOfCommand): 10 | def __init__(self, params, *args, **kwargs): 11 | super().__init__(params, 12 | TOKEN_COMMAND_BROWSE, 13 | 'browse', *args, **kwargs) 14 | self.target_command = 'ex_browse' 15 | 16 | 17 | def scan_command_browse(state): 18 | params = { 19 | 'cmd': None, 20 | } 21 | 22 | state.skip(' ') 23 | state.ignore() 24 | 25 | m = state.match(r'(?P.*)$') 26 | params.update(m.groupdict()) 27 | 28 | if params ['cmd']: 29 | raise NotImplementedError('parameter not implemented') 30 | 31 | return None, [TokenBrowse(params), TokenEof()] 32 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_buffers.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_BUFFERS 4 | from .tokens_base import TokenOfCommand 5 | 6 | from Vintageous.ex.ex_error import ERR_INVALID_ARGUMENT 7 | from Vintageous.ex.ex_error import VimError 8 | from Vintageous import ex 9 | 10 | 11 | @ex.command('buffers', 'buffers') 12 | @ex.command('files', 'files') 13 | @ex.command('ls', 'ls') 14 | class TokenCommandBuffers(TokenOfCommand): 15 | def __init__(self, *args, **kwargs): 16 | super().__init__({}, 17 | TOKEN_COMMAND_BUFFERS, 18 | 'write', *args, **kwargs) 19 | self.target_command = 'ex_prompt_select_open_file' 20 | 21 | 22 | def scan_command_buffers(state): 23 | try: 24 | state.expect(EOF) 25 | except ValueError: 26 | raise VimError('trailing characters') 27 | 28 | return None, [TokenCommandBuffers(), TokenEof()] 29 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_cd_command.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_CD_COMMAND 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('cd', 'cd') 9 | class TokenCdCommand(TokenOfCommand): 10 | def __init__(self, params, *args, **kwargs): 11 | super().__init__(params, 12 | TOKEN_COMMAND_CD_COMMAND, 13 | 'cd', *args, **kwargs) 14 | self.target_command = 'ex_cd' 15 | 16 | @property 17 | def path(self): 18 | return self.params['path'] 19 | 20 | @property 21 | def must_go_back(self): 22 | return self.params['-'] 23 | 24 | 25 | def scan_command_cd_command(state): 26 | params = { 27 | 'path': None, 28 | '-': None, 29 | } 30 | 31 | bang = state.consume() == '!' 32 | 33 | if not bang: 34 | state.backup() 35 | 36 | state.skip(' ') 37 | state.ignore() 38 | 39 | c = state.consume() 40 | 41 | if c == '-': 42 | params['-'] = '-' 43 | state.expect(EOF) 44 | raise NotImplementedError('parameter not implemented') 45 | 46 | elif c != EOF: 47 | state.backup() 48 | m = state.match(r'(?P.+?)\s*$') 49 | params.update(m.groupdict()) 50 | 51 | return None, [TokenCdCommand(params, forced=bang), TokenEof()] 52 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_cdd_command.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_CDD_COMMAND 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('cdd', 'cdd') 9 | class TokenCddCommand(TokenOfCommand): 10 | def __init__(self, *args, **kwargs): 11 | super().__init__({}, 12 | TOKEN_COMMAND_CDD_COMMAND, 13 | 'cdd', *args, **kwargs) 14 | self.target_command = 'ex_cdd' 15 | 16 | 17 | def scan_command_cdd_command(state): 18 | c = state.consume() 19 | 20 | if c == EOF: 21 | return None, [TokenCddCommand(), TokenEof()] 22 | 23 | bang = c == '!' 24 | if not bang: 25 | state.backup() 26 | 27 | state.expect(EOF) 28 | 29 | return None, [TokenCddCommand(forced=bang), TokenEof()] 30 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_copy.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_COPY 4 | from .tokens_base import TokenOfCommand 5 | from .parser import parse_command_line 6 | from Vintageous import ex 7 | 8 | 9 | @ex.command('copy', 'co') 10 | class TokenCopy(TokenOfCommand): 11 | def __init__(self, params, *args, **kwargs): 12 | super().__init__(params, 13 | TOKEN_COMMAND_COPY, 14 | 'copy', *args, **kwargs) 15 | self.addressable = True 16 | self.target_command = 'ex_copy' 17 | 18 | @property 19 | def address(self): 20 | return self.params['address'] 21 | 22 | def calculate_address(self): 23 | # TODO: must calc only the first line ref? 24 | calculated = parse_command_line(self.address) 25 | if calculated is None: 26 | return None 27 | 28 | assert calculated.command is None, 'bad address' 29 | assert calculated.line_range.separator is None, 'bad address' 30 | 31 | return calculated.line_range 32 | 33 | 34 | def scan_command_copy(state): 35 | params = { 36 | 'address': None 37 | } 38 | 39 | m = state.expect_match(r'\s*(?P
.+?)\s*$') 40 | params.update(m.groupdict()) 41 | 42 | return None, [TokenCopy(params), TokenEof()] 43 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_cquit.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_CQUIT 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('cquit', 'cq') 9 | class TokenCquit(TokenOfCommand): 10 | def __init__(self, *args, **kwargs): 11 | super().__init__({}, 12 | TOKEN_COMMAND_CQUIT, 13 | 'cquit', *args, **kwargs) 14 | self.target_command = 'ex_cquit' 15 | 16 | 17 | def scan_command_cquit(state): 18 | state.expect(EOF) 19 | 20 | return None, [TokenCquit(), TokenEof()] 21 | 22 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_delete.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_DELETE 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('delete', 'd') 9 | class TokenDelete(TokenOfCommand): 10 | def __init__(self, params, *args, **kwargs): 11 | super().__init__(params, 12 | TOKEN_COMMAND_DELETE, 13 | 'delete', *args, **kwargs) 14 | self.addressable = True 15 | self.target_command = 'ex_delete' 16 | 17 | @property 18 | def register(self): 19 | return self.params['register'] 20 | 21 | @property 22 | def count(self): 23 | return self.params['count'] 24 | 25 | 26 | def scan_command_delete(state): 27 | params = { 28 | 'register': '"', 29 | 'count': None, 30 | } 31 | 32 | state.skip(' ') 33 | state.ignore() 34 | 35 | c = state.consume() 36 | 37 | if c == EOF: 38 | return None, [TokenDelete(params), TokenEof()] 39 | 40 | state.backup() 41 | state.skip(' ') 42 | state.ignore() 43 | 44 | m = state.expect_match(r'(?P[a-zA-Z0-9"])(?:\s+(?P\d+))?\s*$') 45 | params.update(m.groupdict()) 46 | 47 | if params ['count']: 48 | raise NotImplementedError('parameter not implemented') 49 | 50 | return None, [TokenDelete(params), TokenEof()] 51 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_double_ampersand.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_DOUBLE_AMPERSAND 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('&&', '&&') 9 | class TokenDoubleAmpersand(TokenOfCommand): 10 | def __init__(self, params, *args, **kwargs): 11 | super().__init__(params, 12 | TOKEN_COMMAND_DOUBLE_AMPERSAND, 13 | '&&', *args, **kwargs) 14 | self.addressable = True 15 | self.target_command = 'ex_double_ampersand' 16 | 17 | 18 | def scan_command_double_ampersand(state): 19 | params = { 20 | 'flags': [], 21 | 'count': '', 22 | } 23 | 24 | m = state.match(r'\s*([cgr])*\s*(\d*)\s*$') 25 | params['flags'] = list(m.group(1)) if m.group(1) else [] 26 | params['count'] = m.group(2) or '' 27 | 28 | state.expect(EOF) 29 | 30 | return None, [TokenDoubleAmpersand(params), TokenEof()] 31 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_exit.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_EXIT 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('exit', 'exi') 9 | @ex.command('xit', 'x') 10 | class TokenCommandExit(TokenOfCommand): 11 | def __init__(self, params, *args, **kwargs): 12 | super().__init__(params, 13 | TOKEN_COMMAND_EXIT, 14 | 'exit', *args, **kwargs) 15 | self.addressable = True 16 | self.target_command = 'ex_exit' 17 | 18 | 19 | def scan_command_exit(state): 20 | params = { 21 | 'file_name': '', 22 | } 23 | 24 | bang = state.consume() 25 | 26 | if bang == EOF: 27 | return None, [TokenCommandExit(params), TokenEof()] 28 | 29 | bang = bang == '!' 30 | if not bang: 31 | state.backup() 32 | 33 | state.skip(' ') 34 | state.ignore() 35 | 36 | while True: 37 | c = state.consume() 38 | 39 | if c == EOF: 40 | return None, [TokenCommandExit(params, forced=bang), TokenEof()] 41 | 42 | if c == '+': 43 | state.expect('+') 44 | state.ignore() 45 | # TODO: expect_match should work with emit() 46 | # http://vimdoc.sourceforge.net/htmldoc/editing.html#[++opt] 47 | m = state.expect_match( 48 | r'(?:f(?:ile)?f(?:ormat)?|(?:file)?enc(?:oding)?|(?:no)?bin(?:ary)?|bad|edit)(?=\s|$)', 49 | lambda: VimError(ERR_INVALID_ARGUMENT)) 50 | name = m.group(0) 51 | params['++'] = plus_plus_translations.get(name, name) 52 | state.ignore() 53 | continue 54 | 55 | if c != ' ': 56 | state.match(r'.*') 57 | params['file_name'] = state.emit().strip() 58 | state.skip(' ') 59 | state.ignore() 60 | 61 | state.expect(EOF) 62 | return None, [TokenCommandExit (params, forced=bang == '!'), TokenEof ()] -------------------------------------------------------------------------------- /ex/parser/scanner_command_file.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_FILE 4 | from .tokens_base import TokenOfCommand 5 | 6 | from Vintageous.ex.ex_error import ERR_TRAILING_CHARS 7 | from Vintageous.ex.ex_error import VimError 8 | from Vintageous import ex 9 | 10 | 11 | @ex.command('file', 'f') 12 | class TokenCommandFile(TokenOfCommand): 13 | def __init__(self, *args, **kwargs): 14 | super().__init__({}, 15 | TOKEN_COMMAND_FILE, 16 | 'file', *args, **kwargs) 17 | self.target_command = 'ex_file' 18 | 19 | 20 | def scan_command_file(state): 21 | bang = state.consume() 22 | 23 | if bang == EOF: 24 | return None, [TokenCommandFile(), TokenEof()] 25 | 26 | bang = bang == '!' 27 | if not bang: 28 | raise VimError(ERR_TRAILING_CHARS) 29 | 30 | state.expect(EOF, on_error=lambda: VimError(ERR_TRAILING_CHARS)) 31 | 32 | return None, [TokenCommandFile (forced=bang == '!'), TokenEof ()] 33 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_global.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_GLOBAL 4 | from .tokens_base import TokenOfCommand 5 | from .parser import parse_command_line 6 | from Vintageous import ex 7 | 8 | 9 | @ex.command('global', 'g') 10 | class TokenCommandGlobal(TokenOfCommand): 11 | def __init__(self, params, *args, **kwargs): 12 | super().__init__(params, 13 | TOKEN_COMMAND_GLOBAL, 14 | 'global', *args, **kwargs) 15 | self.addressable = True 16 | self.target_command = 'ex_global' 17 | 18 | @property 19 | def pattern(self): 20 | return self.params['pattern'] 21 | 22 | @property 23 | def subcommand(self): 24 | return self.params['subcommand'] 25 | 26 | 27 | def scan_command_global(state): 28 | params = { 29 | 'pattern': None, 30 | 'subcommand': parse_command_line('print').command 31 | } 32 | 33 | c = state.consume() 34 | 35 | bang = c == '!' 36 | sep = c if not bang else c.consume() 37 | # TODO: we're probably missing legal separators. 38 | assert c in '!:?/\\&$', 'bad separator' 39 | 40 | state.ignore() 41 | 42 | while True: 43 | c = state.consume() 44 | 45 | if c == EOF: 46 | raise ValueError('unexpected EOF in: ' + state.source) 47 | 48 | if c == sep: 49 | state.backup() 50 | params['pattern'] = state.emit() 51 | state.consume() 52 | state.ignore() 53 | break 54 | 55 | command = state.match(r'.*$').group(0).strip() 56 | command = parse_command_line(command).command or params['subcommand'] 57 | params['subcommand'] = command 58 | 59 | return None, [TokenCommandGlobal(params, forced=bang), TokenEof()] 60 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_goto.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_GOTO 4 | from .tokens_base import TokenOfCommand 5 | 6 | 7 | # This command cannot be scanned; it's the default command when no command is 8 | # named. 9 | class TokenCommandGoto(TokenOfCommand): 10 | def __init__(self, *args, **kwargs): 11 | super().__init__([], 12 | TOKEN_COMMAND_GOTO, 13 | 'goto', *args, **kwargs) 14 | self.target_command = 'ex_goto' 15 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_let.py: -------------------------------------------------------------------------------- 1 | from Vintageous.ex.ex_error import ERR_UNDEFINED_VARIABLE 2 | from Vintageous.ex.ex_error import VimError 3 | 4 | from .state import EOF 5 | from .tokens import TokenEof 6 | from .tokens_base import TOKEN_COMMAND_LET 7 | from .tokens_base import TokenOfCommand 8 | from Vintageous import ex 9 | 10 | 11 | @ex.command('let', 'let') 12 | class TokenCommandLet(TokenOfCommand): 13 | def __init__(self, params, *args, **kwargs): 14 | super().__init__(params, 15 | TOKEN_COMMAND_LET, 16 | 'let', *args, **kwargs) 17 | self.target_command = 'ex_let' 18 | 19 | @property 20 | def variable_name(self): 21 | return self.params['name'] 22 | 23 | @property 24 | def variable_value(self): 25 | return self.params['value'] 26 | 27 | 28 | def scan_command_let(state): 29 | params = { 30 | 'name': None, 31 | 'value': None, 32 | } 33 | 34 | # TODO(guillermooo): :let has many more options. 35 | 36 | m = state.expect_match(r'(?P.+?)\s*=\s*(?P.+?)\s*$', 37 | on_error=lambda: VimError(ERR_UNDEFINED_VARIABLE)) 38 | 39 | params.update(m.groupdict()) 40 | 41 | return None, [TokenCommandLet(params), TokenEof()] 42 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_map.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_MAP 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('map', 'map') 9 | class TokenCommandMap(TokenOfCommand): 10 | def __init__(self, params, *args, **kwargs): 11 | super().__init__(params, 12 | TOKEN_COMMAND_MAP, 13 | 'map', *args, **kwargs) 14 | self.target_command = 'ex_map' 15 | 16 | @property 17 | def keys(self): 18 | return self.params['keys'] 19 | 20 | @property 21 | def command(self): 22 | return self.params['command'] 23 | 24 | 25 | def scan_command_map(state): 26 | params = { 27 | 'keys': None, 28 | 'command': None, 29 | } 30 | 31 | m = state.match(r'\s*(?P.+?)\s+(?P.+?)\s*$') 32 | 33 | if m: 34 | params.update(m.groupdict()) 35 | 36 | return None, [TokenCommandMap(params), TokenEof()] 37 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_move.py: -------------------------------------------------------------------------------- 1 | from .parser import parse_command_line 2 | from .state import EOF 3 | from .tokens import TokenEof 4 | from .tokens_base import TOKEN_COMMAND_MOVE 5 | from .tokens_base import TokenOfCommand 6 | from Vintageous import ex 7 | 8 | 9 | @ex.command('move', 'm') 10 | class TokenMove(TokenOfCommand): 11 | def __init__(self, params, *args, **kwargs): 12 | super().__init__(params, 13 | TOKEN_COMMAND_MOVE, 14 | 'move', *args, **kwargs) 15 | self.addressable = True 16 | self.target_command = 'ex_move' 17 | 18 | @property 19 | def address(self): 20 | return self.params['address'] 21 | 22 | 23 | def scan_command_move(state): 24 | params = { 25 | 'address': None 26 | } 27 | 28 | state.skip (' ') 29 | state.ignore() 30 | 31 | m = state.match(r'(?P
.*$)') 32 | if m: 33 | address_command_line = m.group(0).strip() or '.' 34 | params['address'] = parse_command_line(address_command_line).line_range 35 | 36 | return None, [TokenMove(params), TokenEof()] 37 | 38 | 39 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_new.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_NEW 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | plus_plus_translations = { 9 | 'ff': 'fileformat', 10 | 'bin': 'binary', 11 | 'enc': 'fileencoding', 12 | 'nobin': 'nobinary', 13 | } 14 | 15 | 16 | @ex.command('new', 'new') 17 | class TokenNew(TokenOfCommand): 18 | def __init__(self, params, *args, **kwargs): 19 | super().__init__(params, 20 | TOKEN_COMMAND_NEW, 21 | 'new', *args, **kwargs) 22 | self.target_command = 'ex_new' 23 | 24 | 25 | def scan_command_new(state): 26 | params = { 27 | '++': None, 28 | 'cmd': None, 29 | } 30 | state.skip(' ') 31 | state.ignore() 32 | 33 | c = state.consume() 34 | 35 | if c == '+': 36 | state.expect('+') 37 | state.ignore() 38 | # TODO: expect_match should work with emit() 39 | # http://vimdoc.sourceforge.net/htmldoc/editing.html#[++opt] 40 | m = state.expect_match( 41 | r'(?:f(?:ile)?f(?:ormat)?|(?:file)?enc(?:oding)?|(?:no)?bin(?:ary)?|bad|edit)(?=\s|$)', 42 | lambda: VimError(ERR_INVALID_ARGUMENT)) 43 | name = m.group(0) 44 | params['++'] = plus_plus_translations.get(name, name) 45 | state.ignore() 46 | raise NotImplementedError(':new not fully implemented') 47 | 48 | m = state.match(r'.+$') 49 | if m: 50 | params ['cmd'] = m.group(0).strip() 51 | raise NotImplementedError(':new not fully implemented') 52 | 53 | return None, [TokenNew(params), TokenEof()] 54 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_nmap.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_NMAP 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('nmap', 'nm') 9 | class TokenCommandNmap(TokenOfCommand): 10 | def __init__(self, params, *args, **kwargs): 11 | super().__init__(params, 12 | TOKEN_COMMAND_NMAP, 13 | 'nmap', *args, **kwargs) 14 | self.target_command = 'ex_nmap' 15 | 16 | @property 17 | def keys(self): 18 | return self.params['keys'] 19 | 20 | @property 21 | def command(self): 22 | return self.params['command'] 23 | 24 | 25 | def scan_command_nmap(state): 26 | params = { 27 | 'keys': None, 28 | 'command': None, 29 | } 30 | 31 | m = state.match(r'\s*(?P.+?)\s+(?P.+?)\s*$') 32 | 33 | if m: 34 | params.update(m.groupdict()) 35 | 36 | return None, [TokenCommandNmap(params), TokenEof()] 37 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_nunmap.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_NUNMAP 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('nunmap', 'nun') 9 | class TokenCommandNunmap(TokenOfCommand): 10 | def __init__(self, params, *args, **kwargs): 11 | super().__init__(params, 12 | TOKEN_COMMAND_NUNMAP, 13 | 'nunmap', *args, **kwargs) 14 | self.target_command = 'ex_nunmap' 15 | 16 | @property 17 | def keys(self): 18 | return self.params['keys'] 19 | 20 | 21 | def scan_command_nunmap(state): 22 | params = { 23 | 'keys': None, 24 | } 25 | 26 | m = state.match(r'\s*(?P.+?)\s*$') 27 | 28 | if m: 29 | params.update(m.groupdict()) 30 | 31 | return None, [TokenCommandNunmap(params), TokenEof()] 32 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_omap.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_OMAP 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('omap', 'om') 9 | class TokenCommandOmap(TokenOfCommand): 10 | def __init__(self, params, *args, **kwargs): 11 | super().__init__(params, 12 | TOKEN_COMMAND_OMAP, 13 | 'omap', *args, **kwargs) 14 | self.target_command = 'ex_omap' 15 | 16 | @property 17 | def keys(self): 18 | return self.params['keys'] 19 | 20 | @property 21 | def command(self): 22 | return self.params['command'] 23 | 24 | 25 | def scan_command_omap(state): 26 | params = { 27 | 'keys': None, 28 | 'command': None, 29 | } 30 | 31 | m = state.match(r'\s*(?P.+?)\s+(?P.+?)\s*$') 32 | 33 | if m: 34 | params.update(m.groupdict()) 35 | 36 | return None, [TokenCommandOmap(params), TokenEof()] 37 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_only.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_ONLY 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('only', 'on') 9 | class TokenCommandOnly(TokenOfCommand): 10 | def __init__(self, *args, **kwargs): 11 | super().__init__({}, 12 | TOKEN_COMMAND_ONLY, 13 | 'only', *args, **kwargs) 14 | self.target_command = 'ex_only' 15 | 16 | 17 | def scan_command_only(state): 18 | bang = state.consume() 19 | 20 | if bang == '!': 21 | state.ignore() 22 | state.expect(EOF) 23 | return None, [TokenCommandOnly(forced=True), TokenEof()] 24 | 25 | assert bang == EOF, 'trailing characters' 26 | return None, [TokenCommandOnly(), TokenEof()] 27 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_ounmap.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_OUNMAP 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('ounmap', 'ounm') 9 | class TokenCommandOunmap(TokenOfCommand): 10 | def __init__(self, params, *args, **kwargs): 11 | super().__init__(params, 12 | TOKEN_COMMAND_OUNMAP, 13 | 'ounmap', *args, **kwargs) 14 | self.target_command = 'ex_ounmap' 15 | 16 | @property 17 | def keys(self): 18 | return self.params['keys'] 19 | 20 | 21 | def scan_command_ounmap(state): 22 | params = { 23 | 'keys': None, 24 | } 25 | 26 | m = state.match(r'\s*(?P.+?)\s*$') 27 | 28 | if m: 29 | params.update(m.groupdict()) 30 | 31 | return None, [TokenCommandOunmap(params), TokenEof()] 32 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_print.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_PRINT 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('print', 'p') 9 | class TokenCommandPrint(TokenOfCommand): 10 | def __init__(self, params, *args, **kwargs): 11 | super().__init__(params, 12 | TOKEN_COMMAND_PRINT, 13 | 'print', *args, **kwargs) 14 | self.addressable = True 15 | self.cooperates_with_global = True 16 | self.target_command = 'ex_print' 17 | 18 | def __str__(self): 19 | return "{0} {1} {2}".format(self.content, ''.join(self.flags), self.count).strip() 20 | 21 | @property 22 | def count(self): 23 | return self.params['count'] 24 | 25 | @property 26 | def flags(self): 27 | return self.params['flags'] 28 | 29 | 30 | def scan_command_print(state): 31 | params = { 32 | 'count': '', 33 | 'flags': [], 34 | } 35 | 36 | while True: 37 | c = state.consume() 38 | 39 | state.skip(' ') 40 | state.ignore() 41 | 42 | if c == EOF: 43 | return None, [TokenCommandPrint(params), TokenEof()] 44 | 45 | if c.isdigit(): 46 | state.match(r'\d*') 47 | params['count'] = state.emit() 48 | continue 49 | 50 | m = state.expect_match(r'[l#p]+') 51 | params['flags'] = list(m.group(0)) 52 | state.ignore() 53 | state.expect(EOF) 54 | break 55 | 56 | return None, [TokenCommandPrint(params), TokenEof()] 57 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_print_working_dir.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_PRINT_WORKING_DIR 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('pwd', 'pwd') 9 | class TokenPrintWorkingDir(TokenOfCommand): 10 | def __init__(self, *args, **kwargs): 11 | super().__init__({}, 12 | TOKEN_COMMAND_PRINT_WORKING_DIR, 13 | 'pwd', *args, **kwargs) 14 | self.target_command = 'ex_print_working_dir' 15 | 16 | 17 | def scan_command_print_working_dir(state): 18 | state.expect(EOF) 19 | return None, [TokenPrintWorkingDir(), TokenEof()] 20 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_quit_all_command.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_QUIT_ALL_COMMAND 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('quall', 'qa') 9 | class TokenQuitAllCommand(TokenOfCommand): 10 | def __init__(self, *args, **kwargs): 11 | super().__init__({}, 12 | TOKEN_COMMAND_QUIT_ALL_COMMAND, 13 | 'qall', *args, **kwargs) 14 | self.target_command = 'ex_quit_all' 15 | 16 | 17 | def scan_command_quit_all_command(state): 18 | c = state.consume() 19 | 20 | bang = c == '!' 21 | 22 | state.expect(EOF) 23 | 24 | return None, [TokenQuitAllCommand(forced=bang), TokenEof()] 25 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_quit_command.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_QUIT_COMMAND 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('quit', 'q') 9 | class TokenQuitCommand(TokenOfCommand): 10 | def __init__(self, *args, **kwargs): 11 | super().__init__({}, 12 | TOKEN_COMMAND_QUIT_COMMAND, 13 | 'quit', *args, **kwargs) 14 | self.target_command = 'ex_quit' 15 | 16 | 17 | def scan_command_quit_command(state): 18 | c = state.consume() 19 | 20 | bang = c == '!' 21 | 22 | state.expect(EOF) 23 | 24 | return None, [TokenQuitCommand(forced=bang), TokenEof()] 25 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_register.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_REGISTERS 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('registers', 'reg') 9 | class TokenCommandRegisters(TokenOfCommand): 10 | def __init__(self, params, *args, **kwargs): 11 | super().__init__(params, 12 | TOKEN_COMMAND_REGISTERS, 13 | 'registers', *args, **kwargs) 14 | self.target_command = 'ex_list_registers' 15 | 16 | 17 | def scan_command_register(state): 18 | state.skip(' ') 19 | state.ignore() 20 | 21 | params = { 22 | 'names': [] 23 | } 24 | 25 | while True: 26 | c = state.consume() 27 | 28 | if c == EOF: 29 | return None, [TokenCommandRegisters(params), TokenEof()] 30 | 31 | elif c.isalpha() or c.isdigit(): 32 | params['names'].append(c) 33 | 34 | else: 35 | raise ValueError('wrong arguments') 36 | -------------------------------------------------------------------------------- /ex/parser/scanner_command_set.py: -------------------------------------------------------------------------------- 1 | from .state import EOF 2 | from .tokens import TokenEof 3 | from .tokens_base import TOKEN_COMMAND_SET 4 | from .tokens_base import TokenOfCommand 5 | from Vintageous import ex 6 | 7 | 8 | @ex.command('set', 'set') 9 | class TokenSet(TokenOfCommand): 10 | def __init__(self, params, *args, **kwargs): 11 | super().__init__(params, 12 | TOKEN_COMMAND_SET, 13 | 'set', *args, **kwargs) 14 | self.target_command = 'ex_set' 15 | 16 | @property 17 | def value(self): 18 | return self.params ['value'] 19 | 20 | @property 21 | def option(self): 22 | return self.params ['option'] 23 | 24 | 25 | def scan_command_set(state): 26 | params = { 27 | 'option': None, 28 | 'value': None, 29 | } 30 | 31 | state.skip(' ') 32 | state.ignore() 33 | 34 | # TODO(guillermooo): implement other options. 35 | m = state.expect_match(r'(?P