diff --git a/autoload/conque_term.vim b/autoload/conque_term.vim deleted file mode 100644 index 856b97b..0000000 --- a/autoload/conque_term.vim +++ /dev/null @@ -1,1504 +0,0 @@ -" FILE: autoload/conque_term.vim {{{ -" AUTHOR: Nico Raffo -" WEBSITE: http://conque.googlecode.com -" MODIFIED: 2011-08-12 -" VERSION: 2.2, for Vim 7.0 -" LICENSE: -" Conque - Vim terminal/console emulator -" Copyright (C) 2009-__YEAR__ Nico Raffo -" -" MIT License -" -" 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: -" -" The above copyright notice and this permission notice shall be included in -" all copies or substantial portions of the Software. -" -" 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. -" }}} - -" ********************************************************************************************************** -" **** GLOBAL INITIALIZATION ******************************************************************************* -" ********************************************************************************************************** - -" {{{ - -" load plugin file if it hasn't already been loaded (e.g. conque_term#foo() is used in .vimrc) -if !exists('g:ConqueTerm_Loaded') - runtime! plugin/conque_term.vim -endif - -" path to conque install directories -let s:scriptdir = expand(":h") . '/' -let s:scriptdirpy = expand(":h") . '/conque_term/' - -" global list of terminal instances -let s:term_obj = {'idx': 1, 'var': '', 'is_buffer': 1, 'active': 1, 'buffer_name': '', 'command': ''} -let g:ConqueTerm_Terminals = {} - -" global lists of registered functions -let s:hooks = { 'after_startup': [], 'buffer_enter': [], 'buffer_leave': [], 'after_keymap': [] } - -" required for session support -if g:ConqueTerm_SessionSupport == 1 - set sessionoptions+=globals - try - sil! let s:saved_terminals = eval(g:ConqueTerm_TerminalsString) - catch - let s:saved_terminals = {} - endtry -endif - -" more session support -let g:ConqueTerm_TerminalsString = '' - -" init terminal counter -let g:ConqueTerm_Idx = 0 - -" we clobber this value later -let s:save_updatetime = &updatetime - -" have we called the init() function yet? -let s:initialized = 0 - - -" }}} - -" ********************************************************************************************************** -" **** SYSTEM DETECTION ************************************************************************************ -" ********************************************************************************************************** - -" {{{ - -" Display various error messages -function! conque_term#fail(feature) " {{{ - - " create a new buffer - new - setlocal buftype=nofile - setlocal nonumber - setlocal foldcolumn=0 - setlocal wrap - setlocal noswapfile - - " missing vim features - if a:feature == 'python' - - call append('$', 'Conque ERROR: Python interface cannot be loaded') - call append('$', '') - - if !executable("python") - call append('$', 'Your version of Vim appears to be installed without the Python interface. In ') - call append('$', 'addition, you may need to install Python.') - else - call append('$', 'Your version of Vim appears to be installed without the Python interface.') - endif - - call append('$', '') - - if has('unix') == 1 - call append('$', "You are using a Unix-like operating system. Most, if not all, of the popular ") - call append('$', "Linux package managers have Python-enabled Vim available. For example ") - call append('$', "vim-gnome or vim-gtk on Ubuntu will get you everything you need.") - call append('$', "") - call append('$', "If you are compiling Vim from source, make sure you use the --enable-pythoninterp ") - call append('$', "configure option. You will also need to install Python and the Python headers.") - call append('$', "") - call append('$', "If you are using OS X, MacVim will give you Python support by default.") - else - call append('$', "You appear to be using Windows. The official Vim 7.3 installer available at ") - call append('$', "http://www.vim.org comes with the required Python interfaces. You will also ") - call append('$', "need to install Python 2.7 and/or Python 3.1, both available at http://www.python.org") - endif - - elseif a:feature == 'python_exe' - - call append('$', "Conque ERROR: Can't find Python executable") - call append('$', "") - call append('$', "Conque needs to know the full path to python.exe on Windows systems. By default, ") - call append('$', "Conque will check your system path as well as the most common installation path ") - call append('$', "C:\\PythonXX\\python.exe. To fix this error either:") - call append('$', "") - call append('$', "Set the g:ConqueTerm_PyExe option in your .vimrc. E.g.") - call append('$', " let g:ConqueTerm_PyExe = 'C:\Program Files\Python27\python.exe'") - call append('$', "") - call append('$', "Add the directory where you installed python to your system path. This isn't a bad ") - call append('$', "idea in general.") - - elseif a:feature == 'ctypes' - - call append('$', 'Conque ERROR: Python cannot load the ctypes module') - call append('$', "") - call append('$', "Conque requires the 'ctypes' python module. This has been a standard module since Python 2.5.") - call append('$', "") - call append('$', "The recommended fix is to make sure you're using the latest official GVim version 7.3, ") - call append('$', "and have at least one of the two compatible versions of Python installed, ") - call append('$', "2.7 or 3.1. You can download the GVim 7.3 installer from http://www.vim.org. You ") - call append('$', "can download the Python 2.7 or 3.1 installer from http://www.python.org") - - endif - -endfunction " }}} - -" Go through various system checks before attempting to launch conque -function! conque_term#dependency_check() " {{{ - - " don't recheck the second time 'round - if s:initialized == 1 - return 1 - endif - - " choose a python version - let s:py = '' - if g:ConqueTerm_PyVersion == 3 - let pytest = 'python3' - else - let pytest = 'python' - let g:ConqueTerm_PyVersion = 2 - endif - - " first test the requested version - if has(pytest) - if pytest == 'python3' - let s:py = 'py3' - else - let s:py = 'py' - endif - - " otherwise use the other version - else - let py_alternate = 5 - g:ConqueTerm_PyVersion - if py_alternate == 3 - let pytest = 'python3' - else - let pytest = 'python' - endif - if has(pytest) - echohl WarningMsg | echomsg "Python " . g:ConqueTerm_PyVersion . " interface is not installed, using Python " . py_alternate . " instead" | echohl None - let g:ConqueTerm_PyVersion = py_alternate - if pytest == 'python3' - let s:py = 'py3' - else - let s:py = 'py' - endif - endif - endif - - " test if we actually found a python version - if s:py == '' - call conque_term#fail('python') - return 0 - endif - - " quick and dirty platform declaration - if has('unix') == 1 - let s:platform = 'unix' - sil exe s:py . " CONQUE_PLATFORM = 'unix'" - else - let s:platform = 'windows' - sil exe s:py . " CONQUE_PLATFORM = 'windows'" - endif - - " if we're using Windows, make sure ctypes is available - if s:platform == 'windows' - try - sil exe s:py . " import ctypes" - catch - call conque_term#fail('ctypes') - return 0 - endtry - endif - - " if we're using Windows, make sure we can finde python executable - if s:platform == 'windows' && conque_term#find_python_exe() == '' - call conque_term#fail('python_exe') - return 0 - endif - - " check for global cursorhold/cursormove events - let o = '' - silent redir => o - silent autocmd CursorHoldI,CursorMovedI - redir END - for line in split(o, "\n") - if line =~ '^ ' || line =~ '^--' || line =~ 'matchparen' - continue - endif - if g:ConqueTerm_StartMessages - echohl WarningMsg | echomsg "Warning: Global CursorHoldI and CursorMovedI autocommands may cause ConqueTerm to run slowly." | echohl None - endif - endfor - - " check for compatible mode - if &compatible == 1 - echohl WarningMsg | echomsg "Warning: Conque may not function normally in 'compatible' mode." | echohl None - endif - - " check for fast mode - if g:ConqueTerm_FastMode - sil exe s:py . " CONQUE_FAST_MODE = True" - else - sil exe s:py . " CONQUE_FAST_MODE = False" - endif - - " if we're all good, load python files - call conque_term#load_python() - - return 1 - -endfunction " }}} - -" }}} - -" ********************************************************************************************************** -" **** STARTUP MESSAGES ************************************************************************************ -" ********************************************************************************************************** - -" {{{ -"if g:ConqueTerm_StartMessages -" let msg_file = s:scriptdirpy . 'version.vim' -" let msg_show = 1 -" let msg_ct = 1 -" -" " we can write to conque_term directory -" if filewritable(s:scriptdirpy) == 2 -" -" if filewritable(msg_file) -" -" " read current message file -" try -" silent execute "source " . msg_file -" if exists('g:ConqueTerm_MsgCt') && exists('g:ConqueTerm_MsgVer') -" if g:ConqueTerm_MsgVer == g:ConqueTerm_Version && g:ConqueTerm_MsgCt > 2 -" let msg_show = 0 -" else -" let msg_ct = g:ConqueTerm_MsgCt + 1 -" endif -" endif -" catch -" endtry -" endif -" -" " update message file -" if msg_show -" let file_contents = ['let g:ConqueTerm_MsgCt = ' . msg_ct, 'let g:ConqueTerm_MsgVer = ' . g:ConqueTerm_Version] -" call writefile(file_contents, msg_file) -" endif -" endif -" -" " save our final decision -" let g:ConqueTerm_StartMessages = msg_show -"endif -" }}} - -" ********************************************************************************************************** -" **** WINDOWS VK CODES ************************************************************************************ -" ********************************************************************************************************** - -" Windows Virtual Key Codes {{{ -let s:windows_vk = { -\ 'VK_ADD' : 107, -\ 'VK_APPS' : 93, -\ 'VK_ATTN' : 246, -\ 'VK_BACK' : 8, -\ 'VK_BROWSER_BACK' : 166, -\ 'VK_BROWSER_FORWARD' : 167, -\ 'VK_CANCEL' : 3, -\ 'VK_CAPITAL' : 20, -\ 'VK_CLEAR' : 12, -\ 'VK_CONTROL' : 17, -\ 'VK_CONVERT' : 28, -\ 'VK_CRSEL' : 247, -\ 'VK_DECIMAL' : 110, -\ 'VK_DELETE' : 46, -\ 'VK_DIVIDE' : 111, -\ 'VK_DOWN' : 40, -\ 'VK_DOWN_CTL' : '40;1024', -\ 'VK_END' : 35, -\ 'VK_EREOF' : 249, -\ 'VK_ESCAPE' : 27, -\ 'VK_EXECUTE' : 43, -\ 'VK_EXSEL' : 248, -\ 'VK_F1' : 112, -\ 'VK_F10' : 121, -\ 'VK_F11' : 122, -\ 'VK_F12' : 123, -\ 'VK_F13' : 124, -\ 'VK_F14' : 125, -\ 'VK_F15' : 126, -\ 'VK_F16' : 127, -\ 'VK_F17' : 128, -\ 'VK_F18' : 129, -\ 'VK_F19' : 130, -\ 'VK_F2' : 113, -\ 'VK_F20' : 131, -\ 'VK_F21' : 132, -\ 'VK_F22' : 133, -\ 'VK_F23' : 134, -\ 'VK_F24' : 135, -\ 'VK_F3' : 114, -\ 'VK_F4' : 115, -\ 'VK_F5' : 116, -\ 'VK_F6' : 117, -\ 'VK_F7' : 118, -\ 'VK_F8' : 119, -\ 'VK_F9' : 120, -\ 'VK_FINAL' : 24, -\ 'VK_HANGEUL' : 21, -\ 'VK_HANGUL' : 21, -\ 'VK_HANJA' : 25, -\ 'VK_HELP' : 47, -\ 'VK_HOME' : 36, -\ 'VK_INSERT' : 45, -\ 'VK_JUNJA' : 23, -\ 'VK_KANA' : 21, -\ 'VK_KANJI' : 25, -\ 'VK_LBUTTON' : 1, -\ 'VK_LCONTROL' : 162, -\ 'VK_LEFT' : 37, -\ 'VK_LEFT_CTL' : '37;1024', -\ 'VK_LMENU' : 164, -\ 'VK_LSHIFT' : 160, -\ 'VK_LWIN' : 91, -\ 'VK_MBUTTON' : 4, -\ 'VK_MEDIA_NEXT_TRACK' : 176, -\ 'VK_MEDIA_PLAY_PAUSE' : 179, -\ 'VK_MEDIA_PREV_TRACK' : 177, -\ 'VK_MENU' : 18, -\ 'VK_MODECHANGE' : 31, -\ 'VK_MULTIPLY' : 106, -\ 'VK_NEXT' : 34, -\ 'VK_NONAME' : 252, -\ 'VK_NONCONVERT' : 29, -\ 'VK_NUMLOCK' : 144, -\ 'VK_NUMPAD0' : 96, -\ 'VK_NUMPAD1' : 97, -\ 'VK_NUMPAD2' : 98, -\ 'VK_NUMPAD3' : 99, -\ 'VK_NUMPAD4' : 100, -\ 'VK_NUMPAD5' : 101, -\ 'VK_NUMPAD6' : 102, -\ 'VK_NUMPAD7' : 103, -\ 'VK_NUMPAD8' : 104, -\ 'VK_NUMPAD9' : 105, -\ 'VK_OEM_CLEAR' : 254, -\ 'VK_PA1' : 253, -\ 'VK_PAUSE' : 19, -\ 'VK_PLAY' : 250, -\ 'VK_PRINT' : 42, -\ 'VK_PRIOR' : 33, -\ 'VK_PROCESSKEY' : 229, -\ 'VK_RBUTTON' : 2, -\ 'VK_RCONTROL' : 163, -\ 'VK_RETURN' : 13, -\ 'VK_RIGHT' : 39, -\ 'VK_RIGHT_CTL' : '39;1024', -\ 'VK_RMENU' : 165, -\ 'VK_RSHIFT' : 161, -\ 'VK_RWIN' : 92, -\ 'VK_SCROLL' : 145, -\ 'VK_SELECT' : 41, -\ 'VK_SEPARATOR' : 108, -\ 'VK_SHIFT' : 16, -\ 'VK_SNAPSHOT' : 44, -\ 'VK_SPACE' : 32, -\ 'VK_SUBTRACT' : 109, -\ 'VK_TAB' : 9, -\ 'VK_UP' : 38, -\ 'VK_UP_CTL' : '38;1024', -\ 'VK_VOLUME_DOWN' : 174, -\ 'VK_VOLUME_MUTE' : 173, -\ 'VK_VOLUME_UP' : 175, -\ 'VK_XBUTTON1' : 5, -\ 'VK_XBUTTON2' : 6, -\ 'VK_ZOOM' : 251 -\ } -" }}} - -" ********************************************************************************************************** -" **** ACTUAL CONQUE FUNCTIONS! *************************************************************************** -" ********************************************************************************************************** - -" {{{ - -" launch conque -function! conque_term#open(...) "{{{ - let command = get(a:000, 0, '') - let vim_startup_commands = get(a:000, 1, []) - let return_to_current = get(a:000, 2, 0) - let is_buffer = get(a:000, 3, 1) - - " dependency check - if !conque_term#dependency_check() - return 0 - endif - - " switch to buffer if needed - if is_buffer && return_to_current - let save_sb = &switchbuf - sil set switchbuf=usetab - let current_buffer = bufname("%") - endif - - " bare minimum validation - if s:py == '' - echohl WarningMsg | echomsg "Conque requires the Python interface to be installed. See :help ConqueTerm for more information." | echohl None - return 0 - endif - if empty(command) - echohl WarningMsg | echomsg "Invalid usage: no program path given. Use :ConqueTerm YOUR PROGRAM, e.g. :ConqueTerm ipython" | echohl None - return 0 - else - let cmd_args = split(command, '[^\\]\@<=\s') - let cmd_args[0] = substitute(cmd_args[0], '\\ ', ' ', 'g') - if !executable(cmd_args[0]) - echohl WarningMsg | echomsg "Not an executable: " . cmd_args[0] | echohl None - return 0 - endif - endif - - " initialize global identifiers - let g:ConqueTerm_Idx += 1 - let g:ConqueTerm_Var = 'ConqueTerm_' . g:ConqueTerm_Idx - let g:ConqueTerm_BufName = substitute(command, ' ', '\\ ', 'g') . "\\ -\\ " . g:ConqueTerm_Idx - - " initialize global mappings if needed - call conque_term#init() - - " set Vim buffer window options - if is_buffer - call conque_term#set_buffer_settings(command, vim_startup_commands) - - let b:ConqueTerm_Idx = g:ConqueTerm_Idx - let b:ConqueTerm_Var = g:ConqueTerm_Var - endif - - " save terminal instance - let t_obj = conque_term#create_terminal_object(g:ConqueTerm_Idx, is_buffer, g:ConqueTerm_BufName, command) - let g:ConqueTerm_Terminals[g:ConqueTerm_Idx] = t_obj - - " required for session support - let g:ConqueTerm_TerminalsString = string(g:ConqueTerm_Terminals) - - " open command - try - let options = {} - let options["TERM"] = g:ConqueTerm_TERM - let options["CODE_PAGE"] = g:ConqueTerm_CodePage - let options["color"] = g:ConqueTerm_Color - let options["offset"] = 0 " g:ConqueTerm_StartMessages * 10 - - if s:platform == 'unix' - execute s:py . ' ' . g:ConqueTerm_Var . ' = Conque()' - execute s:py . ' ' . g:ConqueTerm_Var . ".open()" - else - " find python.exe and communicator - let py_exe = conque_term#find_python_exe() - let py_vim = s:scriptdirpy . 'conque_sole_communicator.py' - execute s:py . ' ' . g:ConqueTerm_Var . ' = ConqueSole()' - execute s:py . ' ' . g:ConqueTerm_Var . ".open()" - - if g:ConqueTerm_ColorMode == 'conceal' - call conque_term#init_conceal_color() - endif - endif - catch - echohl WarningMsg | echomsg "An error occurred: " . command | echohl None - return 0 - endtry - - " set key mappings and auto commands - if is_buffer - call conque_term#set_mappings('start') - endif - - " call user defined functions - call conque_term#call_hooks('after_startup', t_obj) - - " switch to buffer if needed - if is_buffer && return_to_current - sil exe ":sb " . current_buffer - sil exe ":set switchbuf=" . save_sb - elseif is_buffer - startinsert! - endif - - return t_obj - -endfunction "}}} - -" open(), but no buffer -function! conque_term#subprocess(command) " {{{ - - let t_obj = conque_term#open(a:command, [], 0, 0) - if !exists('b:ConqueTerm_Var') - call conque_term#on_blur() - sil exe s:py . ' ' . g:ConqueTerm_Var . '.idle()' - endif - return t_obj - -endfunction " }}} - -" set buffer options -function! conque_term#set_buffer_settings(command, vim_startup_commands) "{{{ - - " optional hooks to execute, e.g. 'split' - for h in a:vim_startup_commands - sil exe h - endfor - sil exe 'edit ++enc=utf-8 ' . g:ConqueTerm_BufName - - " buffer settings - setlocal fileencoding=utf-8 " file encoding, even tho there's no file - setlocal nopaste " conque won't work in paste mode - setlocal buftype=nofile " this buffer is not a file, you can't save it - setlocal nonumber " hide line numbers - if v:version >= 703 - setlocal norelativenumber " hide relative line numbers (VIM >= 7.3) - endif - setlocal foldcolumn=0 " reasonable left margin - setlocal nowrap " default to no wrap (esp with MySQL) - setlocal noswapfile " don't bother creating a .swp file - setlocal scrolloff=0 " don't use buffer lines. it makes the 'clear' command not work as expected - setlocal sidescrolloff=0 " don't use buffer lines. it makes the 'clear' command not work as expected - setlocal sidescroll=1 " don't use buffer lines. it makes the 'clear' command not work as expected - setlocal foldmethod=manual " don't fold on {{{}}} and stuff - setlocal bufhidden=hide " when buffer is no longer displayed, don't wipe it out - setlocal noreadonly " this is not actually a readonly buffer - if v:version >= 703 - setlocal conceallevel=3 - setlocal concealcursor=nic - endif - if g:ConqueTerm_ReadUnfocused - set cpoptions+=I " Don't remove autoindent when moving cursor up and down - endif - setfiletype conque_term " useful - sil exe "setlocal syntax=" . g:ConqueTerm_Syntax - - " temporary global settings go in here - call conque_term#on_focus(1) - -endfunction " }}} - -" send normal character key press to terminal -function! conque_term#key_press() "{{{ - sil exe s:py . ' ' . b:ConqueTerm_Var . ".write_buffered_ord(" . char2nr(v:char) . ")" - sil let v:char = '' -endfunction " }}} - -" set key mappings and auto commands -function! conque_term#set_mappings(action) "{{{ - - " set action {{{ - if a:action == 'toggle' - if exists('b:conque_on') && b:conque_on == 1 - let l:action = 'stop' - echohl WarningMsg | echomsg "Terminal is paused" | echohl None - else - let l:action = 'start' - echohl WarningMsg | echomsg "Terminal is resumed" | echohl None - endif - else - let l:action = a:action - endif - - " if mappings are being removed, add 'un' - let map_modifier = 'nore' - if l:action == 'stop' - let map_modifier = 'un' - endif - " }}} - - " auto commands {{{ - if l:action == 'stop' - sil exe 'autocmd! ' . b:ConqueTerm_Var - - else - sil exe 'augroup ' . b:ConqueTerm_Var - - " handle unexpected closing of shell, passes HUP to parent and all child processes - sil exe 'autocmd ' . b:ConqueTerm_Var . ' BufUnload ' . s:py . ' ' . b:ConqueTerm_Var . '.close()' - - " check for resized/scrolled buffer when entering buffer - sil exe 'autocmd ' . b:ConqueTerm_Var . ' BufEnter ' . s:py . ' ' . b:ConqueTerm_Var . '.update_window_size()' - sil exe 'autocmd ' . b:ConqueTerm_Var . ' VimResized ' . s:py . ' ' . b:ConqueTerm_Var . '.update_window_size()' - - " set/reset updatetime on entering/exiting buffer - sil exe 'autocmd ' . b:ConqueTerm_Var . ' BufEnter call conque_term#on_focus()' - sil exe 'autocmd ' . b:ConqueTerm_Var . ' BufLeave call conque_term#on_blur()' - - " reposition cursor when going into insert mode - sil exe 'autocmd ' . b:ConqueTerm_Var . ' InsertEnter ' . s:py . ' ' . b:ConqueTerm_Var . '.insert_enter()' - - " poll for more output - sil exe 'autocmd ' . b:ConqueTerm_Var . ' CursorHoldI ' . s:py . ' ' . b:ConqueTerm_Var . '.auto_read()' - endif - " }}} - - " map ASCII 1-31 {{{ - for c in range(1, 31) - " - if c == 27 || c == 3 - continue - endif - if l:action == 'start' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_ord(' . c . ')' - else - sil exe 'i' . map_modifier . 'map ' - endif - endfor - " bonus mapping: send in normal mode to terminal as well for panic interrupts - if l:action == 'start' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_ord(3)' - sil exe 'n' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_ord(3)' - else - sil exe 'i' . map_modifier . 'map ' - sil exe 'n' . map_modifier . 'map ' - endif - - " leave insert mode - if !exists('g:ConqueTerm_EscKey') || g:ConqueTerm_EscKey == '' - " use to send to terminal - if l:action == 'start' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_ord(27)' - else - sil exe 'i' . map_modifier . 'map ' - endif - else - " use to send to terminal - if l:action == 'start' - sil exe 'i' . map_modifier . 'map ' . g:ConqueTerm_EscKey . ' ' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_ord(27)' - else - sil exe 'i' . map_modifier . 'map ' . g:ConqueTerm_EscKey - sil exe 'i' . map_modifier . 'map ' - endif - endif - - " Map in insert mode - if exists('g:ConqueTerm_CWInsert') && g:ConqueTerm_CWInsert == 1 - inoremap - endif - " }}} - - " map 33 and beyond {{{ - if exists('##InsertCharPre') && g:ConqueTerm_InsertCharPre == 1 - if l:action == 'start' - autocmd InsertCharPre call conque_term#key_press() - else - autocmd! InsertCharPre - endif - else - for i in range(33, 127) - " - if i == 124 - if l:action == 'start' - sil exe "i" . map_modifier . "map :" . s:py . ' ' . b:ConqueTerm_Var . ".write_ord(124)" - else - sil exe "i" . map_modifier . "map " - endif - continue - endif - if l:action == 'start' - sil exe "i" . map_modifier . "map " . nr2char(i) . " :" . s:py . ' ' . b:ConqueTerm_Var . ".write_ord(" . i . ")" - else - sil exe "i" . map_modifier . "map " . nr2char(i) - endif - endfor - endif - " }}} - - " Special keys {{{ - if l:action == 'start' - if s:platform == 'unix' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x08"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u(" "))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x08"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u(" "))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[A"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[B"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[C"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[D"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1bOH"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1bOF"))' - else - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x08"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u(" "))' - - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x08"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u(" "))' - - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_UP . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_DOWN . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_RIGHT . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_LEFT . ')' - - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk("' . s:windows_vk.VK_UP_CTL . '")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk("' . s:windows_vk.VK_DOWN_CTL . '")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk("' . s:windows_vk.VK_RIGHT_CTL . '")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk("' . s:windows_vk.VK_LEFT_CTL . '")' - - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_DELETE . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_HOME . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_END . ')' - endif - else - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - endif - " }}} - - " keys {{{ - if g:ConqueTerm_SendFunctionKeys - if l:action == 'start' - if s:platform == 'unix' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[11~"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[12~"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("1b[13~"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[14~"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[15~"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[17~"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[18~"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[19~"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[20~"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[21~"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[23~"))' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[24~"))' - else - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_F1 . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_F2 . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_F3 . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_F4 . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_F5 . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_F6 . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_F7 . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_F8 . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_F9 . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_F10 . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_F11 . ')' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_F12 . ')' - endif - else - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - endif - endif - " }}} - - " various global mappings {{{ - " don't overwrite existing mappings - if l:action == 'start' - if maparg(g:ConqueTerm_SendVisKey, 'v') == '' - sil exe 'v' . map_modifier . 'map ' . g:ConqueTerm_SendVisKey . ' :call conque_term#send_selected(visualmode())' - endif - if maparg(g:ConqueTerm_SendFileKey, 'n') == '' - sil exe 'n' . map_modifier . 'map ' . g:ConqueTerm_SendFileKey . ' :call conque_term#send_file()' - endif - endif - " }}} - - " remap paste keys {{{ - if l:action == 'start' - sil exe 'n' . map_modifier . 'map p :' . s:py . ' ' . b:ConqueTerm_Var . '.write_expr("@@")a' - sil exe 'n' . map_modifier . 'map P :' . s:py . ' ' . b:ConqueTerm_Var . '.write_expr("@@")a' - sil exe 'n' . map_modifier . 'map ]p :' . s:py . ' ' . b:ConqueTerm_Var . '.write_expr("@@")a' - sil exe 'n' . map_modifier . 'map [p :' . s:py . ' ' . b:ConqueTerm_Var . '.write_expr("@@")a' - else - sil exe 'n' . map_modifier . 'map p' - sil exe 'n' . map_modifier . 'map P' - sil exe 'n' . map_modifier . 'map ]p' - sil exe 'n' . map_modifier . 'map [p' - endif - if has('gui_running') == 1 - if l:action == 'start' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_expr("@+")a' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_expr("@+")a' - else - sil exe 'i' . map_modifier . 'map ' - sil exe 'i' . map_modifier . 'map ' - endif - endif - " }}} - - " disable other normal mode keys which insert text {{{ - if l:action == 'start' - sil exe 'n' . map_modifier . 'map r :echo "Replace mode disabled in shell."' - sil exe 'n' . map_modifier . 'map R :echo "Replace mode disabled in shell."' - sil exe 'n' . map_modifier . 'map c :echo "Change mode disabled in shell."' - sil exe 'n' . map_modifier . 'map C :echo "Change mode disabled in shell."' - sil exe 'n' . map_modifier . 'map s :echo "Change mode disabled in shell."' - sil exe 'n' . map_modifier . 'map S :echo "Change mode disabled in shell."' - else - sil exe 'n' . map_modifier . 'map r' - sil exe 'n' . map_modifier . 'map R' - sil exe 'n' . map_modifier . 'map c' - sil exe 'n' . map_modifier . 'map C' - sil exe 'n' . map_modifier . 'map s' - sil exe 'n' . map_modifier . 'map S' - endif - " }}} - - " set conque as on or off {{{ - if l:action == 'start' - let b:conque_on = 1 - else - let b:conque_on = 0 - endif - " }}} - - " map command to toggle terminal key mappings {{{ - if a:action == 'start' - sil exe 'nnoremap ' . g:ConqueTerm_ToggleKey . ' :call conque_term#set_mappings("toggle")' - endif - " }}} - - " call user defined functions - if l:action == 'start' - call conque_term#call_hooks('after_keymap', conque_term#get_instance()) - endif - -endfunction " }}} - -" Initialize global mappings. Should only be called once per Vim session -function! conque_term#init() " {{{ - - if s:initialized == 1 - return - endif - - augroup ConqueTerm - - " abort any remaining running terminals when Vim exits - autocmd ConqueTerm VimLeave * call conque_term#close_all() - - " read more output when this isn't the current buffer - if g:ConqueTerm_ReadUnfocused == 1 - autocmd ConqueTerm CursorHold * call conque_term#read_all(0) - endif - - let s:initialized = 1 - -endfunction " }}} - -" read from all known conque buffers -function! conque_term#read_all(insert_mode) "{{{ - - for i in range(1, g:ConqueTerm_Idx) - try - if !g:ConqueTerm_Terminals[i].active - continue - endif - - let output = g:ConqueTerm_Terminals[i].read(1) - - if !g:ConqueTerm_Terminals[i].is_buffer && exists('*g:ConqueTerm_Terminals[i].callback') - call g:ConqueTerm_Terminals[i].callback(output) - endif - catch - " probably a deleted buffer - endtry - endfor - - " restart updatetime - if a:insert_mode - "call feedkeys("\f\e", "n") - let p = getpos('.') - if p[1] == 1 - sil exe 'call feedkeys("\\", "n")' - else - sil exe 'call feedkeys("\\", "n")' - endif - call setpos('.', p) - else - call feedkeys("f\e", "n") - endif - -endfunction "}}} - -" close all subprocesses -function! conque_term#close_all() "{{{ - - for i in range(1, g:ConqueTerm_Idx) - try - call g:ConqueTerm_Terminals[i].close() - catch - " probably a deleted buffer - endtry - endfor - -endfunction "}}} - -" gets called when user enters conque buffer. -" Useful for making temp changes to global config -function! conque_term#on_focus(...) " {{{ - - let startup = get(a:000, 0, 0) - - " Disable NeoComplCache. It has global hooks on CursorHold and CursorMoved :-/ - let s:NeoComplCache_WasEnabled = exists(':NeoComplCacheLock') - if s:NeoComplCache_WasEnabled == 2 - NeoComplCacheLock - endif - - if g:ConqueTerm_ReadUnfocused == 1 - autocmd! ConqueTerm CursorHoldI * - autocmd! ConqueTerm CursorHold * - endif - - " set poll interval to 50ms - set updatetime=50 - - " resume subprocess fast polling - if startup == 0 && exists('b:ConqueTerm_Var') - sil exe s:py . ' ' . g:ConqueTerm_Var . '.resume()' - endif - - " call user defined functions - if startup == 0 - call conque_term#call_hooks('buffer_enter', conque_term#get_instance()) - endif - - " if configured, go into insert mode - if g:ConqueTerm_InsertOnEnter == 1 - startinsert! - endif - -endfunction " }}} - -" gets called when user exits conque buffer. -" Useful for resetting changes to global config -function! conque_term#on_blur() " {{{ - " re-enable NeoComplCache if needed - if exists('s:NeoComplCache_WasEnabled') && exists(':NeoComplCacheUnlock') && s:NeoComplCache_WasEnabled == 2 - NeoComplCacheUnlock - endif - - " turn off subprocess fast polling - if exists('b:ConqueTerm_Var') - sil exe s:py . ' ' . b:ConqueTerm_Var . '.idle()' - endif - - " reset poll interval - if g:ConqueTerm_ReadUnfocused == 1 - set updatetime=1000 - autocmd ConqueTerm CursorHoldI * call conque_term#read_all(1) - autocmd ConqueTerm CursorHold * call conque_term#read_all(0) - elseif exists('s:save_updatetime') - exe 'set updatetime=' . s:save_updatetime - else - set updatetime=2000 - endif - - " call user defined functions - call conque_term#call_hooks('buffer_leave', conque_term#get_instance()) - -endfunction " }}} - -" bell event (^G) -function! conque_term#bell() " {{{ - echohl WarningMsg | echomsg "BELL!" | echohl None -endfunction " }}} - -" register function to be called at conque events -function! conque_term#register_function(event, function_name) " {{{ - - if !has_key(s:hooks, a:event) - echomsg 'No such event: ' . a:event - return - endif - - if !exists('*' . a:function_name) - echomsg 'No such function: ' . a:function_name) - return - endif - - " register the function - call add(s:hooks[a:event], function(a:function_name)) - -endfunction " }}} - -" call hooks for an event -function! conque_term#call_hooks(event, t_obj) " {{{ - - for Fu in s:hooks[a:event] - call Fu(a:t_obj) - endfor - -endfunction " }}} - -" }}} - -" ********************************************************************************************************** -" **** Windows only functions ****************************************************************************** -" ********************************************************************************************************** - -" {{{ - -" find python.exe in windows -function! conque_term#find_python_exe() " {{{ - - " first check configuration for custom value - if g:ConqueTerm_PyExe != '' && executable(g:ConqueTerm_PyExe) - return g:ConqueTerm_PyExe - endif - - let sys_paths = split($PATH, ';') - - " get exact python version - sil exe ':' . s:py . ' import sys, vim' - sil exe ':' . s:py . ' vim.command("let g:ConqueTerm_PyVersion = " + str(sys.version_info[0]) + str(sys.version_info[1]))' - - " ... and add to path list - call add(sys_paths, 'C:\Python' . g:ConqueTerm_PyVersion) - call reverse(sys_paths) - - " check if python.exe is in paths - for path in sys_paths - let cand = path . '\' . 'python.exe' - if executable(cand) - return cand - endif - endfor - - echohl WarningMsg | echomsg "Unable to find python.exe, see :help ConqueTerm_PythonExe for more information" | echohl None - - return '' - -endfunction " }}} - -" initialize concealed colors -function! conque_term#init_conceal_color() " {{{ - - highlight link ConqueCCBG Normal - - " foreground colors, low intensity - syn region ConqueCCF000 matchgroup=ConqueConceal start="\esf000;" end="\eef000;" concealends contains=ConqueCCBG - syn region ConqueCCF00c matchgroup=ConqueConceal start="\esf00c;" end="\eef00c;" concealends contains=ConqueCCBG - syn region ConqueCCF0c0 matchgroup=ConqueConceal start="\esf0c0;" end="\eef0c0;" concealends contains=ConqueCCBG - syn region ConqueCCF0cc matchgroup=ConqueConceal start="\esf0cc;" end="\eef0cc;" concealends contains=ConqueCCBG - syn region ConqueCCFc00 matchgroup=ConqueConceal start="\esfc00;" end="\eefc00;" concealends contains=ConqueCCBG - syn region ConqueCCFc0c matchgroup=ConqueConceal start="\esfc0c;" end="\eefc0c;" concealends contains=ConqueCCBG - syn region ConqueCCFcc0 matchgroup=ConqueConceal start="\esfcc0;" end="\eefcc0;" concealends contains=ConqueCCBG - syn region ConqueCCFccc matchgroup=ConqueConceal start="\esfccc;" end="\eefccc;" concealends contains=ConqueCCBG - - " foreground colors, high intensity - syn region ConqueCCF000 matchgroup=ConqueConceal start="\esf000;" end="\eef000;" concealends contains=ConqueCCBG - syn region ConqueCCF00f matchgroup=ConqueConceal start="\esf00f;" end="\eef00f;" concealends contains=ConqueCCBG - syn region ConqueCCF0f0 matchgroup=ConqueConceal start="\esf0f0;" end="\eef0f0;" concealends contains=ConqueCCBG - syn region ConqueCCF0ff matchgroup=ConqueConceal start="\esf0ff;" end="\eef0ff;" concealends contains=ConqueCCBG - syn region ConqueCCFf00 matchgroup=ConqueConceal start="\esff00;" end="\eeff00;" concealends contains=ConqueCCBG - syn region ConqueCCFf0f matchgroup=ConqueConceal start="\esff0f;" end="\eeff0f;" concealends contains=ConqueCCBG - syn region ConqueCCFff0 matchgroup=ConqueConceal start="\esfff0;" end="\eefff0;" concealends contains=ConqueCCBG - syn region ConqueCCFfff matchgroup=ConqueConceal start="\esffff;" end="\eeffff;" concealends contains=ConqueCCBG - - " background colors, low intensity - syn region ConqueCCB000 matchgroup=ConqueCCBG start="\esb000;" end="\eeb000;" concealends - syn region ConqueCCB00c matchgroup=ConqueCCBG start="\esb00c;" end="\eeb00c;" concealends - syn region ConqueCCB0c0 matchgroup=ConqueCCBG start="\esb0c0;" end="\eeb0c0;" concealends - syn region ConqueCCB0cc matchgroup=ConqueCCBG start="\esb0cc;" end="\eeb0cc;" concealends - syn region ConqueCCBc00 matchgroup=ConqueCCBG start="\esbc00;" end="\eebc00;" concealends - syn region ConqueCCBc0c matchgroup=ConqueCCBG start="\esbc0c;" end="\eebc0c;" concealends - syn region ConqueCCBcc0 matchgroup=ConqueCCBG start="\esbcc0;" end="\eebcc0;" concealends - syn region ConqueCCBccc matchgroup=ConqueCCBG start="\esbccc;" end="\eebccc;" concealends - - " background colors, high intensity - syn region ConqueCCB000 matchgroup=ConqueCCBG start="\esb000;" end="\eeb000;" concealends - syn region ConqueCCB00f matchgroup=ConqueCCBG start="\esb00f;" end="\eeb00f;" concealends - syn region ConqueCCB0f0 matchgroup=ConqueCCBG start="\esb0f0;" end="\eeb0f0;" concealends - syn region ConqueCCB0ff matchgroup=ConqueCCBG start="\esb0ff;" end="\eeb0ff;" concealends - syn region ConqueCCBf00 matchgroup=ConqueCCBG start="\esbf00;" end="\eebf00;" concealends - syn region ConqueCCBf0f matchgroup=ConqueCCBG start="\esbf0f;" end="\eebf0f;" concealends - syn region ConqueCCBff0 matchgroup=ConqueCCBG start="\esbff0;" end="\eebff0;" concealends - syn region ConqueCCBfff matchgroup=ConqueCCBG start="\esbfff;" end="\eebfff;" concealends - - - """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - - "highlight link ConqueCCConceal Error - - " foreground colors, low intensity - highlight ConqueCCF000 guifg=#000000 - highlight ConqueCCF00c guifg=#0000cc - highlight ConqueCCF0c0 guifg=#00cc00 - highlight ConqueCCF0cc guifg=#00cccc - highlight ConqueCCFc00 guifg=#cc0000 - highlight ConqueCCFc0c guifg=#cc00cc - highlight ConqueCCFcc0 guifg=#cccc00 - highlight ConqueCCFccc guifg=#cccccc - - " foreground colors, high intensity - highlight ConqueCCF000 guifg=#000000 - highlight ConqueCCF00f guifg=#0000ff - highlight ConqueCCF0f0 guifg=#00ff00 - highlight ConqueCCF0ff guifg=#00ffff - highlight ConqueCCFf00 guifg=#ff0000 - highlight ConqueCCFf0f guifg=#ff00ff - highlight ConqueCCFff0 guifg=#ffff00 - highlight ConqueCCFfff guifg=#ffffff - - " background colors, low intensity - highlight ConqueCCB000 guibg=#000000 - highlight ConqueCCB00c guibg=#0000cc - highlight ConqueCCB0c0 guibg=#00cc00 - highlight ConqueCCB0cc guibg=#00cccc - highlight ConqueCCBc00 guibg=#cc0000 - highlight ConqueCCBc0c guibg=#cc00cc - highlight ConqueCCBcc0 guibg=#cccc00 - highlight ConqueCCBccc guibg=#cccccc - - " background colors, high intensity - highlight ConqueCCB000 guibg=#000000 - highlight ConqueCCB00f guibg=#0000ff - highlight ConqueCCB0f0 guibg=#00ff00 - highlight ConqueCCB0ff guibg=#00ffff - highlight ConqueCCBf00 guibg=#ff0000 - highlight ConqueCCBf0f guibg=#ff00ff - highlight ConqueCCBff0 guibg=#ffff00 - highlight ConqueCCBfff guibg=#ffffff - - " background colors, low intensity - highlight link ConqueCCB000 ConqueCCBG - highlight link ConqueCCB00c ConqueCCBG - highlight link ConqueCCB0c0 ConqueCCBG - highlight link ConqueCCB0cc ConqueCCBG - highlight link ConqueCCBc00 ConqueCCBG - highlight link ConqueCCBc0c ConqueCCBG - highlight link ConqueCCBcc0 ConqueCCBG - highlight link ConqueCCBccc ConqueCCBG - - " background colors, high intensity - highlight link ConqueCCB000 ConqueCCBG - highlight link ConqueCCB00f ConqueCCBG - highlight link ConqueCCB0f0 ConqueCCBG - highlight link ConqueCCB0ff ConqueCCBG - highlight link ConqueCCBf00 ConqueCCBG - highlight link ConqueCCBf0f ConqueCCBG - highlight link ConqueCCBff0 ConqueCCBG - highlight link ConqueCCBfff ConqueCCBG - -endfunction " }}} - -" }}} - -" ********************************************************************************************************** -" **** Add-on features ************************************************************************************* -" ********************************************************************************************************** - -" {{{ - -" send selected text from another buffer -function! conque_term#send_selected(type) "{{{ - - " get most recent/relevant terminal - let term = conque_term#get_instance() - - " shove visual text into @@ register - let reg_save = @@ - sil exe "normal! `<" . a:type . "`>y" - let @@ = substitute(@@, '^[\r\n]*', '', '') - let @@ = substitute(@@, '[\r\n]*$', '', '') - - " go to terminal buffer - call term.focus() - - " execute yanked text - call term.write(@@) - - " reset original values - let @@ = reg_save - - " scroll buffer left - startinsert! - normal! 0zH - -endfunction "}}} - -function! conque_term#send_file() "{{{ - - let file_lines = readfile(expand('%:p')) - if type(file_lines) == 3 && len(file_lines) > 0 - let term = conque_term#get_instance() - call term.focus() - - for line in file_lines - call term.writeln(line) - endfor - else - echomsg 'Could not read file: ' . expand('%:p') - endif - -endfunction "}}} - - -function! conque_term#exec_file() "{{{ - - let current_file = expand('%:p') - if !executable(current_file) - echomsg "Could not run " . current_file . ". Not an executable." - return - endif - exe ':ConqueTermSplit ' . current_file - -endfunction "}}} - - -" called on SessionLoadPost event -function! conque_term#resume_session() " {{{ - if g:ConqueTerm_SessionSupport == 1 - - " make sure terminals exist - if !exists('s:saved_terminals') || type(s:saved_terminals) != 4 - return - endif - - " rebuild terminals - for idx in keys(s:saved_terminals) - - " don't recreate inactive terminals - if s:saved_terminals[idx].active == 0 - continue - endif - - " check we're in the right buffer - let bufname = substitute(s:saved_terminals[idx].buffer_name, '\', '', 'g') - if bufname != bufname("%") - continue - endif - - " reopen command - call conque_term#open(s:saved_terminals[idx].command) - - return - endfor - - endif -endfunction " }}} - -" }}} - -" ********************************************************************************************************** -" **** "API" functions ************************************************************************************* -" ********************************************************************************************************** - -" See doc/conque_term.txt for full documentation {{{ - -" Write to a conque terminal buffer -function! s:term_obj.write(...) dict " {{{ - - let text = get(a:000, 0, '') - let jump_to_buffer = get(a:000, 1, 0) - - " if we're not in terminal buffer, pass flag to not position the cursor - sil exe s:py . ' ' . self.var . '.write_expr("text", False, False)' - - " move cursor to conque buffer - if jump_to_buffer - call self.focus() - endif - -endfunction " }}} - -" same as write() but adds a newline -function! s:term_obj.writeln(...) dict " {{{ - - let text = get(a:000, 0, '') - let jump_to_buffer = get(a:000, 1, 0) - - call self.write(text . "\r", jump_to_buffer) - -endfunction " }}} - -" move cursor to terminal buffer -function! s:term_obj.focus() dict " {{{ - - let save_sb = &switchbuf - sil set switchbuf=usetab - exe 'sb ' . self.buffer_name - sil exe ":set switchbuf=" . save_sb - startinsert! - -endfunction " }}} - -" read from terminal buffer and return string -function! s:term_obj.read(...) dict " {{{ - - let read_time = get(a:000, 0, 1) - let update_buffer = get(a:000, 1, self.is_buffer) - - if update_buffer - let up_py = 'True' - else - let up_py = 'False' - endif - - " figure out if we're in the buffer we're updating - if exists('b:ConqueTerm_Var') && b:ConqueTerm_Var == self.var - let in_buffer = 1 - else - let in_buffer = 0 - endif - - let output = '' - - " read! - sil exec s:py . " conque_tmp = " . self.var . ".read(timeout = " . read_time . ", set_cursor = False, return_output = True, update_buffer = " . up_py . ")" - - " ftw! - try - let pycode = "\nif conque_tmp:\n conque_tmp = re.sub('\\\\\\\\', '\\\\\\\\\\\\\\\\', conque_tmp)\n conque_tmp = re.sub('\"', '\\\\\\\\\"', conque_tmp)\n vim.command('let output = \"' + conque_tmp + '\"')\n" - sil exec s:py . pycode - catch - " d'oh - endtry - - return output - -endfunction " }}} - -" set output callback -function! s:term_obj.set_callback(callback_func) dict " {{{ - - let g:ConqueTerm_Terminals[self.idx].callback = function(a:callback_func) - -endfunction " }}} - -" close subprocess with ABORT signal -function! s:term_obj.close() dict " {{{ - - " kill process - try - sil exe s:py . ' ' . self.var . '.abort()' - catch - " probably already dead - endtry - - " delete buffer if option is set - if self.is_buffer - call conque_term#set_mappings('stop') - if exists('g:ConqueTerm_CloseOnEnd') && g:ConqueTerm_CloseOnEnd - sil exe 'bwipeout! ' . self.buffer_name - stopinsert! - endif - endif - - " mark ourselves as inactive - let self.active = 0 - - " rebuild session options - let g:ConqueTerm_TerminalsString = string(g:ConqueTerm_Terminals) - -endfunction " }}} - -" create a new terminal object -function! conque_term#create_terminal_object(...) " {{{ - - " find conque buffer to update - let buf_num = get(a:000, 0, 0) - if buf_num > 0 - let pvar = 'ConqueTerm_' . buf_num - elseif exists('b:ConqueTerm_Var') - let pvar = b:ConqueTerm_Var - let buf_num = b:ConqueTerm_Idx - else - let pvar = g:ConqueTerm_Var - let buf_num = g:ConqueTerm_Idx - endif - - " is ther a buffer? - let is_buffer = get(a:000, 1, 1) - - " the buffer name - let bname = get(a:000, 2, '') - - " the command - let command = get(a:000, 3, '') - - " parse out the program name (not perfect) - let arg_split = split(command, '[^\\]\@<=\s') - let arg_split[0] = substitute(arg_split[0], '\\ ', ' ', 'g') - let slash_split = split(arg_split[0], '[/\\]') - let prg_name = substitute(slash_split[-1], '\(.*\)\..*', '\1', '') - - let l:t_obj = copy(s:term_obj) - let l:t_obj.is_buffer = is_buffer - let l:t_obj.idx = buf_num - let l:t_obj.buffer_name = bname - let l:t_obj.var = pvar - let l:t_obj.command = command - let l:t_obj.program_name = prg_name - - return l:t_obj - -endfunction " }}} - -" get an existing terminal instance -function! conque_term#get_instance(...) " {{{ - - " find conque buffer to update - let buf_num = get(a:000, 0, 0) - - if exists('g:ConqueTerm_Terminals[buf_num]') - - elseif exists('b:ConqueTerm_Var') - let buf_num = b:ConqueTerm_Idx - else - let buf_num = g:ConqueTerm_Idx - endif - - return g:ConqueTerm_Terminals[buf_num] - -endfunction " }}} - -" }}} - -" ********************************************************************************************************** -" **** PYTHON ********************************************************************************************** -" ********************************************************************************************************** - -function! conque_term#load_python() " {{{ - - exec s:py . "file " . s:scriptdirpy . "conque_globals.py" - exec s:py . "file " . s:scriptdirpy . "conque.py" - if s:platform == 'windows' - exec s:py . "file " . s:scriptdirpy . "conque_win32_util.py" - exec s:py . "file " . s:scriptdirpy . "conque_sole_shared_memory.py" - exec s:py . "file " . s:scriptdirpy . "conque_sole.py" - exec s:py . "file " . s:scriptdirpy . "conque_sole_wrapper.py" - else - exec s:py . "file " . s:scriptdirpy . "conque_screen.py" - exec s:py . "file " . s:scriptdirpy . "conque_subprocess.py" - endif - -endfunction " }}} - -" vim:foldmethod=marker diff --git a/autoload/conque_term/conque.py b/autoload/conque_term/conque.py deleted file mode 100644 index 08c92e4..0000000 --- a/autoload/conque_term/conque.py +++ /dev/null @@ -1,1154 +0,0 @@ -# FILE: autoload/conque_term/conque.py -# AUTHOR: Nico Raffo -# WEBSITE: http://conque.googlecode.com -# MODIFIED: 2011-08-12 -# VERSION: 2.2, for Vim 7.0 -# LICENSE: -# Conque - Vim terminal/console emulator -# Copyright (C) 2009-__YEAR__ Nico Raffo -# -# MIT License -# -# 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: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# 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. - -""" -Vim terminal emulator. - -This class is the main interface between Vim and the terminal application. It -handles both updating the Vim buffer with new output and accepting new keyboard -input from the Vim user. - -Although this class was originally designed for a Unix terminal environment, it -has been extended by the ConqueSole class for Windows. - -Usage: - term = Conque() - term.open('/bin/bash', {'TERM': 'vt100'}) - term.write("ls -lha\r") - term.read() - term.close() -""" - -import vim -import re -import math -import time # DEBUG - -class Conque: - - # screen object - screen = None - - # subprocess object - proc = None - - # terminal dimensions and scrolling region - columns = 80 # same as $COLUMNS - lines = 24 # same as $LINES - working_columns = 80 # can be changed by CSI ? 3 l/h - working_lines = 24 # can be changed by CSI r - - # top/bottom of the scroll region - top = 1 # relative to top of screen - bottom = 24 # relative to top of screen - - # cursor position - l = 1 # current cursor line - c = 1 # current cursor column - - # autowrap mode - autowrap = True - - # absolute coordinate mode - absolute_coords = True - - # tabstop positions - tabstops = [] - - # enable colors - enable_colors = True - - # color changes - color_changes = {} - - # color history - color_history = {} - - # color highlight cache - highlight_groups = {} - - # prune terminal colors - color_pruning = True - - # don't wrap table output - unwrap_tables = True - - # wrap CUF/CUB around line breaks - wrap_cursor = False - - # do we need to move the cursor? - cursor_set = False - - # current character set, ascii or graphics - character_set = 'ascii' - - # used for auto_read actions - read_count = 0 - - # input buffer, array of ordinals - input_buffer = [] - - def open(self): - """ Start program and initialize this instance. - - Arguments: - command -- Command string to execute, e.g. '/bin/bash --login' - options -- Dictionary of environment vars to set and other options. - - """ - # get arguments - command = vim.eval('command') - options = vim.eval('options') - - # create terminal screen instance - self.screen = ConqueScreen() - - # int vars - self.columns = vim.current.window.width - self.lines = vim.current.window.height - self.working_columns = vim.current.window.width - self.working_lines = vim.current.window.height - self.bottom = vim.current.window.height - - # offset first line to make room for startup messages - if int(options['offset']) > 0: - self.l = int(options['offset']) - - # init color - self.enable_colors = options['color'] and not CONQUE_FAST_MODE - - # init tabstops - self.init_tabstops() - - # open command - self.proc = ConqueSubprocess() - self.proc.open(command, {'TERM': options['TERM'], 'CONQUE': '1', 'LINES': str(self.lines), 'COLUMNS': str(self.columns)}) - - # send window size signal, in case LINES/COLUMNS is ignored - self.update_window_size(True) - - - def write(self, input, set_cursor=True, read=True): - """ Write a unicode string to the subprocess. - - set_cursor -- Position the cursor in the current buffer when finished - read -- Check program for new output when finished - - """ - # check if window size has changed - if read: - self.update_window_size() - - # write and read - self.proc.write(input) - - # read output immediately - if read: - self.read(1, set_cursor) - - - - def write_ord(self, input, set_cursor=True, read=True): - """ Write a single character to the subprocess, using an unicode ordinal. """ - - if CONQUE_PYTHON_VERSION == 2: - self.write(unichr(input), set_cursor, read) - else: - self.write(chr(input), set_cursor, read) - - - - def write_expr(self, expr, set_cursor=True, read=True): - """ Write the value of a Vim expression to the subprocess. """ - - if CONQUE_PYTHON_VERSION == 2: - try: - val = vim.eval(expr) - self.write(unicode(val, CONQUE_VIM_ENCODING, 'ignore'), set_cursor, read) - except: - - pass - else: - try: - # XXX - Depending on Vim to deal with encoding, sadly - self.write(vim.eval(expr), set_cursor, read) - except: - - pass - - - def write_latin1(self, input, set_cursor=True, read=True): - """ Write latin-1 string to conque. Very ugly, shood be removed. """ - # XXX - this whole method is a hack, to be removed soon - - if CONQUE_PYTHON_VERSION == 2: - try: - input_unicode = input.decode('latin-1', 'ignore') - self.write(input_unicode.encode('utf-8', 'ignore'), set_cursor, read) - except: - return - else: - self.write(input, set_cursor, read) - - - def write_buffered_ord(self, chr): - """ Add character ordinal to input buffer. In case we're not allowed to modify buffer a time of input. """ - self.input_buffer.append(chr) - - - def read(self, timeout=1, set_cursor=True, return_output=False, update_buffer=True): - """ Read new output from the subprocess and update the Vim buffer. - - Arguments: - timeout -- Milliseconds to wait before reading input - set_cursor -- Set the cursor position in the current buffer when finished - return_output -- Return new subprocess STDOUT + STDERR as a string - update_buffer -- Update the current Vim buffer with the new output - - This method goes through the following rough steps: - 1. Get new output from subprocess - 2. Split output string into control codes, escape sequences, or plain text - 3. Loop over and process each chunk, updating the Vim buffer as we go - - """ - output = '' - - # this may not actually work - try: - - # read from subprocess and strip null characters - output = self.proc.read(timeout) - - if output == '': - return - - # for bufferless terminals - if not update_buffer: - return output - - - - # strip null characters. I'm still not sure why they appear - output = output.replace(chr(0), '') - - # split input into individual escape sequences, control codes, and text output - chunks = CONQUE_SEQ_REGEX.split(output) - - - - # if there were no escape sequences, skip processing and treat entire string as plain text - if len(chunks) == 1: - self.plain_text(chunks[0]) - - # loop through and process escape sequences - else: - for s in chunks: - if s == '': - continue - - - - - # Check for control character match - if CONQUE_SEQ_REGEX_CTL.match(s[0]): - - nr = ord(s[0]) - if nr in CONQUE_CTL: - getattr(self, 'ctl_' + CONQUE_CTL[nr])() - else: - - pass - - # check for escape sequence match - elif CONQUE_SEQ_REGEX_CSI.match(s): - - if s[-1] in CONQUE_ESCAPE: - csi = self.parse_csi(s[2:]) - - getattr(self, 'csi_' + CONQUE_ESCAPE[s[-1]])(csi) - else: - - pass - - # check for title match - elif CONQUE_SEQ_REGEX_TITLE.match(s): - - self.change_title(s[2], s[4:-1]) - - # check for hash match - elif CONQUE_SEQ_REGEX_HASH.match(s): - - if s[-1] in CONQUE_ESCAPE_HASH: - getattr(self, 'hash_' + CONQUE_ESCAPE_HASH[s[-1]])() - else: - - pass - - # check for charset match - elif CONQUE_SEQ_REGEX_CHAR.match(s): - - if s[-1] in CONQUE_ESCAPE_CHARSET: - getattr(self, 'charset_' + CONQUE_ESCAPE_CHARSET[s[-1]])() - else: - - pass - - # check for other escape match - elif CONQUE_SEQ_REGEX_ESC.match(s): - - if s[-1] in CONQUE_ESCAPE_PLAIN: - getattr(self, 'esc_' + CONQUE_ESCAPE_PLAIN[s[-1]])() - else: - - pass - - # else process plain text - else: - self.plain_text(s) - - # set cusor position - if set_cursor: - self.screen.set_cursor(self.l, self.c) - - # we need to set the cursor position - self.cursor_set = False - - # redraw screen for immediate feedback - #if not CONQUE_FAST_MODE: - # vim.command('redraw') - - except: - - - pass - - if return_output: - if CONQUE_PYTHON_VERSION == 3: - return output - else: - return output.encode(CONQUE_VIM_ENCODING, 'replace') - - - def auto_read(self): - """ Poll program for more output. - - Since Vim doesn't have a reliable event system that can be triggered when new - output is available, we have to continually poll the subprocess instead. This - method is called many times a second when the terminal buffer is active, so it - needs to be very fast and efficient. - - The feedkeys portion is required to reset Vim's timer system. The timer is used - to execute this command, typically set to go off after 50 ms of inactivity. - - """ - # process buffered input if any - if len(self.input_buffer): - for chr in self.input_buffer: - self.write_ord(chr, set_cursor=False, read=False) - self.input_buffer = [] - self.read(1) - - # check subprocess status, but not every time since it's CPU expensive - if self.read_count % 32 == 0: - if not self.proc.is_alive(): - vim.command('call conque_term#get_instance().close()') - return - - if self.read_count > 512: - self.read_count = 0 - - # trim color history occasionally if desired - if self.enable_colors and self.color_pruning: - self.prune_colors() - - # ++ - self.read_count += 1 - - # read output - self.read(1) - - # reset timer - if self.c == 1: - vim.command('call feedkeys("\\", "n")') - else: - vim.command('call feedkeys("\\", "n")') - - # stop here if cursor doesn't need to be moved - if self.cursor_set: - return - - # otherwise set cursor position - try: - self.set_cursor(self.l, self.c) - except: - - - pass - self.cursor_set = True - - - def plain_text(self, input): - """ Write text output to Vim buffer. - - - This method writes a string of characters without any control characters or escape sequences - to the Vim buffer. In simple terms, it writes the input string to the buffer starting at the - current cursor position, wrapping the text to a new line if needed. It also triggers the - terminal coloring methods if needed. - - - """ - # translate input into graphics character set if needed - if self.character_set == 'graphics': - old_input = input - input = u('') - for i in range(0, len(old_input)): - chrd = ord(old_input[i]) - - - try: - if chrd > 255: - - input = input + old_input[i] - else: - input = input + uchr(CONQUE_GRAPHICS_SET[chrd]) - except: - - pass - - - - # get current line from Vim buffer - current_line = self.screen[self.l] - - # pad current line with spaces, if it's shorter than cursor position - if len(current_line) < self.c: - current_line = current_line + ' ' * (self.c - len(current_line)) - - # if line is wider than screen - if self.c + len(input) - 1 > self.working_columns: - - # Table formatting hack - if self.unwrap_tables and CONQUE_TABLE_OUTPUT.match(input): - self.screen[self.l] = current_line[:self.c - 1] + input + current_line[self.c + len(input) - 1:] - self.apply_color(self.c, self.c + len(input)) - self.c += len(input) - return - - - diff = self.c + len(input) - self.working_columns - 1 - - # if autowrap is enabled - if self.autowrap: - self.screen[self.l] = current_line[:self.c - 1] + input[:-1 * diff] - self.apply_color(self.c, self.working_columns) - self.ctl_nl() - self.ctl_cr() - remaining = input[-1 * diff:] - - self.plain_text(remaining) - else: - self.screen[self.l] = current_line[:self.c - 1] + input[:-1 * diff - 1] + input[-1] - self.apply_color(self.c, self.working_columns) - self.c = self.working_columns - - # no autowrap - else: - self.screen[self.l] = current_line[:self.c - 1] + input + current_line[self.c + len(input) - 1:] - self.apply_color(self.c, self.c + len(input)) - self.c += len(input) - - - - def apply_color(self, start, end, line=0): - """ Apply terminal colors to buffer for a range of characters in a single line. - - When a text attribute escape sequence is encountered during input processing, the - attributes are recorded in the dictionary self.color_changes. After those attributes - have been applied, the changes are recorded in a second dictionary self.color_history. - - - This method inspects both dictionaries to calculate any syntax highlighting - that needs to be executed to render the text attributes in the Vim buffer. - - - """ - - - # stop here if coloration is disabled - if not self.enable_colors: - return - - # allow custom line nr to be passed - if line: - buffer_line = line - else: - buffer_line = self.get_buffer_line(self.l) - - # check for previous overlapping coloration - - to_del = [] - if buffer_line in self.color_history: - for i in range(len(self.color_history[buffer_line])): - syn = self.color_history[buffer_line][i] - - if syn['start'] >= start and syn['start'] < end: - - vim.command('syn clear ' + syn['name']) - to_del.append(i) - # outside - if syn['end'] > end: - - self.exec_highlight(buffer_line, end, syn['end'], syn['highlight']) - elif syn['end'] > start and syn['end'] <= end: - - vim.command('syn clear ' + syn['name']) - to_del.append(i) - # outside - if syn['start'] < start: - - self.exec_highlight(buffer_line, syn['start'], start, syn['highlight']) - - # remove overlapped colors - if len(to_del) > 0: - to_del.reverse() - for di in to_del: - del self.color_history[buffer_line][di] - - # if there are no new colors - if len(self.color_changes) == 0: - return - - # build the color attribute string - highlight = '' - for attr in self.color_changes.keys(): - highlight = highlight + ' ' + attr + '=' + self.color_changes[attr] - - # execute the highlight - self.exec_highlight(buffer_line, start, end, highlight) - - - def exec_highlight(self, buffer_line, start, end, highlight): - """ Execute the Vim commands for a single syntax highlight """ - - syntax_name = 'ConqueHighLightAt_%d_%d_%d_%d' % (self.proc.pid, self.l, start, len(self.color_history) + 1) - syntax_options = 'contains=ALLBUT,ConqueString,MySQLString,MySQLKeyword oneline' - syntax_region = 'syntax match %s /\%%%dl\%%>%dc.\{%d}\%%<%dc/ %s' % (syntax_name, buffer_line, start - 1, end - start, end + 1, syntax_options) - - # check for cached highlight group - hgroup = 'ConqueHL_%d' % (abs(hash(highlight))) - if hgroup not in self.highlight_groups: - syntax_group = 'highlight %s %s' % (hgroup, highlight) - self.highlight_groups[hgroup] = hgroup - vim.command(syntax_group) - - # link this syntax match to existing highlight group - syntax_highlight = 'highlight link %s %s' % (syntax_name, self.highlight_groups[hgroup]) - - - - vim.command(syntax_region) - vim.command(syntax_highlight) - - # add syntax name to history - if not buffer_line in self.color_history: - self.color_history[buffer_line] = [] - - self.color_history[buffer_line].append({'name': syntax_name, 'start': start, 'end': end, 'highlight': highlight}) - - - def prune_colors(self): - """ Remove old syntax highlighting from the Vim buffer - - The kind of syntax highlighting required for terminal colors can make - Conque run slowly. The prune_colors() method will remove old highlight definitions - to keep the maximum number of highlight rules within a reasonable range. - - """ - - - buffer_line = self.get_buffer_line(self.l) - ks = list(self.color_history.keys()) - - for line in ks: - if line < buffer_line - CONQUE_MAX_SYNTAX_LINES: - for syn in self.color_history[line]: - vim.command('syn clear ' + syn['name']) - del self.color_history[line] - - - - - ############################################################################################### - # Control functions - - def ctl_nl(self): - """ Process the newline control character. """ - # if we're in a scrolling region, scroll instead of moving cursor down - if self.lines != self.working_lines and self.l == self.bottom: - del self.screen[self.top] - self.screen.insert(self.bottom, '') - elif self.l == self.bottom: - self.screen.append('') - else: - self.l += 1 - - self.color_changes = {} - - def ctl_cr(self): - """ Process the carriage return control character. """ - self.c = 1 - - self.color_changes = {} - - def ctl_bs(self): - """ Process the backspace control character. """ - if self.c > 1: - self.c += -1 - - def ctl_soh(self): - """ Process the start of heading control character. """ - pass - - def ctl_stx(self): - pass - - def ctl_bel(self): - """ Process the bell control character. """ - vim.command('call conque_term#bell()') - - def ctl_tab(self): - """ Process the tab control character. """ - # default tabstop location - ts = self.working_columns - - # check set tabstops - for i in range(self.c, len(self.tabstops)): - if self.tabstops[i]: - ts = i + 1 - break - - - - self.c = ts - - def ctl_so(self): - """ Process the shift out control character. """ - self.character_set = 'graphics' - - def ctl_si(self): - """ Process the shift in control character. """ - self.character_set = 'ascii' - - - - ############################################################################################### - # CSI functions - - def csi_font(self, csi): - """ Process the text attribute escape sequence. """ - if not self.enable_colors: - return - - # defaults to 0 - if len(csi['vals']) == 0: - csi['vals'] = [0] - - # 256 xterm color foreground - if len(csi['vals']) == 3 and csi['vals'][0] == 38 and csi['vals'][1] == 5: - self.color_changes['ctermfg'] = str(csi['vals'][2]) - self.color_changes['guifg'] = '#' + self.xterm_to_rgb(csi['vals'][2]) - - # 256 xterm color background - elif len(csi['vals']) == 3 and csi['vals'][0] == 48 and csi['vals'][1] == 5: - self.color_changes['ctermbg'] = str(csi['vals'][2]) - self.color_changes['guibg'] = '#' + self.xterm_to_rgb(csi['vals'][2]) - - # 16 colors - else: - for val in csi['vals']: - if val in CONQUE_FONT: - - # ignore starting normal colors - if CONQUE_FONT[val]['normal'] and len(self.color_changes) == 0: - - continue - # clear color changes - elif CONQUE_FONT[val]['normal']: - - self.color_changes = {} - # save these color attributes for next plain_text() call - else: - - for attr in CONQUE_FONT[val]['attributes'].keys(): - if attr in self.color_changes and (attr == 'cterm' or attr == 'gui'): - self.color_changes[attr] += ',' + CONQUE_FONT[val]['attributes'][attr] - else: - self.color_changes[attr] = CONQUE_FONT[val]['attributes'][attr] - - - def csi_clear_line(self, csi): - """ Process the line clear escape sequence. """ - - - # this escape defaults to 0 - if len(csi['vals']) == 0: - csi['val'] = 0 - - - - - # 0 means cursor right - if csi['val'] == 0: - self.screen[self.l] = self.screen[self.l][0:self.c - 1] - - # 1 means cursor left - elif csi['val'] == 1: - self.screen[self.l] = ' ' * (self.c) + self.screen[self.l][self.c:] - - # clear entire line - elif csi['val'] == 2: - self.screen[self.l] = '' - - # clear colors - if csi['val'] == 2 or (csi['val'] == 0 and self.c == 1): - buffer_line = self.get_buffer_line(self.l) - if buffer_line in self.color_history: - for syn in self.color_history[buffer_line]: - vim.command('syn clear ' + syn['name']) - - - - - - def csi_cursor_right(self, csi): - """ Process the move cursor right escape sequence. """ - # we use 1 even if escape explicitly specifies 0 - if csi['val'] == 0: - csi['val'] = 1 - - - - - if self.wrap_cursor and self.c + csi['val'] > self.working_columns: - self.l += int(math.floor((self.c + csi['val']) / self.working_columns)) - self.c = (self.c + csi['val']) % self.working_columns - return - - self.c = self.bound(self.c + csi['val'], 1, self.working_columns) - - - def csi_cursor_left(self, csi): - """ Process the move cursor left escape sequence. """ - # we use 1 even if escape explicitly specifies 0 - if csi['val'] == 0: - csi['val'] = 1 - - if self.wrap_cursor and csi['val'] >= self.c: - self.l += int(math.floor((self.c - csi['val']) / self.working_columns)) - self.c = self.working_columns - (csi['val'] - self.c) % self.working_columns - return - - self.c = self.bound(self.c - csi['val'], 1, self.working_columns) - - - def csi_cursor_to_column(self, csi): - """ Process the move cursor to column escape sequence. """ - self.c = self.bound(csi['val'], 1, self.working_columns) - - - def csi_cursor_up(self, csi): - """ Process the move cursor up escape sequence. """ - self.l = self.bound(self.l - csi['val'], self.top, self.bottom) - - self.color_changes = {} - - - def csi_cursor_down(self, csi): - """ Process the move cursor down escape sequence. """ - self.l = self.bound(self.l + csi['val'], self.top, self.bottom) - - self.color_changes = {} - - - def csi_clear_screen(self, csi): - """ Process the clear screen escape sequence. """ - # default to 0 - if len(csi['vals']) == 0: - csi['val'] = 0 - - # 2 == clear entire screen - if csi['val'] == 2: - self.l = 1 - self.c = 1 - self.screen.clear() - - # 0 == clear down - elif csi['val'] == 0: - for l in range(self.bound(self.l + 1, 1, self.lines), self.lines + 1): - self.screen[l] = '' - - # clear end of current line - self.csi_clear_line(self.parse_csi('K')) - - # 1 == clear up - elif csi['val'] == 1: - for l in range(1, self.bound(self.l, 1, self.lines + 1)): - self.screen[l] = '' - - # clear beginning of current line - self.csi_clear_line(self.parse_csi('1K')) - - # clear coloration - if csi['val'] == 2 or csi['val'] == 0: - buffer_line = self.get_buffer_line(self.l) - for line in self.color_history.keys(): - if line >= buffer_line: - for syn in self.color_history[line]: - vim.command('syn clear ' + syn['name']) - - self.color_changes = {} - - - def csi_delete_chars(self, csi): - self.screen[self.l] = self.screen[self.l][:self.c] + self.screen[self.l][self.c + csi['val']:] - - - def csi_add_spaces(self, csi): - self.screen[self.l] = self.screen[self.l][: self.c - 1] + ' ' * csi['val'] + self.screen[self.l][self.c:] - - - def csi_cursor(self, csi): - if len(csi['vals']) == 2: - new_line = csi['vals'][0] - new_col = csi['vals'][1] - else: - new_line = 1 - new_col = 1 - - if self.absolute_coords: - self.l = self.bound(new_line, 1, self.lines) - else: - self.l = self.bound(self.top + new_line - 1, self.top, self.bottom) - - self.c = self.bound(new_col, 1, self.working_columns) - if self.c > len(self.screen[self.l]): - self.screen[self.l] = self.screen[self.l] + ' ' * (self.c - len(self.screen[self.l])) - - - - def csi_set_coords(self, csi): - if len(csi['vals']) == 2: - new_start = csi['vals'][0] - new_end = csi['vals'][1] - else: - new_start = 1 - new_end = vim.current.window.height - - self.top = new_start - self.bottom = new_end - self.working_lines = new_end - new_start + 1 - - # if cursor is outside scrolling region, reset it - if self.l < self.top: - self.l = self.top - elif self.l > self.bottom: - self.l = self.bottom - - self.color_changes = {} - - - def csi_tab_clear(self, csi): - # this escape defaults to 0 - if len(csi['vals']) == 0: - csi['val'] = 0 - - - - if csi['val'] == 0: - self.tabstops[self.c - 1] = False - elif csi['val'] == 3: - for i in range(0, self.columns + 1): - self.tabstops[i] = False - - - def csi_set(self, csi): - # 132 cols - if csi['val'] == 3: - self.csi_clear_screen(self.parse_csi('2J')) - self.working_columns = 132 - - # relative_origin - elif csi['val'] == 6: - self.absolute_coords = False - - # set auto wrap - elif csi['val'] == 7: - self.autowrap = True - - - self.color_changes = {} - - - def csi_reset(self, csi): - # 80 cols - if csi['val'] == 3: - self.csi_clear_screen(self.parse_csi('2J')) - self.working_columns = 80 - - # absolute origin - elif csi['val'] == 6: - self.absolute_coords = True - - # reset auto wrap - elif csi['val'] == 7: - self.autowrap = False - - - self.color_changes = {} - - - - - ############################################################################################### - # ESC functions - - def esc_scroll_up(self): - self.ctl_nl() - - self.color_changes = {} - - - def esc_next_line(self): - self.ctl_nl() - self.c = 1 - - - def esc_set_tab(self): - - if self.c <= len(self.tabstops): - self.tabstops[self.c - 1] = True - - - def esc_scroll_down(self): - if self.l == self.top: - del self.screen[self.bottom] - self.screen.insert(self.top, '') - else: - self.l += -1 - - self.color_changes = {} - - - - - ############################################################################################### - # HASH functions - - def hash_screen_alignment_test(self): - self.csi_clear_screen(self.parse_csi('2J')) - self.working_lines = self.lines - for l in range(1, self.lines + 1): - self.screen[l] = 'E' * self.working_columns - - - - ############################################################################################### - # CHARSET functions - - def charset_us(self): - self.character_set = 'ascii' - - def charset_uk(self): - self.character_set = 'ascii' - - def charset_graphics(self): - self.character_set = 'graphics' - - - - ############################################################################################### - # Random stuff - - def set_cursor(self, line, col): - """ Set cursor position in the Vim buffer. - - Note: the line and column numbers are relative to the top left corner of the - visible screen. Not the line number in the Vim buffer. - - """ - self.screen.set_cursor(line, col) - - def change_title(self, key, val): - """ Change the Vim window title. """ - - - if key == '0' or key == '2': - - vim.command('setlocal statusline=' + re.escape(val)) - try: - vim.command('set titlestring=' + re.escape(val)) - except: - pass - - def update_window_size(self, force=False): - """ Check and save the current buffer dimensions. - - If the buffer size has changed, the update_window_size() method both updates - the Conque buffer size attributes as well as sending the new dimensions to the - subprocess pty. - - """ - # resize if needed - if force or vim.current.window.width != self.columns or vim.current.window.height != self.lines: - - # reset all window size attributes to default - self.columns = vim.current.window.width - self.lines = vim.current.window.height - self.working_columns = vim.current.window.width - self.working_lines = vim.current.window.height - self.bottom = vim.current.window.height - - # reset screen object attributes - self.l = self.screen.reset_size(self.l) - - # reset tabstops - self.init_tabstops() - - - - # signal process that screen size has changed - self.proc.window_resize(self.lines, self.columns) - - def insert_enter(self): - """ Run commands when user enters insert mode. """ - - # check window size - self.update_window_size() - - # we need to set the cursor position - self.cursor_set = False - - def init_tabstops(self): - """ Intitialize terminal tabstop positions. """ - for i in range(0, self.columns + 1): - if i % 8 == 0: - self.tabstops.append(True) - else: - self.tabstops.append(False) - - def idle(self): - """ Called when this terminal becomes idle. """ - pass - - def resume(self): - """ Called when this terminal is no longer idle. """ - pass - pass - - def close(self): - """ End the process running in the terminal. """ - self.proc.close() - - def abort(self): - """ Forcefully end the process running in the terminal. """ - self.proc.signal(1) - - - - ############################################################################################### - # Utility - - def parse_csi(self, s): - """ Parse an escape sequence into it's meaningful values. """ - - attr = {'key': s[-1], 'flag': '', 'val': 1, 'vals': []} - - if len(s) == 1: - return attr - - full = s[0:-1] - - if full[0] == '?': - full = full[1:] - attr['flag'] = '?' - - if full != '': - vals = full.split(';') - for val in vals: - - val = re.sub("\D", "", val) - - if val != '': - attr['vals'].append(int(val)) - - if len(attr['vals']) == 1: - attr['val'] = int(attr['vals'][0]) - - return attr - - - def bound(self, val, min, max): - """ TODO: This probably exists as a builtin function. """ - if val > max: - return max - - if val < min: - return min - - return val - - - def xterm_to_rgb(self, color_code): - """ Translate a terminal color number into a RGB string. """ - if color_code < 16: - ascii_colors = ['000000', 'CD0000', '00CD00', 'CDCD00', '0000EE', 'CD00CD', '00CDCD', 'E5E5E5', - '7F7F7F', 'FF0000', '00FF00', 'FFFF00', '5C5CFF', 'FF00FF', '00FFFF', 'FFFFFF'] - return ascii_colors[color_code] - - elif color_code < 232: - cc = int(color_code) - 16 - - p1 = "%02x" % (math.floor(cc / 36) * (255 / 5)) - p2 = "%02x" % (math.floor((cc % 36) / 6) * (255 / 5)) - p3 = "%02x" % (math.floor(cc % 6) * (255 / 5)) - - return p1 + p2 + p3 - else: - grey_tone = "%02x" % math.floor((255 / 24) * (color_code - 232)) - return grey_tone + grey_tone + grey_tone - - - - - def get_buffer_line(self, line): - """ Get the buffer line number corresponding to the supplied screen line number. """ - return self.screen.get_buffer_line(line) - - diff --git a/autoload/conque_term/conque_globals.py b/autoload/conque_term/conque_globals.py deleted file mode 100644 index d7a8c8f..0000000 --- a/autoload/conque_term/conque_globals.py +++ /dev/null @@ -1,319 +0,0 @@ -# FILE: autoload/conque_term/conque_globals.py -# AUTHOR: Nico Raffo -# WEBSITE: http://conque.googlecode.com -# MODIFIED: 2011-08-12 -# VERSION: 2.2, for Vim 7.0 -# LICENSE: -# Conque - Vim terminal/console emulator -# Copyright (C) 2009-__YEAR__ Nico Raffo -# -# MIT License -# -# 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: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# 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. - -"""Common global constants and functions for Conque.""" - -import sys -import re -import os # DEBUG - -import traceback # DEBUG - -# PYTHON VERSION -CONQUE_PYTHON_VERSION = sys.version_info[0] - -# Encoding - -try: - # Vim's character encoding - import vim - CONQUE_VIM_ENCODING = vim.eval('&encoding') - -except: - CONQUE_VIM_ENCODING = 'utf-8' - - -def u(str_val, str_encoding='utf-8', errors='strict'): - """ Foolhardy attempt to make unicode string syntax compatible with both python 2 and 3. """ - - if not str_val: - str_val = '' - - if CONQUE_PYTHON_VERSION == 3: - return str_val - - else: - return unicode(str_val, str_encoding, errors) - -def uchr(str): - """ Foolhardy attempt to make unicode string syntax compatible with both python 2 and 3. """ - - if CONQUE_PYTHON_VERSION == 3: - return chr(str) - - else: - return unichr(str) - - - - - - - - - - - - - - - - - - - -# Unix escape sequence settings - -CONQUE_CTL = { - 1: 'soh', # start of heading - 2: 'stx', # start of text - 7: 'bel', # bell - 8: 'bs', # backspace - 9: 'tab', # tab - 10: 'nl', # new line - 13: 'cr', # carriage return - 14: 'so', # shift out - 15: 'si' # shift in -} -# 11 : 'vt', # vertical tab -# 12 : 'ff', # form feed - -# Escape sequences -CONQUE_ESCAPE = { - 'm': 'font', - 'J': 'clear_screen', - 'K': 'clear_line', - '@': 'add_spaces', - 'A': 'cursor_up', - 'B': 'cursor_down', - 'C': 'cursor_right', - 'D': 'cursor_left', - 'G': 'cursor_to_column', - 'H': 'cursor', - 'P': 'delete_chars', - 'f': 'cursor', - 'g': 'tab_clear', - 'r': 'set_coords', - 'h': 'set', - 'l': 'reset' -} -# 'L': 'insert_lines', -# 'M': 'delete_lines', -# 'd': 'cusor_vpos', - -# Alternate escape sequences, no [ -CONQUE_ESCAPE_PLAIN = { - 'D': 'scroll_up', - 'E': 'next_line', - 'H': 'set_tab', - 'M': 'scroll_down' -} -# 'N': 'single_shift_2', -# 'O': 'single_shift_3', -# '=': 'alternate_keypad', -# '>': 'numeric_keypad', -# '7': 'save_cursor', -# '8': 'restore_cursor', - -# Character set escape sequences, with "(" -CONQUE_ESCAPE_CHARSET = { - 'A': 'uk', - 'B': 'us', - '0': 'graphics' -} - -# Uber alternate escape sequences, with # or ? -CONQUE_ESCAPE_QUESTION = { - '1h': 'new_line_mode', - '3h': '132_cols', - '4h': 'smooth_scrolling', - '5h': 'reverse_video', - '6h': 'relative_origin', - '7h': 'set_auto_wrap', - '8h': 'set_auto_repeat', - '9h': 'set_interlacing_mode', - '1l': 'set_cursor_key', - '2l': 'set_vt52', - '3l': '80_cols', - '4l': 'set_jump_scrolling', - '5l': 'normal_video', - '6l': 'absolute_origin', - '7l': 'reset_auto_wrap', - '8l': 'reset_auto_repeat', - '9l': 'reset_interlacing_mode' -} - -CONQUE_ESCAPE_HASH = { - '8': 'screen_alignment_test' -} -# '3': 'double_height_top', -# '4': 'double_height_bottom', -# '5': 'single_height_single_width', -# '6': 'single_height_double_width', - -CONQUE_GRAPHICS_SET = [ - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002A, 0x2192, 0x2190, 0x2191, 0x2193, 0x002F, - 0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x00A0, - 0x25C6, 0x2592, 0x2409, 0x240C, 0x240D, 0x240A, 0x00B0, 0x00B1, - 0x2591, 0x240B, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0xF800, - 0xF801, 0x2500, 0xF803, 0xF804, 0x251C, 0x2524, 0x2534, 0x252C, - 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00B7, 0x007F, - 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, - 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, - 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, - 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF -] - -# Font codes -CONQUE_FONT = { - 0: {'description': 'Normal (default)', 'attributes': {'cterm': 'NONE', 'ctermfg': 'NONE', 'ctermbg': 'NONE', 'gui': 'NONE', 'guifg': 'NONE', 'guibg': 'NONE'}, 'normal': True}, - 1: {'description': 'Bold', 'attributes': {'cterm': 'BOLD', 'gui': 'BOLD'}, 'normal': False}, - 4: {'description': 'Underlined', 'attributes': {'cterm': 'UNDERLINE', 'gui': 'UNDERLINE'}, 'normal': False}, - 5: {'description': 'Blink (appears as Bold)', 'attributes': {'cterm': 'BOLD', 'gui': 'BOLD'}, 'normal': False}, - 7: {'description': 'Inverse', 'attributes': {'cterm': 'REVERSE', 'gui': 'REVERSE'}, 'normal': False}, - 8: {'description': 'Invisible (hidden)', 'attributes': {'ctermfg': '0', 'ctermbg': '0', 'guifg': '#000000', 'guibg': '#000000'}, 'normal': False}, - 22: {'description': 'Normal (neither bold nor faint)', 'attributes': {'cterm': 'NONE', 'gui': 'NONE'}, 'normal': True}, - 24: {'description': 'Not underlined', 'attributes': {'cterm': 'NONE', 'gui': 'NONE'}, 'normal': True}, - 25: {'description': 'Steady (not blinking)', 'attributes': {'cterm': 'NONE', 'gui': 'NONE'}, 'normal': True}, - 27: {'description': 'Positive (not inverse)', 'attributes': {'cterm': 'NONE', 'gui': 'NONE'}, 'normal': True}, - 28: {'description': 'Visible (not hidden)', 'attributes': {'ctermfg': 'NONE', 'ctermbg': 'NONE', 'guifg': 'NONE', 'guibg': 'NONE'}, 'normal': True}, - 30: {'description': 'Set foreground color to Black', 'attributes': {'ctermfg': '16', 'guifg': '#000000'}, 'normal': False}, - 31: {'description': 'Set foreground color to Red', 'attributes': {'ctermfg': '1', 'guifg': '#ff0000'}, 'normal': False}, - 32: {'description': 'Set foreground color to Green', 'attributes': {'ctermfg': '2', 'guifg': '#00ff00'}, 'normal': False}, - 33: {'description': 'Set foreground color to Yellow', 'attributes': {'ctermfg': '3', 'guifg': '#ffff00'}, 'normal': False}, - 34: {'description': 'Set foreground color to Blue', 'attributes': {'ctermfg': '4', 'guifg': '#0000ff'}, 'normal': False}, - 35: {'description': 'Set foreground color to Magenta', 'attributes': {'ctermfg': '5', 'guifg': '#990099'}, 'normal': False}, - 36: {'description': 'Set foreground color to Cyan', 'attributes': {'ctermfg': '6', 'guifg': '#009999'}, 'normal': False}, - 37: {'description': 'Set foreground color to White', 'attributes': {'ctermfg': '7', 'guifg': '#ffffff'}, 'normal': False}, - 39: {'description': 'Set foreground color to default (original)', 'attributes': {'ctermfg': 'NONE', 'guifg': 'NONE'}, 'normal': True}, - 40: {'description': 'Set background color to Black', 'attributes': {'ctermbg': '16', 'guibg': '#000000'}, 'normal': False}, - 41: {'description': 'Set background color to Red', 'attributes': {'ctermbg': '1', 'guibg': '#ff0000'}, 'normal': False}, - 42: {'description': 'Set background color to Green', 'attributes': {'ctermbg': '2', 'guibg': '#00ff00'}, 'normal': False}, - 43: {'description': 'Set background color to Yellow', 'attributes': {'ctermbg': '3', 'guibg': '#ffff00'}, 'normal': False}, - 44: {'description': 'Set background color to Blue', 'attributes': {'ctermbg': '4', 'guibg': '#0000ff'}, 'normal': False}, - 45: {'description': 'Set background color to Magenta', 'attributes': {'ctermbg': '5', 'guibg': '#990099'}, 'normal': False}, - 46: {'description': 'Set background color to Cyan', 'attributes': {'ctermbg': '6', 'guibg': '#009999'}, 'normal': False}, - 47: {'description': 'Set background color to White', 'attributes': {'ctermbg': '7', 'guibg': '#ffffff'}, 'normal': False}, - 49: {'description': 'Set background color to default (original).', 'attributes': {'ctermbg': 'NONE', 'guibg': 'NONE'}, 'normal': True}, - 90: {'description': 'Set foreground color to Black', 'attributes': {'ctermfg': '8', 'guifg': '#000000'}, 'normal': False}, - 91: {'description': 'Set foreground color to Red', 'attributes': {'ctermfg': '9', 'guifg': '#ff0000'}, 'normal': False}, - 92: {'description': 'Set foreground color to Green', 'attributes': {'ctermfg': '10', 'guifg': '#00ff00'}, 'normal': False}, - 93: {'description': 'Set foreground color to Yellow', 'attributes': {'ctermfg': '11', 'guifg': '#ffff00'}, 'normal': False}, - 94: {'description': 'Set foreground color to Blue', 'attributes': {'ctermfg': '12', 'guifg': '#0000ff'}, 'normal': False}, - 95: {'description': 'Set foreground color to Magenta', 'attributes': {'ctermfg': '13', 'guifg': '#990099'}, 'normal': False}, - 96: {'description': 'Set foreground color to Cyan', 'attributes': {'ctermfg': '14', 'guifg': '#009999'}, 'normal': False}, - 97: {'description': 'Set foreground color to White', 'attributes': {'ctermfg': '15', 'guifg': '#ffffff'}, 'normal': False}, - 100: {'description': 'Set background color to Black', 'attributes': {'ctermbg': '8', 'guibg': '#000000'}, 'normal': False}, - 101: {'description': 'Set background color to Red', 'attributes': {'ctermbg': '9', 'guibg': '#ff0000'}, 'normal': False}, - 102: {'description': 'Set background color to Green', 'attributes': {'ctermbg': '10', 'guibg': '#00ff00'}, 'normal': False}, - 103: {'description': 'Set background color to Yellow', 'attributes': {'ctermbg': '11', 'guibg': '#ffff00'}, 'normal': False}, - 104: {'description': 'Set background color to Blue', 'attributes': {'ctermbg': '12', 'guibg': '#0000ff'}, 'normal': False}, - 105: {'description': 'Set background color to Magenta', 'attributes': {'ctermbg': '13', 'guibg': '#990099'}, 'normal': False}, - 106: {'description': 'Set background color to Cyan', 'attributes': {'ctermbg': '14', 'guibg': '#009999'}, 'normal': False}, - 107: {'description': 'Set background color to White', 'attributes': {'ctermbg': '15', 'guibg': '#ffffff'}, 'normal': False} -} - - -# regular expression matching (almost) all control sequences -CONQUE_SEQ_REGEX = re.compile("(\x1b\[?\??#?[0-9;]*[a-zA-Z0-9@=>]|\x1b\][0-9];.*?\x07|[\x01-\x0f]|\x1b\([AB0])") -CONQUE_SEQ_REGEX_CTL = re.compile("^[\x01-\x0f]$") -CONQUE_SEQ_REGEX_CSI = re.compile("^\x1b\[") -CONQUE_SEQ_REGEX_TITLE = re.compile("^\x1b\]") -CONQUE_SEQ_REGEX_HASH = re.compile("^\x1b#") -CONQUE_SEQ_REGEX_ESC = re.compile("^\x1b.$") -CONQUE_SEQ_REGEX_CHAR = re.compile("^\x1b[()]") - -# match table output -CONQUE_TABLE_OUTPUT = re.compile("^\s*\|\s.*\s\|\s*$|^\s*\+[=+-]+\+\s*$") - -# basic terminal colors -CONQUE_COLOR_SEQUENCE = ( - '000', '009', '090', '099', '900', '909', '990', '999', - '000', '00f', '0f0', '0ff', 'f00', 'f0f', 'ff0', 'fff' -) - - -# Windows subprocess constants - -# shared memory size -CONQUE_SOLE_BUFFER_LENGTH = 1000 -CONQUE_SOLE_INPUT_SIZE = 1000 -CONQUE_SOLE_STATS_SIZE = 1000 -CONQUE_SOLE_COMMANDS_SIZE = 255 -CONQUE_SOLE_RESCROLL_SIZE = 255 -CONQUE_SOLE_RESIZE_SIZE = 255 - -# interval of screen redraw -# larger number means less frequent -CONQUE_SOLE_SCREEN_REDRAW = 50 - -# interval of full buffer redraw -# larger number means less frequent -CONQUE_SOLE_BUFFER_REDRAW = 500 - -# interval of full output bucket replacement -# larger number means less frequent, 1 = every time -CONQUE_SOLE_MEM_REDRAW = 1000 - -# maximum number of lines with terminal colors -# ignored if g:ConqueTerm_Color = 2 -CONQUE_MAX_SYNTAX_LINES = 200 - -# windows input splitting on special keys -CONQUE_WIN32_REGEX_VK = re.compile("(\x1b\[[0-9;]+VK)") - -# windows attribute string splitting -CONQUE_WIN32_REGEX_ATTR = re.compile("((.)\\2*)", re.DOTALL) - -# special key attributes -CONQUE_VK_ATTR_CTRL_PRESSED = u('1024') - - diff --git a/autoload/conque_term/conque_screen.py b/autoload/conque_term/conque_screen.py deleted file mode 100644 index 40db616..0000000 --- a/autoload/conque_term/conque_screen.py +++ /dev/null @@ -1,230 +0,0 @@ -# FILE: autoload/conque_term/conque_screen.py -# AUTHOR: Nico Raffo -# WEBSITE: http://conque.googlecode.com -# MODIFIED: 2011-08-12 -# VERSION: 2.2, for Vim 7.0 -# LICENSE: -# Conque - Vim terminal/console emulator -# Copyright (C) 2009-__YEAR__ Nico Raffo -# -# MIT License -# -# 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: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# 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. - -""" -ConqueScreen is an extention of the vim.current.buffer object - -Unix terminal escape sequences usually reference line numbers relative to the -top of the visible screen. However the visible portion of the Vim buffer -representing the terminal probably doesn't start at the first line of the -buffer. - -The ConqueScreen class allows access to the Vim buffer with screen-relative -line numbering. And handles a few other related tasks, such as setting the -correct cursor position. - - E.g.: - s = ConqueScreen() - ... - s[5] = 'Set 5th line in terminal to this line' - s.append('Add new line to terminal') - s[5] = 'Since previous append() command scrolled the terminal down, this is a different line than first cb[5] call' - -""" - -import vim - - -class ConqueScreen(object): - - # the buffer - buffer = None - - # screen and scrolling regions - screen_top = 1 - - # screen width - screen_width = 80 - screen_height = 80 - - # char encoding for vim buffer - screen_encoding = 'utf-8' - - - def __init__(self): - """ Initialize screen size and character encoding. """ - - self.buffer = vim.current.buffer - - # initialize screen size - self.screen_top = 1 - self.screen_width = vim.current.window.width - self.screen_height = vim.current.window.height - - # save screen character encoding type - self.screen_encoding = vim.eval('&fileencoding') - - - def __len__(self): - """ Define the len() function for ConqueScreen objects. """ - return len(self.buffer) - - - def __getitem__(self, key): - """ Define value access for ConqueScreen objects. """ - buffer_line = self.get_real_idx(key) - - # if line is past buffer end, add lines to buffer - if buffer_line >= len(self.buffer): - for i in range(len(self.buffer), buffer_line + 1): - self.append(' ') - - return u(self.buffer[buffer_line], 'utf-8') - - - def __setitem__(self, key, value): - """ Define value assignments for ConqueScreen objects. """ - buffer_line = self.get_real_idx(key) - - if CONQUE_PYTHON_VERSION == 2: - val = value.encode(self.screen_encoding) - else: - # XXX / Vim's python3 interface doesn't accept bytes object - val = str(value) - - # if line is past end of screen, append - if buffer_line == len(self.buffer): - self.buffer.append(val) - else: - self.buffer[buffer_line] = val - - - def __delitem__(self, key): - """ Define value deletion for ConqueScreen objects. """ - del self.buffer[self.screen_top + key - 2] - - - def append(self, value): - """ Define value appending for ConqueScreen objects. """ - - if len(self.buffer) > self.screen_top + self.screen_height - 1: - self.buffer[len(self.buffer) - 1] = value - else: - self.buffer.append(value) - - if len(self.buffer) > self.screen_top + self.screen_height - 1: - self.screen_top += 1 - - if vim.current.buffer.number == self.buffer.number: - vim.command('normal! G') - - - def insert(self, line, value): - """ Define value insertion for ConqueScreen objects. """ - - l = self.screen_top + line - 2 - self.buffer.append(value, l) - - - def get_top(self): - """ Get the Vim line number representing the top of the visible terminal. """ - return self.screen_top - - - def get_real_idx(self, line): - """ Get the zero index Vim line number corresponding to the provided screen line. """ - return (self.screen_top + line - 2) - - - def get_buffer_line(self, line): - """ Get the Vim line number corresponding to the provided screen line. """ - return (self.screen_top + line - 1) - - - def set_screen_width(self, width): - """ Set the screen width. """ - self.screen_width = width - - - def clear(self): - """ Clear the screen. Does not clear the buffer, just scrolls down past all text. """ - - self.screen_width = width - self.buffer.append(' ') - vim.command('normal! Gzt') - self.screen_top = len(self.buffer) - - - def set_cursor(self, line, column): - """ Set cursor position. """ - - # figure out line - buffer_line = self.screen_top + line - 1 - if buffer_line > len(self.buffer): - for l in range(len(self.buffer) - 1, buffer_line): - self.buffer.append('') - - # figure out column - real_column = column - if len(self.buffer[buffer_line - 1]) < real_column: - self.buffer[buffer_line - 1] = self.buffer[buffer_line - 1] + ' ' * (real_column - len(self.buffer[buffer_line - 1])) - - if not CONQUE_FAST_MODE: - # set cursor at byte index of real_column'th character - vim.command('call cursor(' + str(buffer_line) + ', byteidx(getline(' + str(buffer_line) + '), ' + str(real_column) + '))') - - else: - # old version - # python version is occasionally grumpy - try: - vim.current.window.cursor = (buffer_line, real_column - 1) - except: - vim.command('call cursor(' + str(buffer_line) + ', ' + str(real_column) + ')') - - - def reset_size(self, line): - """ Change screen size """ - - - - - - # save cursor line number - buffer_line = self.screen_top + line - - # reset screen size - self.screen_width = vim.current.window.width - self.screen_height = vim.current.window.height - self.screen_top = len(self.buffer) - vim.current.window.height + 1 - if self.screen_top < 1: - self.screen_top = 1 - - - # align bottom of buffer to bottom of screen - vim.command('normal! ' + str(self.screen_height) + 'kG') - - # return new relative line number - return (buffer_line - self.screen_top) - - - def align(self): - """ align bottom of buffer to bottom of screen """ - vim.command('normal! ' + str(self.screen_height) + 'kG') - - diff --git a/autoload/conque_term/conque_sole.py b/autoload/conque_term/conque_sole.py deleted file mode 100644 index 556aee9..0000000 --- a/autoload/conque_term/conque_sole.py +++ /dev/null @@ -1,458 +0,0 @@ -# FILE: autoload/conque_term/conque_sole.py -# AUTHOR: Nico Raffo -# WEBSITE: http://conque.googlecode.com -# MODIFIED: 2011-08-12 -# VERSION: 2.2, for Vim 7.0 -# LICENSE: -# Conque - Vim terminal/console emulator -# Copyright (C) 2009-__YEAR__ Nico Raffo -# -# MIT License -# -# 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: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# 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. - -""" -Windows Console Emulator - -This is the main interface to the Windows emulator. It reads new output from the background console -and updates the Vim buffer. -""" - -import vim - - -class ConqueSole(Conque): - - window_top = None - window_bottom = None - - color_cache = {} - attribute_cache = {} - color_mode = None - color_conceals = {} - - buffer = None - encoding = None - - # counters for periodic rendering - buffer_redraw_ct = 1 - screen_redraw_ct = 1 - - # line offset, shifts output down - offset = 0 - - - def open(self): - """ Start command and initialize this instance - - Arguments: - command - Command string, e.g. "Powershell.exe" - options - Dictionary of config options - python_exe - Path to the python.exe executable. Usually C:\PythonXX\python.exe - communicator_py - Path to subprocess controller script in user's vimfiles directory - - """ - # get arguments - command = vim.eval('command') - options = vim.eval('options') - python_exe = vim.eval('py_exe') - communicator_py = vim.eval('py_vim') - - # init size - self.columns = vim.current.window.width - self.lines = vim.current.window.height - self.window_top = 0 - self.window_bottom = vim.current.window.height - 1 - - # color mode - self.color_mode = vim.eval('g:ConqueTerm_ColorMode') - - # line offset - self.offset = int(options['offset']) - - # init color - self.enable_colors = options['color'] and not CONQUE_FAST_MODE - - # open command - self.proc = ConqueSoleWrapper() - self.proc.open(command, self.lines, self.columns, python_exe, communicator_py, options) - - self.buffer = vim.current.buffer - self.screen_encoding = vim.eval('&fileencoding') - - - def read(self, timeout=1, set_cursor=True, return_output=False, update_buffer=True): - """ Read from console and update Vim buffer. """ - - try: - stats = self.proc.get_stats() - - if not stats: - return - - # disable screen and buffer redraws in fast mode - if not CONQUE_FAST_MODE: - self.buffer_redraw_ct += 1 - self.screen_redraw_ct += 1 - - update_top = 0 - update_bottom = 0 - lines = [] - - # full buffer redraw, our favorite! - #if self.buffer_redraw_ct == CONQUE_SOLE_BUFFER_REDRAW: - # self.buffer_redraw_ct = 0 - # update_top = 0 - # update_bottom = stats['top_offset'] + self.lines - # (lines, attributes) = self.proc.read(update_top, update_bottom) - # if return_output: - # output = self.get_new_output(lines, update_top, stats) - # if update_buffer: - # for i in range(update_top, update_bottom + 1): - # if CONQUE_FAST_MODE: - # self.plain_text(i, lines[i], None, stats) - # else: - # self.plain_text(i, lines[i], attributes[i], stats) - - # full screen redraw - if stats['cursor_y'] + 1 != self.l or stats['top_offset'] != self.window_top or self.screen_redraw_ct >= CONQUE_SOLE_SCREEN_REDRAW: - - self.screen_redraw_ct = 0 - update_top = self.window_top - update_bottom = max([stats['top_offset'] + self.lines + 1, stats['cursor_y']]) - (lines, attributes) = self.proc.read(update_top, update_bottom - update_top + 1) - if return_output: - output = self.get_new_output(lines, update_top, stats) - if update_buffer: - for i in range(update_top, update_bottom + 1): - if CONQUE_FAST_MODE: - self.plain_text(i, lines[i - update_top], None, stats) - else: - self.plain_text(i, lines[i - update_top], attributes[i - update_top], stats) - - - # single line redraw - else: - update_top = stats['cursor_y'] - (lines, attributes) = self.proc.read(update_top, 1) - if return_output: - output = self.get_new_output(lines, update_top, stats) - if update_buffer: - if lines[0].rstrip() != u(self.buffer[update_top].rstrip()): - if CONQUE_FAST_MODE: - self.plain_text(update_top, lines[0], None, stats) - else: - self.plain_text(update_top, lines[0], attributes[0], stats) - - - # reset current position - self.window_top = stats['top_offset'] - self.l = stats['cursor_y'] + 1 - self.c = stats['cursor_x'] + 1 - - # reposition cursor if this seems plausible - if set_cursor: - self.set_cursor(self.l, self.c) - - if return_output: - return output - - except: - - pass - - - def get_new_output(self, lines, update_top, stats): - """ Calculate the "new" output from this read. Fake but useful """ - - if not (stats['cursor_y'] + 1 > self.l or (stats['cursor_y'] + 1 == self.l and stats['cursor_x'] + 1 > self.c)): - return "" - - - - - - - try: - num_to_return = stats['cursor_y'] - self.l + 2 - - lines = lines[self.l - update_top - 1:] - - - new_output = [] - - # first line - new_output.append(lines[0][self.c - 1:].rstrip()) - - # the rest - for i in range(1, num_to_return): - new_output.append(lines[i].rstrip()) - - except: - - pass - - - - return "\n".join(new_output) - - - def plain_text(self, line_nr, text, attributes, stats): - """ Write plain text to Vim buffer. """ - - - - - - # handle line offset - line_nr += self.offset - - self.l = line_nr + 1 - - # remove trailing whitespace - text = text.rstrip() - - # if we're using concealed text for color, then s- is weird - if self.color_mode == 'conceal': - - text = self.add_conceal_color(text, attributes, stats, line_nr) - - - # deal with character encoding - if CONQUE_PYTHON_VERSION == 2: - val = text.encode(self.screen_encoding) - else: - # XXX / Vim's python3 interface doesn't accept bytes object - val = str(text) - - # update vim buffer - if len(self.buffer) <= line_nr: - self.buffer.append(val) - else: - self.buffer[line_nr] = val - - if self.enable_colors and not self.color_mode == 'conceal' and line_nr > self.l - CONQUE_MAX_SYNTAX_LINES: - relevant = attributes[0:len(text)] - if line_nr not in self.attribute_cache or self.attribute_cache[line_nr] != relevant: - self.do_color(attributes=relevant, stats=stats) - self.attribute_cache[line_nr] = relevant - - - def add_conceal_color(self, text, attributes, stats, line_nr): - """ Add 'conceal' color strings to output text """ - - # stop here if coloration is disabled - if not self.enable_colors: - return text - - # if no colors for this line, clear everything out - if len(attributes) == 0 or attributes == u(chr(stats['default_attribute'])) * len(attributes): - return text - - new_text = '' - self.color_conceals[line_nr] = [] - - attribute_chunks = CONQUE_WIN32_REGEX_ATTR.findall(attributes) - offset = 0 - ends = [] - for attr in attribute_chunks: - attr_num = ord(attr[1]) - ends = [] - if attr_num != stats['default_attribute']: - - color = self.translate_color(attr_num) - - new_text += chr(27) + 'sf' + color['fg_code'] + ';' - ends.append(chr(27) + 'ef' + color['fg_code'] + ';') - self.color_conceals[line_nr].append(offset) - - if attr_num > 15: - new_text += chr(27) + 'sb' + color['bg_code'] + ';' - ends.append(chr(27) + 'eb' + color['bg_code'] + ';') - self.color_conceals[line_nr].append(offset) - - new_text += text[offset:offset + len(attr[0])] - - # close color regions - ends.reverse() - for i in range(0, len(ends)): - self.color_conceals[line_nr].append(len(new_text)) - new_text += ends[i] - - offset += len(attr[0]) - - return new_text - - - def do_color(self, start=0, end=0, attributes='', stats=None): - """ Convert Windows console attributes into Vim syntax highlighting """ - - # if no colors for this line, clear everything out - if len(attributes) == 0 or attributes == u(chr(stats['default_attribute'])) * len(attributes): - self.color_changes = {} - self.apply_color(1, len(attributes), self.l) - return - - attribute_chunks = CONQUE_WIN32_REGEX_ATTR.findall(attributes) - offset = 0 - for attr in attribute_chunks: - attr_num = ord(attr[1]) - if attr_num != stats['default_attribute']: - self.color_changes = self.translate_color(attr_num) - self.apply_color(offset + 1, offset + len(attr[0]) + 1, self.l) - offset += len(attr[0]) - - - def translate_color(self, attr): - """ Convert Windows console attributes into RGB colors """ - - # check for cached color - if attr in self.color_cache: - return self.color_cache[attr] - - - - - - - # convert attribute integer to bit string - bit_str = bin(attr) - bit_str = bit_str.replace('0b', '') - - # slice foreground and background portions of bit string - fg = bit_str[-4:].rjust(4, '0') - bg = bit_str[-8:-4].rjust(4, '0') - - # ok, first create foreground #rbg - red = int(fg[1]) * 204 + int(fg[0]) * int(fg[1]) * 51 - green = int(fg[2]) * 204 + int(fg[0]) * int(fg[2]) * 51 - blue = int(fg[3]) * 204 + int(fg[0]) * int(fg[3]) * 51 - fg_str = "#%02x%02x%02x" % (red, green, blue) - fg_code = "%02x%02x%02x" % (red, green, blue) - fg_code = fg_code[0] + fg_code[2] + fg_code[4] - - # ok, first create foreground #rbg - red = int(bg[1]) * 204 + int(bg[0]) * int(bg[1]) * 51 - green = int(bg[2]) * 204 + int(bg[0]) * int(bg[2]) * 51 - blue = int(bg[3]) * 204 + int(bg[0]) * int(bg[3]) * 51 - bg_str = "#%02x%02x%02x" % (red, green, blue) - bg_code = "%02x%02x%02x" % (red, green, blue) - bg_code = bg_code[0] + bg_code[2] + bg_code[4] - - # build value for color_changes - - color = {'guifg': fg_str, 'guibg': bg_str} - - if self.color_mode == 'conceal': - color['fg_code'] = fg_code - color['bg_code'] = bg_code - - self.color_cache[attr] = color - - return color - - - def write_vk(self, vk_code): - """ write virtual key code to shared memory using proprietary escape seq """ - - self.proc.write_vk(vk_code) - - - def update_window_size(self): - """ Resize underlying console if Vim buffer size has changed """ - - if vim.current.window.width != self.columns or vim.current.window.height != self.lines: - - - - # reset all window size attributes to default - self.columns = vim.current.window.width - self.lines = vim.current.window.height - self.working_columns = vim.current.window.width - self.working_lines = vim.current.window.height - self.bottom = vim.current.window.height - - self.proc.window_resize(vim.current.window.height, vim.current.window.width) - - - def set_cursor(self, line, column): - """ Update cursor position in Vim buffer """ - - - - # handle offset - line += self.offset - - # shift cursor position to handle concealed text - if self.enable_colors and self.color_mode == 'conceal': - if line - 1 in self.color_conceals: - for c in self.color_conceals[line - 1]: - if c < column: - column += 7 - else: - break - - - - # figure out line - buffer_line = line - if buffer_line > len(self.buffer): - for l in range(len(self.buffer) - 1, buffer_line): - self.buffer.append('') - - # figure out column - real_column = column - if len(self.buffer[buffer_line - 1]) < real_column: - self.buffer[buffer_line - 1] = self.buffer[buffer_line - 1] + ' ' * (real_column - len(self.buffer[buffer_line - 1])) - - # python version is occasionally grumpy - try: - vim.current.window.cursor = (buffer_line, real_column - 1) - except: - vim.command('call cursor(' + str(buffer_line) + ', ' + str(real_column) + ')') - - - def idle(self): - """ go into idle mode """ - - self.proc.idle() - - - def resume(self): - """ resume from idle mode """ - - self.proc.resume() - - - def close(self): - """ end console subprocess """ - self.proc.close() - - - def abort(self): - """ end subprocess forcefully """ - self.proc.close() - - - def get_buffer_line(self, line): - """ get buffer line """ - return line - - -# vim:foldmethod=marker diff --git a/autoload/conque_term/conque_sole_communicator.py b/autoload/conque_term/conque_sole_communicator.py deleted file mode 100644 index e3f7db3..0000000 --- a/autoload/conque_term/conque_sole_communicator.py +++ /dev/null @@ -1,183 +0,0 @@ -# FILE: autoload/conque_term/conque_sole_communicator.py -# AUTHOR: Nico Raffo -# WEBSITE: http://conque.googlecode.com -# MODIFIED: 2011-08-12 -# VERSION: 2.2, for Vim 7.0 -# LICENSE: -# Conque - Vim terminal/console emulator -# Copyright (C) 2009-__YEAR__ Nico Raffo -# -# MIT License -# -# 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: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# 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. - -""" - -ConqueSoleCommunicator - -This script will create a new Windows console and start the requested program -inside of it. This process is launched independently from the parent Vim -program, so it has no access to the vim module. - -The main loop in this script reads data from the console and syncs it onto -blocks of memory shared with the Vim process. In this way the Vim process -and this script can communicate with each other. - -""" - -import time -import sys - -from conque_globals import * -from conque_win32_util import * -from conque_sole_subprocess import * -from conque_sole_shared_memory import * - -############################################################## -# only run if this file was run directly - -if __name__ == '__main__': - - # attempt to catch ALL exceptions to fend of zombies - try: - - # simple arg validation - - if len(sys.argv) < 5: - - exit() - - # maximum time this thing reads. 0 means no limit. Only for testing. - max_loops = 0 - - # read interval, in seconds - sleep_time = 0.01 - - # idle read interval, in seconds - idle_sleep_time = 0.10 - - # are we idled? - is_idle = False - - # mem key - mem_key = sys.argv[1] - - # console width - console_width = int(sys.argv[2]) - - # console height - console_height = int(sys.argv[3]) - - # code page - code_page = int(sys.argv[4]) - - # code page - fast_mode = int(sys.argv[5]) - - # the actual subprocess to run - cmd_line = " ".join(sys.argv[6:]) - - - # width and height - options = {'LINES': console_height, 'COLUMNS': console_width, 'CODE_PAGE': code_page, 'FAST_MODE': fast_mode} - - - - # set initial idle status - shm_command = ConqueSoleSharedMemory(CONQUE_SOLE_COMMANDS_SIZE, 'command', mem_key, serialize=True) - shm_command.create('write') - - cmd = shm_command.read() - if cmd: - - if cmd['cmd'] == 'idle': - is_idle = True - shm_command.clear() - - - ############################################################## - # Create the subprocess - - proc = ConqueSoleSubprocess() - res = proc.open(cmd_line, mem_key, options) - - if not res: - - exit() - - ############################################################## - # main loop! - - loops = 0 - - while True: - - # check for idle/resume - if is_idle or loops % 25 == 0: - - # check process health - if not proc.is_alive(): - - proc.close() - break - - # check for change in buffer focus - cmd = shm_command.read() - if cmd: - - if cmd['cmd'] == 'idle': - is_idle = True - shm_command.clear() - - elif cmd['cmd'] == 'resume': - is_idle = False - shm_command.clear() - - - # sleep between loops if moderation is requested - if sleep_time > 0: - if is_idle: - time.sleep(idle_sleep_time) - else: - time.sleep(sleep_time) - - # write, read, etc - proc.write() - proc.read() - - # increment loops, and exit if max has been reached - loops += 1 - if max_loops and loops >= max_loops: - - break - - ############################################################## - # all done! - - - - proc.close() - - # if an exception was thrown, croak - except: - - proc.close() - - -# vim:foldmethod=marker diff --git a/autoload/conque_term/conque_sole_shared_memory.py b/autoload/conque_term/conque_sole_shared_memory.py deleted file mode 100644 index 1d4ed3a..0000000 --- a/autoload/conque_term/conque_sole_shared_memory.py +++ /dev/null @@ -1,210 +0,0 @@ -# FILE: autoload/conque_term/conque_sole_shared_memory.py -# AUTHOR: Nico Raffo -# WEBSITE: http://conque.googlecode.com -# MODIFIED: 2011-08-12 -# VERSION: 2.2, for Vim 7.0 -# LICENSE: -# Conque - Vim terminal/console emulator -# Copyright (C) 2009-__YEAR__ Nico Raffo -# -# MIT License -# -# 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: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# 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. - -""" -Wrapper class for shared memory between Windows python processes - -Adds a small amount of functionality to the standard mmap module. - -""" - -import mmap -import sys - -# PYTHON VERSION -CONQUE_PYTHON_VERSION = sys.version_info[0] - -if CONQUE_PYTHON_VERSION == 2: - import cPickle as pickle -else: - import pickle - - -class ConqueSoleSharedMemory(): - - # is the data being stored not fixed length - fixed_length = False - - # maximum number of bytes per character, for fixed width blocks - char_width = 1 - - # fill memory with this character when clearing and fixed_length is true - FILL_CHAR = None - - # serialize and unserialize data automatically - serialize = False - - # size of shared memory, in bytes / chars - mem_size = None - - # size of shared memory, in bytes / chars - mem_type = None - - # unique key, so multiple console instances are possible - mem_key = None - - # mmap instance - shm = None - - # character encoding, dammit - encoding = 'utf-8' - - # pickle terminator - TERMINATOR = None - - - def __init__(self, mem_size, mem_type, mem_key, fixed_length=False, fill_char=' ', serialize=False, encoding='utf-8'): - """ Initialize new shared memory block instance - - Arguments: - mem_size -- Memory size in characters, depends on encoding argument to calcuate byte size - mem_type -- Label to identify what will be stored - mem_key -- Unique, probably random key to identify this block - fixed_length -- If set to true, assume the data stored will always fill the memory size - fill_char -- Initialize memory block with this character, only really helpful with fixed_length blocks - serialize -- Automatically serialize data passed to write. Allows storing non-byte data - encoding -- Character encoding to use when storing character data - - """ - self.mem_size = mem_size - self.mem_type = mem_type - self.mem_key = mem_key - self.fixed_length = fixed_length - self.fill_char = fill_char - self.serialize = serialize - self.encoding = encoding - self.TERMINATOR = str(chr(0)).encode(self.encoding) - - if CONQUE_PYTHON_VERSION == 3: - self.FILL_CHAR = fill_char - else: - self.FILL_CHAR = unicode(fill_char) - - if fixed_length and encoding == 'utf-8': - self.char_width = 4 - - - def create(self, access='write'): - """ Create a new block of shared memory using the mmap module. """ - - if access == 'write': - mmap_access = mmap.ACCESS_WRITE - else: - mmap_access = mmap.ACCESS_READ - - name = "conque_%s_%s" % (self.mem_type, self.mem_key) - - self.shm = mmap.mmap(0, self.mem_size * self.char_width, name, mmap_access) - - if not self.shm: - return False - else: - return True - - - def read(self, chars=1, start=0): - """ Read data from shared memory. - - If this is a fixed length block, read 'chars' characters from memory. - Otherwise read up until the TERMINATOR character (null byte). - If this memory is serialized, unserialize it automatically. - - """ - # go to start position - self.shm.seek(start * self.char_width) - - if self.fixed_length: - chars = chars * self.char_width - else: - chars = self.shm.find(self.TERMINATOR) - - if chars == 0: - return '' - - shm_str = self.shm.read(chars) - - # return unpickled byte object - if self.serialize: - return pickle.loads(shm_str) - - # decode byes in python 3 - if CONQUE_PYTHON_VERSION == 3: - return str(shm_str, self.encoding) - - # encoding - if self.encoding != 'ascii': - shm_str = unicode(shm_str, self.encoding) - - return shm_str - - - def write(self, text, start=0): - """ Write data to memory. - - If memory is fixed length, simply write the 'text' characters at 'start' position. - Otherwise write 'text' characters and append a null character. - If memory is serializable, do so first. - - """ - # simple scenario, let pickle create bytes - if self.serialize: - if CONQUE_PYTHON_VERSION == 3: - tb = pickle.dumps(text, 0) - else: - tb = pickle.dumps(text, 0).encode(self.encoding) - - else: - tb = text.encode(self.encoding, 'replace') - - # write to memory - self.shm.seek(start * self.char_width) - - if self.fixed_length: - self.shm.write(tb) - else: - self.shm.write(tb + self.TERMINATOR) - - - def clear(self, start=0): - """ Clear memory block using self.fill_char. """ - - self.shm.seek(start) - - if self.fixed_length: - self.shm.write(str(self.fill_char * self.mem_size * self.char_width).encode(self.encoding)) - else: - self.shm.write(self.TERMINATOR) - - - def close(self): - """ Close/destroy memory block. """ - - self.shm.close() - - diff --git a/autoload/conque_term/conque_sole_subprocess.py b/autoload/conque_term/conque_sole_subprocess.py deleted file mode 100644 index 0f205b6..0000000 --- a/autoload/conque_term/conque_sole_subprocess.py +++ /dev/null @@ -1,762 +0,0 @@ -# FILE: autoload/conque_term/conque_sole_subprocess.py -# AUTHOR: Nico Raffo -# WEBSITE: http://conque.googlecode.com -# MODIFIED: 2011-08-12 -# VERSION: 2.2, for Vim 7.0 -# LICENSE: -# Conque - Vim terminal/console emulator -# Copyright (C) 2009-__YEAR__ Nico Raffo -# -# MIT License -# -# 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: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# 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. - -""" ConqueSoleSubprocess - -Creates a new subprocess with it's own (hidden) console window. - -Mirrors console window text onto a block of shared memory (mmap), along with -text attribute data. Also handles translation of text input into the format -Windows console expects. - -Sample Usage: - - sh = ConqueSoleSubprocess() - sh.open("cmd.exe", "unique_str") - - shm_in = ConqueSoleSharedMemory(mem_key = "unique_str", mem_type = "input", ...) - shm_out = ConqueSoleSharedMemory(mem_key = "unique_str", mem_type = "output", ...) - - output = shm_out.read(...) - shm_in.write("dir\r") - output = shm_out.read(...) - -""" - -import time -import re -import os -import ctypes - -from conque_globals import * -from conque_win32_util import * -from conque_sole_shared_memory import * - - -class ConqueSoleSubprocess(): - - # subprocess handle and pid - handle = None - pid = None - - # input / output handles - stdin = None - stdout = None - - # size of console window - window_width = 160 - window_height = 40 - - # max lines for the console buffer - buffer_width = 160 - buffer_height = 100 - - # keep track of the buffer number at the top of the window - top = 0 - line_offset = 0 - - # buffer height is CONQUE_SOLE_BUFFER_LENGTH * output_blocks - output_blocks = 1 - - # cursor position - cursor_line = 0 - cursor_col = 0 - - # console data, array of lines - data = [] - - # console attribute data, array of array of int - attributes = [] - attribute_cache = {} - - # default attribute - default_attribute = 7 - - # shared memory objects - shm_input = None - shm_output = None - shm_attributes = None - shm_stats = None - shm_command = None - shm_rescroll = None - shm_resize = None - - # are we still a valid process? - is_alive = True - - # running in fast mode - fast_mode = 0 - - # used for periodic execution of screen and memory redrawing - screen_redraw_ct = 0 - mem_redraw_ct = 0 - - - def open(self, cmd, mem_key, options={}): - """ Create subproccess running in hidden console window. """ - - - - self.reset = True - - try: - # if we're already attached to a console, then unattach - try: - ctypes.windll.kernel32.FreeConsole() - except: - pass - - # set buffer height - self.buffer_height = CONQUE_SOLE_BUFFER_LENGTH - - if 'LINES' in options and 'COLUMNS' in options: - self.window_width = options['COLUMNS'] - self.window_height = options['LINES'] - self.buffer_width = options['COLUMNS'] - - # fast mode - self.fast_mode = options['FAST_MODE'] - - # console window options - si = STARTUPINFO() - - # hide window - si.dwFlags |= STARTF_USESHOWWINDOW - si.wShowWindow = SW_HIDE - #si.wShowWindow = SW_MINIMIZE - - # process options - flags = NORMAL_PRIORITY_CLASS | CREATE_NEW_PROCESS_GROUP | CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE - - # created process info - pi = PROCESS_INFORMATION() - - - - # create the process! - res = ctypes.windll.kernel32.CreateProcessW(None, u(cmd), None, None, 0, flags, None, u('.'), ctypes.byref(si), ctypes.byref(pi)) - - - - - - # process info - self.pid = pi.dwProcessId - self.handle = pi.hProcess - - - - - # attach ourselves to the new console - # console is not immediately available - for i in range(10): - time.sleep(0.25) - try: - - res = ctypes.windll.kernel32.AttachConsole(self.pid) - - - - - - - break - except: - - pass - - # get input / output handles - self.stdout = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE) - self.stdin = ctypes.windll.kernel32.GetStdHandle(STD_INPUT_HANDLE) - - # set buffer size - size = COORD(self.buffer_width, self.buffer_height) - res = ctypes.windll.kernel32.SetConsoleScreenBufferSize(self.stdout, size) - - - - - - - - # prev set size call needs to process - time.sleep(0.2) - - # set window size - self.set_window_size(self.window_width, self.window_height) - - # set utf-8 code page - if 'CODE_PAGE' in options and options['CODE_PAGE'] > 0: - if ctypes.windll.kernel32.IsValidCodePage(ctypes.c_uint(options['CODE_PAGE'])): - - ctypes.windll.kernel32.SetConsoleCP(ctypes.c_uint(options['CODE_PAGE'])) - ctypes.windll.kernel32.SetConsoleOutputCP(ctypes.c_uint(options['CODE_PAGE'])) - - # init shared memory - self.init_shared_memory(mem_key) - - # init read buffers - self.tc = ctypes.create_unicode_buffer(self.buffer_width) - self.ac = ctypes.create_unicode_buffer(self.buffer_width) - - return True - - except: - - return False - - - def init_shared_memory(self, mem_key): - """ Create shared memory objects. """ - - self.shm_input = ConqueSoleSharedMemory(CONQUE_SOLE_INPUT_SIZE, 'input', mem_key) - self.shm_input.create('write') - self.shm_input.clear() - - self.shm_output = ConqueSoleSharedMemory(self.buffer_height * self.buffer_width, 'output', mem_key, True) - self.shm_output.create('write') - self.shm_output.clear() - - if not self.fast_mode: - buf_info = self.get_buffer_info() - self.shm_attributes = ConqueSoleSharedMemory(self.buffer_height * self.buffer_width, 'attributes', mem_key, True, chr(buf_info.wAttributes), encoding='latin-1') - self.shm_attributes.create('write') - self.shm_attributes.clear() - - self.shm_stats = ConqueSoleSharedMemory(CONQUE_SOLE_STATS_SIZE, 'stats', mem_key, serialize=True) - self.shm_stats.create('write') - self.shm_stats.clear() - - self.shm_command = ConqueSoleSharedMemory(CONQUE_SOLE_COMMANDS_SIZE, 'command', mem_key, serialize=True) - self.shm_command.create('write') - self.shm_command.clear() - - self.shm_resize = ConqueSoleSharedMemory(CONQUE_SOLE_RESIZE_SIZE, 'resize', mem_key, serialize=True) - self.shm_resize.create('write') - self.shm_resize.clear() - - self.shm_rescroll = ConqueSoleSharedMemory(CONQUE_SOLE_RESCROLL_SIZE, 'rescroll', mem_key, serialize=True) - self.shm_rescroll.create('write') - self.shm_rescroll.clear() - - return True - - - def check_commands(self): - """ Check for and process commands from Vim. """ - - cmd = self.shm_command.read() - - if cmd: - - # shut it all down - if cmd['cmd'] == 'close': - - # clear command - self.shm_command.clear() - - self.close() - return - - cmd = self.shm_resize.read() - - if cmd: - - # clear command - self.shm_resize.clear() - - # resize console - if cmd['cmd'] == 'resize': - - - - # only change buffer width if it's larger - if cmd['data']['width'] > self.buffer_width: - self.buffer_width = cmd['data']['width'] - - # always change console width and height - self.window_width = cmd['data']['width'] - self.window_height = cmd['data']['height'] - - # reset the console - buf_info = self.get_buffer_info() - self.reset_console(buf_info, add_block=False) - - - def read(self): - """ Read from windows console and update shared memory blocks. """ - - # no point really - if self.screen_redraw_ct == 0 and not self.is_alive(): - stats = {'top_offset': 0, 'default_attribute': 0, 'cursor_x': 0, 'cursor_y': self.cursor_line, 'is_alive': 0} - - self.shm_stats.write(stats) - return - - # check for commands - self.check_commands() - - # get cursor position - buf_info = self.get_buffer_info() - curs_line = buf_info.dwCursorPosition.Y - curs_col = buf_info.dwCursorPosition.X - - # set update range - if curs_line != self.cursor_line or self.top != buf_info.srWindow.Top or self.screen_redraw_ct == CONQUE_SOLE_SCREEN_REDRAW: - self.screen_redraw_ct = 0 - - read_start = self.top - read_end = max([buf_info.srWindow.Bottom + 1, curs_line + 1]) - else: - - read_start = curs_line - read_end = curs_line + 1 - - - - - # vars used in for loop - coord = COORD(0, 0) - chars_read = ctypes.c_int(0) - - # read new data - for i in range(read_start, read_end): - - coord.Y = i - - res = ctypes.windll.kernel32.ReadConsoleOutputCharacterW(self.stdout, ctypes.byref(self.tc), self.buffer_width, coord, ctypes.byref(chars_read)) - if not self.fast_mode: - ctypes.windll.kernel32.ReadConsoleOutputAttribute(self.stdout, ctypes.byref(self.ac), self.buffer_width, coord, ctypes.byref(chars_read)) - - t = self.tc.value - if not self.fast_mode: - a = self.ac.value - - # add data - if i >= len(self.data): - for j in range(len(self.data), i + 1): - self.data.append('') - if not self.fast_mode: - self.attributes.append('') - - self.data[i] = t - if not self.fast_mode: - self.attributes[i] = a - - - - - #for i in range(0, len(t)): - - - - - # write new output to shared memory - try: - if self.mem_redraw_ct == CONQUE_SOLE_MEM_REDRAW: - self.mem_redraw_ct = 0 - - for i in range(0, len(self.data)): - self.shm_output.write(text=self.data[i], start=self.buffer_width * i) - if not self.fast_mode: - self.shm_attributes.write(text=self.attributes[i], start=self.buffer_width * i) - else: - - for i in range(read_start, read_end): - self.shm_output.write(text=self.data[i], start=self.buffer_width * i) - if not self.fast_mode: - self.shm_attributes.write(text=self.attributes[i], start=self.buffer_width * i) - #self.shm_output.write(text=''.join(self.data[read_start:read_end]), start=read_start * self.buffer_width) - #self.shm_attributes.write(text=''.join(self.attributes[read_start:read_end]), start=read_start * self.buffer_width) - - # write cursor position to shared memory - stats = {'top_offset': buf_info.srWindow.Top, 'default_attribute': buf_info.wAttributes, 'cursor_x': curs_col, 'cursor_y': curs_line, 'is_alive': 1} - self.shm_stats.write(stats) - - # adjust screen position - self.top = buf_info.srWindow.Top - self.cursor_line = curs_line - - # check for reset - if curs_line > buf_info.dwSize.Y - 200: - self.reset_console(buf_info) - - except: - - - - - pass - - # increment redraw counters - self.screen_redraw_ct += 1 - self.mem_redraw_ct += 1 - - return None - - - def reset_console(self, buf_info, add_block=True): - """ Extend the height of the current console if the cursor postion gets within 200 lines of the current size. """ - - # sometimes we just want to change the buffer width, - # in which case no need to add another block - if add_block: - self.output_blocks += 1 - - # close down old memory - self.shm_output.close() - self.shm_output = None - - if not self.fast_mode: - self.shm_attributes.close() - self.shm_attributes = None - - # new shared memory key - mem_key = 'mk' + str(time.time()) - - # reallocate memory - self.shm_output = ConqueSoleSharedMemory(self.buffer_height * self.buffer_width * self.output_blocks, 'output', mem_key, True) - self.shm_output.create('write') - self.shm_output.clear() - - # backfill data - if len(self.data[0]) < self.buffer_width: - for i in range(0, len(self.data)): - self.data[i] = self.data[i] + ' ' * (self.buffer_width - len(self.data[i])) - self.shm_output.write(''.join(self.data)) - - if not self.fast_mode: - self.shm_attributes = ConqueSoleSharedMemory(self.buffer_height * self.buffer_width * self.output_blocks, 'attributes', mem_key, True, chr(buf_info.wAttributes), encoding='latin-1') - self.shm_attributes.create('write') - self.shm_attributes.clear() - - # backfill attributes - if len(self.attributes[0]) < self.buffer_width: - for i in range(0, len(self.attributes)): - self.attributes[i] = self.attributes[i] + chr(buf_info.wAttributes) * (self.buffer_width - len(self.attributes[i])) - if not self.fast_mode: - self.shm_attributes.write(''.join(self.attributes)) - - # notify wrapper of new output block - self.shm_rescroll.write({'cmd': 'new_output', 'data': {'blocks': self.output_blocks, 'mem_key': mem_key}}) - - # set buffer size - size = COORD(X=self.buffer_width, Y=self.buffer_height * self.output_blocks) - - res = ctypes.windll.kernel32.SetConsoleScreenBufferSize(self.stdout, size) - - - - - - - # prev set size call needs to process - time.sleep(0.2) - - # set window size - self.set_window_size(self.window_width, self.window_height) - - # init read buffers - self.tc = ctypes.create_unicode_buffer(self.buffer_width) - self.ac = ctypes.create_unicode_buffer(self.buffer_width) - - - - def write(self): - """ Write text to console. - - This function just parses out special sequences for special key events - and passes on the text to the plain or virtual key functions. - - """ - # get input from shared mem - text = self.shm_input.read() - - # nothing to do here - if text == u(''): - return - - - - # clear input queue - self.shm_input.clear() - - # split on VK codes - chunks = CONQUE_WIN32_REGEX_VK.split(text) - - # if len() is one then no vks - if len(chunks) == 1: - self.write_plain(text) - return - - - - # loop over chunks and delegate - for t in chunks: - - if t == '': - continue - - if CONQUE_WIN32_REGEX_VK.match(t): - - self.write_vk(t[2:-2]) - else: - self.write_plain(t) - - - def write_plain(self, text): - """ Write simple text to subprocess. """ - - li = INPUT_RECORD * len(text) - list_input = li() - - for i in range(0, len(text)): - - # create keyboard input - ke = KEY_EVENT_RECORD() - ke.bKeyDown = ctypes.c_byte(1) - ke.wRepeatCount = ctypes.c_short(1) - - cnum = ord(text[i]) - - ke.wVirtualKeyCode = ctypes.windll.user32.VkKeyScanW(cnum) - ke.wVirtualScanCode = ctypes.c_short(ctypes.windll.user32.MapVirtualKeyW(int(cnum), 0)) - - if cnum > 31: - ke.uChar.UnicodeChar = uchr(cnum) - elif cnum == 3: - ctypes.windll.kernel32.GenerateConsoleCtrlEvent(0, self.pid) - ke.uChar.UnicodeChar = uchr(cnum) - ke.wVirtualKeyCode = ctypes.windll.user32.VkKeyScanW(cnum + 96) - ke.dwControlKeyState |= LEFT_CTRL_PRESSED - else: - ke.uChar.UnicodeChar = uchr(cnum) - if cnum in CONQUE_WINDOWS_VK_INV: - ke.wVirtualKeyCode = cnum - else: - ke.wVirtualKeyCode = ctypes.windll.user32.VkKeyScanW(cnum + 96) - ke.dwControlKeyState |= LEFT_CTRL_PRESSED - - - - - kc = INPUT_RECORD(KEY_EVENT) - kc.Event.KeyEvent = ke - list_input[i] = kc - - - - # write input array - events_written = ctypes.c_int() - res = ctypes.windll.kernel32.WriteConsoleInputW(self.stdin, list_input, len(text), ctypes.byref(events_written)) - - - - - - - - - def write_vk(self, vk_code): - """ Write special characters to console subprocess. """ - - - - code = None - ctrl_pressed = False - - # this could be made more generic when more attributes - # other than ctrl_pressed are available - vk_attributes = vk_code.split(';') - - for attr in vk_attributes: - if attr == CONQUE_VK_ATTR_CTRL_PRESSED: - ctrl_pressed = True - else: - code = attr - - li = INPUT_RECORD * 1 - - # create keyboard input - ke = KEY_EVENT_RECORD() - ke.uChar.UnicodeChar = uchr(0) - ke.wVirtualKeyCode = ctypes.c_short(int(code)) - ke.wVirtualScanCode = ctypes.c_short(ctypes.windll.user32.MapVirtualKeyW(int(code), 0)) - ke.bKeyDown = ctypes.c_byte(1) - ke.wRepeatCount = ctypes.c_short(1) - - # set enhanced key mode for arrow keys - if code in CONQUE_WINDOWS_VK_ENHANCED: - - ke.dwControlKeyState |= ENHANCED_KEY - - if ctrl_pressed: - ke.dwControlKeyState |= LEFT_CTRL_PRESSED - - kc = INPUT_RECORD(KEY_EVENT) - kc.Event.KeyEvent = ke - list_input = li(kc) - - # write input array - events_written = ctypes.c_int() - res = ctypes.windll.kernel32.WriteConsoleInputW(self.stdin, list_input, 1, ctypes.byref(events_written)) - - - - - - - - def close(self): - """ Close all running subproccesses """ - - # record status - self.is_alive = False - try: - stats = {'top_offset': 0, 'default_attribute': 0, 'cursor_x': 0, 'cursor_y': self.cursor_line, 'is_alive': 0} - self.shm_stats.write(stats) - except: - pass - - pid_list = (ctypes.c_int * 10)() - num = ctypes.windll.kernel32.GetConsoleProcessList(pid_list, 10) - - - - current_pid = os.getpid() - - - - - - # kill subprocess pids - for pid in pid_list[0:num]: - if not pid: - break - - # kill current pid last - if pid == current_pid: - continue - try: - self.close_pid(pid) - except: - - pass - - # kill this process - try: - self.close_pid(current_pid) - except: - - pass - - - def close_pid(self, pid): - """ Terminate a single process. """ - - - handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, 0, pid) - ctypes.windll.kernel32.TerminateProcess(handle, -1) - ctypes.windll.kernel32.CloseHandle(handle) - - - def is_alive(self): - """ Check process health. """ - - status = ctypes.windll.kernel32.WaitForSingleObject(self.handle, 1) - - if status == 0: - - self.is_alive = False - - return self.is_alive - - - def get_screen_text(self): - """ Return screen data as string. """ - - return "\n".join(self.data) - - - def set_window_size(self, width, height): - """ Change Windows console size. """ - - - - # get current window size object - window_size = SMALL_RECT(0, 0, 0, 0) - - # buffer info has maximum window size data - buf_info = self.get_buffer_info() - - - # set top left corner - window_size.Top = 0 - window_size.Left = 0 - - # set bottom right corner - if buf_info.dwMaximumWindowSize.X < width: - - window_size.Right = buf_info.dwMaximumWindowSize.X - 1 - else: - window_size.Right = width - 1 - - if buf_info.dwMaximumWindowSize.Y < height: - - window_size.Bottom = buf_info.dwMaximumWindowSize.Y - 1 - else: - window_size.Bottom = height - 1 - - - - # set the window size! - res = ctypes.windll.kernel32.SetConsoleWindowInfo(self.stdout, ctypes.c_bool(True), ctypes.byref(window_size)) - - - - - - - # reread buffer info to get final console max lines - buf_info = self.get_buffer_info() - - self.window_width = buf_info.srWindow.Right + 1 - self.window_height = buf_info.srWindow.Bottom + 1 - - - def get_buffer_info(self): - """ Retrieve commonly-used buffer information. """ - - buf_info = CONSOLE_SCREEN_BUFFER_INFO() - ctypes.windll.kernel32.GetConsoleScreenBufferInfo(self.stdout, ctypes.byref(buf_info)) - - return buf_info - - - diff --git a/autoload/conque_term/conque_sole_wrapper.py b/autoload/conque_term/conque_sole_wrapper.py deleted file mode 100644 index 4e4816f..0000000 --- a/autoload/conque_term/conque_sole_wrapper.py +++ /dev/null @@ -1,278 +0,0 @@ -# FILE: autoload/conque_term/conque_sole_wrapper.py -# AUTHOR: Nico Raffo -# WEBSITE: http://conque.googlecode.com -# MODIFIED: 2011-08-12 -# VERSION: 2.2, for Vim 7.0 -# LICENSE: -# Conque - Vim terminal/console emulator -# Copyright (C) 2009-__YEAR__ Nico Raffo -# -# MIT License -# -# 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: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# 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. - -""" - -ConqueSoleSubprocessWrapper - -Subprocess wrapper to deal with Windows insanity. Launches console based python, -which in turn launches originally requested command. Communicates with cosole -python through shared memory objects. - -""" - -import ctypes -import time - - -class ConqueSoleWrapper(): - - # unique key used for shared memory block names - shm_key = '' - - # process info - handle = None - pid = None - - # queue input in this bucket - bucket = None - - # console size - lines = 24 - columns = 80 - - # shared memory objects - shm_input = None - shm_output = None - shm_attributes = None - shm_stats = None - shm_command = None - shm_rescroll = None - shm_resize = None - - # console python process - proc = None - - - def open(self, cmd, lines, columns, python_exe='python.exe', communicator_py='conque_sole_communicator.py', options={}): - """ Launch python.exe subprocess which will in turn launch the user's program. - - Arguments: - cmd -- The user's command to run. E.g. "Powershell.exe" or "C:\Python27\Scripts\ipython.bat" - lines, columns -- The size of the console, also the size of the Vim buffer - python.exe -- The path to the python executable, typically C:\PythonXX\python.exe - communicator_py -- The path to the subprocess controller script in the user's vimfiles directory - options -- optional configuration - - """ - self.lines = lines - self.columns = columns - self.bucket = u('') - - # create a shm key - self.shm_key = 'mk' + str(time.time()) - - # python command - cmd_line = '%s "%s" %s %d %d %d %d %s' % (python_exe, communicator_py, self.shm_key, int(self.columns), int(self.lines), int(options['CODE_PAGE']), int(CONQUE_FAST_MODE), cmd) - - - # console window attributes - flags = NORMAL_PRIORITY_CLASS | DETACHED_PROCESS | CREATE_UNICODE_ENVIRONMENT - si = STARTUPINFO() - pi = PROCESS_INFORMATION() - - # start the stupid process already - try: - res = ctypes.windll.kernel32.CreateProcessW(None, u(cmd_line), None, None, 0, flags, None, u('.'), ctypes.byref(si), ctypes.byref(pi)) - except: - - raise - - # handle - self.pid = pi.dwProcessId - - - - # init shared memory objects - self.init_shared_memory(self.shm_key) - - - def read(self, start_line, num_lines, timeout=0): - """ Read a range of console lines from shared memory. - - Returns a pair of lists containing the console text and console text attributes. - - """ - # emulate timeout by sleeping timeout time - if timeout > 0: - read_timeout = float(timeout) / 1000 - - time.sleep(read_timeout) - - output = [] - attributes = [] - - # get output - for i in range(start_line, start_line + num_lines + 1): - output.append(self.shm_output.read(self.columns, i * self.columns)) - if not CONQUE_FAST_MODE: - attributes.append(self.shm_attributes.read(self.columns, i * self.columns)) - - return (output, attributes) - - - def get_stats(self): - """ Return a dictionary with current console cursor and scrolling information. """ - - try: - rescroll = self.shm_rescroll.read() - if rescroll != '' and rescroll != None: - - - - self.shm_rescroll.clear() - - # close down old memory - self.shm_output.close() - self.shm_output = None - - if not CONQUE_FAST_MODE: - self.shm_attributes.close() - self.shm_attributes = None - - # reallocate memory - - self.shm_output = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns * rescroll['data']['blocks'], 'output', rescroll['data']['mem_key'], True) - self.shm_output.create('read') - - if not CONQUE_FAST_MODE: - self.shm_attributes = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns * rescroll['data']['blocks'], 'attributes', rescroll['data']['mem_key'], True, encoding='latin-1') - self.shm_attributes.create('read') - - stats_str = self.shm_stats.read() - if stats_str != '': - self.stats = stats_str - else: - return False - except: - - return False - - return self.stats - - - def is_alive(self): - """ Get process status. """ - - if not self.shm_stats: - return True - - stats_str = self.shm_stats.read() - if stats_str: - return (stats_str['is_alive']) - else: - return True - - - def write(self, text): - """ Write input to shared memory. """ - - self.bucket += text - - istr = self.shm_input.read() - - if istr == '': - - self.shm_input.write(self.bucket[:500]) - self.bucket = self.bucket[500:] - - - def write_vk(self, vk_code): - """ Write virtual key code to shared memory using proprietary escape sequences. """ - - seq = u("\x1b[") + u(str(vk_code)) + u("VK") - self.write(seq) - - - def idle(self): - """ Write idle command to shared memory block, so subprocess controller can hibernate. """ - - - self.shm_command.write({'cmd': 'idle', 'data': {}}) - - - def resume(self): - """ Write resume command to shared memory block, so subprocess controller can wake up. """ - - self.shm_command.write({'cmd': 'resume', 'data': {}}) - - - def close(self): - """ Shut it all down. """ - - self.shm_command.write({'cmd': 'close', 'data': {}}) - time.sleep(0.2) - - - def window_resize(self, lines, columns): - """ Resize console window. """ - - self.lines = lines - - # we don't shrink buffer width - if columns > self.columns: - self.columns = columns - - self.shm_resize.write({'cmd': 'resize', 'data': {'width': columns, 'height': lines}}) - - - def init_shared_memory(self, mem_key): - """ Create shared memory objects. """ - - self.shm_input = ConqueSoleSharedMemory(CONQUE_SOLE_INPUT_SIZE, 'input', mem_key) - self.shm_input.create('write') - self.shm_input.clear() - - self.shm_output = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns, 'output', mem_key, True) - self.shm_output.create('write') - - if not CONQUE_FAST_MODE: - self.shm_attributes = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns, 'attributes', mem_key, True, encoding='latin-1') - self.shm_attributes.create('write') - - self.shm_stats = ConqueSoleSharedMemory(CONQUE_SOLE_STATS_SIZE, 'stats', mem_key, serialize=True) - self.shm_stats.create('write') - self.shm_stats.clear() - - self.shm_command = ConqueSoleSharedMemory(CONQUE_SOLE_COMMANDS_SIZE, 'command', mem_key, serialize=True) - self.shm_command.create('write') - self.shm_command.clear() - - self.shm_resize = ConqueSoleSharedMemory(CONQUE_SOLE_RESIZE_SIZE, 'resize', mem_key, serialize=True) - self.shm_resize.create('write') - self.shm_resize.clear() - - self.shm_rescroll = ConqueSoleSharedMemory(CONQUE_SOLE_RESCROLL_SIZE, 'rescroll', mem_key, serialize=True) - self.shm_rescroll.create('write') - self.shm_rescroll.clear() - - return True - - -# vim:foldmethod=marker diff --git a/autoload/conque_term/conque_subprocess.py b/autoload/conque_term/conque_subprocess.py deleted file mode 100644 index 87d93c3..0000000 --- a/autoload/conque_term/conque_subprocess.py +++ /dev/null @@ -1,198 +0,0 @@ -# FILE: autoload/conque_term/conque_subprocess.py -# AUTHOR: Nico Raffo -# WEBSITE: http://conque.googlecode.com -# MODIFIED: 2011-08-12 -# VERSION: 2.2, for Vim 7.0 -# LICENSE: -# Conque - Vim terminal/console emulator -# Copyright (C) 2009-__YEAR__ Nico Raffo -# -# MIT License -# -# 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: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# 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. - -""" -ConqueSubprocess - -Create and interact with a subprocess through a pty. - -Usage: - - p = ConqueSubprocess() - p.open('bash', {'TERM':'vt100'}) - output = p.read() - p.write('cd ~/vim' + "\r") - p.write('ls -lha' + "\r") - output += p.read(timeout = 500) - p.close() -""" - -import os -import signal -import pty -import tty -import select -import fcntl -import termios -import struct -import shlex - - -class ConqueSubprocess: - - # process id - pid = 0 - - # stdout+stderr file descriptor - fd = None - - - def open(self, command, env={}): - """ Create subprocess using forkpty() """ - - # parse command - command_arr = shlex.split(command) - executable = command_arr[0] - args = command_arr - - # try to fork a new pty - try: - self.pid, self.fd = pty.fork() - - except: - - return False - - # child proc, replace with command after altering terminal attributes - if self.pid == 0: - - # set requested environment variables - for k in env.keys(): - os.environ[k] = env[k] - - # set tty attributes - try: - attrs = tty.tcgetattr(1) - attrs[0] = attrs[0] ^ tty.IGNBRK - attrs[0] = attrs[0] | tty.BRKINT | tty.IXANY | tty.IMAXBEL - attrs[2] = attrs[2] | tty.HUPCL - attrs[3] = attrs[3] | tty.ICANON | tty.ECHO | tty.ISIG | tty.ECHOKE - attrs[6][tty.VMIN] = 1 - attrs[6][tty.VTIME] = 0 - tty.tcsetattr(1, tty.TCSANOW, attrs) - except: - - pass - - # replace this process with the subprocess - os.execvp(executable, args) - - # else master, do nothing - else: - pass - - - def read(self, timeout=1): - """ Read from subprocess and return new output """ - - output = '' - read_timeout = float(timeout) / 1000 - read_ct = 0 - - try: - # read from fd until no more output - while 1: - s_read, s_write, s_error = select.select([self.fd], [], [], read_timeout) - - lines = '' - for s_fd in s_read: - try: - # increase read buffer so huge reads don't slow down - if read_ct < 10: - lines = os.read(self.fd, 32) - elif read_ct < 50: - lines = os.read(self.fd, 512) - else: - lines = os.read(self.fd, 2048) - read_ct += 1 - except: - pass - output = output + lines.decode('utf-8') - - if lines == '' or read_ct > 100: - break - except: - - pass - - return output - - - def write(self, input): - """ Write new input to subprocess """ - - try: - if CONQUE_PYTHON_VERSION == 2: - os.write(self.fd, input.encode('utf-8', 'ignore')) - else: - os.write(self.fd, bytes(input, 'utf-8')) - except: - - pass - - - def signal(self, signum): - """ signal process """ - - try: - os.kill(self.pid, signum) - except: - pass - - - def close(self): - """ close process with sigterm signal """ - - self.signal(15) - - - def is_alive(self): - """ get process status """ - - p_status = True - try: - if os.waitpid(self.pid, os.WNOHANG)[0]: - p_status = False - except: - p_status = False - - return p_status - - - def window_resize(self, lines, columns): - """ update window size in kernel, then send SIGWINCH to fg process """ - - try: - fcntl.ioctl(self.fd, termios.TIOCSWINSZ, struct.pack("HHHH", lines, columns, 0, 0)) - os.kill(self.pid, signal.SIGWINCH) - except: - pass - - -# vim:foldmethod=marker diff --git a/autoload/conque_term/conque_win32_util.py b/autoload/conque_term/conque_win32_util.py deleted file mode 100644 index 6ae7652..0000000 --- a/autoload/conque_term/conque_win32_util.py +++ /dev/null @@ -1,448 +0,0 @@ -# FILE: autoload/conque_term/conque_win32_util.py -# AUTHOR: Nico Raffo -# WEBSITE: http://conque.googlecode.com -# MODIFIED: 2011-08-12 -# VERSION: 2.2, for Vim 7.0 -# LICENSE: -# Conque - Vim terminal/console emulator -# Copyright (C) 2009-__YEAR__ Nico Raffo -# -# MIT License -# -# 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: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# 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. - -""" Python constants and structures used for ctypes interaction. """ - -from ctypes import * - -# Constants - -# create process flag constants - -CREATE_BREAKAWAY_FROM_JOB = 0x01000000 -CREATE_DEFAULT_ERROR_MODE = 0x04000000 -CREATE_NEW_CONSOLE = 0x00000010 -CREATE_NEW_PROCESS_GROUP = 0x00000200 -CREATE_NO_WINDOW = 0x08000000 -CREATE_PROTECTED_PROCESS = 0x00040000 -CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000 -CREATE_SEPARATE_WOW_VDM = 0x00000800 -CREATE_SHARED_WOW_VDM = 0x00001000 -CREATE_SUSPENDED = 0x00000004 -CREATE_UNICODE_ENVIRONMENT = 0x00000400 -DEBUG_ONLY_THIS_PROCESS = 0x00000002 -DEBUG_PROCESS = 0x00000001 -DETACHED_PROCESS = 0x00000008 -EXTENDED_STARTUPINFO_PRESENT = 0x00080000 -INHERIT_PARENT_AFFINITY = 0x00010000 - - -# process priority constants - -ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000 -BELOW_NORMAL_PRIORITY_CLASS = 0x00004000 -HIGH_PRIORITY_CLASS = 0x00000080 -IDLE_PRIORITY_CLASS = 0x00000040 -NORMAL_PRIORITY_CLASS = 0x00000020 -REALTIME_PRIORITY_CLASS = 0x00000100 - - -# startup info constants - -STARTF_FORCEONFEEDBACK = 0x00000040 -STARTF_FORCEOFFFEEDBACK = 0x00000080 -STARTF_PREVENTPINNING = 0x00002000 -STARTF_RUNFULLSCREEN = 0x00000020 -STARTF_TITLEISAPPID = 0x00001000 -STARTF_TITLEISLINKNAME = 0x00000800 -STARTF_USECOUNTCHARS = 0x00000008 -STARTF_USEFILLATTRIBUTE = 0x00000010 -STARTF_USEHOTKEY = 0x00000200 -STARTF_USEPOSITION = 0x00000004 -STARTF_USESHOWWINDOW = 0x00000001 -STARTF_USESIZE = 0x00000002 -STARTF_USESTDHANDLES = 0x00000100 - - -# show window constants - -SW_FORCEMINIMIZE = 11 -SW_HIDE = 0 -SW_MAXIMIZE = 3 -SW_MINIMIZE = 6 -SW_RESTORE = 9 -SW_SHOW = 5 -SW_SHOWDEFAULT = 10 -SW_SHOWMAXIMIZED = 3 -SW_SHOWMINIMIZED = 2 -SW_SHOWMINNOACTIVE = 7 -SW_SHOWNA = 8 -SW_SHOWNOACTIVATE = 4 -SW_SHOWNORMAL = 1 - - -# input event types - -FOCUS_EVENT = 0x0010 -KEY_EVENT = 0x0001 -MENU_EVENT = 0x0008 -MOUSE_EVENT = 0x0002 -WINDOW_BUFFER_SIZE_EVENT = 0x0004 - - -# key event modifiers - -CAPSLOCK_ON = 0x0080 -ENHANCED_KEY = 0x0100 -LEFT_ALT_PRESSED = 0x0002 -LEFT_CTRL_PRESSED = 0x0008 -NUMLOCK_ON = 0x0020 -RIGHT_ALT_PRESSED = 0x0001 -RIGHT_CTRL_PRESSED = 0x0004 -SCROLLLOCK_ON = 0x0040 -SHIFT_PRESSED = 0x0010 - - -# process access - -PROCESS_CREATE_PROCESS = 0x0080 -PROCESS_CREATE_THREAD = 0x0002 -PROCESS_DUP_HANDLE = 0x0040 -PROCESS_QUERY_INFORMATION = 0x0400 -PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 -PROCESS_SET_INFORMATION = 0x0200 -PROCESS_SET_QUOTA = 0x0100 -PROCESS_SUSPEND_RESUME = 0x0800 -PROCESS_TERMINATE = 0x0001 -PROCESS_VM_OPERATION = 0x0008 -PROCESS_VM_READ = 0x0010 -PROCESS_VM_WRITE = 0x0020 - - -# input / output handles - -STD_INPUT_HANDLE = c_ulong(-10) -STD_OUTPUT_HANDLE = c_ulong(-11) -STD_ERROR_HANDLE = c_ulong(-12) - - -CONQUE_WINDOWS_VK = { - 'VK_LBUTTON': 0x0001, - 'VK_RBUTTON': 0x0002, - 'VK_CANCEL': 0x0003, - 'VK_BACK': 0x0008, - 'VK_TAB': 0x0009, - 'VK_CLEAR': 0x000C, - 'VK_RETURN': 0x0D, - 'VK_SHIFT': 0x10, - 'VK_CONTROL': 0x11, - 'VK_MENU': 0x12, - 'VK_PAUSE': 0x0013, - 'VK_CAPITAL': 0x0014, - 'VK_ESCAPE': 0x001B, - 'VK_SPACE': 0x0020, - 'VK_PRIOR': 0x0021, - 'VK_NEXT': 0x0022, - 'VK_END': 0x0023, - 'VK_HOME': 0x0024, - 'VK_LEFT': 0x0025, - 'VK_UP': 0x0026, - 'VK_RIGHT': 0x0027, - 'VK_DOWN': 0x0028, - 'VK_SELECT': 0x0029, - 'VK_PRINT': 0x002A, - 'VK_EXECUTE': 0x002B, - 'VK_SNAPSHOT': 0x002C, - 'VK_INSERT': 0x002D, - 'VK_DELETE': 0x002E, - 'VK_HELP': 0x002F, - 'VK_0': 0x0030, - 'VK_1': 0x0031, - 'VK_2': 0x0032, - 'VK_3': 0x0033, - 'VK_4': 0x0034, - 'VK_5': 0x0035, - 'VK_6': 0x0036, - 'VK_7': 0x0037, - 'VK_8': 0x0038, - 'VK_9': 0x0039, - 'VK_A': 0x0041, - 'VK_B': 0x0042, - 'VK_C': 0x0043, - 'VK_D': 0x0044, - 'VK_E': 0x0045, - 'VK_F': 0x0046, - 'VK_G': 0x0047, - 'VK_H': 0x0048, - 'VK_I': 0x0049, - 'VK_J': 0x004A, - 'VK_K': 0x004B, - 'VK_L': 0x004C, - 'VK_M': 0x004D, - 'VK_N': 0x004E, - 'VK_O': 0x004F, - 'VK_P': 0x0050, - 'VK_Q': 0x0051, - 'VK_R': 0x0052, - 'VK_S': 0x0053, - 'VK_T': 0x0054, - 'VK_U': 0x0055, - 'VK_V': 0x0056, - 'VK_W': 0x0057, - 'VK_X': 0x0058, - 'VK_Y': 0x0059, - 'VK_Z': 0x005A, - 'VK_LWIN': 0x005B, - 'VK_RWIN': 0x005C, - 'VK_APPS': 0x005D, - 'VK_SLEEP': 0x005F, - 'VK_NUMPAD0': 0x0060, - 'VK_NUMPAD1': 0x0061, - 'VK_NUMPAD2': 0x0062, - 'VK_NUMPAD3': 0x0063, - 'VK_NUMPAD4': 0x0064, - 'VK_NUMPAD5': 0x0065, - 'VK_NUMPAD6': 0x0066, - 'VK_NUMPAD7': 0x0067, - 'VK_NUMPAD8': 0x0068, - 'VK_MULTIPLY': 0x006A, - 'VK_ADD': 0x006B, - 'VK_SEPARATOR': 0x006C, - 'VK_SUBTRACT': 0x006D, - 'VK_DECIMAL': 0x006E, - 'VK_DIVIDE': 0x006F, - 'VK_F1': 0x0070, - 'VK_F2': 0x0071, - 'VK_F3': 0x0072, - 'VK_F4': 0x0073, - 'VK_F5': 0x0074, - 'VK_F6': 0x0075, - 'VK_F7': 0x0076, - 'VK_F8': 0x0077, - 'VK_F9': 0x0078, - 'VK_F10': 0x0079, - 'VK_F11': 0x007A, - 'VK_F12': 0x007B, - 'VK_F13': 0x007C, - 'VK_F14': 0x007D, - 'VK_F15': 0x007E, - 'VK_F16': 0x007F, - 'VK_F17': 0x0080, - 'VK_F18': 0x0081, - 'VK_F19': 0x0082, - 'VK_F20': 0x0083, - 'VK_F21': 0x0084, - 'VK_F22': 0x0085, - 'VK_F23': 0x0086, - 'VK_F24': 0x0087, - 'VK_NUMLOCK': 0x0090, - 'VK_SCROLL': 0x0091, - 'VK_LSHIFT': 0x00A0, - 'VK_RSHIFT': 0x00A1, - 'VK_LCONTROL': 0x00A2, - 'VK_RCONTROL': 0x00A3, - 'VK_LMENU': 0x00A4, - 'VK_RMENU': 0x00A5 -} - -CONQUE_WINDOWS_VK_INV = dict([v, k] for k, v in CONQUE_WINDOWS_VK.items()) - -CONQUE_WINDOWS_VK_ENHANCED = { - str(int(CONQUE_WINDOWS_VK['VK_UP'])): 1, - str(int(CONQUE_WINDOWS_VK['VK_DOWN'])): 1, - str(int(CONQUE_WINDOWS_VK['VK_LEFT'])): 1, - str(int(CONQUE_WINDOWS_VK['VK_RIGHT'])): 1, - str(int(CONQUE_WINDOWS_VK['VK_HOME'])): 1, - str(int(CONQUE_WINDOWS_VK['VK_END'])): 1 -} - - -# structures used for CreateProcess - -# Odd types - -LPBYTE = POINTER(c_ubyte) -LPTSTR = POINTER(c_char) - - -class STARTUPINFO(Structure): - _fields_ = [("cb", c_ulong), - ("lpReserved", LPTSTR), - ("lpDesktop", LPTSTR), - ("lpTitle", LPTSTR), - ("dwX", c_ulong), - ("dwY", c_ulong), - ("dwXSize", c_ulong), - ("dwYSize", c_ulong), - ("dwXCountChars", c_ulong), - ("dwYCountChars", c_ulong), - ("dwFillAttribute", c_ulong), - ("dwFlags", c_ulong), - ("wShowWindow", c_short), - ("cbReserved2", c_short), - ("lpReserved2", LPBYTE), - ("hStdInput", c_void_p), - ("hStdOutput", c_void_p), - ("hStdError", c_void_p),] - - def to_str(self): - return '' - - -class PROCESS_INFORMATION(Structure): - _fields_ = [("hProcess", c_void_p), - ("hThread", c_void_p), - ("dwProcessId", c_ulong), - ("dwThreadId", c_ulong),] - - def to_str(self): - return '' - - -class MEMORY_BASIC_INFORMATION(Structure): - _fields_ = [("BaseAddress", c_void_p), - ("AllocationBase", c_void_p), - ("AllocationProtect", c_ulong), - ("RegionSize", c_ulong), - ("State", c_ulong), - ("Protect", c_ulong), - ("Type", c_ulong),] - - def to_str(self): - return '' - - -class SECURITY_ATTRIBUTES(Structure): - _fields_ = [("Length", c_ulong), - ("SecDescriptor", c_void_p), - ("InheritHandle", c_bool)] - - def to_str(self): - return '' - - -class COORD(Structure): - _fields_ = [("X", c_short), - ("Y", c_short)] - - def to_str(self): - return '' - - -class SMALL_RECT(Structure): - _fields_ = [("Left", c_short), - ("Top", c_short), - ("Right", c_short), - ("Bottom", c_short)] - - def to_str(self): - return '' - - -class CONSOLE_SCREEN_BUFFER_INFO(Structure): - _fields_ = [("dwSize", COORD), - ("dwCursorPosition", COORD), - ("wAttributes", c_short), - ("srWindow", SMALL_RECT), - ("dwMaximumWindowSize", COORD)] - - def to_str(self): - return '' - - -class CHAR_UNION(Union): - _fields_ = [("UnicodeChar", c_wchar), - ("AsciiChar", c_char)] - - def to_str(self): - return '' - - -class CHAR_INFO(Structure): - _fields_ = [("Char", CHAR_UNION), - ("Attributes", c_short)] - - def to_str(self): - return '' - - -class KEY_EVENT_RECORD(Structure): - _fields_ = [("bKeyDown", c_byte), - ("pad2", c_byte), - ('pad1', c_short), - ("wRepeatCount", c_short), - ("wVirtualKeyCode", c_short), - ("wVirtualScanCode", c_short), - ("uChar", CHAR_UNION), - ("dwControlKeyState", c_int)] - - def to_str(self): - return '' - - -class MOUSE_EVENT_RECORD(Structure): - _fields_ = [("dwMousePosition", COORD), - ("dwButtonState", c_int), - ("dwControlKeyState", c_int), - ("dwEventFlags", c_int)] - - def to_str(self): - return '' - - -class WINDOW_BUFFER_SIZE_RECORD(Structure): - _fields_ = [("dwSize", COORD)] - - def to_str(self): - return '' - - -class MENU_EVENT_RECORD(Structure): - _fields_ = [("dwCommandId", c_uint)] - - def to_str(self): - return '' - - -class FOCUS_EVENT_RECORD(Structure): - _fields_ = [("bSetFocus", c_byte)] - - def to_str(self): - return '' - - -class INPUT_UNION(Union): - _fields_ = [("KeyEvent", KEY_EVENT_RECORD), - ("MouseEvent", MOUSE_EVENT_RECORD), - ("WindowBufferSizeEvent", WINDOW_BUFFER_SIZE_RECORD), - ("MenuEvent", MENU_EVENT_RECORD), - ("FocusEvent", FOCUS_EVENT_RECORD)] - - def to_str(self): - return '' - - -class INPUT_RECORD(Structure): - _fields_ = [("EventType", c_short), - ("Event", INPUT_UNION)] - - def to_str(self): - return '' - - diff --git a/doc/conque_term.txt b/doc/conque_term.txt deleted file mode 100644 index 64deb83..0000000 --- a/doc/conque_term.txt +++ /dev/null @@ -1,646 +0,0 @@ -*ConqueTerm* Plugin to run a shell inside a Vim buffer - -The ConqueTerm plugin will turn a Vim buffer into a terminal emulator, allowing -you to run and interact with a shell or shell application inside the buffer. - - 1. Installation |conque-term-setup| - 1.1 Requirements for Unix |conque-term-requirements| - 1.2 Requirements for Windows |conque-term-windows| - 1.3 Installation |conque-term-installation| - 2. Usage |conque-term-usage| - 2.1 General Usage |conque-term-gen-usage| - 2.2 Special keys |conque-term-special-keys| - 2.2.1 Send text to Conque |conque-term-send| - 2.2.2 Toggle terminal input mode |conque-term-input-mode| - 2.2.3 Sending the key press |conque-term-esc| - 3. Configuration |conque-term-options| - 3.1 General |conque-config-general| - 3.1.1 Python version |ConqueTerm_PyVersion| - 3.1.2 Fast mode |ConqueTerm_FastMode| - 3.1.3 Color support |ConqueTerm_Color| - 3.1.4 Session Support |ConqueTerm_SessionSupport| - 3.1.5 Keep updating terminal buffer |ConqueTerm_ReadUnfocused| - 3.1.6 Insert mode when entering buffer |ConqueTerm_InsertOnEnter| - 3.1.7 Close buffer when program exits |ConqueTerm_CloseOnEnd| - 3.1.8 Hide start messages |ConqueTerm_StartMessages| - 3.1.9 Regex for highlighting your prompt |ConqueTerm_PromptRegex| - 3.1.10 Syntax type |ConqueTerm_Syntax| - 3.2 Keyboard |conque-config-keyboard| - 3.2.1 The key |ConqueTerm_EscKey| - 3.2.2 Toggle terminal input mode |ConqueTerm_ToggleKey| - 3.2.3 Enable in insert mode |ConqueTerm_CWInsert| - 3.2.4 Execute current file in Conque |ConqueTerm_ExecFileKey| - 3.2.5 Send current file contents to Conque|ConqueTerm_SendFileKey| - 3.2.6 Send selected text to Conque |ConqueTerm_SendVisKey| - 3.2.7 Function Keys |ConqueTerm_SendFunctionKeys| - 3.3 Unix |conque-config-unix| - 3.3.1 Choose your terminal type |ConqueTerm_TERM| - 3.4 Windows |conque-config-windows| - 3.4.1 Python executable |ConqueTerm_PyExe| - 3.4.2 Windows character code page |ConqueTerm_CodePage| - 3.4.3 Terminal color method |ConqueTerm_ColorMode| - 4. VimScript API |conque-term-api| - 4.1 conque_term#open() |conque-term-open| - 4.2 conque_term#subprocess() |conque-term-subprocess| - 4.3 conque_term#get_instance() |conque-term-get-instance| - 4.4 CONQUE_OBJECT.write() |conque-term-write| - 4.5 CONQUE_OBJECT.writeln() |conque-term-writeln| - 4.6 CONQUE_OBJECT.read() |conque-term-read| - 4.7 CONQUE_OBJECT.set_callback() |conque-term-set-callback| - 4.8 CONQUE_OBJECT.close() |conque-term-close| - 4.9 Registering functions |conque-term-events| - 5. Misc |conque-term-misc| - 5.1 Known bugs |conque-term-bugs| - 5.2 Contribute |conque-term-contribute| - 5.3 Feedback |conque-term-feedback| - -============================================================================== - -1. Installation *conque-term-setup* - -Conque is designed for both Unix and Windows operating systems, however the -requirements are slightly different. Please check section below corresponding -to your installed OS. - -1.1 Requirements for Unix *conque-term-requirements* - - * [G]Vim 7.0+ with +python and/or +python3 - * Python 2.3+ and/or 3.x - * Unix-like OS: Linux, OS X, Solaris, Cygwin, etc - -The most common stumbling block is getting a version of Vim which has the -python interface enabled. Most all software package managers will have a copy -of Vim with Python support, so that is often the easiest way to get it. If -you're compiling Vim from source, be sure to use the --enable-pythoninterp -option, or --enable-python3interp for Python 3. On OS X the best option is -MacVim, which installs with Python support by default. - -1.2 Requirements for Windows *conque-term-windows* - - * [G]Vim 7.3 with +python and/or +python3 - * Python 2.7 and/or 3.1 - * Modern Windows OS (XP or later) - -Conque only officially supports the latest GVim 7.3 Windows installer -available at www.vim.org. If you are currently using Vim 7.2 or earlier you -will need to upgrade to 7.3 for Windows support. The Windows installer already -has the +python/+python3 interface built in. - -The official 7.3 release of Vim for Windows only works with Python versions -2.7 and/or 3.1. You can download and install Python from their website -http://www.python.org/download - -If you are compiling Vim + Python from source on Windows, the requirements -become only Vim 7.3+ and Python 2.7+. - - -1.3 Installation *conque-term-installation* - -Download the latest vimball from http://conque.googlecode.com - -Open the .vba file with Vim and run the following commands: -> - :so % - :q -< -That's it! The :ConqueTerm command will be available the next time you start -Vim. You can delete the .vba file when you've verified Conque was successfully -installed. - -============================================================================== - -2. Usage *conque-term-usage* - -2.1 General Usage *conque-term-gen-usage* - -Type :ConqueTerm to launch an application in the current buffer. Eg: -> - :ConqueTerm bash - :ConqueTerm mysql -h localhost -u joe_lunchbox Menu - :ConqueTerm Powershell.exe -< -Use :ConqueTermSplit or :ConqueTermVSplit to open Conque in a new horizontal -or vertical buffer. Use :ConqueTermTab to open Conque in a new tab. - -In insert mode you can interact with the shell as you would expect in a -normal terminal. All key presses will be sent to the terminal, including -control characters. See |conque-term-special-keys| for more information, -particularly regarding the key. - -In normal mode you can use Vim commands to browse your terminal output and -scroll back through the history. Most all Vim functionality will work, such -as searching, yanking or highlighting text. - - -2.2 Special keys *conque-term-special-keys* - -There are several keys which can be configured to have special behavior with -Conque. - -2.2.1 Send text to Conque *conque-term-send* - -Conque gives you three different commands to send text from a different -buffer, probably a source code file, to the Conque terminal buffer. All three -are configurable to use your choice of key combinations. - -To send a visually selected range of text to an existing terminal buffer, -press the key. - -To send the entire contents of the file you are editing to an existing -terminal buffer, press the key. - -Finally, to execute the current file in a new terminal buffer press the -key. This will split the screen with a new Conque buffer. The file you are -editing must be executable for this command to work. - -See |conque-term-options| for information about configuring these commands. - -2.2.2 Toggle terminal input mode *conque-term-input-mode* - -If you want to use insert mode to edit the terminal screen, press . You -will now be able to edit the terminal output freely without your cursor -jumping the the active prompt line. This may be useful if you want to reformat -terminal output for readability. - -While the terminal is paused new output will not be displayed on the screen -until you press again to resume. - -You can configure Conque to use a different key with the |ConqueTerm_ToggleKey| -option. - -2.2.3 Sending the key press *conque-term-esc* - -By default if you press the key in a Conque buffer you will leave insert -mode. But what if you want the character to be sent to your terminal? -There are two options. By default, pressing twice will send one -character to the terminal and you will remain in insert mode, while pressing -it once will leave insert mode. - -Alternatively you can use the |ConqueTerm_EscKey| option to choose a -different key for leaving insert mode. If a custom key is set, then all -key presses will be sent to the terminal. - -2.3 Registering functions *conque-term-register* - -Conque allows you to write your own VimScript functions which will be called -at certain events. See the API section |conque-term-events| for more. - -============================================================================== - -3. Options *conque-term-options* - -You can set the following options in your .vimrc (default values shown) - -3.1 General *conque-config-general* - -3.1.1 Python version *ConqueTerm_PyVersion* - -Conque will work with either Python 2.x or 3.x, assuming the interfaces have -been installed. By default it will try to use Python 2 first, then will try -Python 3. If you want Conque to use Python 3, set this variable to 3. - -Note: even if you set this to 3, if you don't have the python3 interface -Conque will fall back to using Python 2. -> - let g:ConqueTerm_PyVersion = 2 -< -3.1.2 Fast Mode *ConqueTerm_FastMode* - -Disable features which could make Conque run slowly. This includes most -terminal colors and some unicode support. Set this to 1 to enable fast mode. -> - let g:ConqueTerm_FastMode = 0 -< -3.1.3 Color support *ConqueTerm_Color* - -Terminal colors have the potential to slow down terminal screen rendering, -depending on how many colors are used and how fast the computer is. This -option allows you to choose how much color support will be enabled. - -If set to 0, terminal colors will be disabled. This will allow the terminal to -render most quickly. Syntax highlighting will still work. For example -highlighting quoted strings or MySQL output. - -If set to 1, terminal colors will be enabled, but only for the most recent 200 -lines of terminal output. Older output will be periodically stripped of color -highlighting to keep the display responsive. - -If set to 2, terminal colors will always be enabled. If your programs don't -use color output very frequently this is a good choice. - -Note: Color support is automatically disabled in "fast mode". -> - let g:ConqueTerm_Color = 1 -< -3.1.4 Session Support *ConqueTerm_SessionSupport* - -Vim's :mksession command allows you to save your current buffer configuration -to a file, which can be loaded at a later time after you've closed Vim. - -By default, Conque buffers are not restored. This is mostly for safety -reasons; you may not want Vim to automatically re-run a destructive command. - -However, if you're not working with missile launch code, and want Vim to -restart your Conque buffers when you load a session file, set this variable -to 1. Note your original subprocess and shell output will not be restored, but -the same command will be started in your buffer. -> - let g:ConqueTerm_SessionSupport = 0 -< -3.1.5 Keep updating terminal buffer *ConqueTerm_ReadUnfocused* - -If set to 1 then your Conque buffers will continue to update after you've -switched to another buffer. - -Note: Conque buffers may continue to update, but they will not scroll down as -new lines are added beyond the bottom of the visible buffer area. This is a -limitation of the Vim scripting language for which I haven't found a -workaround. -> - let g:ConqueTerm_ReadUnfocused = 1 -< -3.1.6 Insert mode when entering buffer *ConqueTerm_InsertOnEnter* - -If set to 1 then you will automatically go into insert mode when you enter the -buffer. This diverges from normal Vim behavior. If 0 you will still be in -normal mode. -> - let g:ConqueTerm_InsertOnEnter = 0 -< -3.1.7 Close buffer when program exits *ConqueTerm_CloseOnEnd* - -If you want your terminal buffer to be closed and permanently deleted when the -program running inside of it exits, set this option to 1. Otherwise the buffer -will become a simple text buffer after the program exits, and you can edit the -program output in insert mode. -> - let g:ConqueTerm_CloseOnEnd = 0 -< -3.1.8 Show start messages *ConqueTerm_StartMessages* - -Display warning messages when starting up ConqueTerm if your system is -configured incorrectly. -> - let g:ConqueTerm_StartMessages = 1 -< -3.1.9 Regex for highlighting your prompt *ConqueTerm_PromptRegex* - -Use this regular expression for sytax highlighting your terminal prompt. Your -terminal will generally run faster if you use Vim highlighting instead of -terminal colors for your prompt. You can also use it to do more advanced -syntax highlighting for the prompt line. -> - let g:ConqueTerm_PromptRegex = '^\w\+@[0-9A-Za-z_.-]\+:[0-9A-Za-z_./\~,:-]\+\$' -< -3.1.10 Choose Vim syntax type *ConqueTerm_Syntax* - -Set the buffer syntax. The default 'conque' has highlighting for MySQL, but -not much else. -> - let g:ConqueTerm_Syntax = 'conque' -< -3.2 Keyboard *conque-config-keyboard* - -3.2.1 The key *ConqueTerm_EscKey* - -If a custom key is set, then all key presses will be sent to the -terminal and you must use this custom key to leave insert mode. If left to the -default value of '' then you must press it twice to send the escape -character to the terminal, while pressing it once will leave insert mode. - -Note: You cannot use a key which is internally coded with the escape -character. This includes the keys and often the and keys. -Picking a control key, such as will be your best bet. -> - let g:ConqueTerm_EscKey = '' -< -3.2.2 Toggle terminal input mode *ConqueTerm_ToggleKey* - -Press this key to pause terminal input and output display. You will then be -able to edit the terminal screen as if it were a normal text buffer. Press -this key again to resume terminal mode. -> - let g:ConqueTerm_ToggleKey = '' -< -3.2.3 Enable in insert mode *ConqueTerm_CWInsert* - -If set to 1 then you can leave the Conque buffer using the commands -while you're still in insert mode. If set to 0 then the character will -be sent to the terminal. If both this option and ConqueTerm_InsertOnEnter are -set you can go in and out of the terminal buffer while never leaving insert -mode. -> - let g:ConqueTerm_CWInsert = 0 -< -3.2.4 Execute current file in Conque *ConqueTerm_ExecFileKey* - -Press this key to execute the file you're currently editing in a Conque -buffer. Is equivelent to running the command :ConqueTermSplit YOUR_FILE. Your -file must be executable for this command to work correctly. -> - let g:ConqueTerm_ExecFileKey = '' -< -3.2.5 Send current file contents to Conque *ConqueTerm_SendFileKey* - -Press this key to send your entire file contents to the most recently opened -Conque buffer as keyboard input. -> - let g:ConqueTerm_SendFileKey = '' -< -3.2.6 Send selected text to Conque *ConqueTerm_SendVisKey* - -Use this key to send the currently selected text to the most recently created -Conque buffer. -> - let g:ConqueTerm_SendVisKey = '' -< -3.2.7 Function Keys *ConqueTerm_SendFunctionKeys* - -By default, function keys (the F1-F12 row at the top of your keyboard) are not -passed to the terminal. Set this option to 1 to send these key events. - -Note: Unless you configured |ConqueTerm_SendVisKey| and |ConqueTerm_ToggleKey| -to use different keys, and will not be sent to the terminal even if -you set this option to 1. -> - let g:ConqueTerm_SendFunctionKeys = 0 -< -3.3 Unix *conque-config-unix* - -3.3.1 Choose your terminal type, Unix ONLY *ConqueTerm_TERM* - -Use this option to tell Conque what type of terminal it should identify itself -as. Conque officially uses the more limited VT100 terminal type for -developement and testing, although it supports some more advanced features -such as colors and title strings. - -You can change this setting to a more advanced type, namely 'xterm', but your -results may vary depending on which programs you're running. -> - let g:ConqueTerm_TERM = 'vt100' -< -3.4 Windows *conque-config-windows* - -3.4.1 Python executable, Windows ONLY *ConqueTerm_PyExe* - -The Windows version of Conque needs to know the path to the python.exe -executable for the version of Python Conque is using. If you installed Python -in the default location, or added the Python directory to your system path, -Conque should be able to find python.exe without you changing this variable. - -For example, you might set this to 'C:\Program Files\Python27\python.exe' -> - let g:ConqueTerm_PyExe = '' -< -3.4.2 Windows character code page *ConqueTerm_CodePage* - -Set the "code page" Windows will use for your console. Leave this value set to -zero to use the environment code page. - -Note: Displaying unicode characters on Conque for Windows needs work. -> - let g:ConqueTerm_CodePage = 0 -< -3.4.3 Terminal color method, Windows ONLY *ConqueTerm_ColorMode* - -Vim syntax highlighting by coordinate (e.g. the 3-7th characters on the 42nd -line) can be very slow. If you set this variable to 'conceal', you can use -the new conceal feature to render terminal colors. Requires Vim 7.3 and only -works on the Windows version of Conque. This will make colors render faster, -however it will also add hidden characters to the screen, which may be -annoying if you're copying and pasting terminal output out of the Conque -buffer. Set this to an empty string '' to disable concealed highlighting. -> - let g:ConqueTerm_ColorMode = 'conceal' -< -============================================================================== - -4. VimScript API (Beta) *conque-term-api* - -The Conque scripting API allows you to create and interact with Conque -terminals with the VimScript language. This API is still in beta stage. - -4.1 conque_term#open({command}, [buf_opts], [remain]) *conque-term-open* - -The open() function will create a new terminal buffer and start your command. - -The {command} must be an executable, either an absolute path or relative to -your system path. - -You can pass in a list of vim commands [buf_opts] which will be executed after -the new buffer is created but before the command is started. These are -typically commands to alter the size, position or configuration of the buffer -window. - -Note: If you don't pass in a command such as 'split', the terminal will open -in the current buffer. - -If you don't want the new terminal buffer to become the new active buffer, set - [remain] to 1. Only works if you create a split screen using [options]. - -Returns a Conque terminal object. - -Examples: -> - let my_terminal = conque_term#open('/bin/bash') - let my_terminal = conque_term#open('ipython', ['split', 'resize 20'], 1) -< -4.2 conque_term#subprocess({command}) *conque-term-subprocess* - -Starts a new subprocess with your {command}, but no terminal buffer is ever -created. This may be useful if you need asynchronous interaction with a -subprocess, but want to handle the output on your own. - -Returns a Conque terminal object. - -Example: -> - let my_subprocess = conque_term#subprocess('tail -f /var/log/foo.log') -< -4.3 conque_term#get_instance( [terminal_number] ) *conque-term-get-instance* - -Use the get_instance() function to retrieve an existing terminal object. The -terminal could have been created either with the user command :ConqueTerm or -with an API call to conque_term#open() or subprocess(). - -Use the optional [terminal_number] to retrieve a specific terminal instance. -Otherwise if the current buffer is a Conque terminal, it will be returned, -else the most recently created terminal. The terminal number is what you see -at the end of a terminal buffer name, e.g. "bash - 2". - -Returns a Conque terminal object. - -Example: -> - nnoremap :call conque_term#get_instance().writeln('clear') -< -4.4 CONQUE_OBJECT.write({text}) *conque-term-write* - -Once you have a terminal object from open(), subprocess() or get_instance() -you can send text input to it with the write() method. - -No return value. - -Examples: -> - call my_terminal.write("whoami\n") - call my_terminal.write("\") -< -4.5 CONQUE_OBJECT.writeln({text}) *conque-term-writeln* - -The same as write() except adds a \n character to the end if your input. - -Examples: -> - call my_subprocess.writeln('make') -< -4.6 CONQUE_OBJECT.read( [timeout], [update_buffer] ) *conque-term-read* - -Read new output from a Conque terminal subprocess. New output will be returned -as a string, and the terminal buffer will also be updated by default. - -If you are reading immediately after calling the write() method, you may want -to wait [timeout] milliseconds for output to be ready. - -If you want to prevent the output from being displayed in the terminal buffer, -set [update_buffer] to 0. This option has no effect if the terminal was -created with the subprocess() function, since there never is a buffer to -update. - -Returns output string. - -Note: The terminal buffer will not automatically scroll down if the new output -extends beyond the bottom of the visible buffer. Vim doesn't allow "unfocused" -buffers to be scrolled at the current version, although hopefully this will -change. - -Examples: -> - call my_terminal.writeln('whoami') - let output = my_terminal.read(500) - call my_terminal.writeln('ls -lha') - let output = my_terminal.read(1000, 1) -< -4.7 CONQUE_OBJECT.set_callback( {funcname} ) *conque-term-set-callback* - -Register a callback function for this subprocess instance. This function will -automatically be called whenever new output is available. Only practical with -subprocess() objects. - -Conque checkes for new subprocess output once a second when Vim is idle. If -new output is found your function will be called. - -Pass in the callback function name {funcname} as a string. - -No return value. - -Note: this method requires the g:ConqueTerm_ReadUnfocused option to be set. - -Note: this method is experimental, results may vary. - -Example: -> - let sp = conque_term#subprocess('tail -f /home/joe/log/error_log') - - function! MyErrorAlert(output) - echo a:output - endfunction - - call sp.set_callback('MyErrorAlert') -< -4.8 CONQUE_OBJECT.close() *conque-term-close* - -Kill your terminal subprocess. Sends the ABORT signal. You probably want to -close your subprocess in a more graceful manner with the write() method, but -this can be used when needed. Does not close the terminal buffer, if it -exists. - -This method will be called on all existing Conque subprocesses when Vim exits. - -Example: -> - let term = conque_term#open('ping google.com', ['belowright split']) - call term.read(5000) - call term.close() -< -4.9 Registering functions *conque-term-events* - -Conque provides the option to register callback functions which will be -executed at several different events. The currently available events are: - - after_startup After your application has loaded into the buffer. - buffer_enter When you switch to a Conque buffer. - buffer_leave When you leave a Conque buffer. - -You may use the function conque_term#register_function(event, function_name) -to add additional hooks at a particular event. The second argument should be -the name of a callback function which has one parameter, the current -terminal object (see|conque-term-api|for more about terminal objects). - -For example: -> - function MyConqueStartup(term) - - " set buffer syntax using the name of the program currently running - let syntax_associations = { 'ipython': 'python', 'irb': 'ruby' } - - if has_key(syntax_associations, a:term.program_name) - execute 'setlocal syntax=' . syntax_associations[a:term.program_name] - else - execute 'setlocal syntax=' . a:term.program_name - endif - - " shrink window height to 10 rows - resize 10 - - " silly example of terminal api usage - if a:term.program_name == 'bash' - call a:term.writeln('svn up ~/projects/*') - endif - - endfunction - - call conque_term#register_function('after_startup', 'MyConqueStartup') -< - -============================================================================== - -5. Misc *conque-term-misc* - - -5.1 Known bugs *conque-term-bugs* - -The following are known limitations: - - - Font/color highlighting is imperfect and slow. If you don't care about - color in your shell, set g:ConqueTerm_Color = 0 in your .vimrc - - Conque only supports the extended ASCII character set for input, not utf-8. - - VT100 escape sequence support is not complete. - - Alt/Meta key support in Vim isn't great in general, and conque is no - exception. Pressing x or instead of works in - most cases. - - -5.2 Contribute *conque-term-contribute* - -The two contributions most in need are improvements to Vim itself. I currently -use hacks to capture key press input from the user, and to poll the terminal -for more output. The Vim todo.txt document lists proposed improvements to give -users this behavior without hacks. Having a key press event should allow -Conque to work with multi- byte input. If you are a Vim developer, please -consider prioritizing these two items: - - - todo.txt (Autocommands, line ~3137) - 8 Add an event like CursorHold that is triggered repeatedly, not just - once after typing something. - - -5.3 Feedback *conque-term-feedback* - -Bugs, suggestions and patches are all welcome. - -For more information visit http://conque.googlecode.com - -Check out the latest from svn at http://conque.googlecode.com/svn/trunk/ - - vim:tw=78:ts=8:ft=help:norl: diff --git a/ftplugin/plist.vim b/ftplugin/plist.vim deleted file mode 100644 index 4569115..0000000 --- a/ftplugin/plist.vim +++ /dev/null @@ -1,73 +0,0 @@ - -" ViM autocommands for binary plist files -" Copyright (C) 2005 Moritz Heckscher -" -" Note: When a file changes externally and you answer no to vim's question if -" you want to write anyway, the autocommands (e.g. for BufWritePost) are still -" executed, it seems, which could have some unwanted side effects. -" -" This program is free software; you can redistribute it and/or modify -" it under the terms of the GNU General Public License as published by -" the Free Software Foundation; either version 2 of the License, or -" (at your option) any later version. -" -" This program is distributed in the hope that it will be useful, -" but WITHOUT ANY WARRANTY; without even the implied warranty of -" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -" GNU General Public License for more details. -autocmd BufReadPre,FileReadPre *.plist set binary ft=plist syntax=xml -" ... and call it just after editing a file in a new buffer... -autocmd BufReadPost *.plist call MyBinaryPlistReadPost() -" ... or when reading a file into an existing buffer (in that case, don't -" save as binary later on). -autocmd FileReadPost *.plist call MyBinaryPlistReadPost() | let b:saveAsBinaryPlist = 0 -autocmd BufWritePre,FileWritePre *.plist call MyBinaryPlistWritePre() -autocmd BufWritePost,FileWritePost *.plist call MyBinaryPlistWritePost() - - -" breaking lines etc; since setting this for normal plist files doesn't -" hurt and it's not yet known whether or not the file to be read is stored -" in binary format, set the option in any case to be sure). -" Do it before editing a file in a new buffer and before reading a file -" into in an existing buffer (using ':read foo.plist'). - -" Define a little function to convert binary files if necessary... -fun MyBinaryPlistReadPost() - " Check if the first line just read in indicates a binary plist - if getline("'[") =~ "^bplist" - " Filter lines read into buffer (convert to XML with plutil) - '[,']!plutil -convert xml1 /dev/stdin -o /dev/stdout - " Many people seem to want to save files originally stored - " in binary format as such after editing, so memorize format. - let b:saveAsBinaryPlist = 1 - endif - " Yeah, plain text (finally or all the way through, either way...)! - set nobinary - " Trigger file type detection to get syntax coloring etc. according - " to file contents (alternative: 'setfiletype xml' to force xml). - filetype detect -endfun - -" Define and use functions for conversion back to binary format -fun MyBinaryPlistWritePre() - if exists("b:saveAsBinaryPlist") && b:saveAsBinaryPlist - " Must set binary mode before conversion (for EOL settings) - set binary - " Convert buffer lines to be written to binary - silent '[,']!plutil -convert binary1 /dev/stdin -o /dev/stdout - " If there was a problem, e.g. when the file contains syntax - " errors, undo the conversion and go back to nobinary so the - " file will be saved in text format. - if v:shell_error | undo | set nobinary | endif - endif -endfun -fun MyBinaryPlistWritePost() - " If file was to be written in binary format and there was no error - " doing the conversion, ... - if exists("b:saveAsBinaryPlist") && b:saveAsBinaryPlist && !v:shell_error - " ... undo the conversion and go back to nobinary so the - " lines are shown as text again in vim. - undo - set nobinary - endif -endfun diff --git a/ftplugin/python/flake8.py b/ftplugin/python/flake8.py deleted file mode 100755 index 517f623..0000000 --- a/ftplugin/python/flake8.py +++ /dev/null @@ -1,160 +0,0 @@ -# coding: utf-8 - -from mccabe.mccabe import get_module_complexity -from pyflakes import checker, messages -import _ast -from pep8 import pep8 as p8 -from pep8.autopep8 import fix_file as pep8_fix, fix_lines as pep8_fix_lines -import os - - -class Pep8Options(): - verbose = 0 - diff = False - in_place = True - recursive = False - pep8_passes = 100 - max_line_length = 79 - ignore = '' - select = '' - aggressive = False - - -class MccabeOptions(): - complexity = 10 - -flake_code_mapping = { - 'W402': (messages.UnusedImport,), - 'W403': (messages.ImportShadowedByLoopVar,), - 'W404': (messages.ImportStarUsed,), - 'W405': (messages.LateFutureImport,), - 'W801': (messages.RedefinedWhileUnused, - messages.RedefinedInListComp,), - 'W802': (messages.UndefinedName,), - 'W803': (messages.UndefinedExport,), - 'W804': (messages.UndefinedLocal, - messages.UnusedVariable,), - 'W805': (messages.DuplicateArgument,), - 'W806': (messages.Redefined,), -} - -flake_class_mapping = dict( - (k, c) for (c, v) in flake_code_mapping.items() for k in v) - - -def fix_file(filename): - pep8_fix(filename, Pep8Options) - - -def fix_lines(lines): - return pep8_fix_lines(lines, Pep8Options) - - -def run_checkers(filename, checkers, ignore): - - result = [] - - for c in checkers: - - checker_fun = globals().get(c) - if not checker: - continue - - try: - for e in checker_fun(filename): - e.update( - col=e.get('col') or 0, - text="{0} [{1}]".format( - e.get('text', '').strip( - ).replace("'", "\"").splitlines()[0], - c), - filename=os.path.normpath(filename), - type=e.get('type') or 'W', - bufnr=0, - ) - result.append(e) - except: - pass - - result = filter(lambda e: _ignore_error(e, ignore), result) - return sorted(result, key=lambda x: x['lnum']) - - -def mccabe(filename): - return get_module_complexity(filename, min=MccabeOptions.complexity) - - -def pep8(filename): - style = PEP8 or _init_pep8() - return style.input_file(filename) - - -def pyflakes(filename): - codeString = file(filename, 'U').read() + '\n' - errors = [] - try: - tree = compile(codeString, filename, "exec", _ast.PyCF_ONLY_AST) - except SyntaxError as e: - errors.append(dict( - lnum=e.lineno or 0, - col=e.offset or 0, - text=getattr(e, 'msg', None) or str(e), - type='E' - )) - else: - w = checker.Checker(tree, filename) - w.messages.sort(lambda a, b: cmp(a.lineno, b.lineno)) - for w in w.messages: - errors.append(dict( - lnum=w.lineno, - col=0, - text=u'{0} {1}'.format( - flake_class_mapping.get(w.__class__, ''), - w.message % w.message_args), - type='E' - )) - return errors - - -PEP8 = None - - -def _init_pep8(): - global PEP8 - - class _PEP8Report(p8.BaseReport): - - def init_file(self, filename, lines, expected, line_offset): - super(_PEP8Report, self).init_file( - filename, lines, expected, line_offset) - self.errors = [] - - def error(self, line_number, offset, text, check): - code = super(_PEP8Report, self).error( - line_number, offset, text, check) - - self.errors.append(dict( - text=text, - type=code, - col=offset + 1, - lnum=line_number, - )) - - def get_file_results(self): - return self.errors - - PEP8 = p8.StyleGuide(reporter=_PEP8Report) - return PEP8 - - -def _ignore_error(e, ignore): - for i in ignore: - if e['text'].startswith(i): - return False - return True - -if __name__ == '__main__': - for r in run_checkers( - '/home/andrew/devel/vim/bundle/flake8-vim/ftplugin/python/flake8.py', - checkers=['mccabe', 'pyflakes', 'pep8'], ignore=[]): - print r diff --git a/ftplugin/python/flake8.vim b/ftplugin/python/flake8.vim deleted file mode 100755 index c91cf48..0000000 --- a/ftplugin/python/flake8.vim +++ /dev/null @@ -1,188 +0,0 @@ -" Check python support -if !has('python') - echo "Error: PyFlake.vim required vim compiled with +python." - finish -endif - -if !exists('g:PyFlakeRangeCommand') - let g:PyFlakeRangeCommand = 'Q' -endif - -if !exists('b:PyFlake_initialized') - let b:PyFlake_initialized = 1 - - au BufWritePost call flake8#on_write() - au CursorHold call flake8#get_message() - au CursorMoved call flake8#get_message() - - " Commands - command! -buffer PyFlakeToggle :let b:PyFlake_disabled = exists('b:PyFlake_disabled') ? b:PyFlake_disabled ? 0 : 1 : 1 - command! -buffer PyFlake :call flake8#run() - command! -buffer -range=% PyFlakeAuto :call flake8#auto(,) - - " Keymaps - if g:PyFlakeRangeCommand != '' - exec 'vnoremap ' . g:PyFlakeRangeCommand . ' :PyFlakeAuto' - endif - - let b:showing_message = 0 - - " Signs definition - sign define W text=WW texthl=Todo - sign define C text=CC texthl=Comment - sign define R text=RR texthl=Visual - sign define E text=EE texthl=Error -endif - - "Check for flake8 plugin is loaded -if exists("g:PyFlakeDirectory") - finish -endif - -if !exists('g:PyFlakeOnWrite') - let g:PyFlakeOnWrite = 1 -endif - -" Init variables -let g:PyFlakeDirectory = expand(':p:h') - -if !exists('g:PyFlakeCheckers') - let g:PyFlakeCheckers = 'pep8,mccabe,pyflakes' -endif -if !exists('g:PyFlakeDefaultComplexity') - let g:PyFlakeDefaultComplexity=10 -endif -if !exists('g:PyFlakeDisabledMessages') - let g:PyFlakeDisabledMessages = 'E501' -endif -if !exists('g:PyFlakeCWindow') - let g:PyFlakeCWindow = 6 -endif -if !exists('g:PyFlakeSigns') - let g:PyFlakeSigns = 1 -endif -if !exists('g:PyFlakeMaxLineLength') - let g:PyFlakeMaxLineLength = 100 -endif - -python << EOF - -import sys -import json -import vim - -sys.path.insert(0, vim.eval("g:PyFlakeDirectory")) -from flake8 import run_checkers, fix_lines, Pep8Options, MccabeOptions - -def flake8_check(): - checkers=vim.eval('g:PyFlakeCheckers').split(',') - ignore=vim.eval('g:PyFlakeDisabledMessages').split(',') - MccabeOptions.complexity=int(vim.eval('g:PyFlakeDefaultComplexity')) - Pep8Options.max_line_length=int(vim.eval('g:PyFlakeMaxLineLength')) - filename=vim.current.buffer.name - parse_result(run_checkers(filename, checkers, ignore)) - -def parse_result(result): - vim.command('let g:qf_list = {}'.format(json.dumps(result, ensure_ascii=False))) - -EOF - -function! flake8#on_write() - if !g:PyFlakeOnWrite || exists("b:PyFlake_disabled") && b:PyFlake_disabled - return - endif - call flake8#check() -endfunction - -function! flake8#run() - if &modifiable && &modified - write - endif - call flake8#check() -endfun - -function! flake8#check() - py flake8_check() - let s:matchDict = {} - for err in g:qf_list - let s:matchDict[err.lnum] = err.text - endfor - call setqflist(g:qf_list, 'r') - - " Place signs - if g:PyFlakeSigns - call flake8#place_signs() - endif - - " Open cwindow - if g:PyFlakeCWindow - cclose - if len(g:qf_list) - let l:winsize = len(g:qf_list) > g:PyFlakeCWindow ? g:PyFlakeCWindow : len(g:qf_list) - exec l:winsize . 'cwindow' - endif - endif -endfunction - -function! flake8#auto(l1, l2) "{{{ - cclose - sign unplace * - let s:matchDict = {} - call setqflist([]) - -python << EOF -start, end = int(vim.eval('a:l1'))-1, int(vim.eval('a:l2')) -enc = vim.eval('&enc') -lines = fix_lines(vim.current.buffer[start:end]).splitlines() -res = [ln.encode(enc, 'replace') for ln in lines] -vim.current.buffer[start:end] = res -EOF -endfunction "}}} - -function! flake8#place_signs() - "first remove all sings - sign unplace * - - "now we place one sign for every quickfix line - let l:id = 1 - for item in getqflist() - execute(':sign place '.l:id.' name='.l:item.type.' line='.l:item.lnum.' buffer='.l:item.bufnr) - let l:id = l:id + 1 - endfor -endfunction - -" keep track of whether or not we are showing a message -" WideMsg() prints [long] message up to (&columns-1) length -" guaranteed without "Press Enter" prompt. -function! flake8#wide_msg(msg) - let x=&ruler | let y=&showcmd - set noruler noshowcmd - redraw - echo strpart(a:msg, 0, &columns-1) - let &ruler=x | let &showcmd=y -endfun - - -function! flake8#get_message() - let s:cursorPos = getpos(".") - - " Bail if RunPyflakes hasn't been called yet. - if !exists('s:matchDict') - return - endif - - " if there's a message for the line the cursor is currently on, echo - " it to the console - if has_key(s:matchDict, s:cursorPos[1]) - let s:pyflakesMatch = get(s:matchDict, s:cursorPos[1]) - call flake8#wide_msg(s:pyflakesMatch) - let b:showing_message = 1 - return - endif - - " otherwise, if we're showing a message, clear it - if b:showing_message == 1 - echo - let b:showing_message = 0 - endif -endfunction diff --git a/ftplugin/python/fn.vim b/ftplugin/python/fn.vim deleted file mode 100644 index fbdd003..0000000 --- a/ftplugin/python/fn.vim +++ /dev/null @@ -1,446 +0,0 @@ -" -*- vim -*- -" FILE: python.vim -" LAST MODIFICATION: 2008-05-17 6:29pm -" (C) Copyright 2001-2005 Mikael Berthe -" Maintained by Jon Franklin -" Version: 1.12 - -" USAGE: -" -" Save this file to $VIMFILES/ftplugin/python.vim. You can have multiple -" python ftplugins by creating $VIMFILES/ftplugin/python and saving your -" ftplugins in that directory. If saving this to the global ftplugin -" directory, this is the recommended method, since vim ships with an -" ftplugin/python.vim file already. -" You can set the global variable "g:py_select_leading_comments" to 0 -" if you don't want to select comments preceding a declaration (these -" are usually the description of the function/class). -" You can set the global variable "g:py_select_trailing_comments" to 0 -" if you don't want to select comments at the end of a function/class. -" If these variables are not defined, both leading and trailing comments -" are selected. -" Example: (in your .vimrc) "let g:py_select_leading_comments = 0" -" You may want to take a look at the 'shiftwidth' option for the -" shift commands... -" -" REQUIREMENTS: -" vim (>= 7) -" -" Shortcuts: -" ]t -- Jump to beginning of block -" ]e -- Jump to end of block -" ]v -- Select (Visual Line Mode) block -" ]< -- Shift block to left -" ]> -- Shift block to right -" ]# -- Comment selection -" ]u -- Uncomment selection -" ]c -- Select current/previous class -" ]d -- Select current/previous function -" ] -- Jump to previous line with the same/lower indentation -" ] -- Jump to next line with the same/lower indentation - -" Only do this when not done yet for this buffer -if exists("b:loaded_py_ftplugin") - finish -endif -let b:loaded_py_ftplugin = 1 - -map ]t :PBoB -vmap ]t :PBOBm'gv`` -map ]e :PEoB -vmap ]e :PEoBm'gv`` - -map ]v ]tV]e -map ]< ]tV]e< -vmap ]< < -map ]> ]tV]e> -vmap ]> > - -map ]# :call PythonCommentSelection() -vmap ]# :call PythonCommentSelection() -map ]u :call PythonUncommentSelection() -vmap ]u :call PythonUncommentSelection() - -map ]c :call PythonSelectObject("class") -map ]d :call PythonSelectObject("function") - -map ] :call PythonNextLine(-1) -map ] :call PythonNextLine(1) -" You may prefer use and ... :-) - -" jump to previous class -map ]J :call PythonDec("class", -1) -vmap ]J :call PythonDec("class", -1) - -" jump to next class -map ]j :call PythonDec("class", 1) -vmap ]j :call PythonDec("class", 1) - -" jump to previous function -map ]F :call PythonDec("function", -1) -vmap ]F :call PythonDec("function", -1) - -" jump to next function -map ]f :call PythonDec("function", 1) -vmap ]f :call PythonDec("function", 1) - - - -" Menu entries -nmenu &Python.Update\ IM-Python\ Menu - \:call UpdateMenu() -nmenu &Python.-Sep1- : -nmenu &Python.Beginning\ of\ Block[t - \]t -nmenu &Python.End\ of\ Block]e - \]e -nmenu &Python.-Sep2- : -nmenu &Python.Shift\ Block\ Left]< - \]< -vmenu &Python.Shift\ Block\ Left]< - \]< -nmenu &Python.Shift\ Block\ Right]> - \]> -vmenu &Python.Shift\ Block\ Right]> - \]> -nmenu &Python.-Sep3- : -vmenu &Python.Comment\ Selection]# - \]# -nmenu &Python.Comment\ Selection]# - \]# -vmenu &Python.Uncomment\ Selection]u - \]u -nmenu &Python.Uncomment\ Selection]u - \]u -nmenu &Python.-Sep4- : -nmenu &Python.Previous\ Class]J - \]J -nmenu &Python.Next\ Class]j - \]j -nmenu &Python.Previous\ Function]F - \]F -nmenu &Python.Next\ Function]f - \]f -nmenu &Python.-Sep5- : -nmenu &Python.Select\ Block]v - \]v -nmenu &Python.Select\ Function]d - \]d -nmenu &Python.Select\ Class]c - \]c -nmenu &Python.-Sep6- : -nmenu &Python.Previous\ Line\ wrt\ indent] - \] -nmenu &Python.Next\ Line\ wrt\ indent] - \] - -:com! PBoB execute "normal ".PythonBoB(line('.'), -1, 1)."G" -:com! PEoB execute "normal ".PythonBoB(line('.'), 1, 1)."G" -:com! UpdateMenu call UpdateMenu() - - -" Go to a block boundary (-1: previous, 1: next) -" If force_sel_comments is true, 'g:py_select_trailing_comments' is ignored -function! PythonBoB(line, direction, force_sel_comments) - let ln = a:line - let ind = indent(ln) - let mark = ln - let indent_valid = strlen(getline(ln)) - let ln = ln + a:direction - if (a:direction == 1) && (!a:force_sel_comments) && - \ exists("g:py_select_trailing_comments") && - \ (!g:py_select_trailing_comments) - let sel_comments = 0 - else - let sel_comments = 1 - endif - - while((ln >= 1) && (ln <= line('$'))) - if (sel_comments) || (match(getline(ln), "^\\s*#") == -1) - if (!indent_valid) - let indent_valid = strlen(getline(ln)) - let ind = indent(ln) - let mark = ln - else - if (strlen(getline(ln))) - if (indent(ln) < ind) - break - endif - let mark = ln - endif - endif - endif - let ln = ln + a:direction - endwhile - - return mark -endfunction - - -" Go to previous (-1) or next (1) class/function definition -function! PythonDec(obj, direction) - if (a:obj == "class") - let objregexp = "^\\s*class\\s\\+[a-zA-Z0-9_]\\+" - \ . "\\s*\\((\\([a-zA-Z0-9_,. \\t\\n]\\)*)\\)\\=\\s*:" - else - let objregexp = "^\\s*def\\s\\+[a-zA-Z0-9_]\\+\\s*(\\_[^:#]*)\\s*:" - endif - let flag = "W" - if (a:direction == -1) - let flag = flag."b" - endif - let res = search(objregexp, flag) -endfunction - - -" Comment out selected lines -" commentString is inserted in non-empty lines, and should be aligned with -" the block -function! PythonCommentSelection() range - let commentString = "#" - let cl = a:firstline - let ind = 1000 " I hope nobody use so long lines! :) - - " Look for smallest indent - while (cl <= a:lastline) - if strlen(getline(cl)) - let cind = indent(cl) - let ind = ((ind < cind) ? ind : cind) - endif - let cl = cl + 1 - endwhile - if (ind == 1000) - let ind = 1 - else - let ind = ind + 1 - endif - - let cl = a:firstline - execute ":".cl - " Insert commentString in each non-empty line, in column ind - while (cl <= a:lastline) - if strlen(getline(cl)) - execute "normal ".ind."|i".commentString - endif - execute "normal \" - let cl = cl + 1 - endwhile -endfunction - -" Uncomment selected lines -function! PythonUncommentSelection() range - " commentString could be different than the one from CommentSelection() - " For example, this could be "# \\=" - let commentString = "#" - let cl = a:firstline - while (cl <= a:lastline) - let ul = substitute(getline(cl), - \"\\(\\s*\\)".commentString."\\(.*\\)$", "\\1\\2", "") - call setline(cl, ul) - let cl = cl + 1 - endwhile -endfunction - - -" Select an object ("class"/"function") -function! PythonSelectObject(obj) - " Go to the object declaration - normal $ - call PythonDec(a:obj, -1) - let beg = line('.') - - if !exists("g:py_select_leading_comments") || (g:py_select_leading_comments) - let decind = indent(beg) - let cl = beg - while (cl>1) - let cl = cl - 1 - if (indent(cl) == decind) && (getline(cl)[decind] == "#") - let beg = cl - else - break - endif - endwhile - endif - - if (a:obj == "class") - let eod = "\\(^\\s*class\\s\\+[a-zA-Z0-9_]\\+\\s*" - \ . "\\((\\([a-zA-Z0-9_,. \\t\\n]\\)*)\\)\\=\\s*\\)\\@<=:" - else - let eod = "\\(^\\s*def\\s\\+[a-zA-Z0-9_]\\+\\s*(\\_[^:#]*)\\s*\\)\\@<=:" - endif - " Look for the end of the declaration (not always the same line!) - call search(eod, "") - - " Is it a one-line definition? - if match(getline('.'), "^\\s*\\(#.*\\)\\=$", col('.')) == -1 - let cl = line('.') - execute ":".beg - execute "normal V".cl."G" - else - " Select the whole block - execute "normal \" - let cl = line('.') - execute ":".beg - execute "normal V".PythonBoB(cl, 1, 0)."G" - endif -endfunction - - -" Jump to the next line with the same (or lower) indentation -" Useful for moving between "if" and "else", for example. -function! PythonNextLine(direction) - let ln = line('.') - let ind = indent(ln) - let indent_valid = strlen(getline(ln)) - let ln = ln + a:direction - - while((ln >= 1) && (ln <= line('$'))) - if (!indent_valid) && strlen(getline(ln)) - break - else - if (strlen(getline(ln))) - if (indent(ln) <= ind) - break - endif - endif - endif - let ln = ln + a:direction - endwhile - - execute "normal ".ln."G" -endfunction - -function! UpdateMenu() - " delete menu if it already exists, then rebuild it. - " this is necessary in case you've got multiple buffers open - " a future enhancement to this would be to make the menu aware of - " all buffers currently open, and group classes and functions by buffer - if exists("g:menuran") - aunmenu IM-Python - endif - let restore_fe = &foldenable - set nofoldenable - " preserve disposition of window and cursor - let cline=line('.') - let ccol=col('.') - 1 - norm H - let hline=line('.') - " create the menu - call MenuBuilder() - " restore disposition of window and cursor - exe "norm ".hline."Gzt" - let dnscroll=cline-hline - exe "norm ".dnscroll."j".ccol."l" - let &foldenable = restore_fe -endfunction - -function! MenuBuilder() - norm gg0 - let currentclass = -1 - let classlist = [] - let parentclass = "" - while line(".") < line("$") - " search for a class or function - if match ( getline("."), '^\s*class\s\+[_a-zA-Z].*:\|^\s*def\s\+[_a-zA-Z].*:' ) != -1 - norm ^ - let linenum = line('.') - let indentcol = col('.') - norm "nye - let classordef=@n - norm w"nywge - let objname=@n - let parentclass = FindParentClass(classlist, indentcol) - if classordef == "class" - call AddClass(objname, linenum, parentclass) - else " this is a function - call AddFunction(objname, linenum, parentclass) - endif - " We actually created a menu, so lets set the global variable - let g:menuran=1 - call RebuildClassList(classlist, [objname, indentcol], classordef) - endif " line matched - norm j - endwhile -endfunction - -" classlist contains the list of nested classes we are in. -" in most cases it will be empty or contain a single class -" but where a class is nested within another, it will contain 2 or more -" this function adds or removes classes from the list based on indentation -function! RebuildClassList(classlist, newclass, classordef) - let i = len(a:classlist) - 1 - while i > -1 - if a:newclass[1] <= a:classlist[i][1] - call remove(a:classlist, i) - endif - let i = i - 1 - endwhile - if a:classordef == "class" - call add(a:classlist, a:newclass) - endif -endfunction - -" we found a class or function, determine its parent class based on -" indentation and what's contained in classlist -function! FindParentClass(classlist, indentcol) - let i = 0 - let parentclass = "" - while i < len(a:classlist) - if a:indentcol <= a:classlist[i][1] - break - else - if len(parentclass) == 0 - let parentclass = a:classlist[i][0] - else - let parentclass = parentclass.'\.'.a:classlist[i][0] - endif - endif - let i = i + 1 - endwhile - return parentclass -endfunction - -" add a class to the menu -function! AddClass(classname, lineno, parentclass) - if len(a:parentclass) > 0 - let classstring = a:parentclass.'\.'.a:classname - else - let classstring = a:classname - endif - exe 'menu IM-Python.classes.'.classstring.' :call JumpToAndUnfold('.a:lineno.')' -endfunction - -" add a function to the menu, grouped by member class -function! AddFunction(functionname, lineno, parentclass) - if len(a:parentclass) > 0 - let funcstring = a:parentclass.'.'.a:functionname - else - let funcstring = a:functionname - endif - exe 'menu IM-Python.functions.'.funcstring.' :call JumpToAndUnfold('.a:lineno.')' -endfunction - - -function! s:JumpToAndUnfold(line) - " Go to the right line - execute 'normal '.a:line.'gg' - " Check to see if we are in a fold - let lvl = foldlevel(a:line) - if lvl != 0 - " and if so, then expand the fold out, other wise, ignore this part. - execute 'normal 15zo' - endif -endfunction - -"" This one will work only on vim 6.2 because of the try/catch expressions. -" function! s:JumpToAndUnfoldWithExceptions(line) -" try -" execute 'normal '.a:line.'gg15zo' -" catch /^Vim\((\a\+)\)\=:E490:/ -" " Do nothing, just consume the error -" endtry -"endfunction - - -" vim:set et sts=2 sw=2: - diff --git a/ftplugin/python/fold.vim b/ftplugin/python/fold.vim deleted file mode 100644 index 8964790..0000000 --- a/ftplugin/python/fold.vim +++ /dev/null @@ -1,122 +0,0 @@ -" Vim folding file -" Language: Python -" Author: Jorrit Wiersma (foldexpr), Max Ischenko (foldtext), Robert -" Ames (line counts) -" Last Change: 2005 Jul 14 -" Version: 2.3 -" Bug fix: Drexler Christopher, Tom Schumm, Geoff Gerrietts - - -setlocal foldmethod=expr -setlocal foldexpr=GetPythonFold(v:lnum) -setlocal foldtext=PythonFoldText() - - -function! PythonFoldText() - let line = getline(v:foldstart) - let nnum = nextnonblank(v:foldstart + 1) - let nextline = getline(nnum) - if nextline =~ '^\s\+"""$' - let line = line . getline(nnum + 1) - elseif nextline =~ '^\s\+"""' - let line = line . ' ' . matchstr(nextline, '"""\zs.\{-}\ze\("""\)\?$') - elseif nextline =~ '^\s\+"[^"]\+"$' - let line = line . ' ' . matchstr(nextline, '"\zs.*\ze"') - elseif nextline =~ '^\s\+pass\s*$' - let line = line . ' pass' - endif - let size = 1 + v:foldend - v:foldstart - if size < 10 - let size = " " . size - endif - if size < 100 - let size = " " . size - endif - if size < 1000 - let size = " " . size - endif - return size . " lines: " . line -endfunction - - -function! GetPythonFold(lnum) - " Determine folding level in Python source - " - let line = getline(a:lnum) - let ind = indent(a:lnum) - - " Ignore blank lines - if line =~ '^\s*$' - return "=" - endif - - " Ignore triple quoted strings - if line =~ "(\"\"\"|''')" - return "=" - endif - - " Ignore continuation lines - if line =~ '\\$' - return '=' - endif - - " Support markers - if line =~ '{{{' - return "a1" - elseif line =~ '}}}' - return "s1" - endif - - " Classes and functions get their own folds - if line =~ '^\s*\(class\|def\)\s' - return ">" . (ind / &sw + 1) - endif - - let pnum = prevnonblank(a:lnum - 1) - - if pnum == 0 - " Hit start of file - return 0 - endif - - " If the previous line has foldlevel zero, and we haven't increased - " it, we should have foldlevel zero also - if foldlevel(pnum) == 0 - return 0 - endif - - " The end of a fold is determined through a difference in indentation - " between this line and the next. - " So first look for next line - let nnum = nextnonblank(a:lnum + 1) - if nnum == 0 - return "=" - endif - - " First I check for some common cases where this algorithm would - " otherwise fail. (This is all a hack) - let nline = getline(nnum) - if nline =~ '^\s*\(except\|else\|elif\)' - return "=" - endif - - " Python programmers love their readable code, so they're usually - " going to have blank lines at the ends of functions or classes - " If the next line isn't blank, we probably don't need to end a fold - if nnum == a:lnum + 1 - return "=" - endif - - " If next line has less indentation we end a fold. - " This ends folds that aren't there a lot of the time, and this sometimes - " confuses vim. Luckily only rarely. - let nind = indent(nnum) - if nind < ind - return "<" . (nind / &sw + 1) - endif - - " If none of the above apply, keep the indentation - return "=" - -endfunction - diff --git a/ftplugin/python/mccabe/__init__.py b/ftplugin/python/mccabe/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/ftplugin/python/mccabe/mccabe.py b/ftplugin/python/mccabe/mccabe.py deleted file mode 100755 index 96fb6e7..0000000 --- a/ftplugin/python/mccabe/mccabe.py +++ /dev/null @@ -1,293 +0,0 @@ -""" Meager code path measurement tool. - Ned Batchelder - http://nedbatchelder.com/blog/200803/python_code_complexity_microtool.html - MIT License. -""" -try: - from compiler import parse # NOQA - iter_child_nodes = None # NOQA -except ImportError: - from ast import parse, iter_child_nodes # NOQA - -import optparse -import sys -from collections import defaultdict - -WARNING_CODE = "W901" - - -class ASTVisitor: - - VERBOSE = 0 - - def __init__(self): - self.node = None - self._cache = {} - - def default(self, node, *args): - if hasattr(node, 'getChildNodes'): - children = node.getChildNodes() - else: - children = iter_child_nodes(node) - - for child in children: - self.dispatch(child, *args) - - def dispatch(self, node, *args): - self.node = node - klass = node.__class__ - meth = self._cache.get(klass) - if meth is None: - className = klass.__name__ - meth = getattr(self.visitor, 'visit' + className, self.default) - self._cache[klass] = meth - - return meth(node, *args) - - def preorder(self, tree, visitor, *args): - """Do preorder walk of tree using visitor""" - self.visitor = visitor - visitor.visit = self.dispatch - self.dispatch(tree, *args) # XXX *args make sense? - - -class PathNode: - def __init__(self, name, look="circle"): - self.name = name - self.look = look - - def to_dot(self): - print('node [shape=%s,label="%s"] %d;' % \ - (self.look, self.name, self.dot_id())) - - def dot_id(self): - return id(self) - - -class PathGraph: - def __init__(self, name, entity, lineno): - self.name = name - self.entity = entity - self.lineno = lineno - self.nodes = defaultdict(list) - - def connect(self, n1, n2): - self.nodes[n1].append(n2) - - def to_dot(self): - print('subgraph {') - for node in self.nodes: - node.to_dot() - for node, nexts in self.nodes.items(): - for next in nexts: - print('%s -- %s;' % (node.dot_id(), next.dot_id())) - print('}') - - def complexity(self): - """ Return the McCabe complexity for the graph. - V-E+2 - """ - num_edges = sum([len(n) for n in self.nodes.values()]) - num_nodes = len(self.nodes) - return num_edges - num_nodes + 2 - - -class PathGraphingAstVisitor(ASTVisitor): - """ A visitor for a parsed Abstract Syntax Tree which finds executable - statements. - """ - - def __init__(self): - ASTVisitor.__init__(self) - self.classname = "" - self.graphs = {} - self.reset() - - def reset(self): - self.graph = None - self.tail = None - - def visitFunction(self, node): - - if self.classname: - entity = '%s%s' % (self.classname, node.name) - else: - entity = node.name - - name = '%d:1: %r' % (node.lineno, entity) - - if self.graph is not None: - # closure - pathnode = self.appendPathNode(name) - self.tail = pathnode - self.default(node) - bottom = PathNode("", look='point') - self.graph.connect(self.tail, bottom) - self.graph.connect(pathnode, bottom) - self.tail = bottom - else: - self.graph = PathGraph(name, entity, node.lineno) - pathnode = PathNode(name) - self.tail = pathnode - self.default(node) - self.graphs["%s%s" % (self.classname, node.name)] = self.graph - self.reset() - - visitFunctionDef = visitFunction - - def visitClass(self, node): - old_classname = self.classname - self.classname += node.name + "." - self.default(node) - self.classname = old_classname - - def appendPathNode(self, name): - if not self.tail: - return - pathnode = PathNode(name) - self.graph.connect(self.tail, pathnode) - self.tail = pathnode - return pathnode - - def visitSimpleStatement(self, node): - if node.lineno is None: - lineno = 0 - else: - lineno = node.lineno - name = "Stmt %d" % lineno - self.appendPathNode(name) - - visitAssert = visitAssign = visitAssTuple = visitPrint = \ - visitPrintnl = visitRaise = visitSubscript = visitDecorators = \ - visitPass = visitDiscard = visitGlobal = visitReturn = \ - visitSimpleStatement - - def visitLoop(self, node): - name = "Loop %d" % node.lineno - - if self.graph is None: - # global loop - self.graph = PathGraph(name, name, node.lineno) - pathnode = PathNode(name) - self.tail = pathnode - self.default(node) - self.graphs["%s%s" % (self.classname, name)] = self.graph - self.reset() - else: - pathnode = self.appendPathNode(name) - self.tail = pathnode - self.default(node.body) - bottom = PathNode("", look='point') - self.graph.connect(self.tail, bottom) - self.graph.connect(pathnode, bottom) - self.tail = bottom - - # TODO: else clause in node.else_ - - visitFor = visitWhile = visitLoop - - def visitIf(self, node): - name = "If %d" % node.lineno - pathnode = self.appendPathNode(name) - if not pathnode: - return # TODO: figure out what to do with if's outside def's. - loose_ends = [] - for t, n in node.tests: - self.tail = pathnode - self.default(n) - loose_ends.append(self.tail) - if node.else_: - self.tail = pathnode - self.default(node.else_) - loose_ends.append(self.tail) - else: - loose_ends.append(pathnode) - bottom = PathNode("", look='point') - for le in loose_ends: - self.graph.connect(le, bottom) - self.tail = bottom - - # TODO: visitTryExcept - # TODO: visitTryFinally - # TODO: visitWith - - # XXX todo: determine which ones can add to the complexity - # py2 - # TODO: visitStmt - # TODO: visitAssName - # TODO: visitCallFunc - # TODO: visitConst - - # py3 - # TODO: visitStore - # TODO: visitCall - # TODO: visitLoad - # TODO: visitNum - # TODO: visitarguments - # TODO: visitExpr - - -def get_code_complexity(code, min=7, filename='stdin'): - complex = [] - try: - ast = parse(code) - except AttributeError: - e = sys.exc_info()[1] - sys.stderr.write("Unable to parse %s: %s\n" % (filename, e)) - return 0 - - visitor = PathGraphingAstVisitor() - visitor.preorder(ast, visitor) - for graph in visitor.graphs.values(): - if graph is None: - # ? - continue - if graph.complexity() >= min: - complex.append(dict( - type = 'W', - lnum = graph.lineno, - text = '%s %r is too complex (%d)' % ( - WARNING_CODE, - graph.entity, - graph.complexity(), - ) - )) - - return complex - - -def get_module_complexity(module_path, min=7): - """Returns the complexity of a module""" - code = open(module_path, "rU").read() + '\n\n' - return get_code_complexity(code, min, filename=module_path) - - -def main(argv): - opar = optparse.OptionParser() - opar.add_option("-d", "--dot", dest="dot", - help="output a graphviz dot file", action="store_true") - opar.add_option("-m", "--min", dest="min", - help="minimum complexity for output", type="int", - default=2) - - options, args = opar.parse_args(argv) - - text = open(args[0], "rU").read() + '\n\n' - ast = parse(text) - visitor = PathGraphingAstVisitor() - visitor.preorder(ast, visitor) - - if options.dot: - print('graph {') - for graph in visitor.graphs.values(): - if graph.complexity() >= options.min: - graph.to_dot() - print('}') - else: - for graph in visitor.graphs.values(): - if graph.complexity() >= options.min: - print(graph.name, graph.complexity()) - - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/ftplugin/python/pep8/__init__.py b/ftplugin/python/pep8/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/ftplugin/python/pep8/autopep8.py b/ftplugin/python/pep8/autopep8.py deleted file mode 100755 index 143e28e..0000000 --- a/ftplugin/python/pep8/autopep8.py +++ /dev/null @@ -1,2047 +0,0 @@ -#!/usr/bin/env python -# -# 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: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# 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. - -"""Automatically formats Python code to conform to the PEP 8 style guide.""" - -from __future__ import print_function -from __future__ import division - -import copy -import os -import re -import sys -import inspect -import codecs -try: - from StringIO import StringIO -except ImportError: - from io import StringIO -import token -import tokenize -from optparse import OptionParser -from subprocess import Popen, PIPE -import difflib -import tempfile - -from distutils.version import StrictVersion -try: - import pep8 - try: - if StrictVersion(pep8.__version__) < StrictVersion('1.3a2'): - pep8 = None - except ValueError: - # Ignore non-standard version tags. - pass -except ImportError: - pep8 = None - - -__version__ = '0.8.5' - - -PEP8_BIN = 'pep8' -CR = '\r' -LF = '\n' -CRLF = '\r\n' - -try: - unicode -except NameError: - unicode = str - - -def open_with_encoding(filename, encoding=None, mode='r'): - """Return opened file with a specific encoding.""" - if not encoding: - encoding = detect_encoding(filename) - - import io - return io.open(filename, mode=mode, encoding=encoding, - newline='') # Preserve line endings - - -def detect_encoding(filename): - """Return file encoding.""" - try: - with open(filename, 'rb') as input_file: - from lib2to3.pgen2 import tokenize as lib2to3_tokenize - encoding = lib2to3_tokenize.detect_encoding(input_file.readline)[0] - - # Check for correctness of encoding - with open_with_encoding(filename, encoding) as test_file: - test_file.read() - - return encoding - except (SyntaxError, LookupError, UnicodeDecodeError): - return 'latin-1' - - -def read_from_filename(filename, readlines=False): - """Return contents of file.""" - with open_with_encoding(filename) as input_file: - return input_file.readlines() if readlines else input_file.read() - - -class FixPEP8(object): - - """Fix invalid code. - - Fixer methods are prefixed "fix_". The _fix_source() method looks for these - automatically. - - The fixer method can take either one or two arguments (in addition to - self). The first argument is "result", which is the error information from - pep8. The second argument, "logical", is required only for logical-line - fixes. - - The fixer method can return the list of modified lines or None. An empty - list would mean that no changes were made. None would mean that only the - line reported in the pep8 error was modified. Note that the modified line - numbers that are returned are indexed at 1. This typically would correspond - with the line number reported in the pep8 error information. - - [fixed method list] - - e111 - - e121,e122,e123,e124,e125,e126,e127,e128 - - e201,e202,e203 - - e211 - - e221,e222,e223,e224,e225 - - e231 - - e251 - - e261,e262 - - e271,e272,e273,e274 - - e301,e302,e303 - - e401 - - e502 - - e701,e702 - - e711 - - e721 - - w291,w293 - - w391 - - w602,w603,w604 - - """ - - def __init__(self, filename, options, contents=None): - self.filename = filename - if contents is None: - self.source = read_from_filename(filename, readlines=True) - else: - sio = StringIO(contents) - self.source = sio.readlines() - self.newline = find_newline(self.source) - self.options = options - self.indent_word = _get_indentword(unicode().join(self.source)) - self.logical_start = None - self.logical_end = None - # method definition - self.fix_e111 = self.fix_e101 - self.fix_e128 = self.fix_e127 - self.fix_e202 = self.fix_e201 - self.fix_e203 = self.fix_e201 - self.fix_e211 = self.fix_e201 - self.fix_e221 = self.fix_e271 - self.fix_e222 = self.fix_e271 - self.fix_e223 = self.fix_e271 - self.fix_e226 = self.fix_e225 - self.fix_e241 = self.fix_e271 - self.fix_e242 = self.fix_e224 - self.fix_e261 = self.fix_e262 - self.fix_e272 = self.fix_e271 - self.fix_e273 = self.fix_e271 - self.fix_e274 = self.fix_e271 - self.fix_e703 = self.fix_e702 - self.fix_w191 = self.fix_e101 - - def _fix_source(self, results): - completed_lines = set() - for result in sorted(results, key=_priority_key): - if result['line'] in completed_lines: - continue - - fixed_methodname = 'fix_%s' % result['id'].lower() - if hasattr(self, fixed_methodname): - fix = getattr(self, fixed_methodname) - - is_logical_fix = len(inspect.getargspec(fix).args) > 2 - if is_logical_fix: - # Do not run logical fix if any lines have been modified. - if completed_lines: - continue - - logical = self._get_logical(result) - if not logical: - continue - - modified_lines = fix(result, logical) - else: - modified_lines = fix(result) - - if modified_lines: - completed_lines.update(modified_lines) - elif modified_lines == []: # Empty list means no fix - if self.options.verbose >= 2: - print( - '---> Not fixing {f} on line {l}'.format( - f=result['id'], l=result['line']), - file=sys.stderr) - else: # We assume one-line fix when None - completed_lines.add(result['line']) - else: - if self.options.verbose >= 3: - print("---> '%s' is not defined." % fixed_methodname, - file=sys.stderr) - info = result['info'].strip() - print('---> %s:%s:%s:%s' % (self.filename, - result['line'], - result['column'], - info), - file=sys.stderr) - - def fix(self): - """Return a version of the source code with PEP 8 violations fixed.""" - if pep8: - pep8_options = { - 'ignore': - self.options.ignore and self.options.ignore.split(','), - 'select': - self.options.select and self.options.select.split(','), - 'max_line_length': - self.options.max_line_length, - } - results = _execute_pep8(pep8_options, self.source) - else: - encoding = detect_encoding(self.filename) - - (_tmp_open_file, tmp_filename) = tempfile.mkstemp() - os.close(_tmp_open_file) - fp = open_with_encoding(tmp_filename, encoding=encoding, mode='w') - fp.write(unicode().join(self.source)) - fp.close() - - if self.options.verbose: - print('Running in compatibility mode. Consider ' - 'upgrading to the latest pep8.', - file=sys.stderr) - results = _spawn_pep8((['--ignore=' + self.options.ignore] - if self.options.ignore else []) + - (['--select=' + self.options.select] - if self.options.select else []) + - (['--max-line-length={length}'.format( - length=self.options.max_line_length)] - if self.options.max_line_length else []) + - [tmp_filename]) - if not pep8: - os.remove(tmp_filename) - - if self.options.verbose: - progress = {} - for r in results: - if r['id'] not in progress: - progress[r['id']] = set() - progress[r['id']].add(r['line']) - print('---> {n} issue(s) to fix {progress}'.format( - n=len(results), progress=progress), file=sys.stderr) - - self._fix_source(filter_results(source=unicode().join(self.source), - results=results, - aggressive=self.options.aggressive)) - return unicode().join(self.source) - - def fix_e101(self, _): - """Reindent all lines.""" - reindenter = Reindenter(self.source, self.newline) - modified_line_numbers = reindenter.run() - if modified_line_numbers: - self.source = reindenter.fixed_lines() - return modified_line_numbers - else: - return [] - - def find_logical(self, force=False): - # make a variable which is the index of all the starts of lines - if not force and self.logical_start is not None: - return - logical_start = [] - logical_end = [] - last_newline = True - sio = StringIO(''.join(self.source)) - parens = 0 - for t in tokenize.generate_tokens(sio.readline): - if t[0] in [tokenize.COMMENT, tokenize.DEDENT, - tokenize.INDENT, tokenize.NL, - tokenize.ENDMARKER]: - continue - if not parens and t[0] in [ - tokenize.NEWLINE, tokenize.SEMI - ]: - last_newline = True - logical_end.append((t[3][0] - 1, t[2][1])) - continue - if last_newline and not parens: - logical_start.append((t[2][0] - 1, t[2][1])) - last_newline = False - if t[0] == tokenize.OP: - if t[1] in '([{': - parens += 1 - elif t[1] in '}])': - parens -= 1 - self.logical_start = logical_start - self.logical_end = logical_end - - def _get_logical(self, result): - """Return the logical line corresponding to the result. - - Assumes input is already E702-clean. - - """ - try: - self.find_logical() - except (IndentationError, tokenize.TokenError): - return None - - row = result['line'] - 1 - col = result['column'] - 1 - ls = None - le = None - for i in range(0, len(self.logical_start), 1): - x = self.logical_end[i] - if x[0] > row or (x[0] == row and x[1] > col): - le = x - ls = self.logical_start[i] - break - if ls is None: - return None - original = self.source[ls[0]:le[0] + 1] - return ls, le, original - - def _fix_reindent(self, result, logical, fix_distinct=False): - """Fix a badly indented line. - - This is done by adding or removing from its initial indent only. - - """ - if not logical: - return [] - ls, _, original = logical - try: - rewrapper = Wrapper(original) - except (tokenize.TokenError, IndentationError): - return [] - valid_indents = rewrapper.pep8_expected() - if not rewrapper.rel_indent: - return [] - if result['line'] > ls[0]: - # got a valid continuation line number from pep8 - row = result['line'] - ls[0] - 1 - # always pick the first option for this - valid = valid_indents[row] - got = rewrapper.rel_indent[row] - else: - # Line number from pep8 isn't a continuation line. Instead, - # compare our own function's result, look for the first mismatch, - # and just hope that we take fewer than 100 iterations to finish. - for row in range(0, len(original), 1): - valid = valid_indents[row] - got = rewrapper.rel_indent[row] - if valid != got: - break - line = ls[0] + row - # always pick the expected indent, for now. - indent_to = valid[0] - if fix_distinct and indent_to == 4: - if len(valid) == 1: - return [] - else: - indent_to = valid[1] - - if got != indent_to: - orig_line = self.source[line] - new_line = ' ' * (indent_to) + orig_line.lstrip() - if new_line == orig_line: - return [] - else: - self.source[line] = new_line - return [line + 1] # Line indexed at 1 - else: - return [] - - def fix_e121(self, result, logical): - """Fix indentation to be a multiple of four.""" - # Fix by adjusting initial indent level. - return self._fix_reindent(result, logical) - - def fix_e122(self, result, logical): - """Add absent indentation for hanging indentation.""" - # Fix by adding an initial indent. - return self._fix_reindent(result, logical) - - def fix_e123(self, result, logical): - """Align closing bracket to match opening bracket.""" - # Fix by deleting whitespace to the correct level. - if not logical: - return [] - logical_lines = logical[2] - line_index = result['line'] - 1 - original_line = self.source[line_index] - - fixed_line = (_get_indentation(logical_lines[0]) + - original_line.lstrip()) - if fixed_line == original_line: - # Fall back to slower method. - return self._fix_reindent(result, logical) - else: - self.source[line_index] = fixed_line - - def fix_e124(self, result, logical): - """Align closing bracket to match visual indentation.""" - # Fix by inserting whitespace before the closing bracket. - return self._fix_reindent(result, logical) - - def fix_e125(self, result, logical): - """Indent to distinguish line from next logical line.""" - # Fix by indenting the line in error to the next stop. - modified_lines = self._fix_reindent(result, logical, fix_distinct=True) - if modified_lines: - return modified_lines - else: - # Fallback - line_index = result['line'] - 1 - original_line = self.source[line_index] - self.source[line_index] = self.indent_word + original_line - - def fix_e126(self, result, logical): - """Fix over-indented hanging indentation.""" - # fix by deleting whitespace to the left - if not logical: - return [] - logical_lines = logical[2] - line_index = result['line'] - 1 - original = self.source[line_index] - - fixed = (_get_indentation(logical_lines[0]) + - self.indent_word + original.lstrip()) - if fixed == original: - # Fallback to slower method. - return self._fix_reindent(result, logical) - else: - self.source[line_index] = fixed - - def fix_e127(self, result, logical): - """Fix visual indentation.""" - # Fix by inserting/deleting whitespace to the correct level. - modified_lines = self._align_visual_indent(result, logical) - if modified_lines != []: - return modified_lines - else: - # Fallback to slower method. - return self._fix_reindent(result, logical) - - def _align_visual_indent(self, result, logical): - """Correct visual indent. - - This includes over (E127) and under (E128) indented lines. - - """ - if not logical: - return [] - logical_lines = logical[2] - line_index = result['line'] - 1 - original = self.source[line_index] - fixed = original - - if logical_lines[0].rstrip().endswith('\\'): - fixed = (_get_indentation(logical_lines[0]) + - self.indent_word + original.lstrip()) - else: - for symbol in '([{': - if symbol in logical_lines[0]: - fixed = logical_lines[0].find( - symbol) * ' ' + original.lstrip() - break - - if fixed == original: - return [] - else: - self.source[line_index] = fixed - - def fix_e201(self, result): - """Remove extraneous whitespace.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - # When multiline strings are involved, pep8 reports the error as - # being at the start of the multiline string, which doesn't work - # for us. - if ('"""' in target or - "'''" in target or - target.rstrip().endswith('\\')): - return [] - - fixed = fix_whitespace(target, - offset=offset, - replacement='') - - if fixed == target: - return [] - else: - self.source[line_index] = fixed - - def fix_e224(self, result): - """Remove extraneous whitespace around operator.""" - target = self.source[result['line'] - 1] - offset = result['column'] - 1 - fixed = target[:offset] + target[offset:].replace('\t', ' ') - self.source[result['line'] - 1] = fixed - - def fix_e225(self, result): - """Fix missing whitespace around operator.""" - target = self.source[result['line'] - 1] - offset = result['column'] - 1 - fixed = target[:offset] + ' ' + target[offset:] - - # Only proceed if non-whitespace characters match. - # And make sure we don't break the indentation. - if (fixed.replace(' ', '') == target.replace(' ', '') and - _get_indentation(fixed) == _get_indentation(target)): - self.source[result['line'] - 1] = fixed - else: - return [] - - def fix_e231(self, result): - """Add missing whitespace.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - fixed = target[:offset] + ' ' + target[offset:] - self.source[line_index] = fixed - - def fix_e251(self, result): - """Remove whitespace around parameter '=' sign.""" - line_index = result['line'] - 1 - target = self.source[line_index] - - # This is necessary since pep8 sometimes reports columns that goes - # past the end of the physical line. This happens in cases like, - # foo(bar\n=None) - c = min(result['column'] - 1, - len(target) - 1) - - if target[c].strip(): - fixed = target - else: - fixed = target[:c].rstrip() + target[c:].lstrip() - - # There could be an escaped newline - # - # def foo(a=\ - # 1) - if (fixed.endswith('=\\\n') or - fixed.endswith('=\\\r\n') or - fixed.endswith('=\\\r')): - self.source[line_index] = fixed.rstrip('\n\r \t\\') - self.source[line_index + 1] = self.source[line_index + 1].lstrip() - return [line_index + 1, line_index + 2] # Line indexed at 1 - - self.source[result['line'] - 1] = fixed - - def fix_e262(self, result): - """Fix spacing after comment hash.""" - target = self.source[result['line'] - 1] - offset = result['column'] - - code = target[:offset].rstrip(' \t#') - comment = target[offset:].lstrip(' \t#') - - fixed = code + (' # ' + comment if comment.strip() - else self.newline) - - self.source[result['line'] - 1] = fixed - - def fix_e271(self, result): - """Fix extraneous whitespace around keywords.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - # When multiline strings are involved, pep8 reports the error as - # being at the start of the multiline string, which doesn't work - # for us. - if ('"""' in target or - "'''" in target or - target.rstrip().endswith('\\')): - return [] - - fixed = fix_whitespace(target, - offset=offset, - replacement=' ') - - if fixed == target: - return [] - else: - self.source[line_index] = fixed - - def fix_e301(self, result): - """Add missing blank line.""" - cr = self.newline - self.source[result['line'] - 1] = cr + self.source[result['line'] - 1] - - def fix_e302(self, result): - """Add missing 2 blank lines.""" - add_linenum = 2 - int(result['info'].split()[-1]) - cr = self.newline * add_linenum - self.source[result['line'] - 1] = cr + self.source[result['line'] - 1] - - def fix_e303(self, result): - """Remove extra blank lines.""" - delete_linenum = int(result['info'].split('(')[1].split(')')[0]) - 2 - delete_linenum = max(1, delete_linenum) - - # We need to count because pep8 reports an offset line number if there - # are comments. - cnt = 0 - line = result['line'] - 2 - modified_lines = [] - while cnt < delete_linenum: - if line < 0: - break - if not self.source[line].strip(): - self.source[line] = '' - modified_lines.append(1 + line) # Line indexed at 1 - cnt += 1 - line -= 1 - - return modified_lines - - def fix_e304(self, result): - """Remove blank line following function decorator.""" - line = result['line'] - 2 - if not self.source[line].strip(): - self.source[line] = '' - - def fix_e401(self, result): - """Put imports on separate lines.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - if not target.lstrip().startswith('import'): - return [] - - # pep8 (1.3.1) reports false positive if there is an import statement - # followed by a semicolon and some unrelated statement with commas in - # it. - if ';' in target: - return [] - - indentation = re.split(pattern=r'\bimport\b', - string=target, maxsplit=1)[0] - fixed = (target[:offset].rstrip('\t ,') + self.newline + - indentation + 'import ' + target[offset:].lstrip('\t ,')) - self.source[line_index] = fixed - - def fix_e501(self, result): - """Try to make lines fit within --max-line-length characters.""" - line_index = result['line'] - 1 - target = self.source[line_index] - - if target.lstrip().startswith('#'): - # Shorten comment if it is the last comment line. - try: - if self.source[line_index + 1].lstrip().startswith('#'): - return [] - except IndexError: - pass - - # Wrap commented lines. - fixed = shorten_comment( - line=target, - newline=self.newline, - max_line_length=self.options.max_line_length) - if fixed == self.source[line_index]: - return [] - else: - self.source[line_index] = fixed - return - - indent = _get_indentation(target) - source = target[len(indent):] - sio = StringIO(target) - - # Check for multiline string. - try: - tokens = list(tokenize.generate_tokens(sio.readline)) - except (tokenize.TokenError, IndentationError): - multi_line_candidate = break_multi_line( - target, newline=self.newline, - indent_word=self.indent_word, - max_line_length=self.options.max_line_length) - - if multi_line_candidate: - self.source[line_index] = multi_line_candidate - return - else: - return [] - - # Prefer - # my_long_function_name( - # x, y, z, ...) - # - # over - # my_long_function_name(x, y, - # z, ...) - candidates = [None, None] - for candidate_index, reverse in enumerate([False, True]): - candidates[candidate_index] = shorten_line( - tokens, source, target, indent, - self.indent_word, newline=self.newline, - max_line_length=self.options.max_line_length, - reverse=reverse, - aggressive=self.options.aggressive) - - if candidates[0] and candidates[1]: - if candidates[0].split(self.newline)[0].endswith('('): - self.source[line_index] = candidates[0] - else: - self.source[line_index] = candidates[1] - elif candidates[0]: - self.source[line_index] = candidates[0] - elif candidates[1]: - self.source[line_index] = candidates[1] - else: - # Otherwise both don't work - return [] - - def fix_e502(self, result): - """Remove extraneous escape of newline.""" - line_index = result['line'] - 1 - target = self.source[line_index] - self.source[line_index] = target.rstrip('\n\r \t\\') + self.newline - - def fix_e701(self, result): - """Put colon-separated compound statement on separate lines.""" - line_index = result['line'] - 1 - target = self.source[line_index] - c = result['column'] - - fixed_source = (target[:c] + self.newline + - _get_indentation(target) + self.indent_word + - target[c:].lstrip('\n\r \t\\')) - self.source[result['line'] - 1] = fixed_source - - def fix_e702(self, result, logical): - """Put semicolon-separated compound statement on separate lines.""" - logical_lines = logical[2] - - line_index = result['line'] - 1 - target = self.source[line_index] - - if target.rstrip().endswith('\\'): - # Normalize '1; \\\n2' into '1; 2'. - self.source[line_index] = target.rstrip('\n \r\t\\') - self.source[line_index + 1] = self.source[line_index + 1].lstrip() - return [line_index + 1, line_index + 2] - - if target.rstrip().endswith(';'): - self.source[line_index] = target.rstrip('\n \r\t;') + self.newline - return - - offset = result['column'] - 1 - first = target[:offset].rstrip(';').rstrip() - second = (_get_indentation(logical_lines[0]) + - target[offset:].lstrip(';').lstrip()) - - self.source[line_index] = first + self.newline + second - - def fix_e711(self, result): - """Fix comparison with None.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - right_offset = offset + 2 - if right_offset >= len(target): - return [] - - left = target[:offset].rstrip() - center = target[offset:right_offset] - right = target[right_offset:].lstrip() - - if not right.startswith('None'): - return [] - - if center.strip() == '==': - new_center = 'is' - elif center.strip() == '!=': - new_center = 'is not' - else: - return [] - - self.source[line_index] = ' '.join([left, new_center, right]) - - def fix_e712(self, result): - """Fix comparison with boolean.""" - line_index = result['line'] - 1 - target = self.source[line_index] - offset = result['column'] - 1 - - right_offset = offset + 2 - if right_offset >= len(target): - return [] - - left = target[:offset].rstrip() - center = target[offset:right_offset] - right = target[right_offset:].lstrip() - - # Handle simple cases only. - new_right = None - if center.strip() == '==': - if re.match(r'\bTrue\b', right): - new_right = re.sub(r'\bTrue\b *', '', right, count=1) - elif center.strip() == '!=': - if re.match(r'\bFalse\b', right): - new_right = re.sub(r'\bFalse\b *', '', right, count=1) - - if new_right is None: - return [] - - if new_right[0].isalnum(): - new_right = ' ' + new_right - - self.source[line_index] = left + new_right - - def fix_e721(self, _): - """Switch to use isinstance().""" - return self.refactor('idioms') - - def fix_w291(self, result): - """Remove trailing whitespace.""" - fixed_line = self.source[result['line'] - 1].rstrip() - self.source[result['line'] - 1] = '%s%s' % (fixed_line, self.newline) - - def fix_w293(self, result): - """Remove trailing whitespace on blank line.""" - assert not self.source[result['line'] - 1].strip() - self.source[result['line'] - 1] = self.newline - - def fix_w391(self, _): - """Remove trailing blank lines.""" - blank_count = 0 - for line in reversed(self.source): - line = line.rstrip() - if line: - break - else: - blank_count += 1 - - original_length = len(self.source) - self.source = self.source[:original_length - blank_count] - return range(1, 1 + original_length) - - def refactor(self, fixer_name, ignore=None): - """Return refactored code using lib2to3. - - Skip if ignore string is produced in the refactored code. - - """ - from lib2to3 import pgen2 - try: - new_text = refactor_with_2to3(''.join(self.source), - fixer_name=fixer_name) - except (pgen2.parse.ParseError, - UnicodeDecodeError, UnicodeEncodeError): - return [] - - original = unicode().join(self.source).strip() - if original == new_text.strip(): - return [] - else: - if ignore: - if ignore in new_text and ignore not in ''.join(self.source): - return [] - original_length = len(self.source) - self.source = [new_text] - return range(1, 1 + original_length) - - def fix_w601(self, _): - """Replace the {}.has_key() form with 'in'.""" - return self.refactor('has_key') - - def fix_w602(self, _): - """Fix deprecated form of raising exception.""" - return self.refactor('raise', - ignore='with_traceback') - - def fix_w603(self, _): - """Replace <> with !=.""" - return self.refactor('ne') - - def fix_w604(self, _): - """Replace backticks with repr().""" - return self.refactor('repr') - - -def find_newline(source): - """Return type of newline used in source.""" - cr, lf, crlf = 0, 0, 0 - for s in source: - if s.endswith(CRLF): - crlf += 1 - elif s.endswith(CR): - cr += 1 - elif s.endswith(LF): - lf += 1 - _max = max(cr, crlf, lf) - if _max == lf: - return LF - elif _max == crlf: - return CRLF - elif _max == cr: - return CR - else: - return LF - - -def _get_indentword(source): - """Return indentation type.""" - sio = StringIO(source) - indent_word = ' ' # Default in case source has no indentation - try: - for t in tokenize.generate_tokens(sio.readline): - if t[0] == token.INDENT: - indent_word = t[1] - break - except (tokenize.TokenError, IndentationError): - pass - return indent_word - - -def _get_indentation(line): - """Return leading whitespace.""" - if line.strip(): - non_whitespace_index = len(line) - len(line.lstrip()) - return line[:non_whitespace_index] - else: - return '' - - -def _analyze_pep8result(result): - tmp = result.split(':') - info = ' '.join(result.split()[1:]) - return {'id': info.lstrip().split()[0], - 'filename': tmp[0], - 'line': int(tmp[1]), - 'column': int(tmp[2]), - 'info': info} - - -def _get_difftext(old, new, filename): - diff = difflib.unified_diff( - old, new, - 'original/' + filename, - 'fixed/' + filename) - return ''.join(diff) - - -def _priority_key(pep8_result): - """Key for sorting PEP8 results. - - Global fixes should be done first. This is important for things - like indentation. - - """ - priority = ['e101', 'e111', 'w191', # Global fixes - 'e701', # Fix multiline colon-based before semicolon based - 'e702', # Break multiline statements early - 'e225', 'e231', # things that make lines longer - 'e201', # Remove extraneous whitespace before breaking lines - 'e501', # before we break lines - ] - key = pep8_result['id'].lower() - if key in priority: - return priority.index(key) - else: - # Lowest priority - return len(priority) - - -def shorten_line(tokens, source, target, indentation, indent_word, newline, - max_line_length, reverse=False, aggressive=False): - """Separate line at OPERATOR.""" - actual_length = len(indentation) + len(source) - - delta = (actual_length - max_line_length) // 3 - assert delta >= 0 - - if not delta: - delta = 1 - - shortened = None - length = None - for length in range(max_line_length, actual_length, delta): - shortened = _shorten_line( - tokens=tokens, - source=source, - target=target, - indentation=indentation, - indent_word=indent_word, - newline=newline, - max_line_length=length, - reverse=reverse, - aggressive=aggressive) - - if shortened is not None: - break - - if aggressive and (length is None or length > max_line_length): - commas_shortened = _shorten_line_at_commas( - tokens=tokens, - source=source, - indentation=indentation, - indent_word=indent_word, - newline=newline) - - if commas_shortened is not None and commas_shortened != source: - shortened = commas_shortened - - return shortened - - -def _shorten_line(tokens, source, target, indentation, indent_word, newline, - max_line_length, reverse=False, aggressive=False): - """Separate line at OPERATOR.""" - max_line_length_minus_indentation = max_line_length - len(indentation) - if reverse: - tokens = reversed(tokens) - for tkn in tokens: - # Don't break on '=' after keyword as this violates PEP 8. - if token.OP == tkn[0] and tkn[1] != '=': - offset = tkn[2][1] + 1 - if reverse: - if offset > (max_line_length_minus_indentation - - len(indent_word)): - continue - else: - if (len(target.rstrip()) - offset > - (max_line_length_minus_indentation - - len(indent_word))): - continue - first = source[:offset - len(indentation)] - - second_indent = indentation - if first.rstrip().endswith('('): - second_indent += indent_word - elif '(' in first: - second_indent += ' ' * (1 + first.find('(')) - else: - second_indent += indent_word - - second = (second_indent + - source[offset - len(indentation):].lstrip()) - if not second.strip(): - continue - - # Don't modify if lines are not short enough - if len(first) > max_line_length_minus_indentation: - continue - if len(second) > max_line_length: # Already includes indentation - continue - # Do not begin a line with a comma - if second.lstrip().startswith(','): - continue - # Do end a line with a dot - if first.rstrip().endswith('.'): - continue - if tkn[1] in '+-*/': - fixed = first + ' \\' + newline + second - else: - fixed = first + newline + second - - # Only fix if syntax is okay. - if check_syntax(normalize_multiline(fixed) - if aggressive else fixed): - return indentation + fixed - return None - - -def _shorten_line_at_commas(tokens, source, indentation, indent_word, newline): - """Separate line by breaking at commas.""" - if ',' not in source: - return None - - fixed = '' - for tkn in tokens: - token_type = tkn[0] - token_string = tkn[1] - - if token_string == '.': - fixed = fixed.rstrip() - - fixed += token_string - - if token_type == token.OP and token_string == ',': - fixed += newline + indent_word - elif token_type not in (token.NEWLINE, token.ENDMARKER): - if token_string != '.': - fixed += ' ' - - if check_syntax(fixed): - return indentation + fixed - else: - return None - - -def normalize_multiline(line): - """Remove multiline-related code that will cause syntax error. - - This is for purposes of checking syntax. - - """ - for quote in '\'"': - dict_pattern = r'^{q}[^{q}]*{q}\s*:\s*'.format(q=quote) - if re.match(dict_pattern, line): - if not line.strip().endswith('}'): - line += '}' - return '{' + line - - return line - - -def fix_whitespace(line, offset, replacement): - """Replace whitespace at offset and return fixed line.""" - # Replace escaped newlines too - left = line[:offset].rstrip('\n\r \t\\') - right = line[offset:].lstrip('\n\r \t\\') - if right.startswith('#'): - return line - else: - return left + replacement + right - - -def _spawn_pep8(pep8_options): - """Execute pep8 via subprocess.Popen.""" - p = Popen([PEP8_BIN] + pep8_options, stdout=PIPE) - output = p.communicate()[0].decode('utf-8') - return [_analyze_pep8result(l) for l in output.splitlines()] - - -def _execute_pep8(pep8_options, source): - """Execute pep8 via python method calls.""" - class QuietReport(pep8.BaseReport): - - """Version of checker that does not print.""" - - def __init__(self, options): - super(QuietReport, self).__init__(options) - self.__full_error_results = [] - - def error(self, line_number, offset, text, _): - """Collect errors.""" - code = super(QuietReport, self).error(line_number, offset, text, _) - if code: - self.__full_error_results.append( - {'id': code, - 'line': line_number, - 'column': offset + 1, - 'info': text}) - - def full_error_results(self): - """Return error results in detail. - - Results are in the form of a list of dictionaries. Each dictionary - contains 'id', 'line', 'column', and 'info'. - - """ - return self.__full_error_results - - checker = pep8.Checker('', lines=source, - reporter=QuietReport, **pep8_options) - checker.check_all() - return checker.report.full_error_results() - - -class Reindenter(object): - - """Reindents badly-indented code to uniformly use four-space indentation. - - Released to the public domain, by Tim Peters, 03 October 2000. - - """ - - def __init__(self, input_text, newline): - self.newline = newline - - # Raw file lines. - self.raw = input_text - self.after = None - - self.string_content_line_numbers = multiline_string_lines( - ''.join(self.raw)) - - # File lines, rstripped & tab-expanded. Dummy at start is so - # that we can use tokenize's 1-based line numbering easily. - # Note that a line is all-blank iff it is a newline. - self.lines = [] - for line_number, line in enumerate(self.raw, start=1): - # Do not modify if inside a multi-line string. - if line_number in self.string_content_line_numbers: - self.lines.append(line) - else: - # Only expand leading tabs. - self.lines.append(_get_indentation(line).expandtabs() + - line.strip() + newline) - - self.lines.insert(0, None) - self.index = 1 # index into self.lines of next line - - def run(self): - """Fix indentation and return modified line numbers. - - Line numbers are indexed at 1. - - """ - try: - stats = reindent_stats(tokenize.generate_tokens(self.getline)) - except (tokenize.TokenError, IndentationError): - return set() - # Remove trailing empty lines. - lines = self.lines - while lines and lines[-1] == self.newline: - lines.pop() - # Sentinel. - stats.append((len(lines), 0)) - # Map count of leading spaces to # we want. - have2want = {} - # Program after transformation. - after = self.after = [] - # Copy over initial empty lines -- there's nothing to do until - # we see a line with *something* on it. - i = stats[0][0] - after.extend(lines[1:i]) - for i in range(len(stats) - 1): - thisstmt, thislevel = stats[i] - nextstmt = stats[i + 1][0] - have = _leading_space_count(lines[thisstmt]) - want = thislevel * 4 - if want < 0: - # A comment line. - if have: - # An indented comment line. If we saw the same - # indentation before, reuse what it most recently - # mapped to. - want = have2want.get(have, - 1) - if want < 0: - # Then it probably belongs to the next real stmt. - for j in range(i + 1, len(stats) - 1): - jline, jlevel = stats[j] - if jlevel >= 0: - if have == _leading_space_count(lines[jline]): - want = jlevel * 4 - break - if want < 0: # Maybe it's a hanging - # comment like this one, - # in which case we should shift it like its base - # line got shifted. - for j in range(i - 1, -1, -1): - jline, jlevel = stats[j] - if jlevel >= 0: - want = (have + _leading_space_count( - after[jline - 1]) - - _leading_space_count(lines[jline])) - break - if want < 0: - # Still no luck -- leave it alone. - want = have - else: - want = 0 - assert want >= 0 - have2want[have] = want - diff = want - have - if diff == 0 or have == 0: - after.extend(lines[thisstmt:nextstmt]) - else: - for line_number, line in enumerate(lines[thisstmt:nextstmt], - start=thisstmt): - if line_number in self.string_content_line_numbers: - after.append(line) - elif diff > 0: - if line == self.newline: - after.append(line) - else: - after.append(' ' * diff + line) - else: - remove = min(_leading_space_count(line), -diff) - after.append(line[remove:]) - - if self.raw == self.after: - return set() - else: - return (set(range(1, 1 + len(self.raw))) - - self.string_content_line_numbers) - - def fixed_lines(self): - return self.after - - def getline(self): - """Line-getter for tokenize.""" - if self.index >= len(self.lines): - line = '' - else: - line = self.lines[self.index] - self.index += 1 - return line - - -def reindent_stats(tokens): - """Return list of (lineno, indentlevel) pairs. - - One for each stmt and comment line. indentlevel is -1 for comment lines, as - a signal that tokenize doesn't know what to do about them; indeed, they're - our headache! - - """ - find_stmt = 1 # next token begins a fresh stmt? - level = 0 # current indent level - stats = [] - - for t in tokens: - token_type = t[0] - sline = t[2][0] - line = t[4] - - if token_type == tokenize.NEWLINE: - # A program statement, or ENDMARKER, will eventually follow, - # after some (possibly empty) run of tokens of the form - # (NL | COMMENT)* (INDENT | DEDENT+)? - find_stmt = 1 - - elif token_type == tokenize.INDENT: - find_stmt = 1 - level += 1 - - elif token_type == tokenize.DEDENT: - find_stmt = 1 - level -= 1 - - elif token_type == tokenize.COMMENT: - if find_stmt: - stats.append((sline, -1)) - # but we're still looking for a new stmt, so leave - # find_stmt alone - - elif token_type == tokenize.NL: - pass - - elif find_stmt: - # This is the first "real token" following a NEWLINE, so it - # must be the first token of the next program statement, or an - # ENDMARKER. - find_stmt = 0 - if line: # not endmarker - stats.append((sline, level)) - - return stats - - -class Wrapper(object): - - """Class for functions relating to continuation lines and line folding. - - Each instance operates on a single logical line. - - """ - - SKIP_TOKENS = frozenset([ - tokenize.COMMENT, tokenize.NL, tokenize.INDENT, - tokenize.DEDENT, tokenize.NEWLINE, tokenize.ENDMARKER - ]) - - def __init__(self, physical_lines): - self.lines = physical_lines - self.tokens = [] - self.rel_indent = None - sio = StringIO(''.join(physical_lines)) - for t in tokenize.generate_tokens(sio.readline): - if not len(self.tokens) and t[0] in self.SKIP_TOKENS: - continue - if t[0] != tokenize.ENDMARKER: - self.tokens.append(t) - - self.logical_line = self.build_tokens_logical(self.tokens) - - def build_tokens_logical(self, tokens): - """Build a logical line from a list of tokens. - - Return the logical line and a list of (offset, token) tuples. Does - not mute strings like the version in pep8.py. - - """ - # from pep8.py with minor modifications - logical = [] - previous = None - for t in tokens: - token_type, text = t[0:2] - if token_type in self.SKIP_TOKENS: - continue - if previous: - end_line, end = previous[3] - start_line, start = t[2] - if end_line != start_line: # different row - prev_text = self.lines[end_line - 1][end - 1] - if prev_text == ',' or (prev_text not in '{[(' - and text not in '}])'): - logical.append(' ') - elif end != start: # different column - fill = self.lines[end_line - 1][end:start] - logical.append(fill) - logical.append(text) - previous = t - logical_line = ''.join(logical) - assert logical_line.lstrip() == logical_line - assert logical_line.rstrip() == logical_line - return logical_line - - def pep8_expected(self): - """Replicate logic in pep8.py, to know what level to indent things to. - - Return a list of lists; each list represents valid indent levels for - the line in question, relative from the initial indent. However, the - first entry is the indent level which was expected. - - """ - # What follows is an adjusted version of - # pep8.py:continuation_line_indentation. All of the comments have been - # stripped and the 'yield' statements replaced with 'pass'. - tokens = self.tokens - if not tokens: - return - - first_row = tokens[0][2][0] - nrows = 1 + tokens[-1][2][0] - first_row - - # here are the return values - valid_indents = [list()] * nrows - indent_level = tokens[0][2][1] - valid_indents[0].append(indent_level) - - if nrows == 1: - # bug, really. - return valid_indents - - indent_next = self.logical_line.endswith(':') - - row = depth = 0 - parens = [0] * nrows - self.rel_indent = rel_indent = [0] * nrows - indent = [indent_level] - indent_chances = {} - last_indent = (0, 0) - last_token_multiline = None - - for token_type, text, start, end, _ in self.tokens: - newline = row < start[0] - first_row - if newline: - row = start[0] - first_row - newline = (not last_token_multiline and - token_type not in (tokenize.NL, tokenize.NEWLINE)) - - if newline: - # This is where the differences start. Instead of looking at - # the line and determining whether the observed indent matches - # our expectations, we decide which type of indentation is in - # use at the given indent level, and return the offset. This - # algorithm is susceptible to "carried errors", but should - # through repeated runs eventually solve indentation for - # multi-line expressions less than PEP8_PASSES_MAX lines long. - - if depth: - for open_row in range(row - 1, -1, -1): - if parens[open_row]: - break - else: - open_row = 0 - - # That's all we get to work with. This code attempts to - # "reverse" the below logic, and place into the valid indents - # list - vi = [] - add_second_chances = False - if token_type == tokenize.OP and text in ']})': - # this line starts with a closing bracket, so it needs to - # be closed at the same indent as the opening one. - if indent[depth]: - # hanging indent - vi.append(indent[depth]) - else: - # visual indent - vi.append(indent_level + rel_indent[open_row]) - elif depth and indent[depth]: - # visual indent was previously confirmed. - vi.append(indent[depth]) - add_second_chances = True - elif depth and True in indent_chances.values(): - # visual indent happened before, so stick to - # visual indent this time. - if depth > 1 and indent[depth - 1]: - vi.append(indent[depth - 1]) - else: - # stupid fallback - vi.append(indent_level + 4) - add_second_chances = True - elif not depth: - vi.append(indent_level + 4) - else: - # must be in hanging indent - hang = rel_indent[open_row] + 4 - vi.append(indent_level + hang) - - # about the best we can do without look-ahead - if (indent_next and vi[0] == indent_level + 4 and - nrows == row + 1): - vi[0] += 4 - - if add_second_chances: - # visual indenters like to line things up. - min_indent = vi[0] - for col, what in indent_chances.items(): - if col > min_indent and ( - what is True or - (what == str and token_type == tokenize.STRING) or - (what == text and token_type == tokenize.OP) - ): - vi.append(col) - vi = sorted(vi) - - valid_indents[row] = vi - - # Returning to original continuation_line_indentation() from - # pep8. - visual_indent = indent_chances.get(start[1]) - last_indent = start - rel_indent[row] = start[1] - indent_level - hang = rel_indent[row] - rel_indent[open_row] - - if token_type == tokenize.OP and text in ']})': - pass - elif visual_indent is True: - if not indent[depth]: - indent[depth] = start[1] - - # line altered: comments shouldn't define a visual indent - if parens[row] and not indent[depth] and token_type not in ( - tokenize.NL, tokenize.COMMENT - ): - indent[depth] = start[1] - indent_chances[start[1]] = True - elif token_type == tokenize.STRING or text in ( - 'u', 'ur', 'b', 'br' - ): - indent_chances[start[1]] = str - - if token_type == tokenize.OP: - if text in '([{': - depth += 1 - indent.append(0) - parens[row] += 1 - elif text in ')]}' and depth > 0: - prev_indent = indent.pop() or last_indent[1] - for d in range(depth): - if indent[d] > prev_indent: - indent[d] = 0 - for ind in list(indent_chances): - if ind >= prev_indent: - del indent_chances[ind] - depth -= 1 - if depth and indent[depth]: # modified - indent_chances[indent[depth]] = True - for idx in range(row, -1, -1): - if parens[idx]: - parens[idx] -= 1 - break - assert len(indent) == depth + 1 - if start[1] not in indent_chances: - indent_chances[start[1]] = text - - last_token_multiline = (start[0] != end[0]) - - return valid_indents - - -def _leading_space_count(line): - """Return number of leading spaces in line.""" - i = 0 - while i < len(line) and line[i] == ' ': - i += 1 - return i - - -def refactor_with_2to3(source_text, fixer_name): - """Use lib2to3 to refactor the source. - - Return the refactored source code. - - """ - from lib2to3 import refactor - fixers = ['lib2to3.fixes.fix_' + fixer_name] - tool = refactor.RefactoringTool( - fixer_names=fixers, - explicit=fixers) - return unicode(tool.refactor_string(source_text, name='')) - - -def break_multi_line(source_text, newline, indent_word, max_line_length): - """Break first line of multi-line code. - - Return None if a break is not possible. - - """ - # Handle special case only. - for symbol in '([{': - # Only valid if symbol is not on a line by itself. - if (symbol in source_text - and source_text.rstrip().endswith(',') - and not source_text.lstrip().startswith(symbol)): - index = 1 + source_text.find(symbol) - if index >= max_line_length: - return None - - # Make sure we are not in a string. - for quote in ['"', "'"]: - if quote in source_text: - if source_text.find(quote) < index: - return None - - # Make sure we are not in a comment. - if '#' in source_text: - if source_text.find('#') < index: - return None - - assert index < len(source_text) - return ( - source_text[:index].rstrip() + newline + - _get_indentation(source_text) + indent_word + - source_text[index:].lstrip()) - - return None - - -def check_syntax(code): - """Return True if syntax is okay.""" - try: - return compile(code, '', 'exec') - except (SyntaxError, TypeError, UnicodeDecodeError): - return False - - -def filter_results(source, results, aggressive=False): - """Filter out spurious reports from pep8. - - If aggressive is True, we allow possibly unsafe fixes (E711, E712). - - """ - non_docstring_string_line_numbers = multiline_string_lines( - source, include_docstrings=False) - all_string_line_numbers = multiline_string_lines( - source, include_docstrings=True) - - split_source = [None] + source.splitlines() - - for r in results: - issue_id = r['id'].lower() - - if r['line'] in non_docstring_string_line_numbers: - if issue_id.startswith('e1'): - continue - elif issue_id in ['e501', 'w191']: - continue - - if r['line'] in all_string_line_numbers: - if issue_id in ['e501']: - continue - - # Filter out incorrect E101 reports when there are no tabs. - # pep8 will complain about this even if the tab indentation found - # elsewhere is in a multi-line string. - if issue_id == 'e101' and '\t' not in split_source[r['line']]: - continue - - if issue_id in ['e711', 'e712'] and not aggressive: - continue - - yield r - - -def multiline_string_lines(source, include_docstrings=False): - """Return line numbers that are within multiline strings. - - The line numbers are indexed at 1. - - Docstrings are ignored. - - """ - sio = StringIO(source) - line_numbers = set() - previous_token_type = '' - try: - for t in tokenize.generate_tokens(sio.readline): - token_type = t[0] - start_row = t[2][0] - end_row = t[3][0] - start_row = t[2][0] - end_row = t[3][0] - - if (token_type == tokenize.STRING and start_row != end_row): - if (include_docstrings or - previous_token_type != tokenize.INDENT): - # We increment by one since we want the contents of the - # string. - line_numbers |= set(range(1 + start_row, 1 + end_row)) - - previous_token_type = token_type - except (IndentationError, tokenize.TokenError): - pass - - return line_numbers - - -def shorten_comment(line, newline, max_line_length): - """Return trimmed or split long comment line.""" - assert len(line) > max_line_length - line = line.rstrip() - - # PEP 8 recommends 72 characters for comment text. - indentation = _get_indentation(line) + '# ' - max_line_length = min(max_line_length, - len(indentation) + 72) - - MIN_CHARACTER_REPEAT = 5 - if (len(line) - len(line.rstrip(line[-1])) >= MIN_CHARACTER_REPEAT and - not line[-1].isalnum()): - # Trim comments that end with things like --------- - return line[:max_line_length] + newline - elif re.match(r'\s*#+\s*\w+', line): - import textwrap - split_lines = textwrap.wrap(line.lstrip(' \t#'), - initial_indent=indentation, - subsequent_indent=indentation, - width=max_line_length, - break_long_words=False) - return newline.join(split_lines) + newline - else: - return line + newline - - -def format_block_comments(source): - """Format block comments.""" - if '#' not in source: - # Optimization. - return source - - string_line_numbers = multiline_string_lines(source, - include_docstrings=True) - fixed_lines = [] - sio = StringIO(source) - for (line_number, line) in enumerate(sio.readlines(), start=1): - if (re.match(r'\s*#+\w+', line) and - line_number not in string_line_numbers): - fixed_lines.append(_get_indentation(line) + - '# ' + - line.lstrip().lstrip('#')) - else: - fixed_lines.append(line) - - return ''.join(fixed_lines) - - -def normalize_line_endings(lines): - """Return fixed line endings. - - All lines will be modified to use the most common line ending. - - """ - newline = find_newline(lines) - return [line.rstrip('\n\r') + newline for line in lines] - - -def mutual_startswith(a, b): - return b.startswith(a) or a.startswith(b) - - -def code_match(code, select, ignore): - if ignore: - for ignored_code in [c.strip() for c in ignore.split(',')]: - if mutual_startswith(code.lower(), ignored_code.lower()): - return False - - if select: - for selected_code in [c.strip() for c in select.split(',')]: - if mutual_startswith(code.lower(), selected_code.lower()): - return True - return False - - return True - - -def fix_string(source, options=None): - """Return fixed source code.""" - if not options: - options = parse_args([''])[0] - - sio = StringIO(source) - return fix_lines(sio.readlines(), options=options) - - -def fix_lines(source_lines, options, filename=''): - """Return fixed source code.""" - tmp_source = unicode().join(normalize_line_endings(source_lines)) - - # Keep a history to break out of cycles. - previous_hashes = set([hash(tmp_source)]) - - fixed_source = tmp_source - if code_match('e26', select=options.select, ignore=options.ignore): - fixed_source = format_block_comments(fixed_source) - - for _ in range(-1, options.pep8_passes): - tmp_source = copy.copy(fixed_source) - - fix = FixPEP8(filename, options, contents=tmp_source) - fixed_source = fix.fix() - - if hash(fixed_source) in previous_hashes: - break - else: - previous_hashes.add(hash(fixed_source)) - - return fixed_source - - -def fix_file(filename, options=None, output=None): - if not options: - options = parse_args([filename])[0] - - original_source = read_from_filename(filename, readlines=True) - - fixed_source = original_source - - if options.in_place: - encoding = detect_encoding(filename) - - interruption = None - try: - fixed_source = fix_lines(fixed_source, options, filename=filename) - except KeyboardInterrupt as exception: - # Allow stopping early. - interruption = exception - - if options.diff: - new = StringIO(fixed_source) - new = new.readlines() - diff = _get_difftext(original_source, new, filename) - if output: - output.write(diff) - else: - return output - elif options.in_place: - fp = open_with_encoding(filename, encoding=encoding, - mode='w') - fp.write(fixed_source) - fp.close() - else: - if output: - output.write(fixed_source) - else: - return fixed_source - - if interruption: - raise interruption - - -def parse_args(args): - """Parse command-line options.""" - parser = OptionParser(usage='Usage: autopep8 [options] ' - '[filename [filename ...]]' - '\nUse filename \'-\' for stdin.', - version='autopep8: %s' % __version__, - description=__doc__, - prog='autopep8') - parser.add_option('-v', '--verbose', action='count', dest='verbose', - default=0, - help='print verbose messages; ' - 'multiple -v result in more verbose messages') - parser.add_option('-d', '--diff', action='store_true', dest='diff', - help='print the diff for the fixed source') - parser.add_option('-i', '--in-place', action='store_true', - help='make changes to files in place') - parser.add_option('-r', '--recursive', action='store_true', - help='run recursively; must be used with --in-place or ' - '--diff') - parser.add_option('-p', '--pep8-passes', - default=100, type=int, - help='maximum number of additional pep8 passes' - ' (default: %default)') - parser.add_option('--list-fixes', action='store_true', - help='list codes for fixes; ' - 'used by --ignore and --select') - parser.add_option('--ignore', default='', - help='do not fix these errors/warnings (e.g. E4,W)') - parser.add_option('--select', default='', - help='fix only these errors/warnings (e.g. E4,W)') - parser.add_option('--max-line-length', default=79, type=int, - help='set maximum allowed line length ' - '(default: %default)') - parser.add_option('--aggressive', action='store_true', - help='enable possibly unsafe changes (E711, E712)') - options, args = parser.parse_args(args) - - if not len(args) and not options.list_fixes: - parser.error('incorrect number of arguments') - - if '-' in args and len(args) > 1: - parser.error('cannot mix stdin and regular files') - - if len(args) > 1 and not (options.in_place or options.diff): - parser.error('autopep8 only takes one filename as argument ' - 'unless the "--in-place" or "--diff" options are ' - 'used') - - if options.recursive and not (options.in_place or options.diff): - parser.error('--recursive must be used with --in-place or --diff') - - if options.in_place and options.diff: - parser.error('--in-place and --diff are mutually exclusive') - - if options.max_line_length < 8: - parser.error('--max-line-length must greater than 8') - - if args == ['-'] and (options.in_place or options.recursive): - parser.error('--in-place or --recursive cannot be used with ' - 'standard input') - - return options, args - - -def supported_fixes(): - """Yield pep8 error codes that autopep8 fixes. - - Each item we yield is a tuple of the code followed by its description. - - """ - instance = FixPEP8(filename=None, options=None, contents='') - for attribute in dir(instance): - code = re.match('fix_([ew][0-9][0-9][0-9])', attribute) - if code: - yield (code.group(1).upper(), - re.sub(r'\s+', ' ', - getattr(instance, attribute).__doc__)) - - -class LineEndingWrapper(object): - - r"""Replace line endings to work with sys.stdout. - - It seems that sys.stdout expects only '\n' as the line ending, no matter - the platform. Otherwise, we get repeated line endings. - - """ - - def __init__(self, output): - self.__output = output - - def write(self, s): - self.__output.write(s.replace('\r\n', '\n').replace('\r', '\n')) - - def __getattr__(self, key): - return getattr(self.__output, key) - - -def temporary_file(): - """Return temporary file.""" - try: - return tempfile.NamedTemporaryFile(mode='w', encoding='utf-8') - except TypeError: - return tempfile.NamedTemporaryFile(mode='w') - - -def fix_multiple_files(filenames, options=None, output=None): - """Fix list of files. - - Optionally fix files recursively. - - """ - while filenames: - name = filenames.pop(0) - if options.recursive and os.path.isdir(name): - for root, directories, children in os.walk(name): - filenames += [os.path.join(root, f) for f in children - if f.endswith('.py') and - not f.startswith('.')] - for d in directories: - if d.startswith('.'): - directories.remove(d) - else: - if options.verbose: - print('[file:%s]' % name, file=sys.stderr) - try: - fix_file(name, options, output) - except IOError as error: - print(str(error), file=sys.stderr) - - -def main(): - """Tool main.""" - options, args = parse_args(sys.argv[1:]) - - if options.list_fixes: - for code, description in supported_fixes(): - print('{code} - {description}'.format( - code=code, description=description)) - return 0 - - if options.in_place or options.diff: - filenames = list(set(args)) - else: - assert len(args) == 1 - assert not options.recursive - if args == ['-']: - assert not options.in_place - temp = temporary_file() - temp.write(sys.stdin.read()) - temp.flush() - filenames = [temp.name] - else: - filenames = args[:1] - - output = codecs.getwriter('utf-8')(sys.stdout.buffer - if sys.version_info[0] >= 3 - else sys.stdout) - - output = LineEndingWrapper(output) - - fix_multiple_files(filenames, options, output) - - -if __name__ == '__main__': - try: - sys.exit(main()) - except KeyboardInterrupt: - sys.exit(1) diff --git a/ftplugin/python/pep8/pep8.py b/ftplugin/python/pep8/pep8.py deleted file mode 100755 index 8823436..0000000 --- a/ftplugin/python/pep8/pep8.py +++ /dev/null @@ -1,1991 +0,0 @@ -#!/usr/bin/env python -# pep8.py - Check Python source code formatting, according to PEP 8 -# Copyright (C) 2006-2009 Johann C. Rocholl -# Copyright (C) 2009-2012 Florent Xicluna -# -# 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: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# 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. - -r""" -Check Python source code formatting, according to PEP 8: -http://www.python.org/dev/peps/pep-0008/ - -For usage and a list of options, try this: -$ python pep8.py -h - -This program and its regression test suite live here: -http://github.com/jcrocholl/pep8 - -Groups of errors and warnings: -E errors -W warnings -100 indentation -200 whitespace -300 blank lines -400 imports -500 line length -600 deprecation -700 statements -900 syntax error -""" -__version__ = '1.4.2a0' - -import os -import sys -import re -import time -import inspect -import keyword -import tokenize -from optparse import OptionParser -from fnmatch import fnmatch -try: - from configparser import RawConfigParser - from io import TextIOWrapper -except ImportError: - from ConfigParser import RawConfigParser - -DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git' -DEFAULT_IGNORE = 'E226,E24' -if sys.platform == 'win32': - DEFAULT_CONFIG = os.path.expanduser(r'~\.pep8') -else: - DEFAULT_CONFIG = os.path.join(os.getenv('XDG_CONFIG_HOME') or - os.path.expanduser('~/.config'), 'pep8') -PROJECT_CONFIG = ('.pep8', 'tox.ini', 'setup.cfg') -MAX_LINE_LENGTH = 79 -REPORT_FORMAT = { - 'default': '%(path)s:%(row)d:%(col)d: %(code)s %(text)s', - 'pylint': '%(path)s:%(row)d: [%(code)s] %(text)s', -} - -PyCF_ONLY_AST = 1024 -SINGLETONS = frozenset(['False', 'None', 'True']) -KEYWORDS = frozenset(keyword.kwlist + ['print']) - SINGLETONS -UNARY_OPERATORS = frozenset(['>>', '**', '*', '+', '-']) -WS_OPTIONAL_OPERATORS = frozenset(['**', '*', '/', '//', '+', '-']) -WS_NEEDED_OPERATORS = frozenset([ - '**=', '*=', '/=', '//=', '+=', '-=', '!=', '<>', - '%=', '^=', '&=', '|=', '==', '<=', '>=', '<<=', '>>=', - '%', '^', '&', '|', '=', '<', '>', '<<']) -WHITESPACE = frozenset(' \t') -SKIP_TOKENS = frozenset([tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE, - tokenize.INDENT, tokenize.DEDENT]) -BENCHMARK_KEYS = ['directories', 'files', 'logical lines', 'physical lines'] - -INDENT_REGEX = re.compile(r'([ \t]*)') -RAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*(,)') -RERAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*,\s*\w+\s*,\s*\w+') -SELFTEST_REGEX = re.compile(r'(Okay|[EW]\d{3}):\s(.*)') -ERRORCODE_REGEX = re.compile(r'[EW]\d{3}') -DOCSTRING_REGEX = re.compile(r'u?r?["\']') -EXTRANEOUS_WHITESPACE_REGEX = re.compile(r'[[({] | []}),;:]') -WHITESPACE_AFTER_COMMA_REGEX = re.compile(r'[,;:]\s*(?: |\t)') -COMPARE_SINGLETON_REGEX = re.compile(r'([=!]=)\s*(None|False|True)') -COMPARE_TYPE_REGEX = re.compile(r'([=!]=|is|is\s+not)\s*type(?:s\.(\w+)Type' - r'|\(\s*(\(\s*\)|[^)]*[^ )])\s*\))') -KEYWORD_REGEX = re.compile(r'(?:[^\s]|\b)(\s*)\b(?:%s)\b(\s*)' % - r'|'.join(KEYWORDS)) -OPERATOR_REGEX = re.compile(r'(?:[^,\s])(\s*)(?:[-+*/|!<=>%&^]+)(\s*)') -LAMBDA_REGEX = re.compile(r'\blambda\b') -HUNK_REGEX = re.compile(r'^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@.*$') - -# Work around Python < 2.6 behaviour, which does not generate NL after -# a comment which is on a line by itself. -COMMENT_WITH_NL = tokenize.generate_tokens(['#\n'].pop).send(None)[1] == '#\n' - - -############################################################################## -# Plugins (check functions) for physical lines -############################################################################## - - -def tabs_or_spaces(physical_line, indent_char): - r""" - Never mix tabs and spaces. - - The most popular way of indenting Python is with spaces only. The - second-most popular way is with tabs only. Code indented with a mixture - of tabs and spaces should be converted to using spaces exclusively. When - invoking the Python command line interpreter with the -t option, it issues - warnings about code that illegally mixes tabs and spaces. When using -tt - these warnings become errors. These options are highly recommended! - - Okay: if a == 0:\n a = 1\n b = 1 - E101: if a == 0:\n a = 1\n\tb = 1 - """ - indent = INDENT_REGEX.match(physical_line).group(1) - for offset, char in enumerate(indent): - if char != indent_char: - return offset, "E101 indentation contains mixed spaces and tabs" - - -def tabs_obsolete(physical_line): - r""" - For new projects, spaces-only are strongly recommended over tabs. Most - editors have features that make this easy to do. - - Okay: if True:\n return - W191: if True:\n\treturn - """ - indent = INDENT_REGEX.match(physical_line).group(1) - if '\t' in indent: - return indent.index('\t'), "W191 indentation contains tabs" - - -def trailing_whitespace(physical_line): - r""" - JCR: Trailing whitespace is superfluous. - FBM: Except when it occurs as part of a blank line (i.e. the line is - nothing but whitespace). According to Python docs[1] a line with only - whitespace is considered a blank line, and is to be ignored. However, - matching a blank line to its indentation level avoids mistakenly - terminating a multi-line statement (e.g. class declaration) when - pasting code into the standard Python interpreter. - - [1] http://docs.python.org/reference/lexical_analysis.html#blank-lines - - The warning returned varies on whether the line itself is blank, for easier - filtering for those who want to indent their blank lines. - - Okay: spam(1)\n# - W291: spam(1) \n# - W293: class Foo(object):\n \n bang = 12 - """ - physical_line = physical_line.rstrip('\n') # chr(10), newline - physical_line = physical_line.rstrip('\r') # chr(13), carriage return - physical_line = physical_line.rstrip('\x0c') # chr(12), form feed, ^L - stripped = physical_line.rstrip(' \t\v') - if physical_line != stripped: - if stripped: - return len(stripped), "W291 trailing whitespace" - else: - return 0, "W293 blank line contains whitespace" - - -def trailing_blank_lines(physical_line, lines, line_number): - r""" - JCR: Trailing blank lines are superfluous. - - Okay: spam(1) - W391: spam(1)\n - """ - if not physical_line.rstrip() and line_number == len(lines): - return 0, "W391 blank line at end of file" - - -def missing_newline(physical_line): - """ - JCR: The last line should have a newline. - - Reports warning W292. - """ - if physical_line.rstrip() == physical_line: - return len(physical_line), "W292 no newline at end of file" - - -def maximum_line_length(physical_line, max_line_length): - """ - Limit all lines to a maximum of 79 characters. - - There are still many devices around that are limited to 80 character - lines; plus, limiting windows to 80 characters makes it possible to have - several windows side-by-side. The default wrapping on such devices looks - ugly. Therefore, please limit all lines to a maximum of 79 characters. - For flowing long blocks of text (docstrings or comments), limiting the - length to 72 characters is recommended. - - Reports error E501. - """ - line = physical_line.rstrip() - length = len(line) - if length > max_line_length: - if noqa(line): - return - if hasattr(line, 'decode'): # Python 2 - # The line could contain multi-byte characters - try: - length = len(line.decode('utf-8')) - except UnicodeError: - pass - if length > max_line_length: - return (max_line_length, "E501 line too long " - "(%d > %d characters)" % (length, max_line_length)) - - -############################################################################## -# Plugins (check functions) for logical lines -############################################################################## - - -def blank_lines(logical_line, blank_lines, indent_level, line_number, - previous_logical, previous_indent_level): - r""" - Separate top-level function and class definitions with two blank lines. - - Method definitions inside a class are separated by a single blank line. - - Extra blank lines may be used (sparingly) to separate groups of related - functions. Blank lines may be omitted between a bunch of related - one-liners (e.g. a set of dummy implementations). - - Use blank lines in functions, sparingly, to indicate logical sections. - - Okay: def a():\n pass\n\n\ndef b():\n pass - Okay: def a():\n pass\n\n\n# Foo\n# Bar\n\ndef b():\n pass - - E301: class Foo:\n b = 0\n def bar():\n pass - E302: def a():\n pass\n\ndef b(n):\n pass - E303: def a():\n pass\n\n\n\ndef b(n):\n pass - E303: def a():\n\n\n\n pass - E304: @decorator\n\ndef a():\n pass - """ - if line_number == 1: - return # Don't expect blank lines before the first line - if previous_logical.startswith('@'): - if blank_lines: - yield 0, "E304 blank lines found after function decorator" - elif blank_lines > 2 or (indent_level and blank_lines == 2): - yield 0, "E303 too many blank lines (%d)" % blank_lines - elif logical_line.startswith(('def ', 'class ', '@')): - if indent_level: - if not (blank_lines or previous_indent_level < indent_level or - DOCSTRING_REGEX.match(previous_logical)): - yield 0, "E301 expected 1 blank line, found 0" - elif blank_lines != 2: - yield 0, "E302 expected 2 blank lines, found %d" % blank_lines - - -def extraneous_whitespace(logical_line): - """ - Avoid extraneous whitespace in the following situations: - - - Immediately inside parentheses, brackets or braces. - - - Immediately before a comma, semicolon, or colon. - - Okay: spam(ham[1], {eggs: 2}) - E201: spam( ham[1], {eggs: 2}) - E201: spam(ham[ 1], {eggs: 2}) - E201: spam(ham[1], { eggs: 2}) - E202: spam(ham[1], {eggs: 2} ) - E202: spam(ham[1 ], {eggs: 2}) - E202: spam(ham[1], {eggs: 2 }) - - E203: if x == 4: print x, y; x, y = y , x - E203: if x == 4: print x, y ; x, y = y, x - E203: if x == 4 : print x, y; x, y = y, x - """ - line = logical_line - for match in EXTRANEOUS_WHITESPACE_REGEX.finditer(line): - text = match.group() - char = text.strip() - found = match.start() - if text == char + ' ': - # assert char in '([{' - yield found + 1, "E201 whitespace after '%s'" % char - elif line[found - 1] != ',': - code = ('E202' if char in '}])' else 'E203') # if char in ',;:' - yield found, "%s whitespace before '%s'" % (code, char) - - -def whitespace_around_keywords(logical_line): - r""" - Avoid extraneous whitespace around keywords. - - Okay: True and False - E271: True and False - E272: True and False - E273: True and\tFalse - E274: True\tand False - """ - for match in KEYWORD_REGEX.finditer(logical_line): - before, after = match.groups() - - if '\t' in before: - yield match.start(1), "E274 tab before keyword" - elif len(before) > 1: - yield match.start(1), "E272 multiple spaces before keyword" - - if '\t' in after: - yield match.start(2), "E273 tab after keyword" - elif len(after) > 1: - yield match.start(2), "E271 multiple spaces after keyword" - - -def missing_whitespace(logical_line): - """ - JCR: Each comma, semicolon or colon should be followed by whitespace. - - Okay: [a, b] - Okay: (3,) - Okay: a[1:4] - Okay: a[:4] - Okay: a[1:] - Okay: a[1:4:2] - E231: ['a','b'] - E231: foo(bar,baz) - E231: [{'a':'b'}] - """ - line = logical_line - for index in range(len(line) - 1): - char = line[index] - if char in ',;:' and line[index + 1] not in WHITESPACE: - before = line[:index] - if char == ':' and before.count('[') > before.count(']') and \ - before.rfind('{') < before.rfind('['): - continue # Slice syntax, no space required - if char == ',' and line[index + 1] == ')': - continue # Allow tuple with only one element: (3,) - yield index, "E231 missing whitespace after '%s'" % char - - -def indentation(logical_line, previous_logical, indent_char, - indent_level, previous_indent_level): - r""" - Use 4 spaces per indentation level. - - For really old code that you don't want to mess up, you can continue to - use 8-space tabs. - - Okay: a = 1 - Okay: if a == 0:\n a = 1 - E111: a = 1 - - Okay: for item in items:\n pass - E112: for item in items:\npass - - Okay: a = 1\nb = 2 - E113: a = 1\n b = 2 - """ - if indent_char == ' ' and indent_level % 4: - yield 0, "E111 indentation is not a multiple of four" - indent_expect = previous_logical.endswith(':') - if indent_expect and indent_level <= previous_indent_level: - yield 0, "E112 expected an indented block" - if indent_level > previous_indent_level and not indent_expect: - yield 0, "E113 unexpected indentation" - - -def continuation_line_indentation(logical_line, tokens, indent_level, verbose): - r""" - Continuation lines should align wrapped elements either vertically using - Python's implicit line joining inside parentheses, brackets and braces, or - using a hanging indent. - - When using a hanging indent the following considerations should be applied: - - - there should be no arguments on the first line, and - - - further indentation should be used to clearly distinguish itself as a - continuation line. - - Okay: a = (\n) - E123: a = (\n ) - - Okay: a = (\n 42) - E121: a = (\n 42) - E122: a = (\n42) - E123: a = (\n 42\n ) - E124: a = (24,\n 42\n) - E125: if (a or\n b):\n pass - E126: a = (\n 42) - E127: a = (24,\n 42) - E128: a = (24,\n 42) - """ - first_row = tokens[0][2][0] - nrows = 1 + tokens[-1][2][0] - first_row - if nrows == 1: - return - - # indent_next tells us whether the next block is indented; assuming - # that it is indented by 4 spaces, then we should not allow 4-space - # indents on the final continuation line; in turn, some other - # indents are allowed to have an extra 4 spaces. - indent_next = logical_line.endswith(':') - - row = depth = 0 - # remember how many brackets were opened on each line - parens = [0] * nrows - # relative indents of physical lines - rel_indent = [0] * nrows - # visual indents - indent = [indent_level] - indent_chances = {} - last_indent = tokens[0][2] - if verbose >= 3: - print(">>> " + tokens[0][4].rstrip()) - - for token_type, text, start, end, line in tokens: - if noqa(line): - continue - - newline = row < start[0] - first_row - if newline: - row = start[0] - first_row - newline = (not last_token_multiline and - token_type not in (tokenize.NL, tokenize.NEWLINE)) - - if newline: - # this is the beginning of a continuation line. - last_indent = start - if verbose >= 3: - print("... " + line.rstrip()) - - # record the initial indent. - rel_indent[row] = start[1] - indent_level - - if depth: - # a bracket expression in a continuation line. - # find the line that it was opened on - for open_row in range(row - 1, -1, -1): - if parens[open_row]: - break - else: - # an unbracketed continuation line (ie, backslash) - open_row = 0 - hang = rel_indent[row] - rel_indent[open_row] - visual_indent = indent_chances.get(start[1]) - - if token_type == tokenize.OP and text in ']})': - # this line starts with a closing bracket - if indent[depth]: - if start[1] != indent[depth]: - yield (start, "E124 closing bracket does not match " - "visual indentation") - elif hang: - yield (start, "E123 closing bracket does not match " - "indentation of opening bracket's line") - elif visual_indent is True: - # visual indent is verified - if not indent[depth]: - indent[depth] = start[1] - elif visual_indent in (text, str): - # ignore token lined up with matching one from a previous line - pass - elif indent[depth] and start[1] < indent[depth]: - # visual indent is broken - yield (start, "E128 continuation line " - "under-indented for visual indent") - elif hang == 4 or (indent_next and rel_indent[row] == 8): - # hanging indent is verified - pass - else: - # indent is broken - if hang <= 0: - error = "E122", "missing indentation or outdented" - elif indent[depth]: - error = "E127", "over-indented for visual indent" - elif hang % 4: - error = "E121", "indentation is not a multiple of four" - else: - error = "E126", "over-indented for hanging indent" - yield start, "%s continuation line %s" % error - - # look for visual indenting - if (parens[row] and token_type not in (tokenize.NL, tokenize.COMMENT) - and not indent[depth]): - indent[depth] = start[1] - indent_chances[start[1]] = True - if verbose >= 4: - print("bracket depth %s indent to %s" % (depth, start[1])) - # deal with implicit string concatenation - elif (token_type in (tokenize.STRING, tokenize.COMMENT) or - text in ('u', 'ur', 'b', 'br')): - indent_chances[start[1]] = str - - # keep track of bracket depth - if token_type == tokenize.OP: - if text in '([{': - depth += 1 - indent.append(0) - parens[row] += 1 - if verbose >= 4: - print("bracket depth %s seen, col %s, visual min = %s" % - (depth, start[1], indent[depth])) - elif text in ')]}' and depth > 0: - # parent indents should not be more than this one - prev_indent = indent.pop() or last_indent[1] - for d in range(depth): - if indent[d] > prev_indent: - indent[d] = 0 - for ind in list(indent_chances): - if ind >= prev_indent: - del indent_chances[ind] - depth -= 1 - if depth: - indent_chances[indent[depth]] = True - for idx in range(row, -1, -1): - if parens[idx]: - parens[idx] -= 1 - break - assert len(indent) == depth + 1 - if start[1] not in indent_chances: - # allow to line up tokens - indent_chances[start[1]] = text - - last_token_multiline = (start[0] != end[0]) - - if indent_next and rel_indent[-1] == 4: - yield (last_indent, "E125 continuation line does not distinguish " - "itself from next logical line") - - -def whitespace_before_parameters(logical_line, tokens): - """ - Avoid extraneous whitespace in the following situations: - - - Immediately before the open parenthesis that starts the argument - list of a function call. - - - Immediately before the open parenthesis that starts an indexing or - slicing. - - Okay: spam(1) - E211: spam (1) - - Okay: dict['key'] = list[index] - E211: dict ['key'] = list[index] - E211: dict['key'] = list [index] - """ - prev_type = tokens[0][0] - prev_text = tokens[0][1] - prev_end = tokens[0][3] - for index in range(1, len(tokens)): - token_type, text, start, end, line = tokens[index] - if (token_type == tokenize.OP and - text in '([' and - start != prev_end and - (prev_type == tokenize.NAME or prev_text in '}])') and - # Syntax "class A (B):" is allowed, but avoid it - (index < 2 or tokens[index - 2][1] != 'class') and - # Allow "return (a.foo for a in range(5))" - not keyword.iskeyword(prev_text)): - yield prev_end, "E211 whitespace before '%s'" % text - prev_type = token_type - prev_text = text - prev_end = end - - -def whitespace_around_operator(logical_line): - r""" - Avoid extraneous whitespace in the following situations: - - - More than one space around an assignment (or other) operator to - align it with another. - - Okay: a = 12 + 3 - E221: a = 4 + 5 - E222: a = 4 + 5 - E223: a = 4\t+ 5 - E224: a = 4 +\t5 - """ - for match in OPERATOR_REGEX.finditer(logical_line): - before, after = match.groups() - - if '\t' in before: - yield match.start(1), "E223 tab before operator" - elif len(before) > 1: - yield match.start(1), "E221 multiple spaces before operator" - - if '\t' in after: - yield match.start(2), "E224 tab after operator" - elif len(after) > 1: - yield match.start(2), "E222 multiple spaces after operator" - - -def missing_whitespace_around_operator(logical_line, tokens): - r""" - - Always surround these binary operators with a single space on - either side: assignment (=), augmented assignment (+=, -= etc.), - comparisons (==, <, >, !=, <>, <=, >=, in, not in, is, is not), - Booleans (and, or, not). - - - Use spaces around arithmetic operators. - - Okay: i = i + 1 - Okay: submitted += 1 - Okay: x = x * 2 - 1 - Okay: hypot2 = x * x + y * y - Okay: c = (a + b) * (a - b) - Okay: foo(bar, key='word', *args, **kwargs) - Okay: baz(**kwargs) - Okay: negative = -1 - Okay: spam(-1) - Okay: alpha[:-i] - Okay: if not -5 < x < +5:\n pass - Okay: lambda *args, **kw: (args, kw) - Okay: z = 2 ** 30 - Okay: x = x / 2 - 1 - - E225: i=i+1 - E225: submitted +=1 - E225: c = alpha -4 - E225: x = x /2 - 1 - E225: z = x **y - E226: c = (a+b) * (a-b) - E226: z = 2**30 - E226: x = x*2 - 1 - E226: x = x/2 - 1 - E226: hypot2 = x*x + y*y - """ - parens = 0 - need_space = False - prev_type = tokenize.OP - prev_text = prev_end = None - for token_type, text, start, end, line in tokens: - if token_type in (tokenize.NL, tokenize.NEWLINE, tokenize.ERRORTOKEN): - # ERRORTOKEN is triggered by backticks in Python 3 - continue - if text in ('(', 'lambda'): - parens += 1 - elif text == ')': - parens -= 1 - if need_space: - if start != prev_end: - # Found a (probably) needed space - if need_space is not True and not need_space[1]: - yield (need_space[0], - "E225 missing whitespace around operator") - need_space = False - elif text == '>' and prev_text in ('<', '-'): - # Tolerate the "<>" operator, even if running Python 3 - # Deal with Python 3's annotated return value "->" - pass - else: - if need_space is True or need_space[1]: - # A needed trailing space was not found - yield prev_end, "E225 missing whitespace around operator" - else: - yield (need_space[0], - "E226 missing optional whitespace around operator") - need_space = False - elif token_type == tokenize.OP and prev_end is not None: - if text == '=' and parens: - # Allow keyword args or defaults: foo(bar=None). - pass - elif text in WS_NEEDED_OPERATORS: - need_space = True - elif text in UNARY_OPERATORS: - # Check if the operator is being used as a binary operator - # Allow unary operators: -123, -x, +1. - # Allow argument unpacking: foo(*args, **kwargs). - if prev_type == tokenize.OP: - binary_usage = (prev_text in '}])') - elif prev_type == tokenize.NAME: - binary_usage = (prev_text not in KEYWORDS) - else: - binary_usage = (prev_type not in SKIP_TOKENS) - - if binary_usage: - if text in WS_OPTIONAL_OPERATORS: - need_space = None - else: - need_space = True - elif text in WS_OPTIONAL_OPERATORS: - need_space = None - - if need_space is None: - # Surrounding space is optional, but ensure that - # trailing space matches opening space - need_space = (prev_end, start != prev_end) - elif need_space and start == prev_end: - # A needed opening space was not found - yield prev_end, "E225 missing whitespace around operator" - need_space = False - prev_type = token_type - prev_text = text - prev_end = end - - -def whitespace_around_comma(logical_line): - r""" - Avoid extraneous whitespace in the following situations: - - - More than one space around an assignment (or other) operator to - align it with another. - - Note: these checks are disabled by default - - Okay: a = (1, 2) - E241: a = (1, 2) - E242: a = (1,\t2) - """ - line = logical_line - for m in WHITESPACE_AFTER_COMMA_REGEX.finditer(line): - found = m.start() + 1 - if '\t' in m.group(): - yield found, "E242 tab after '%s'" % m.group()[0] - else: - yield found, "E241 multiple spaces after '%s'" % m.group()[0] - - -def whitespace_around_named_parameter_equals(logical_line, tokens): - """ - Don't use spaces around the '=' sign when used to indicate a - keyword argument or a default parameter value. - - Okay: def complex(real, imag=0.0): - Okay: return magic(r=real, i=imag) - Okay: boolean(a == b) - Okay: boolean(a != b) - Okay: boolean(a <= b) - Okay: boolean(a >= b) - - E251: def complex(real, imag = 0.0): - E251: return magic(r = real, i = imag) - """ - parens = 0 - no_space = False - prev_end = None - for token_type, text, start, end, line in tokens: - if no_space: - no_space = False - if start != prev_end: - yield (prev_end, - "E251 no spaces around keyword / parameter equals") - elif token_type == tokenize.OP: - if text == '(': - parens += 1 - elif text == ')': - parens -= 1 - elif parens and text == '=': - no_space = True - if start != prev_end: - yield (prev_end, - "E251 no spaces around keyword / parameter equals") - prev_end = end - - -def whitespace_before_inline_comment(logical_line, tokens): - """ - Separate inline comments by at least two spaces. - - An inline comment is a comment on the same line as a statement. Inline - comments should be separated by at least two spaces from the statement. - They should start with a # and a single space. - - Okay: x = x + 1 # Increment x - Okay: x = x + 1 # Increment x - E261: x = x + 1 # Increment x - E262: x = x + 1 #Increment x - E262: x = x + 1 # Increment x - """ - prev_end = (0, 0) - for token_type, text, start, end, line in tokens: - if token_type == tokenize.COMMENT: - if not line[:start[1]].strip(): - continue - if prev_end[0] == start[0] and start[1] < prev_end[1] + 2: - yield (prev_end, - "E261 at least two spaces before inline comment") - symbol, sp, comment = text.partition(' ') - if symbol not in ('#', '#:') or comment[:1].isspace(): - yield start, "E262 inline comment should start with '# '" - elif token_type != tokenize.NL: - prev_end = end - - -def imports_on_separate_lines(logical_line): - r""" - Imports should usually be on separate lines. - - Okay: import os\nimport sys - E401: import sys, os - - Okay: from subprocess import Popen, PIPE - Okay: from myclas import MyClass - Okay: from foo.bar.yourclass import YourClass - Okay: import myclass - Okay: import foo.bar.yourclass - """ - line = logical_line - if line.startswith('import '): - found = line.find(',') - if -1 < found and ';' not in line[:found]: - yield found, "E401 multiple imports on one line" - - -def compound_statements(logical_line): - r""" - Compound statements (multiple statements on the same line) are - generally discouraged. - - While sometimes it's okay to put an if/for/while with a small body - on the same line, never do this for multi-clause statements. Also - avoid folding such long lines! - - Okay: if foo == 'blah':\n do_blah_thing() - Okay: do_one() - Okay: do_two() - Okay: do_three() - - E701: if foo == 'blah': do_blah_thing() - E701: for x in lst: total += x - E701: while t < 10: t = delay() - E701: if foo == 'blah': do_blah_thing() - E701: else: do_non_blah_thing() - E701: try: something() - E701: finally: cleanup() - E701: if foo == 'blah': one(); two(); three() - - E702: do_one(); do_two(); do_three() - E703: do_four(); # useless semicolon - """ - line = logical_line - last_char = len(line) - 1 - found = line.find(':') - if -1 < found < last_char: - before = line[:found] - if (before.count('{') <= before.count('}') and # {'a': 1} (dict) - before.count('[') <= before.count(']') and # [1:2] (slice) - before.count('(') <= before.count(')') and # (Python 3 annotation) - not LAMBDA_REGEX.search(before)): # lambda x: x - yield found, "E701 multiple statements on one line (colon)" - found = line.find(';') - if -1 < found: - if found < last_char: - yield found, "E702 multiple statements on one line (semicolon)" - else: - yield found, "E703 statement ends with a semicolon" - - -def explicit_line_join(logical_line, tokens): - r""" - Avoid explicit line join between brackets. - - The preferred way of wrapping long lines is by using Python's implied line - continuation inside parentheses, brackets and braces. Long lines can be - broken over multiple lines by wrapping expressions in parentheses. These - should be used in preference to using a backslash for line continuation. - - E502: aaa = [123, \\n 123] - E502: aaa = ("bbb " \\n "ccc") - - Okay: aaa = [123,\n 123] - Okay: aaa = ("bbb "\n "ccc") - Okay: aaa = "bbb " \\n "ccc" - """ - prev_start = prev_end = parens = 0 - for token_type, text, start, end, line in tokens: - if start[0] != prev_start and parens and backslash: - yield backslash, "E502 the backslash is redundant between brackets" - if end[0] != prev_end: - if line.rstrip('\r\n').endswith('\\'): - backslash = (end[0], len(line.splitlines()[-1]) - 1) - else: - backslash = None - prev_start = prev_end = end[0] - else: - prev_start = start[0] - if token_type == tokenize.OP: - if text in '([{': - parens += 1 - elif text in ')]}': - parens -= 1 - - -def comparison_to_singleton(logical_line): - """ - Comparisons to singletons like None should always be done - with "is" or "is not", never the equality operators. - - Okay: if arg is not None: - E711: if arg != None: - E712: if arg == True: - - Also, beware of writing if x when you really mean if x is not None -- - e.g. when testing whether a variable or argument that defaults to None was - set to some other value. The other value might have a type (such as a - container) that could be false in a boolean context! - """ - match = COMPARE_SINGLETON_REGEX.search(logical_line) - if match: - same = (match.group(1) == '==') - singleton = match.group(2) - msg = "'if cond is %s:'" % (('' if same else 'not ') + singleton) - if singleton in ('None',): - code = 'E711' - else: - code = 'E712' - nonzero = ((singleton == 'True' and same) or - (singleton == 'False' and not same)) - msg += " or 'if %scond:'" % ('' if nonzero else 'not ') - yield match.start(1), ("%s comparison to %s should be %s" % - (code, singleton, msg)) - - -def comparison_type(logical_line): - """ - Object type comparisons should always use isinstance() instead of - comparing types directly. - - Okay: if isinstance(obj, int): - E721: if type(obj) is type(1): - - When checking if an object is a string, keep in mind that it might be a - unicode string too! In Python 2.3, str and unicode have a common base - class, basestring, so you can do: - - Okay: if isinstance(obj, basestring): - Okay: if type(a1) is type(b1): - """ - match = COMPARE_TYPE_REGEX.search(logical_line) - if match: - inst = match.group(3) - if inst and isidentifier(inst) and inst not in SINGLETONS: - return # Allow comparison for types which are not obvious - yield match.start(1), "E721 do not compare types, use 'isinstance()'" - - -def python_3000_has_key(logical_line): - r""" - The {}.has_key() method is removed in the Python 3. - Use the 'in' operation instead. - - Okay: if "alph" in d:\n print d["alph"] - W601: assert d.has_key('alph') - """ - pos = logical_line.find('.has_key(') - if pos > -1: - yield pos, "W601 .has_key() is deprecated, use 'in'" - - -def python_3000_raise_comma(logical_line): - """ - When raising an exception, use "raise ValueError('message')" - instead of the older form "raise ValueError, 'message'". - - The paren-using form is preferred because when the exception arguments - are long or include string formatting, you don't need to use line - continuation characters thanks to the containing parentheses. The older - form is removed in Python 3. - - Okay: raise DummyError("Message") - W602: raise DummyError, "Message" - """ - match = RAISE_COMMA_REGEX.match(logical_line) - if match and not RERAISE_COMMA_REGEX.match(logical_line): - yield match.start(1), "W602 deprecated form of raising exception" - - -def python_3000_not_equal(logical_line): - """ - != can also be written <>, but this is an obsolete usage kept for - backwards compatibility only. New code should always use !=. - The older syntax is removed in Python 3. - - Okay: if a != 'no': - W603: if a <> 'no': - """ - pos = logical_line.find('<>') - if pos > -1: - yield pos, "W603 '<>' is deprecated, use '!='" - - -def python_3000_backticks(logical_line): - """ - Backticks are removed in Python 3. - Use repr() instead. - - Okay: val = repr(1 + 2) - W604: val = `1 + 2` - """ - pos = logical_line.find('`') - if pos > -1: - yield pos, "W604 backticks are deprecated, use 'repr()'" - - -############################################################################## -# Helper functions -############################################################################## - - -if '' == ''.encode(): - # Python 2: implicit encoding. - def readlines(filename): - f = open(filename) - try: - return f.readlines() - finally: - f.close() - - isidentifier = re.compile(r'[a-zA-Z_]\w*').match - stdin_get_value = sys.stdin.read -else: - # Python 3 - def readlines(filename): - f = open(filename, 'rb') - try: - coding, lines = tokenize.detect_encoding(f.readline) - f = TextIOWrapper(f, coding, line_buffering=True) - return [l.decode(coding) for l in lines] + f.readlines() - except (LookupError, SyntaxError, UnicodeError): - f.close() - # Fall back if files are improperly declared - f = open(filename, encoding='latin-1') - return f.readlines() - finally: - f.close() - - isidentifier = str.isidentifier - - def stdin_get_value(): - return TextIOWrapper(sys.stdin.buffer, errors='ignore').read() -readlines.__doc__ = " Read the source code." - - -def expand_indent(line): - r""" - Return the amount of indentation. - Tabs are expanded to the next multiple of 8. - - >>> expand_indent(' ') - 4 - >>> expand_indent('\t') - 8 - >>> expand_indent(' \t') - 8 - >>> expand_indent(' \t') - 8 - >>> expand_indent(' \t') - 16 - """ - if '\t' not in line: - return len(line) - len(line.lstrip()) - result = 0 - for char in line: - if char == '\t': - result = result // 8 * 8 + 8 - elif char == ' ': - result += 1 - else: - break - return result - - -def mute_string(text): - """ - Replace contents with 'xxx' to prevent syntax matching. - - >>> mute_string('"abc"') - '"xxx"' - >>> mute_string("'''abc'''") - "'''xxx'''" - >>> mute_string("r'abc'") - "r'xxx'" - """ - # String modifiers (e.g. u or r) - start = text.index(text[-1]) + 1 - end = len(text) - 1 - # Triple quotes - if text[-3:] in ('"""', "'''"): - start += 2 - end -= 2 - return text[:start] + 'x' * (end - start) + text[end:] - - -def noqa(line): - return line.strip().lower().endswith(('# noqa', '# nopep8')) - - -def parse_udiff(diff, patterns=None, parent='.'): - """Return a dictionary of matching lines.""" - # For each file of the diff, the entry key is the filename, - # and the value is a set of row numbers to consider. - rv = {} - path = nrows = None - for line in diff.splitlines(): - if nrows: - if line[:1] != '-': - nrows -= 1 - continue - if line[:3] == '@@ ': - hunk_match = HUNK_REGEX.match(line) - row, nrows = [int(g or '1') for g in hunk_match.groups()] - rv[path].update(range(row, row + nrows)) - elif line[:3] == '+++': - path = line[4:].split('\t', 1)[0] - if path[:2] == 'b/': - path = path[2:] - rv[path] = set() - return dict([(os.path.join(parent, path), rows) - for (path, rows) in rv.items() - if rows and filename_match(path, patterns)]) - - -def filename_match(filename, patterns, default=True): - """ - Check if patterns contains a pattern that matches filename. - If patterns is unspecified, this always returns True. - """ - if not patterns: - return default - return any(fnmatch(filename, pattern) for pattern in patterns) - - -############################################################################## -# Framework to run all checks -############################################################################## - - -_checks = {'physical_line': {}, 'logical_line': {}, 'tree': {}} - - -def register_check(check, codes=None): - """ - Register a new check object. - """ - if inspect.isfunction(check): - args = inspect.getargspec(check)[0] - if args and args[0] in ('physical_line', 'logical_line'): - if codes is None: - codes = ERRORCODE_REGEX.findall(check.__doc__ or '') - _checks[args[0]][check] = (codes or [''], args) - elif inspect.isclass(check): - if inspect.getargspec(check.__init__)[0][:2] == ['self', 'tree']: - _checks['tree'][check] = (codes or [''], None) - - -def init_checks_registry(): - """ - Register all globally visible functions where the first argument name - is 'physical_line' or 'logical_line'. - """ - mod = inspect.getmodule(register_check) - for (name, function) in inspect.getmembers(mod, inspect.isfunction): - register_check(function) -init_checks_registry() - - -class Checker(object): - """ - Load a Python source file, tokenize it, check coding style. - """ - - def __init__(self, filename=None, lines=None, - options=None, report=None, **kwargs): - if options is None: - options = StyleGuide(kwargs).options - else: - assert not kwargs - self._io_error = None - self._physical_checks = options.physical_checks - self._logical_checks = options.logical_checks - self._ast_checks = options.ast_checks - self._options = options - self.max_line_length = options.max_line_length - self.verbose = options.verbose - self.filename = filename - if filename is None: - self.filename = 'stdin' - self.lines = lines or [] - elif filename == '-': - self.filename = 'stdin' - self.lines = stdin_get_value().splitlines(True) - elif lines is None: - try: - self.lines = readlines(filename) - except IOError: - exc_type, exc = sys.exc_info()[:2] - self._io_error = '%s: %s' % (exc_type.__name__, exc) - self.lines = [] - else: - self.lines = lines - self.report = report or options.report - self.report_error = self.report.error - - def report_invalid_syntax(self): - exc_type, exc = sys.exc_info()[:2] - offset = exc.args[1] - if len(offset) > 2: - offset = offset[1:3] - self.report_error(offset[0], offset[1], - 'E901 %s: %s' % (exc_type.__name__, exc.args[0]), - self.report_invalid_syntax) - report_invalid_syntax.__doc__ = " Check if the syntax is valid." - - def readline(self): - """ - Get the next line from the input buffer. - """ - self.line_number += 1 - if self.line_number > len(self.lines): - return '' - return self.lines[self.line_number - 1] - - def readline_check_physical(self): - """ - Check and return the next physical line. This method can be - used to feed tokenize.generate_tokens. - """ - line = self.readline() - if line: - self.check_physical(line) - return line - - def run_check(self, check, argument_names): - """ - Run a check plugin. - """ - arguments = [] - for name in argument_names: - arguments.append(getattr(self, name)) - return check(*arguments) - - def check_physical(self, line): - """ - Run all physical checks on a raw input line. - """ - self.physical_line = line - if self.indent_char is None and line[:1] in WHITESPACE: - self.indent_char = line[0] - for name, check, argument_names in self._physical_checks: - result = self.run_check(check, argument_names) - if result is not None: - offset, text = result - self.report_error(self.line_number, offset, text, check) - - def build_tokens_line(self): - """ - Build a logical line from tokens. - """ - self.mapping = [] - logical = [] - length = 0 - previous = None - for token in self.tokens: - token_type, text = token[0:2] - if token_type in SKIP_TOKENS: - continue - if token_type == tokenize.STRING: - text = mute_string(text) - if previous: - end_row, end = previous[3] - start_row, start = token[2] - if end_row != start_row: # different row - prev_text = self.lines[end_row - 1][end - 1] - if prev_text == ',' or (prev_text not in '{[(' - and text not in '}])'): - logical.append(' ') - length += 1 - elif end != start: # different column - fill = self.lines[end_row - 1][end:start] - logical.append(fill) - length += len(fill) - self.mapping.append((length, token)) - logical.append(text) - length += len(text) - previous = token - self.logical_line = ''.join(logical) - # With Python 2, if the line ends with '\r\r\n' the assertion fails - # assert self.logical_line.strip() == self.logical_line - - def check_logical(self): - """ - Build a line from tokens and run all logical checks on it. - """ - self.build_tokens_line() - self.report.increment_logical_line() - first_line = self.lines[self.mapping[0][1][2][0] - 1] - indent = first_line[:self.mapping[0][1][2][1]] - self.previous_indent_level = self.indent_level - self.indent_level = expand_indent(indent) - if self.verbose >= 2: - print(self.logical_line[:80].rstrip()) - for name, check, argument_names in self._logical_checks: - if self.verbose >= 4: - print(' ' + name) - for result in self.run_check(check, argument_names): - offset, text = result - if isinstance(offset, tuple): - orig_number, orig_offset = offset - else: - for token_offset, token in self.mapping: - if offset >= token_offset: - orig_number = token[2][0] - orig_offset = (token[2][1] + offset - token_offset) - self.report_error(orig_number, orig_offset, text, check) - self.previous_logical = self.logical_line - - def check_ast(self): - try: - tree = compile(''.join(self.lines), '', 'exec', PyCF_ONLY_AST) - except SyntaxError: - return self.report_invalid_syntax() - for name, cls, _ in self._ast_checks: - checker = cls(tree, self.filename, self._options) - for lineno, offset, text, check in checker.run(): - if not noqa(self.lines[lineno - 1]): - self.report_error(lineno, offset, text, check) - - def generate_tokens(self): - if self._io_error: - self.report_error(1, 0, 'E902 %s' % self._io_error, readlines) - tokengen = tokenize.generate_tokens(self.readline_check_physical) - try: - for token in tokengen: - yield token - except (SyntaxError, tokenize.TokenError): - self.report_invalid_syntax() - - def check_all(self, expected=None, line_offset=0): - """ - Run all checks on the input file. - """ - self.report.init_file(self.filename, self.lines, expected, line_offset) - if self._ast_checks: - self.check_ast() - self.line_number = 0 - self.indent_char = None - self.indent_level = 0 - self.previous_logical = '' - self.tokens = [] - self.blank_lines = blank_lines_before_comment = 0 - parens = 0 - for token in self.generate_tokens(): - self.tokens.append(token) - token_type, text = token[0:2] - if self.verbose >= 3: - if token[2][0] == token[3][0]: - pos = '[%s:%s]' % (token[2][1] or '', token[3][1]) - else: - pos = 'l.%s' % token[3][0] - print('l.%s\t%s\t%s\t%r' % - (token[2][0], pos, tokenize.tok_name[token[0]], text)) - if token_type == tokenize.OP: - if text in '([{': - parens += 1 - elif text in '}])': - parens -= 1 - elif not parens: - if token_type == tokenize.NEWLINE: - if self.blank_lines < blank_lines_before_comment: - self.blank_lines = blank_lines_before_comment - self.check_logical() - self.tokens = [] - self.blank_lines = blank_lines_before_comment = 0 - elif token_type == tokenize.NL: - if len(self.tokens) == 1: - # The physical line contains only this token. - self.blank_lines += 1 - self.tokens = [] - elif token_type == tokenize.COMMENT and len(self.tokens) == 1: - if blank_lines_before_comment < self.blank_lines: - blank_lines_before_comment = self.blank_lines - self.blank_lines = 0 - if COMMENT_WITH_NL: - # The comment also ends a physical line - self.tokens = [] - return self.report.get_file_results() - - -class BaseReport(object): - """Collect the results of the checks.""" - print_filename = False - - def __init__(self, options): - self._benchmark_keys = options.benchmark_keys - self._ignore_code = options.ignore_code - # Results - self.elapsed = 0 - self.total_errors = 0 - self.counters = dict.fromkeys(self._benchmark_keys, 0) - self.messages = {} - - def start(self): - """Start the timer.""" - self._start_time = time.time() - - def stop(self): - """Stop the timer.""" - self.elapsed = time.time() - self._start_time - - def init_file(self, filename, lines, expected, line_offset): - """Signal a new file.""" - self.filename = filename - self.lines = lines - self.expected = expected or () - self.line_offset = line_offset - self.file_errors = 0 - self.counters['files'] += 1 - self.counters['physical lines'] += len(lines) - - def increment_logical_line(self): - """Signal a new logical line.""" - self.counters['logical lines'] += 1 - - def error(self, line_number, offset, text, check): - """Report an error, according to options.""" - code = text[:4] - if self._ignore_code(code): - return - if code in self.counters: - self.counters[code] += 1 - else: - self.counters[code] = 1 - self.messages[code] = text[5:] - # Don't care about expected errors or warnings - if code in self.expected: - return - if self.print_filename and not self.file_errors: - print(self.filename) - self.file_errors += 1 - self.total_errors += 1 - return code - - def get_file_results(self): - """Return the count of errors and warnings for this file.""" - return self.file_errors - - def get_count(self, prefix=''): - """Return the total count of errors and warnings.""" - return sum([self.counters[key] - for key in self.messages if key.startswith(prefix)]) - - def get_statistics(self, prefix=''): - """ - Get statistics for message codes that start with the prefix. - - prefix='' matches all errors and warnings - prefix='E' matches all errors - prefix='W' matches all warnings - prefix='E4' matches all errors that have to do with imports - """ - return ['%-7s %s %s' % (self.counters[key], key, self.messages[key]) - for key in sorted(self.messages) if key.startswith(prefix)] - - def print_statistics(self, prefix=''): - """Print overall statistics (number of errors and warnings).""" - for line in self.get_statistics(prefix): - print(line) - - def print_benchmark(self): - """Print benchmark numbers.""" - print('%-7.2f %s' % (self.elapsed, 'seconds elapsed')) - if self.elapsed: - for key in self._benchmark_keys: - print('%-7d %s per second (%d total)' % - (self.counters[key] / self.elapsed, key, - self.counters[key])) - - -class FileReport(BaseReport): - """Collect the results of the checks and print only the filenames.""" - print_filename = True - - -class StandardReport(BaseReport): - """Collect and print the results of the checks.""" - - def __init__(self, options): - super(StandardReport, self).__init__(options) - self._fmt = REPORT_FORMAT.get(options.format.lower(), - options.format) - self._repeat = options.repeat - self._show_source = options.show_source - self._show_pep8 = options.show_pep8 - - def error(self, line_number, offset, text, check): - """ - Report an error, according to options. - """ - code = super(StandardReport, self).error(line_number, offset, - text, check) - if code and (self.counters[code] == 1 or self._repeat): - print(self._fmt % { - 'path': self.filename, - 'row': self.line_offset + line_number, 'col': offset + 1, - 'code': code, 'text': text[5:], - }) - if self._show_source: - if line_number > len(self.lines): - line = '' - else: - line = self.lines[line_number - 1] - print(line.rstrip()) - print(' ' * offset + '^') - if self._show_pep8: - print(check.__doc__.lstrip('\n').rstrip()) - return code - - -class DiffReport(StandardReport): - """Collect and print the results for the changed lines only.""" - - def __init__(self, options): - super(DiffReport, self).__init__(options) - self._selected = options.selected_lines - - def error(self, line_number, offset, text, check): - if line_number not in self._selected[self.filename]: - return - return super(DiffReport, self).error(line_number, offset, text, check) - - -class TestReport(StandardReport): - """Collect the results for the tests.""" - - def __init__(self, options): - options.benchmark_keys += ['test cases', 'failed tests'] - super(TestReport, self).__init__(options) - self._verbose = options.verbose - - def get_file_results(self): - # Check if the expected errors were found - label = '%s:%s:1' % (self.filename, self.line_offset) - codes = sorted(self.expected) - for code in codes: - if not self.counters.get(code): - self.file_errors += 1 - self.total_errors += 1 - print('%s: error %s not found' % (label, code)) - if self._verbose and not self.file_errors: - print('%s: passed (%s)' % - (label, ' '.join(codes) or 'Okay')) - self.counters['test cases'] += 1 - if self.file_errors: - self.counters['failed tests'] += 1 - # Reset counters - for key in set(self.counters) - set(self._benchmark_keys): - del self.counters[key] - self.messages = {} - return self.file_errors - - def print_results(self): - results = ("%(physical lines)d lines tested: %(files)d files, " - "%(test cases)d test cases%%s." % self.counters) - if self.total_errors: - print(results % ", %s failures" % self.total_errors) - else: - print(results % "") - print("Test failed." if self.total_errors else "Test passed.") - - -class StyleGuide(object): - """Initialize a PEP-8 instance with few options.""" - - def __init__(self, *args, **kwargs): - # build options from the command line - parse_argv = kwargs.pop('parse_argv', False) - config_file = kwargs.pop('config_file', None) - parser = kwargs.pop('parser', None) - options, self.paths = process_options( - parse_argv=parse_argv, config_file=config_file, parser=parser) - if args or kwargs: - # build options from dict - options_dict = dict(*args, **kwargs) - options.__dict__.update(options_dict) - if 'paths' in options_dict: - self.paths = options_dict['paths'] - - self.runner = self.input_file - self.options = options - - if not options.reporter: - options.reporter = BaseReport if options.quiet else StandardReport - - for index, value in enumerate(options.exclude): - options.exclude[index] = value.rstrip('/') - # Ignore all checks which are not explicitly selected - options.select = tuple(options.select or ()) - options.ignore = tuple(options.ignore or options.select and ('',)) - options.benchmark_keys = BENCHMARK_KEYS[:] - options.ignore_code = self.ignore_code - options.physical_checks = self.get_checks('physical_line') - options.logical_checks = self.get_checks('logical_line') - options.ast_checks = self.get_checks('tree') - self.init_report() - - def init_report(self, reporter=None): - """Initialize the report instance.""" - self.options.report = (reporter or self.options.reporter)(self.options) - return self.options.report - - def check_files(self, paths=None): - """Run all checks on the paths.""" - if paths is None: - paths = self.paths - report = self.options.report - runner = self.runner - report.start() - for path in paths: - if os.path.isdir(path): - self.input_dir(path) - elif not self.excluded(path): - runner(path) - report.stop() - return report - - def input_file(self, filename, lines=None, expected=None, line_offset=0): - """Run all checks on a Python source file.""" - if self.options.verbose: - print('checking %s' % filename) - fchecker = Checker(filename, lines=lines, options=self.options) - return fchecker.check_all(expected=expected, line_offset=line_offset) - - def input_dir(self, dirname): - """Check all files in this directory and all subdirectories.""" - dirname = dirname.rstrip('/') - if self.excluded(dirname): - return 0 - counters = self.options.report.counters - verbose = self.options.verbose - filepatterns = self.options.filename - runner = self.runner - for root, dirs, files in os.walk(dirname): - if verbose: - print('directory ' + root) - counters['directories'] += 1 - for subdir in sorted(dirs): - if self.excluded(os.path.join(root, subdir)): - dirs.remove(subdir) - for filename in sorted(files): - # contain a pattern that matches? - if ((filename_match(filename, filepatterns) and - not self.excluded(filename))): - runner(os.path.join(root, filename)) - - def excluded(self, filename): - """ - Check if options.exclude contains a pattern that matches filename. - """ - basename = os.path.basename(filename) - return any((filename_match(filename, self.options.exclude, - default=False), - filename_match(basename, self.options.exclude, - default=False))) - - def ignore_code(self, code): - """ - Check if the error code should be ignored. - - If 'options.select' contains a prefix of the error code, - return False. Else, if 'options.ignore' contains a prefix of - the error code, return True. - """ - return (code.startswith(self.options.ignore) and - not code.startswith(self.options.select)) - - def get_checks(self, argument_name): - """ - Find all globally visible functions where the first argument name - starts with argument_name and which contain selected tests. - """ - checks = [] - for check, attrs in _checks[argument_name].items(): - (codes, args) = attrs - if any(not (code and self.ignore_code(code)) for code in codes): - checks.append((check.__name__, check, args)) - return sorted(checks) - - -def init_tests(pep8style): - """ - Initialize testing framework. - - A test file can provide many tests. Each test starts with a - declaration. This declaration is a single line starting with '#:'. - It declares codes of expected failures, separated by spaces or 'Okay' - if no failure is expected. - If the file does not contain such declaration, it should pass all - tests. If the declaration is empty, following lines are not checked, - until next declaration. - - Examples: - - * Only E224 and W701 are expected: #: E224 W701 - * Following example is conform: #: Okay - * Don't check these lines: #: - """ - report = pep8style.init_report(TestReport) - runner = pep8style.input_file - - def run_tests(filename): - """Run all the tests from a file.""" - lines = readlines(filename) + ['#:\n'] - line_offset = 0 - codes = ['Okay'] - testcase = [] - count_files = report.counters['files'] - for index, line in enumerate(lines): - if not line.startswith('#:'): - if codes: - # Collect the lines of the test case - testcase.append(line) - continue - if codes and index: - codes = [c for c in codes if c != 'Okay'] - # Run the checker - runner(filename, testcase, expected=codes, - line_offset=line_offset) - # output the real line numbers - line_offset = index + 1 - # configure the expected errors - codes = line.split()[1:] - # empty the test case buffer - del testcase[:] - report.counters['files'] = count_files + 1 - return report.counters['failed tests'] - - pep8style.runner = run_tests - - -def selftest(options): - """ - Test all check functions with test cases in docstrings. - """ - count_failed = count_all = 0 - report = BaseReport(options) - counters = report.counters - checks = options.physical_checks + options.logical_checks - for name, check, argument_names in checks: - for line in check.__doc__.splitlines(): - line = line.lstrip() - match = SELFTEST_REGEX.match(line) - if match is None: - continue - code, source = match.groups() - lines = [part.replace(r'\t', '\t') + '\n' - for part in source.split(r'\n')] - checker = Checker(lines=lines, options=options, report=report) - checker.check_all() - error = None - if code == 'Okay': - if len(counters) > len(options.benchmark_keys): - codes = [key for key in counters - if key not in options.benchmark_keys] - error = "incorrectly found %s" % ', '.join(codes) - elif not counters.get(code): - error = "failed to find %s" % code - # Keep showing errors for multiple tests - for key in set(counters) - set(options.benchmark_keys): - del counters[key] - report.messages = {} - count_all += 1 - if not error: - if options.verbose: - print("%s: %s" % (code, source)) - else: - count_failed += 1 - print("%s: %s:" % (__file__, error)) - for line in checker.lines: - print(line.rstrip()) - return count_failed, count_all - - -def get_parser(prog='pep8', version=__version__): - parser = OptionParser(prog=prog, version=version, - usage="%prog [options] input ...") - parser.config_options = [ - 'exclude', 'filename', 'select', 'ignore', 'max-line-length', 'count', - 'format', 'quiet', 'show-pep8', 'show-source', 'statistics', 'verbose'] - parser.add_option('-v', '--verbose', default=0, action='count', - help="print status messages, or debug with -vv") - parser.add_option('-q', '--quiet', default=0, action='count', - help="report only file names, or nothing with -qq") - parser.add_option('-r', '--repeat', default=True, action='store_true', - help="(obsolete) show all occurrences of the same error") - parser.add_option('--first', action='store_false', dest='repeat', - help="show first occurrence of each error") - parser.add_option('--exclude', metavar='patterns', default=DEFAULT_EXCLUDE, - help="exclude files or directories which match these " - "comma separated patterns (default: %default)") - parser.add_option('--filename', metavar='patterns', default='*.py', - help="when parsing directories, only check filenames " - "matching these comma separated patterns " - "(default: %default)") - parser.add_option('--select', metavar='errors', default='', - help="select errors and warnings (e.g. E,W6)") - parser.add_option('--ignore', metavar='errors', default='', - help="skip errors and warnings (e.g. E4,W)") - parser.add_option('--show-source', action='store_true', - help="show source code for each error") - parser.add_option('--show-pep8', action='store_true', - help="show text of PEP 8 for each error " - "(implies --first)") - parser.add_option('--statistics', action='store_true', - help="count errors and warnings") - parser.add_option('--count', action='store_true', - help="print total number of errors and warnings " - "to standard error and set exit code to 1 if " - "total is not null") - parser.add_option('--max-line-length', type='int', metavar='n', - default=MAX_LINE_LENGTH, - help="set maximum allowed line length " - "(default: %default)") - parser.add_option('--format', metavar='format', default='default', - help="set the error format [default|pylint|]") - parser.add_option('--diff', action='store_true', - help="report only lines changed according to the " - "unified diff received on STDIN") - group = parser.add_option_group("Testing Options") - group.add_option('--testsuite', metavar='dir', - help="run regression tests from dir") - group.add_option('--doctest', action='store_true', - help="run doctest on myself") - group.add_option('--benchmark', action='store_true', - help="measure processing speed") - return parser - - -def read_config(options, args, arglist, parser): - """Read both user configuration and local configuration.""" - config = RawConfigParser() - - user_conf = options.config - if user_conf and os.path.isfile(user_conf): - if options.verbose: - print('user configuration: %s' % user_conf) - config.read(user_conf) - - parent = tail = args and os.path.abspath(os.path.commonprefix(args)) - while tail: - for name in PROJECT_CONFIG: - local_conf = os.path.join(parent, name) - if os.path.isfile(local_conf): - break - else: - parent, tail = os.path.split(parent) - continue - if options.verbose: - print('local configuration: %s' % local_conf) - config.read(local_conf) - break - - pep8_section = parser.prog - if config.has_section(pep8_section): - option_list = dict([(o.dest, o.type or o.action) - for o in parser.option_list]) - - # First, read the default values - new_options, _ = parser.parse_args([]) - - # Second, parse the configuration - for opt in config.options(pep8_section): - if options.verbose > 1: - print(" %s = %s" % (opt, config.get(pep8_section, opt))) - if opt.replace('_', '-') not in parser.config_options: - print("Unknown option: '%s'\n not in [%s]" % - (opt, ' '.join(parser.config_options))) - sys.exit(1) - normalized_opt = opt.replace('-', '_') - opt_type = option_list[normalized_opt] - if opt_type in ('int', 'count'): - value = config.getint(pep8_section, opt) - elif opt_type == 'string': - value = config.get(pep8_section, opt) - else: - assert opt_type in ('store_true', 'store_false') - value = config.getboolean(pep8_section, opt) - setattr(new_options, normalized_opt, value) - - # Third, overwrite with the command-line options - options, _ = parser.parse_args(arglist, values=new_options) - - return options - - -def process_options(arglist=None, parse_argv=False, config_file=None, - parser=None): - """Process options passed either via arglist or via command line args.""" - if not arglist and not parse_argv: - # Don't read the command line if the module is used as a library. - arglist = [] - if not parser: - parser = get_parser() - if not parser.has_option('--config'): - if config_file is True: - config_file = DEFAULT_CONFIG - group = parser.add_option_group("Configuration", description=( - "The project options are read from the [%s] section of the " - "tox.ini file or the setup.cfg file located in any parent folder " - "of the path(s) being processed. Allowed options are: %s." % - (parser.prog, ', '.join(parser.config_options)))) - group.add_option('--config', metavar='path', default=config_file, - help="user config file location (default: %default)") - options, args = parser.parse_args(arglist) - options.reporter = None - - if options.testsuite: - args.append(options.testsuite) - elif not options.doctest: - if parse_argv and not args: - if options.diff or any(os.path.exists(name) - for name in PROJECT_CONFIG): - args = ['.'] - else: - parser.error('input not specified') - options = read_config(options, args, arglist, parser) - options.reporter = parse_argv and options.quiet == 1 and FileReport - - if options.filename: - options.filename = options.filename.split(',') - options.exclude = options.exclude.split(',') - if options.select: - options.select = options.select.split(',') - if options.ignore: - options.ignore = options.ignore.split(',') - elif not (options.select or - options.testsuite or options.doctest) and DEFAULT_IGNORE: - # The default choice: ignore controversial checks - # (for doctest and testsuite, all checks are required) - options.ignore = DEFAULT_IGNORE.split(',') - - if options.diff: - options.reporter = DiffReport - stdin = stdin_get_value() - options.selected_lines = parse_udiff(stdin, options.filename, args[0]) - args = sorted(options.selected_lines) - - return options, args - - -def _main(): - """Parse options and run checks on Python source.""" - pep8style = StyleGuide(parse_argv=True, config_file=True) - options = pep8style.options - if options.doctest: - import doctest - fail_d, done_d = doctest.testmod(report=False, verbose=options.verbose) - fail_s, done_s = selftest(options) - count_failed = fail_s + fail_d - if not options.quiet: - count_passed = done_d + done_s - count_failed - print("%d passed and %d failed." % (count_passed, count_failed)) - print("Test failed." if count_failed else "Test passed.") - if count_failed: - sys.exit(1) - if options.testsuite: - init_tests(pep8style) - report = pep8style.check_files() - if options.statistics: - report.print_statistics() - if options.benchmark: - report.print_benchmark() - if options.testsuite and not options.quiet: - report.print_results() - if report.total_errors: - if options.count: - sys.stderr.write(str(report.total_errors) + '\n') - sys.exit(1) - -if __name__ == '__main__': - _main() diff --git a/ftplugin/python/pyflakes/__init__.py b/ftplugin/python/pyflakes/__init__.py deleted file mode 100755 index 7a2d0cd..0000000 --- a/ftplugin/python/pyflakes/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ - -__version__ = '0.6.1' diff --git a/ftplugin/python/pyflakes/api.py b/ftplugin/python/pyflakes/api.py deleted file mode 100755 index 5648c56..0000000 --- a/ftplugin/python/pyflakes/api.py +++ /dev/null @@ -1,130 +0,0 @@ -""" -API for the command-line I{pyflakes} tool. -""" - -import sys -import os -import _ast - -from pyflakes import checker -from pyflakes import reporter as modReporter - -__all__ = ['check', 'checkPath', 'checkRecursive', 'iterSourceCode', 'main'] - - -def check(codeString, filename, reporter=None): - """ - Check the Python source given by C{codeString} for flakes. - - @param codeString: The Python source to check. - @type codeString: C{str} - - @param filename: The name of the file the source came from, used to report - errors. - @type filename: C{str} - - @param reporter: A L{Reporter} instance, where errors and warnings will be - reported. - - @return: The number of warnings emitted. - @rtype: C{int} - """ - if reporter is None: - reporter = modReporter._makeDefaultReporter() - # First, compile into an AST and handle syntax errors. - try: - tree = compile(codeString, filename, "exec", _ast.PyCF_ONLY_AST) - except SyntaxError: - value = sys.exc_info()[1] - msg = value.args[0] - - (lineno, offset, text) = value.lineno, value.offset, value.text - - # If there's an encoding problem with the file, the text is None. - if text is None: - # Avoid using msg, since for the only known case, it contains a - # bogus message that claims the encoding the file declared was - # unknown. - reporter.unexpectedError(filename, 'problem decoding source') - else: - reporter.syntaxError(filename, msg, lineno, offset, text) - return 1 - except Exception: - reporter.unexpectedError(filename, 'problem decoding source') - return 1 - else: - # Okay, it's syntactically valid. Now check it. - w = checker.Checker(tree, filename) - w.messages.sort(key=lambda m: m.lineno) - for warning in w.messages: - reporter.flake(warning) - return len(w.messages) - - -def checkPath(filename, reporter=None): - """ - Check the given path, printing out any warnings detected. - - @param reporter: A L{Reporter} instance, where errors and warnings will be - reported. - - @return: the number of warnings printed - """ - if reporter is None: - reporter = modReporter._makeDefaultReporter() - try: - f = open(filename, 'U') - try: - return check(f.read() + '\n', filename, reporter) - finally: - f.close() - except UnicodeError: - reporter.unexpectedError(filename, 'problem decoding source') - except IOError: - msg = sys.exc_info()[1] - reporter.unexpectedError(filename, msg.args[1]) - return 1 - - -def iterSourceCode(paths): - """ - Iterate over all Python source files in C{paths}. - - @param paths: A list of paths. Directories will be recursed into and - any .py files found will be yielded. Any non-directories will be - yielded as-is. - """ - for path in paths: - if os.path.isdir(path): - for dirpath, dirnames, filenames in os.walk(path): - for filename in filenames: - if filename.endswith('.py'): - yield os.path.join(dirpath, filename) - else: - yield path - - -def checkRecursive(paths, reporter): - """ - Recursively check all source files in C{paths}. - - @param paths: A list of paths to Python source files and directories - containing Python source files. - @param reporter: A L{Reporter} where all of the warnings and errors - will be reported to. - @return: The number of warnings found. - """ - warnings = 0 - for sourcePath in iterSourceCode(paths): - warnings += checkPath(sourcePath, reporter) - return warnings - - -def main(): - args = sys.argv[1:] - reporter = modReporter._makeDefaultReporter() - if args: - warnings = checkRecursive(args, reporter) - else: - warnings = check(sys.stdin.read(), '', reporter) - raise SystemExit(warnings > 0) diff --git a/ftplugin/python/pyflakes/checker.py b/ftplugin/python/pyflakes/checker.py deleted file mode 100755 index fd38d18..0000000 --- a/ftplugin/python/pyflakes/checker.py +++ /dev/null @@ -1,723 +0,0 @@ -# -*- test-case-name: pyflakes -*- -# (c) 2005-2010 Divmod, Inc. -# See LICENSE file for details - -import os.path -try: - import builtins - PY2 = False -except ImportError: - import __builtin__ as builtins - PY2 = True - -try: - import ast - iter_child_nodes = ast.iter_child_nodes -except (ImportError, AttributeError): # Python 2.5 - import _ast as ast - - def iter_child_nodes(node, astcls=ast.AST): - """ - Yield all direct child nodes of *node*, that is, all fields that are nodes - and all items of fields that are lists of nodes. - """ - for name in node._fields: - field = getattr(node, name, None) - if isinstance(field, astcls): - yield field - elif isinstance(field, list): - for item in field: - yield item -# Python >= 3.3 uses ast.Try instead of (ast.TryExcept + ast.TryFinally) -if hasattr(ast, 'Try'): - ast_TryExcept = ast.Try - ast_TryFinally = () -else: - ast_TryExcept = ast.TryExcept - ast_TryFinally = ast.TryFinally - -from pyflakes import messages - - -class Binding(object): - """ - Represents the binding of a value to a name. - - The checker uses this to keep track of which names have been bound and - which names have not. See L{Assignment} for a special type of binding that - is checked with stricter rules. - - @ivar used: pair of (L{Scope}, line-number) indicating the scope and - line number that this binding was last used - """ - - def __init__(self, name, source): - self.name = name - self.source = source - self.used = False - - def __str__(self): - return self.name - - def __repr__(self): - return '<%s object %r from line %r at 0x%x>' % (self.__class__.__name__, - self.name, - self.source.lineno, - id(self)) - - -class UnBinding(Binding): - """Created by the 'del' operator.""" - - -class Importation(Binding): - """ - A binding created by an import statement. - - @ivar fullName: The complete name given to the import statement, - possibly including multiple dotted components. - @type fullName: C{str} - """ - def __init__(self, name, source): - self.fullName = name - name = name.split('.')[0] - super(Importation, self).__init__(name, source) - - -class Argument(Binding): - """ - Represents binding a name as an argument. - """ - - -class Definition(Binding): - """ - A binding that defines a function or a class. - """ - - -class Assignment(Binding): - """ - Represents binding a name with an explicit assignment. - - The checker will raise warnings for any Assignment that isn't used. Also, - the checker does not consider assignments in tuple/list unpacking to be - Assignments, rather it treats them as simple Bindings. - """ - - -class FunctionDefinition(Definition): - pass - - -class ClassDefinition(Definition): - pass - - -class ExportBinding(Binding): - """ - A binding created by an C{__all__} assignment. If the names in the list - can be determined statically, they will be treated as names for export and - additional checking applied to them. - - The only C{__all__} assignment that can be recognized is one which takes - the value of a literal list containing literal strings. For example:: - - __all__ = ["foo", "bar"] - - Names which are imported and not otherwise used but appear in the value of - C{__all__} will not have an unused import warning reported for them. - """ - def names(self): - """ - Return a list of the names referenced by this binding. - """ - names = [] - if isinstance(self.source, ast.List): - for node in self.source.elts: - if isinstance(node, ast.Str): - names.append(node.s) - return names - - -class Scope(dict): - importStarred = False # set to True when import * is found - usesLocals = False - - def __repr__(self): - return '<%s at 0x%x %s>' % (self.__class__.__name__, id(self), dict.__repr__(self)) - - -class ClassScope(Scope): - pass - - -class FunctionScope(Scope): - """ - I represent a name scope for a function. - - @ivar globals: Names declared 'global' in this function. - """ - def __init__(self): - super(FunctionScope, self).__init__() - self.globals = {} - - -class ModuleScope(Scope): - pass - - -# Globally defined names which are not attributes of the builtins module, or -# are only present on some platforms. -_MAGIC_GLOBALS = ['__file__', '__builtins__', 'WindowsError'] - - -def getNodeName(node): - # Returns node.id, or node.name, or None - if hasattr(node, 'id'): # One of the many nodes with an id - return node.id - if hasattr(node, 'name'): # a ExceptHandler node - return node.name - - -class Checker(object): - """ - I check the cleanliness and sanity of Python code. - - @ivar _deferredFunctions: Tracking list used by L{deferFunction}. Elements - of the list are two-tuples. The first element is the callable passed - to L{deferFunction}. The second element is a copy of the scope stack - at the time L{deferFunction} was called. - - @ivar _deferredAssignments: Similar to C{_deferredFunctions}, but for - callables which are deferred assignment checks. - """ - - nodeDepth = 0 - traceTree = False - builtIns = set(dir(builtins)) | set(_MAGIC_GLOBALS) - - def __init__(self, tree, filename='(none)', builtins=None): - self._deferredFunctions = [] - self._deferredAssignments = [] - self.deadScopes = [] - self.messages = [] - self.filename = filename - if builtins: - self.builtIns = self.builtIns.union(builtins) - self.scopeStack = [ModuleScope()] - self.futuresAllowed = True - self.root = tree - self.handleChildren(tree) - self.runDeferred(self._deferredFunctions) - # Set _deferredFunctions to None so that deferFunction will fail - # noisily if called after we've run through the deferred functions. - self._deferredFunctions = None - self.runDeferred(self._deferredAssignments) - # Set _deferredAssignments to None so that deferAssignment will fail - # noisily if called after we've run through the deferred assignments. - self._deferredAssignments = None - del self.scopeStack[1:] - self.popScope() - self.checkDeadScopes() - - def deferFunction(self, callable): - """ - Schedule a function handler to be called just before completion. - - This is used for handling function bodies, which must be deferred - because code later in the file might modify the global scope. When - `callable` is called, the scope at the time this is called will be - restored, however it will contain any new bindings added to it. - """ - self._deferredFunctions.append((callable, self.scopeStack[:])) - - def deferAssignment(self, callable): - """ - Schedule an assignment handler to be called just after deferred - function handlers. - """ - self._deferredAssignments.append((callable, self.scopeStack[:])) - - def runDeferred(self, deferred): - """ - Run the callables in C{deferred} using their associated scope stack. - """ - for handler, scope in deferred: - self.scopeStack = scope - handler() - - @property - def scope(self): - return self.scopeStack[-1] - - def popScope(self): - self.deadScopes.append(self.scopeStack.pop()) - - def checkDeadScopes(self): - """ - Look at scopes which have been fully examined and report names in them - which were imported but unused. - """ - for scope in self.deadScopes: - export = isinstance(scope.get('__all__'), ExportBinding) - if export: - all = scope['__all__'].names() - if not scope.importStarred and os.path.basename(self.filename) != '__init__.py': - # Look for possible mistakes in the export list - undefined = set(all) - set(scope) - for name in undefined: - self.report(messages.UndefinedExport, - scope['__all__'].source.lineno, name) - else: - all = [] - - # Look for imported names that aren't used. - for importation in scope.values(): - if isinstance(importation, Importation): - if not importation.used and importation.name not in all: - self.report(messages.UnusedImport, - importation.source.lineno, importation.name) - - def pushFunctionScope(self): - self.scopeStack.append(FunctionScope()) - - def pushClassScope(self): - self.scopeStack.append(ClassScope()) - - def report(self, messageClass, *args, **kwargs): - self.messages.append(messageClass(self.filename, *args, **kwargs)) - - def hasParent(self, node, kind): - while hasattr(node, 'parent'): - node = node.parent - if isinstance(node, kind): - return True - - def getCommonAncestor(self, lnode, rnode, stop=None): - if not stop: - stop = self.root - if lnode is rnode: - return lnode - if stop in (lnode, rnode): - return stop - - if not hasattr(lnode, 'parent') or not hasattr(rnode, 'parent'): - return - if (lnode.level > rnode.level): - return self.getCommonAncestor(lnode.parent, rnode, stop) - if (rnode.level > lnode.level): - return self.getCommonAncestor(lnode, rnode.parent, stop) - return self.getCommonAncestor(lnode.parent, rnode.parent, stop) - - def descendantOf(self, node, ancestors, stop=None): - for a in ancestors: - if self.getCommonAncestor(node, a, stop) not in (stop, None): - return True - return False - - def onFork(self, parent, lnode, rnode, items): - return (self.descendantOf(lnode, items, parent) ^ - self.descendantOf(rnode, items, parent)) - - def differentForks(self, lnode, rnode): - """True, if lnode and rnode are located on different forks of IF/TRY""" - ancestor = self.getCommonAncestor(lnode, rnode) - if isinstance(ancestor, ast.If): - for fork in (ancestor.body, ancestor.orelse): - if self.onFork(ancestor, lnode, rnode, fork): - return True - elif isinstance(ancestor, ast_TryExcept): - body = ancestor.body + ancestor.orelse - for fork in [body] + [[hdl] for hdl in ancestor.handlers]: - if self.onFork(ancestor, lnode, rnode, fork): - return True - elif isinstance(ancestor, ast_TryFinally): - if self.onFork(ancestor, lnode, rnode, ancestor.body): - return True - return False - - def addBinding(self, node, value, reportRedef=True): - """ - Called when a binding is altered. - - - `node` is the statement responsible for the change - - `value` is the optional new value, a Binding instance, associated - with the binding; if None, the binding is deleted if it exists. - - if `reportRedef` is True (default), rebinding while unused will be - reported. - """ - redefinedWhileUnused = False - if not isinstance(self.scope, ClassScope): - for scope in self.scopeStack[::-1]: - existing = scope.get(value.name) - if (isinstance(existing, Importation) - and not existing.used - and (not isinstance(value, Importation) or value.fullName == existing.fullName) - and reportRedef - and not self.differentForks(node, existing.source)): - redefinedWhileUnused = True - self.report(messages.RedefinedWhileUnused, - node.lineno, value.name, existing.source.lineno) - - existing = self.scope.get(value.name) - if not redefinedWhileUnused and self.hasParent(value.source, ast.ListComp): - if (existing and reportRedef - and not self.hasParent(existing.source, (ast.For, ast.ListComp))): - self.report(messages.RedefinedInListComp, - node.lineno, value.name, existing.source.lineno) - - if isinstance(value, UnBinding): - try: - del self.scope[value.name] - except KeyError: - self.report(messages.UndefinedName, node.lineno, value.name) - elif (isinstance(existing, Definition) - and not existing.used - and not self.differentForks(node, existing.source)): - self.report(messages.RedefinedWhileUnused, - node.lineno, value.name, existing.source.lineno) - else: - self.scope[value.name] = value - - def handleNodeLoad(self, node): - name = getNodeName(node) - if not name: - return - # try local scope - importStarred = self.scope.importStarred - try: - self.scope[name].used = (self.scope, node.lineno) - except KeyError: - pass - else: - return - - # try enclosing function scopes - for scope in self.scopeStack[-2:0:-1]: - importStarred = importStarred or scope.importStarred - if not isinstance(scope, FunctionScope): - continue - try: - scope[name].used = (self.scope, node.lineno) - except KeyError: - pass - else: - return - - # try global scope - importStarred = importStarred or self.scopeStack[0].importStarred - try: - self.scopeStack[0][name].used = (self.scope, node.lineno) - except KeyError: - if not importStarred and name not in self.builtIns: - if (os.path.basename(self.filename) == '__init__.py' and name == '__path__'): - # the special name __path__ is valid only in packages - pass - else: - self.report(messages.UndefinedName, node.lineno, name) - - def handleNodeStore(self, node): - name = getNodeName(node) - if not name: - return - # if the name hasn't already been defined in the current scope - if isinstance(self.scope, FunctionScope) and name not in self.scope: - # for each function or module scope above us - for scope in self.scopeStack[:-1]: - if not isinstance(scope, (FunctionScope, ModuleScope)): - continue - # if the name was defined in that scope, and the name has - # been accessed already in the current scope, and hasn't - # been declared global - if (name in scope and scope[name].used and scope[name].used[0] is self.scope - and name not in self.scope.globals): - # then it's probably a mistake - self.report(messages.UndefinedLocal, - scope[name].used[1], name, scope[name].source.lineno) - break - - parent = getattr(node, 'parent', None) - if isinstance(parent, (ast.For, ast.comprehension, ast.Tuple, ast.List)): - binding = Binding(name, node) - elif parent is not None and name == '__all__' and isinstance(self.scope, ModuleScope): - binding = ExportBinding(name, parent.value) - else: - binding = Assignment(name, node) - if name in self.scope: - binding.used = self.scope[name].used - self.addBinding(node, binding) - - def handleNodeDelete(self, node): - name = getNodeName(node) - if not name: - return - if isinstance(self.scope, FunctionScope) and name in self.scope.globals: - del self.scope.globals[name] - else: - self.addBinding(node, UnBinding(name, node)) - - def handleChildren(self, tree): - for node in iter_child_nodes(tree): - self.handleNode(node, tree) - - def isDocstring(self, node): - """ - Determine if the given node is a docstring, as long as it is at the - correct place in the node tree. - """ - return isinstance(node, ast.Str) or (isinstance(node, ast.Expr) and - isinstance(node.value, ast.Str)) - - def handleNode(self, node, parent): - if node is None: - return - node.parent = parent - if self.traceTree: - print(' ' * self.nodeDepth + node.__class__.__name__) - self.nodeDepth += 1 - if self.futuresAllowed and not (isinstance(node, ast.ImportFrom) or - self.isDocstring(node)): - self.futuresAllowed = False - nodeType = node.__class__.__name__.upper() - node.level = self.nodeDepth - try: - handler = getattr(self, nodeType) - handler(node) - finally: - self.nodeDepth -= 1 - if self.traceTree: - print(' ' * self.nodeDepth + 'end ' + node.__class__.__name__) - - def ignore(self, node): - pass - - # "stmt" type nodes - RETURN = DELETE = PRINT = WHILE = IF = WITH = WITHITEM = RAISE = \ - TRYEXCEPT = TRYFINALLY = TRY = ASSERT = EXEC = EXPR = handleChildren - - CONTINUE = BREAK = PASS = ignore - - # "expr" type nodes - BOOLOP = BINOP = UNARYOP = IFEXP = DICT = SET = YIELD = YIELDFROM = \ - COMPARE = CALL = REPR = ATTRIBUTE = SUBSCRIPT = LIST = TUPLE = \ - STARRED = handleChildren - - NUM = STR = BYTES = ELLIPSIS = ignore - - # "slice" type nodes - SLICE = EXTSLICE = INDEX = handleChildren - - # expression contexts are node instances too, though being constants - LOAD = STORE = DEL = AUGLOAD = AUGSTORE = PARAM = ignore - - # same for operators - AND = OR = ADD = SUB = MULT = DIV = MOD = POW = LSHIFT = RSHIFT = \ - BITOR = BITXOR = BITAND = FLOORDIV = INVERT = NOT = UADD = USUB = \ - EQ = NOTEQ = LT = LTE = GT = GTE = IS = ISNOT = IN = NOTIN = ignore - - # additional node types - COMPREHENSION = KEYWORD = handleChildren - - def GLOBAL(self, node): - """ - Keep track of globals declarations. - """ - if isinstance(self.scope, FunctionScope): - self.scope.globals.update(dict.fromkeys(node.names)) - - NONLOCAL = GLOBAL - - def LISTCOMP(self, node): - # handle generators before element - for gen in node.generators: - self.handleNode(gen, node) - self.handleNode(node.elt, node) - - GENERATOREXP = SETCOMP = LISTCOMP - - def DICTCOMP(self, node): - for gen in node.generators: - self.handleNode(gen, node) - self.handleNode(node.key, node) - self.handleNode(node.value, node) - - def FOR(self, node): - """ - Process bindings for loop variables. - """ - vars = [] - - def collectLoopVars(n): - if isinstance(n, ast.Name): - vars.append(n.id) - elif isinstance(n, ast.expr_context): - return - else: - for c in iter_child_nodes(n): - collectLoopVars(c) - - collectLoopVars(node.target) - for varn in vars: - if (isinstance(self.scope.get(varn), Importation) - # unused ones will get an unused import warning - and self.scope[varn].used): - self.report(messages.ImportShadowedByLoopVar, - node.lineno, varn, self.scope[varn].source.lineno) - - self.handleChildren(node) - - def NAME(self, node): - """ - Handle occurrence of Name (which can be a load/store/delete access.) - """ - if node.id == 'locals' and isinstance(node.parent, ast.Call): - # we are doing locals() call in current scope - self.scope.usesLocals = True - # Locate the name in locals / function / globals scopes. - if isinstance(node.ctx, (ast.Load, ast.AugLoad)): - self.handleNodeLoad(node) - elif isinstance(node.ctx, (ast.Store, ast.AugStore)): - self.handleNodeStore(node) - elif isinstance(node.ctx, ast.Del): - self.handleNodeDelete(node) - else: - # must be a Param context -- this only happens for names in function - # arguments, but these aren't dispatched through here - raise RuntimeError("Got impossible expression context: %r" % (node.ctx,)) - - def FUNCTIONDEF(self, node): - if not hasattr(node, 'decorator_list'): # Python 2.5 - node.decorator_list = node.decorators - for deco in node.decorator_list: - self.handleNode(deco, node) - self.addBinding(node, FunctionDefinition(node.name, node)) - self.LAMBDA(node) - - def LAMBDA(self, node): - args = [] - - if PY2: - def addArgs(arglist): - for arg in arglist: - if isinstance(arg, ast.Tuple): - addArgs(arg.elts) - else: - if arg.id in args: - self.report(messages.DuplicateArgument, - node.lineno, arg.id) - args.append(arg.id) - addArgs(node.args.args) - defaults = node.args.defaults - else: - for arg in node.args.args + node.args.kwonlyargs: - if arg.arg in args: - self.report(messages.DuplicateArgument, - node.lineno, arg.arg) - args.append(arg.arg) - self.handleNode(arg.annotation, node) - if hasattr(node, 'returns'): # Only for FunctionDefs - for annotation in (node.args.varargannotation, - node.args.kwargannotation, node.returns): - self.handleNode(annotation, node) - defaults = node.args.defaults + node.args.kw_defaults - - # vararg/kwarg identifiers are not Name nodes - for wildcard in (node.args.vararg, node.args.kwarg): - if not wildcard: - continue - if wildcard in args: - self.report(messages.DuplicateArgument, node.lineno, wildcard) - args.append(wildcard) - for default in defaults: - self.handleNode(default, node) - - def runFunction(): - - self.pushFunctionScope() - for name in args: - self.addBinding(node, Argument(name, node), reportRedef=False) - if isinstance(node.body, list): - # case for FunctionDefs - for stmt in node.body: - self.handleNode(stmt, node) - else: - # case for Lambdas - self.handleNode(node.body, node) - - def checkUnusedAssignments(): - """ - Check to see if any assignments have not been used. - """ - for name, binding in self.scope.items(): - if (not binding.used and name not in self.scope.globals - and not self.scope.usesLocals - and isinstance(binding, Assignment)): - self.report(messages.UnusedVariable, - binding.source.lineno, name) - self.deferAssignment(checkUnusedAssignments) - self.popScope() - - self.deferFunction(runFunction) - - def CLASSDEF(self, node): - """ - Check names used in a class definition, including its decorators, base - classes, and the body of its definition. Additionally, add its name to - the current scope. - """ - # no class decorator in Python 2.5 - for deco in getattr(node, 'decorator_list', ''): - self.handleNode(deco, node) - for baseNode in node.bases: - self.handleNode(baseNode, node) - if not PY2: - for keywordNode in node.keywords: - self.handleNode(keywordNode, node) - self.pushClassScope() - for stmt in node.body: - self.handleNode(stmt, node) - self.popScope() - self.addBinding(node, ClassDefinition(node.name, node)) - - def ASSIGN(self, node): - self.handleNode(node.value, node) - for target in node.targets: - self.handleNode(target, node) - - def AUGASSIGN(self, node): - self.handleNodeLoad(node.target) - self.handleNode(node.value, node) - self.handleNode(node.target, node) - - def IMPORT(self, node): - for alias in node.names: - name = alias.asname or alias.name - importation = Importation(name, node) - self.addBinding(node, importation) - - def IMPORTFROM(self, node): - if node.module == '__future__': - if not self.futuresAllowed: - self.report(messages.LateFutureImport, - node.lineno, [n.name for n in node.names]) - else: - self.futuresAllowed = False - - for alias in node.names: - if alias.name == '*': - self.scope.importStarred = True - self.report(messages.ImportStarUsed, node.lineno, node.module) - continue - name = alias.asname or alias.name - importation = Importation(name, node) - if node.module == '__future__': - importation.used = (self.scope, node.lineno) - self.addBinding(node, importation) - - def EXCEPTHANDLER(self, node): - # 3.x: in addition to handling children, we must handle the name of - # the exception, which is not a Name node, but a simple string. - if isinstance(node.name, str): - self.handleNodeStore(node) - self.handleChildren(node) diff --git a/ftplugin/python/pyflakes/messages.py b/ftplugin/python/pyflakes/messages.py deleted file mode 100755 index e3abab6..0000000 --- a/ftplugin/python/pyflakes/messages.py +++ /dev/null @@ -1,113 +0,0 @@ -# (c) 2005 Divmod, Inc. See LICENSE file for details - - -class Message(object): - message = '' - message_args = () - - def __init__(self, filename, lineno): - self.filename = filename - self.lineno = lineno - - def __str__(self): - return '%s:%s: %s' % (self.filename, self.lineno, self.message % self.message_args) - - -class UnusedImport(Message): - message = '%r imported but unused' - - def __init__(self, filename, lineno, name): - Message.__init__(self, filename, lineno) - self.message_args = (name,) - - -class RedefinedWhileUnused(Message): - message = 'redefinition of unused %r from line %r' - - def __init__(self, filename, lineno, name, orig_lineno): - Message.__init__(self, filename, lineno) - self.message_args = (name, orig_lineno) - - -class RedefinedInListComp(Message): - message = 'list comprehension redefines %r from line %r' - - def __init__(self, filename, lineno, name, orig_lineno): - Message.__init__(self, filename, lineno) - self.message_args = (name, orig_lineno) - - -class ImportShadowedByLoopVar(Message): - message = 'import %r from line %r shadowed by loop variable' - - def __init__(self, filename, lineno, name, orig_lineno): - Message.__init__(self, filename, lineno) - self.message_args = (name, orig_lineno) - - -class ImportStarUsed(Message): - message = "'from %s import *' used; unable to detect undefined names" - - def __init__(self, filename, lineno, modname): - Message.__init__(self, filename, lineno) - self.message_args = (modname,) - - -class UndefinedName(Message): - message = 'undefined name %r' - - def __init__(self, filename, lineno, name): - Message.__init__(self, filename, lineno) - self.message_args = (name,) - - -class UndefinedExport(Message): - message = 'undefined name %r in __all__' - - def __init__(self, filename, lineno, name): - Message.__init__(self, filename, lineno) - self.message_args = (name,) - - -class UndefinedLocal(Message): - message = "local variable %r (defined in enclosing scope on line %r) referenced before assignment" - - def __init__(self, filename, lineno, name, orig_lineno): - Message.__init__(self, filename, lineno) - self.message_args = (name, orig_lineno) - - -class DuplicateArgument(Message): - message = 'duplicate argument %r in function definition' - - def __init__(self, filename, lineno, name): - Message.__init__(self, filename, lineno) - self.message_args = (name,) - - -class Redefined(Message): - message = 'redefinition of %r from line %r' - - def __init__(self, filename, lineno, name, orig_lineno): - Message.__init__(self, filename, lineno) - self.message_args = (name, orig_lineno) - - -class LateFutureImport(Message): - message = 'future import(s) %r after other statements' - - def __init__(self, filename, lineno, names): - Message.__init__(self, filename, lineno) - self.message_args = (names,) - - -class UnusedVariable(Message): - """ - Indicates that a variable has been explicity assigned to but not actually - used. - """ - message = 'local variable %r is assigned to but never used' - - def __init__(self, filename, lineno, names): - Message.__init__(self, filename, lineno) - self.message_args = (names,) diff --git a/ftplugin/python/pyflakes/reporter.py b/ftplugin/python/pyflakes/reporter.py deleted file mode 100755 index 09956f4..0000000 --- a/ftplugin/python/pyflakes/reporter.py +++ /dev/null @@ -1,79 +0,0 @@ -# (c) 2005-2012 Divmod, Inc. -# See LICENSE file for details - -import sys -try: - u = unicode -except NameError: - u = str - - -class Reporter(object): - """ - Formats the results of pyflakes checks to users. - """ - - def __init__(self, warningStream, errorStream): - """ - Construct a L{Reporter}. - - @param warningStream: A file-like object where warnings will be - written to. The stream's C{write} method must accept unicode. - C{sys.stdout} is a good value. - @param errorStream: A file-like object where error output will be - written to. The stream's C{write} method must accept unicode. - C{sys.stderr} is a good value. - """ - self._stdout = warningStream - self._stderr = errorStream - - def unexpectedError(self, filename, msg): - """ - An unexpected error occurred trying to process C{filename}. - - @param filename: The path to a file that we could not process. - @ptype filename: C{unicode} - @param msg: A message explaining the problem. - @ptype msg: C{unicode} - """ - self._stderr.write(u("%s: %s\n") % (filename, msg)) - - def syntaxError(self, filename, msg, lineno, offset, text): - """ - There was a syntax errror in C{filename}. - - @param filename: The path to the file with the syntax error. - @ptype filename: C{unicode} - @param msg: An explanation of the syntax error. - @ptype msg: C{unicode} - @param lineno: The line number where the syntax error occurred. - @ptype lineno: C{int} - @param offset: The column on which the syntax error occurred. - @ptype offset: C{int} - @param text: The source code containing the syntax error. - @ptype text: C{unicode} - """ - line = text.splitlines()[-1] - if offset is not None: - offset = offset - (len(text) - len(line)) - self._stderr.write(u('%s:%d: %s\n') % (filename, lineno, msg)) - self._stderr.write(u(line)) - self._stderr.write(u('\n')) - if offset is not None: - self._stderr.write(u(" " * (offset + 1) + "^\n")) - - def flake(self, message): - """ - pyflakes found something wrong with the code. - - @param: A L{pyflakes.messages.Message}. - """ - self._stdout.write(u(message)) - self._stdout.write(u('\n')) - - -def _makeDefaultReporter(): - """ - Make a reporter that can be used when no reporter is specified. - """ - return Reporter(sys.stdout, sys.stderr) diff --git a/gvimrc b/gvimrc index 8a0967d..47e3d5e 100644 --- a/gvimrc +++ b/gvimrc @@ -32,9 +32,10 @@ if &background == "dark" hi normal guibg=black endif +colorscheme Tomorrow-Night-Eighties " colorscheme railscasts " colorscheme zenburn -colorscheme freya +" colorscheme freya " colorscheme southwest-fog " colorscheme moria " colorscheme morning diff --git a/plugin/getscriptPlugin.vim b/plugin/getscriptPlugin.vim deleted file mode 100644 index 1d67382..0000000 --- a/plugin/getscriptPlugin.vim +++ /dev/null @@ -1,38 +0,0 @@ -" --------------------------------------------------------------------- -" getscriptPlugin.vim -" Author: Charles E. Campbell, Jr. -" Date: Jan 07, 2008 -" Installing: :help glvs-install -" Usage: :help glvs -" -" GetLatestVimScripts: 642 1 :AutoInstall: getscript.vim -" -" (Rom 15:11 WEB) Again, "Praise the Lord, all you Gentiles! Let -" all the peoples praise Him." -" --------------------------------------------------------------------- -" Initialization: {{{1 -" if you're sourcing this file, surely you can't be -" expecting vim to be in its vi-compatible mode -if &cp || exists("g:loaded_getscriptPlugin") - if &verbose - echo "GetLatestVimScripts is not vi-compatible; not loaded (you need to set nocp)" - endif - finish -endif -let g:loaded_getscriptPlugin = "v33" -let s:keepcpo = &cpo -set cpo&vim - -" --------------------------------------------------------------------- -" Public Interface: {{{1 -com! -nargs=0 GetLatestVimScripts call getscript#GetLatestVimScripts() -com! -nargs=0 GetScripts call getscript#GetLatestVimScripts() -silent! com -nargs=0 GLVS call getscript#GetLatestVimScripts() - -" --------------------------------------------------------------------- -" Restore Options: {{{1 -let &cpo= s:keepcpo -unlet s:keepcpo - -" --------------------------------------------------------------------- -" vim: ts=8 sts=2 fdm=marker nowrap diff --git a/syntax/conque_term.vim b/syntax/conque_term.vim deleted file mode 100644 index 7bb194c..0000000 --- a/syntax/conque_term.vim +++ /dev/null @@ -1,113 +0,0 @@ -" FILE: syntax/conque_term.vim {{{ -" AUTHOR: Nico Raffo -" WEBSITE: http://conque.googlecode.com -" MODIFIED: 2011-08-12 -" VERSION: 2.2, for Vim 7.0 -" LICENSE: -" Conque - Vim terminal/console emulator -" Copyright (C) 2009-__YEAR__ Nico Raffo -" -" MIT License -" -" 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: -" -" The above copyright notice and this permission notice shall be included in -" all copies or substantial portions of the Software. -" -" 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. -" }}} - - -" ******************************************************************************************************************* -" MySQL ************************************************************************************************************* -" ******************************************************************************************************************* - -" TODO Move these to syntax which is only executed for mysql -"syn match MySQLTableBodyG "^\s*\w\+:\(.\+\)\=$" contains=MySQLTableHeadG,MySQLNullG,MySQLBool,MySQLNumberG,MySQLStorageClass oneline skipwhite skipnl -"syn match MySQLTableHeadG "^\s*\w\+:" contains=MySQLTableColon skipwhite contained -"syn match MySQLTableColon ":" contained - -syn match MySQLTableHead "^ *|.*| *$" nextgroup=MySQLTableDivide contains=MySQLTableBar oneline skipwhite skipnl -syn match MySQLTableBody "^ *|.*| *$" nextgroup=MySQLTableBody,MySQLTableEnd contains=MySQLTableBar,MySQLNull,MySQLBool,MySQLNumber,MySQLStorageClass oneline skipwhite skipnl -syn match MySQLTableEnd "^ *+[+=-]\++ *$" oneline -syn match MySQLTableDivide "^ *+[+=-]\++ *$" nextgroup=MySQLTableBody oneline skipwhite skipnl -syn match MySQLTableStart "^ *+[+=-]\++ *$" nextgroup=MySQLTableHead oneline skipwhite skipnl -syn match MySQLNull " NULL " contained contains=MySQLTableBar -syn match MySQLStorageClass " PRI " contained -syn match MySQLStorageClass " MUL " contained -syn match MySQLStorageClass " UNI " contained -syn match MySQLStorageClass " CURRENT_TIMESTAMP " contained -syn match MySQLStorageClass " auto_increment " contained -syn match MySQLTableBar "|" contained -syn match MySQLNumber "|\? *\d\+\(\.\d\+\)\? *|" contained contains=MySQLTableBar -syn match MySQLQueryStat "^\d\+ rows\? in set.*" oneline -syn match MySQLPromptLine "^.\?mysql> .*$" contains=MySQLKeyword,MySQLPrompt,MySQLString oneline -syn match MySQLPromptLine "^ -> .*$" contains=MySQLKeyword,MySQLPrompt,MySQLString oneline -syn match MySQLPrompt "^.\?mysql>" contained oneline -syn match MySQLPrompt "^ ->" contained oneline -syn case ignore -syn keyword MySQLKeyword select count max sum avg date show table tables status like as from left right outer inner join contained -syn keyword MySQLKeyword where group by having limit offset order desc asc show contained and interval is null on -syn case match -syn region MySQLString start=+'+ end=+'+ skip=+\\'+ contained oneline -syn region MySQLString start=+"+ end=+"+ skip=+\\"+ contained oneline -syn region MySQLString start=+`+ end=+`+ skip=+\\`+ contained oneline - - -hi def link MySQLPrompt Identifier -hi def link MySQLTableHead Title -hi def link MySQLTableBody Normal -hi def link MySQLBool Boolean -hi def link MySQLStorageClass StorageClass -hi def link MySQLNumber Number -hi def link MySQLKeyword Keyword -hi def link MySQLString String - -" terms which have no reasonable default highlight group to link to -hi MySQLTableHead term=bold cterm=bold gui=bold -if &background == 'dark' - hi MySQLTableEnd term=NONE cterm=NONE gui=NONE ctermfg=238 guifg=#444444 - hi MySQLTableDivide term=NONE cterm=NONE gui=NONE ctermfg=238 guifg=#444444 - hi MySQLTableStart term=NONE cterm=NONE gui=NONE ctermfg=238 guifg=#444444 - hi MySQLTableBar term=NONE cterm=NONE gui=NONE ctermfg=238 guifg=#444444 - hi MySQLNull term=NONE cterm=NONE gui=NONE ctermfg=238 guifg=#444444 - hi MySQLQueryStat term=NONE cterm=NONE gui=NONE ctermfg=238 guifg=#444444 -elseif &background == 'light' - hi MySQLTableEnd term=NONE cterm=NONE gui=NONE ctermfg=247 guifg=#9e9e9e - hi MySQLTableDivide term=NONE cterm=NONE gui=NONE ctermfg=247 guifg=#9e9e9e - hi MySQLTableStart term=NONE cterm=NONE gui=NONE ctermfg=247 guifg=#9e9e9e - hi MySQLTableBar term=NONE cterm=NONE gui=NONE ctermfg=247 guifg=#9e9e9e - hi MySQLNull term=NONE cterm=NONE gui=NONE ctermfg=247 guifg=#9e9e9e - hi MySQLQueryStat term=NONE cterm=NONE gui=NONE ctermfg=247 guifg=#9e9e9e -endif - - -" ******************************************************************************************************************* -" Bash ************************************************************************************************************** -" ******************************************************************************************************************* - -" Typical Prompt -if g:ConqueTerm_PromptRegex != '' - silent execute "syn match ConquePromptLine '" . g:ConqueTerm_PromptRegex . ".*$' contains=ConquePrompt,ConqueString oneline" - silent execute "syn match ConquePrompt '" . g:ConqueTerm_PromptRegex . "' contained oneline" - hi def link ConquePrompt Identifier -endif - -" Strings -syn region ConqueString start=+'+ end=+'+ skip=+\\'+ contained oneline -syn region ConqueString start=+"+ end=+"+ skip=+\\"+ contained oneline -syn region ConqueString start=+`+ end=+`+ skip=+\\`+ contained oneline -hi def link ConqueString String - -" vim: foldmethod=marker diff --git a/vimrc b/vimrc index 0b6a004..580d862 100644 --- a/vimrc +++ b/vimrc @@ -27,6 +27,7 @@ Plugin 'The-NERD-Tree' Plugin 'open-terminal-filemanager' Plugin 'Conque-Shell' Plugin 'taglist-plus' +Plugin 'darfink/vim-plist' Plugin 'vcscommand.vim' Plugin 'TextFormat' Plugin 'jsbeautify' @@ -36,6 +37,7 @@ Plugin 'vim-pandoc/vim-pandoc' Plugin 'vim-pandoc/vim-pandoc-syntax' Plugin 'bling/vim-airline' Plugin 'saltstack/salt-vim' +Plugin 'andviro/flake8-vim' call vundle#end() " required @@ -56,6 +58,7 @@ set expandtab set softtabstop=4 " set autoindent " set smartindent +let g:PyFlakeDisabledMessages = 'E128,E501,E116' " Highlightinh in python: let python_highlight_numbers = 1