From 28435f05d24807b3ee8dd42515244f5f298b8b75 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 8 Nov 2014 13:19:02 +0300 Subject: [PATCH 1/7] Add support for Command-T --- powerline/bindings/vim/__init__.py | 13 ++++ .../colorschemes/vim/__main__.json | 7 +- powerline/config_files/config.json | 1 + .../themes/vim/plugin_commandt.json | 26 +++++++ powerline/matchers/vim/plugin/commandt.py | 11 +++ powerline/segments/vim/plugin/commandt.py | 78 +++++++++++++++++++ tests/test_provided_config_files.py | 5 +- 7 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 powerline/config_files/themes/vim/plugin_commandt.json create mode 100644 powerline/matchers/vim/plugin/commandt.py create mode 100644 powerline/segments/vim/plugin/commandt.py diff --git a/powerline/bindings/vim/__init__.py b/powerline/bindings/vim/__init__.py index 15543f04..cf06b4eb 100644 --- a/powerline/bindings/vim/__init__.py +++ b/powerline/bindings/vim/__init__.py @@ -398,3 +398,16 @@ def on_bwipe(): environ = VimEnviron() + + +def create_ruby_dpowerline(): + vim.command(( + ''' + ruby + if $powerline == nil + class Powerline + end + $powerline = Powerline.new + end + ''' + )) diff --git a/powerline/config_files/colorschemes/vim/__main__.json b/powerline/config_files/colorschemes/vim/__main__.json index 6adb61ce..02a8e094 100644 --- a/powerline/config_files/colorschemes/vim/__main__.json +++ b/powerline/config_files/colorschemes/vim/__main__.json @@ -26,6 +26,11 @@ "buf_nc:file_directory": "tab_nc:file_directory", "buf_nc:file_name": "tab_nc:file_name", "buf_nc:bufnr": "tab_nc:tabnr", - "buf_nc:modified_indicator": "tab_nc:modified_indicator" + "buf_nc:modified_indicator": "tab_nc:modified_indicator", + + "commandt:label": "file_name", + "commandt:background": "background", + "commandt:finder": "file_name", + "commandt:path": "file_directory" } } diff --git a/powerline/config_files/config.json b/powerline/config_files/config.json index a5389b6c..2bb53b9d 100644 --- a/powerline/config_files/config.json +++ b/powerline/config_files/config.json @@ -36,6 +36,7 @@ "powerline.matchers.vim.plugin.nerdtree.nerdtree": "plugin_nerdtree", "powerline.matchers.vim.plugin.ctrlp.ctrlp": "plugin_ctrlp", + "powerline.matchers.vim.plugin.commandt.commandt": "plugin_commandt", "powerline.matchers.vim.plugin.gundo.gundo": "plugin_gundo", "powerline.matchers.vim.plugin.gundo.gundo_preview": "plugin_gundo-preview" } diff --git a/powerline/config_files/themes/vim/plugin_commandt.json b/powerline/config_files/themes/vim/plugin_commandt.json new file mode 100644 index 00000000..a9ad7c99 --- /dev/null +++ b/powerline/config_files/themes/vim/plugin_commandt.json @@ -0,0 +1,26 @@ +{ + "segments": { + "left": [ + { + "type": "string", + "contents": "Command-T", + "highlight_group": ["commandt:label"] + }, + { + "function": "powerline.segments.vim.plugin.commandt.finder" + }, + { + "function": "powerline.segments.vim.plugin.commandt.path" + }, + { + "type": "string", + "highlight_group": ["commandt:background"], + "draw_soft_divider": false, + "draw_hard_divider": false, + "width": "auto" + } + ], + "right": [ + ] + } +} diff --git a/powerline/matchers/vim/plugin/commandt.py b/powerline/matchers/vim/plugin/commandt.py new file mode 100644 index 00000000..e4236f3e --- /dev/null +++ b/powerline/matchers/vim/plugin/commandt.py @@ -0,0 +1,11 @@ +# vim:fileencoding=utf-8:noet +from __future__ import (unicode_literals, division, absolute_import, print_function) + +import os + +from powerline.bindings.vim import buffer_name + + +def commandt(matcher_info): + name = buffer_name(matcher_info) + return name and os.path.basename(name) == b'GoToFile' diff --git a/powerline/segments/vim/plugin/commandt.py b/powerline/segments/vim/plugin/commandt.py new file mode 100644 index 00000000..96ed134c --- /dev/null +++ b/powerline/segments/vim/plugin/commandt.py @@ -0,0 +1,78 @@ +# vim:fileencoding=utf-8:noet +from __future__ import (unicode_literals, division, absolute_import, print_function) + +try: + import vim +except ImportError: + vim = object() + +from powerline.bindings.vim import create_ruby_dpowerline + + +def initialize(): + global initialized + if initialized: + return + initialized = True + create_ruby_dpowerline() + vim.command(( + # When using :execute (vim.command uses the same code) one should not + # use << EOF. + ''' + ruby + if (not ($command_t.respond_to? 'active_finder')) + def $command_t.active_finder + @active_finder.class.name + end + end + if (not ($command_t.respond_to? 'path')) + def $command_t.path + @path + end + end + def $powerline.commandt_set_active_finder + ::VIM::command "let g:powerline_commandt_reply = '#{$command_t.active_finder}'" + end + def $powerline.commandt_set_path + ::VIM::command "let g:powerline_commandt_reply = '#{$command_t.path.gsub(/'/, "''")}'" + end + ''' + )) + + +initialized = False + + +def finder(pl): + '''Display Command-T finder name + + Requires $command_t.active_finder and .path methods (code above may + monkey-patch $command_t to add them). + ''' + initialize() + vim.command('ruby $powerline.commandt_set_active_finder') + return [{ + 'highlight_group': ['commandt:finder'], + 'contents': vim.eval('g:powerline_commandt_reply').replace('CommandT::', '') + }] + + +FINDERS_WITHOUT_PATH = set(( + 'CommandT::MRUBufferFinder', + 'CommandT::BufferFinder', + 'CommandT::TagFinder', + 'CommandT::JumpFinder', +)) + + +def path(pl): + initialize() + vim.command('ruby $powerline.commandt_set_active_finder') + finder = vim.eval('g:powerline_commandt_reply') + if finder in FINDERS_WITHOUT_PATH: + return None + vim.command('ruby $powerline.commandt_set_path') + return [{ + 'highlight_group': ['commandt:path'], + 'contents': vim.eval('g:powerline_commandt_reply') + }] diff --git a/tests/test_provided_config_files.py b/tests/test_provided_config_files.py index ace5d14b..d0752d0e 100644 --- a/tests/test_provided_config_files.py +++ b/tests/test_provided_config_files.py @@ -55,12 +55,15 @@ class TestVimConfig(TestCase): (('bufname', '__Gundo__'), {}), (('bufname', '__Gundo_Preview__'), {}), (('bufname', 'ControlP'), {}), + # No Command-T tests here: requires +ruby or emulation + # No tabline here: tablines are tested separately ) with open(os.path.join(cfg_path, 'config.json'), 'r') as f: local_themes_raw = json.load(f)['ext']['vim']['local_themes'] # Don’t run tests on external/plugin segments local_themes = dict((k, v) for (k, v) in local_themes_raw.items()) - self.assertEqual(len(buffers), len(local_themes) - 1) + # See end of the buffers definition above for `- 2` + self.assertEqual(len(buffers), len(local_themes) - 2) outputs = {} i = 0 From d392cf3322964ed9e4fe737d7af25f909456feb2 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 9 Nov 2014 23:11:15 +0300 Subject: [PATCH 2/7] Add support for csv files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Equivalent to airline csv Christian Brabandt plugin integration, but uses Python own facilities. Note: filetype detection is out of the scope of the powerline responsibilities. CSV is supported by powerline, but only as long as filetype detection is done by Vim correctly. By default CSV files are neither detected nor highlighted. Some known differences between powerline code and @chrisbra plugin with corresponding airline integration: 1. Detection work differently. I cannot say which is better because I have not tested it much, but it is definitely different. 2. My variant is able to detect whether there is (no) header. (Of course, relying on Python code.) Airline is using a setting. (Both do not allow manual per-filetype setting.) Of course, user can force either variant (no headers at all or headers always). 3. My variant makes it possible to configure header output format, including truncating it at 15 characters (the default). 4. CSV plugin does not work with multiline CSV items (in some dialects one can use code like `abc;"Iammultilinestring"`). See `:h csv-column` on how to fix this if possible (will require also changing `WColumn` function because currently it only works with one line). 5. AFAIK Python does not such a thing as “fixed width CSV”. Thus I do not work with this, but CSV plugin does. Not sure whether it is different with space-separated CSV files though. --- .../colorschemes/vim/__main__.json | 3 + .../config_files/themes/vim/default.json | 4 + powerline/segments/vim/__init__.py | 100 ++++++++++++++++++ powerline/segments/vim/plugin/commandt.py | 6 +- tests/test_segments.py | 67 ++++++++++++ 5 files changed, 177 insertions(+), 3 deletions(-) diff --git a/powerline/config_files/colorschemes/vim/__main__.json b/powerline/config_files/colorschemes/vim/__main__.json index 02a8e094..96505185 100644 --- a/powerline/config_files/colorschemes/vim/__main__.json +++ b/powerline/config_files/colorschemes/vim/__main__.json @@ -19,6 +19,9 @@ "winnr": "information:unimportant", "tabnr": "file_directory", + "csv:column_number": "line_current", + "csv:column_name": "line_current_symbol", + "tab_nc:file_directory": "information:unimportant", "tab_nc:file_name": "tab_nc:file_directory", "tab_nc:tabnr": "tab_nc:file_directory", diff --git a/powerline/config_files/themes/vim/default.json b/powerline/config_files/themes/vim/default.json index a71c2136..af0955b2 100644 --- a/powerline/config_files/themes/vim/default.json +++ b/powerline/config_files/themes/vim/default.json @@ -95,6 +95,10 @@ "width": 4, "align": "r" }, + { + "function": "csv_col_current", + "priority": 30 + }, { "type": "string", "name": "line_current_symbol", diff --git a/powerline/segments/vim/__init__.py b/powerline/segments/vim/__init__.py index 86260e6b..77a89864 100644 --- a/powerline/segments/vim/__init__.py +++ b/powerline/segments/vim/__init__.py @@ -5,6 +5,9 @@ import os import re from collections import defaultdict +from csv import Sniffer, reader + +from csv import Error as CSVError try: import vim @@ -22,6 +25,7 @@ from powerline.lib.humanize_bytes import humanize_bytes from powerline.lib import wraps_saveargs as wraps from powerline.segments.common.vcs import BranchSegment from powerline.segments import with_docstring +from powerline.lib.unicode import string, unicode try: from __builtin__ import xrange as range @@ -627,3 +631,99 @@ def winnr(pl, segment_info, show_current=True): winnr = segment_info['winnr'] if show_current or winnr != vim.current.window.number: return str(winnr) + + +csv_cache = None +sniffer = Sniffer() + + +def detect_text_csv_dialect(text, display_name, header_text=None): + return ( + sniffer.sniff(string(text)), + sniffer.has_header(string(header_text or text)) if display_name == 'auto' else display_name, + ) + + +CSV_SNIFF_LINES = 100 +CSV_PARSE_LINES = 10 + + +def process_csv_buffer(pl, buffer, line, col, display_name): + global csv_cache + if csv_cache is None: + csv_cache = register_buffer_cache(defaultdict(lambda: (None, None, None))) + try: + cur_first_line = buffer[0] + except UnicodeDecodeError: + cur_first_line = vim.eval('strtrans(getline(1))') + dialect, has_header, first_line = csv_cache[buffer.number] + if dialect is None or (cur_first_line != first_line and display_name == 'auto'): + try: + text = '\n'.join(buffer[:CSV_SNIFF_LINES]) + except UnicodeDecodeError: # May happen in Python 3 + text = vim.eval('join(map(getline(1, {0}), "strtrans(v:val)"), "\\n")'.format(CSV_SNIFF_LINES)) + try: + dialect, has_header = detect_text_csv_dialect(text, display_name) + except CSVError as e: + pl.warn('Failed to detect csv format: {0}', str(e)) + # Try detecting using three lines only: + if line == 1: + rng = (0, line + 2) + elif line == len(buffer): + rng = (line - 3, line) + else: + rng = (line - 2, line + 1) + try: + dialect, has_header = detect_text_csv_dialect( + '\n'.join(buffer[rng[0]:rng[1]]), + display_name, + header_text='\n'.join(buffer[:4]), + ) + except CSVError as e: + pl.error('Failed to detect csv format: {0}', str(e)) + return None, None + if len(buffer) > 2: + csv_cache[buffer.number] = dialect, has_header, cur_first_line + column_number = len(list(reader( + buffer[max(0, line - CSV_PARSE_LINES):line - 1] + [buffer[line - 1][:col]], dialect=dialect))[-1]) or 1 + if has_header: + try: + header = next(reader(buffer[0:1], dialect=dialect)) + except UnicodeDecodeError: + header = next(reader([vim.eval('strtrans(getline(1))')], dialect=dialect)) + column_name = header[column_number - 1] + else: + column_name = None + return unicode(column_number), column_name + + +@requires_segment_info +def csv_col_current(pl, segment_info, display_name='auto', name_format=' ({column_name:.15})'): + '''Display CSV column number and column name + + Requires filetype to be set to ``csv``. + + :param bool or str name: + May be ``True``, ``False`` and ``"auto"``. In the first case value from + the first raw will always be displayed. In the second case it will never + be displayed. In thi last case ``csv.Sniffer().has_header()`` will be + used to detect whether current file contains header in the first column. + :param str name_format: + String used to format column name (in case ``display_name`` is set to + ``True`` or ``"auto"``). Accepts ``column_name`` keyword argument. + + Highlight groups used: ``csv:column_number`` or ``csv``, ``csv:column_name`` or ``csv``. + ''' + if vim_getbufoption(segment_info, 'filetype') != 'csv': + return None + line, col = segment_info['window'].cursor + column_number, column_name = process_csv_buffer(pl, segment_info['buffer'], line, col, display_name) + if not column_number: + return None + return [{ + 'contents': column_number, + 'highlight_group': ['csv:column_number', 'csv'], + }] + ([{ + 'contents': name_format.format(column_name=column_name), + 'highlight_group': ['csv:column_name', 'csv'], + }] if column_name else []) diff --git a/powerline/segments/vim/plugin/commandt.py b/powerline/segments/vim/plugin/commandt.py index 96ed134c..e48a0d2f 100644 --- a/powerline/segments/vim/plugin/commandt.py +++ b/powerline/segments/vim/plugin/commandt.py @@ -22,19 +22,19 @@ def initialize(): ruby if (not ($command_t.respond_to? 'active_finder')) def $command_t.active_finder - @active_finder.class.name + @active_finder and @active_finder.class.name or '' end end if (not ($command_t.respond_to? 'path')) def $command_t.path - @path + @path or '' end end def $powerline.commandt_set_active_finder ::VIM::command "let g:powerline_commandt_reply = '#{$command_t.active_finder}'" end def $powerline.commandt_set_path - ::VIM::command "let g:powerline_commandt_reply = '#{$command_t.path.gsub(/'/, "''")}'" + ::VIM::command "let g:powerline_commandt_reply = '#{($command_t.path or '').gsub(/'/, "''")}'" end ''' )) diff --git a/tests/test_segments.py b/tests/test_segments.py index 1e3bb8eb..d533f495 100644 --- a/tests/test_segments.py +++ b/tests/test_segments.py @@ -1196,6 +1196,73 @@ class TestVim(TestCase): 'highlight_group': ['tab_modified_indicator', 'modified_indicator'], }]) + def test_csv_col_current(self): + pl = Pl() + segment_info = vim_module._get_segment_info() + + def csv_col_current(**kwargs): + self.vim.csv_cache and self.vim.csv_cache.clear() + return self.vim.csv_col_current(pl=pl, segment_info=segment_info, **kwargs) + + buffer = segment_info['buffer'] + try: + self.assertEqual(csv_col_current(), None) + buffer.options['filetype'] = 'csv' + self.assertEqual(csv_col_current(), None) + buffer[:] = ['1;2;3', '4;5;6'] + vim_module._set_cursor(1, 1) + self.assertEqual(csv_col_current(), [{ + 'contents': '1', 'highlight_group': ['csv:column_number', 'csv'] + }]) + vim_module._set_cursor(2, 3) + self.assertEqual(csv_col_current(), [{ + 'contents': '2', 'highlight_group': ['csv:column_number', 'csv'] + }]) + vim_module._set_cursor(2, 3) + self.assertEqual(csv_col_current(display_name=True), [{ + 'contents': '2', 'highlight_group': ['csv:column_number', 'csv'] + }, { + 'contents': ' (2)', 'highlight_group': ['csv:column_name', 'csv'] + }]) + buffer[:0] = ['Foo;Bar;Baz'] + vim_module._set_cursor(2, 3) + self.assertEqual(csv_col_current(), [{ + 'contents': '2', 'highlight_group': ['csv:column_number', 'csv'] + }, { + 'contents': ' (Bar)', 'highlight_group': ['csv:column_name', 'csv'] + }]) + buffer[len(buffer):] = ['1;"bc', 'def', 'ghi', 'jkl";3'] + vim_module._set_cursor(5, 1) + self.assertEqual(csv_col_current(), [{ + 'contents': '2', 'highlight_group': ['csv:column_number', 'csv'] + }, { + 'contents': ' (Bar)', 'highlight_group': ['csv:column_name', 'csv'] + }]) + vim_module._set_cursor(7, 6) + self.assertEqual(csv_col_current(), [{ + 'contents': '3', 'highlight_group': ['csv:column_number', 'csv'] + }, { + 'contents': ' (Baz)', 'highlight_group': ['csv:column_name', 'csv'] + }]) + self.assertEqual(csv_col_current(name_format=' ({column_name:.1})'), [{ + 'contents': '3', 'highlight_group': ['csv:column_number', 'csv'] + }, { + 'contents': ' (B)', 'highlight_group': ['csv:column_name', 'csv'] + }]) + self.assertEqual(csv_col_current(display_name=True, name_format=' ({column_name:.1})'), [{ + 'contents': '3', 'highlight_group': ['csv:column_number', 'csv'] + }, { + 'contents': ' (B)', 'highlight_group': ['csv:column_name', 'csv'] + }]) + self.assertEqual(csv_col_current(display_name=False, name_format=' ({column_name:.1})'), [{ + 'contents': '3', 'highlight_group': ['csv:column_number', 'csv'] + }]) + self.assertEqual(csv_col_current(display_name=False), [{ + 'contents': '3', 'highlight_group': ['csv:column_number', 'csv'] + }]) + finally: + vim_module._bw(segment_info['bufnr']) + @classmethod def setUpClass(cls): sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'path'))) From 8cf2a86672adc1bd3babd940c2e06df7d2042fbc Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 9 Nov 2014 23:52:11 +0300 Subject: [PATCH 3/7] Add support for capslock plugin --- docs/source/configuration/segments/vim.rst | 6 +++ powerline/bindings/vim/__init__.py | 16 ++++++++ .../colorschemes/vim/__main__.json | 37 ++++++++++--------- .../config_files/themes/vim/default.json | 5 +++ powerline/segments/vim/plugin/capslock.py | 30 +++++++++++++++ 5 files changed, 76 insertions(+), 18 deletions(-) create mode 100644 powerline/segments/vim/plugin/capslock.py diff --git a/docs/source/configuration/segments/vim.rst b/docs/source/configuration/segments/vim.rst index ace646c4..cb7b3429 100644 --- a/docs/source/configuration/segments/vim.rst +++ b/docs/source/configuration/segments/vim.rst @@ -32,3 +32,9 @@ NERDTree segments .. automodule:: powerline.segments.vim.plugin.nerdtree :members: + +Capslock segments +----------------- + +.. automodule:: powerline.segments.vim.plugin.capslock + :members: diff --git a/powerline/bindings/vim/__init__.py b/powerline/bindings/vim/__init__.py index cf06b4eb..3f69dfb1 100644 --- a/powerline/bindings/vim/__init__.py +++ b/powerline/bindings/vim/__init__.py @@ -124,6 +124,22 @@ else: vim_get_func = VimFunc +if hasattr(vim, 'Function'): + def vim_func_exists(f): + try: + vim.Function(f) + except ValueError: + return False + else: + return True +else: + def vim_func_exists(f): + try: + return bool(int(vim.eval('type(function("{0}")) == 2'.format(f)))) + except vim.error: + return False + + if type(vim) is object: vim_get_func = lambda *args, **kwargs: None diff --git a/powerline/config_files/colorschemes/vim/__main__.json b/powerline/config_files/colorschemes/vim/__main__.json index 96505185..1f408836 100644 --- a/powerline/config_files/colorschemes/vim/__main__.json +++ b/powerline/config_files/colorschemes/vim/__main__.json @@ -1,23 +1,24 @@ { "groups": { - "branch_clean": "branch", - "environment": "information:unimportant", - "file_size": "information:unimportant", - "file_format": "information:unimportant", - "file_encoding": "file_format", - "file_type": "file_format", - "branch": "information:additional", - "file_scheme": "file_name", - "file_directory": "information:additional", - "file_name_empty": "file_directory", - "line_percent": "information:additional", - "line_count": "line_current", - "position": "information:additional", - "single_tab": "line_current", - "many_tabs": "line_current", - "bufnr": "file_directory", - "winnr": "information:unimportant", - "tabnr": "file_directory", + "branch_clean": "branch", + "environment": "information:unimportant", + "file_size": "information:unimportant", + "file_format": "information:unimportant", + "file_encoding": "file_format", + "file_type": "file_format", + "branch": "information:additional", + "file_scheme": "file_name", + "file_directory": "information:additional", + "file_name_empty": "file_directory", + "line_percent": "information:additional", + "line_count": "line_current", + "position": "information:additional", + "single_tab": "line_current", + "many_tabs": "line_current", + "bufnr": "file_directory", + "winnr": "information:unimportant", + "tabnr": "file_directory", + "capslock_indicator": "paste_indicator", "csv:column_number": "line_current", "csv:column_name": "line_current_symbol", diff --git a/powerline/config_files/themes/vim/default.json b/powerline/config_files/themes/vim/default.json index af0955b2..44738ed0 100644 --- a/powerline/config_files/themes/vim/default.json +++ b/powerline/config_files/themes/vim/default.json @@ -15,6 +15,11 @@ "exclude_modes": ["nc"], "priority": 10 }, + { + "function": "powerline.segments.vim.plugin.capslock.capslock_indicator", + "include_modes": ["i", "R", "Rv"], + "priority": 10 + }, { "function": "branch", "exclude_modes": ["nc"], diff --git a/powerline/segments/vim/plugin/capslock.py b/powerline/segments/vim/plugin/capslock.py new file mode 100644 index 00000000..824d55b9 --- /dev/null +++ b/powerline/segments/vim/plugin/capslock.py @@ -0,0 +1,30 @@ +# vim:fileencoding=utf-8:noet +from __future__ import (unicode_literals, division, absolute_import, print_function) + +try: + import vim +except ImportError: + vim = object() + +from powerline.bindings.vim import vim_func_exists +from powerline.theme import requires_segment_info + + +@requires_segment_info +def capslock_indicator(pl, segment_info, text='CAPS'): + '''Shows the indicator if tpope/vim-capslock plugin is enabled + + .. _note:: + In the current state plugin automatically disables itself when leaving + insert mode. So trying to use this segment not in insert or replace + modes is useless. + + :param str text: + String to show when software capslock presented by this plugin is + active. + ''' + if not vim_func_exists('CapsLockStatusline'): + return None + # CapsLockStatusline() function returns an empty string when plugin is + # disabled. If it is not then string is non-empty. + return text if vim.eval('CapsLockStatusline()') else None From a4fddff1fa1d46bc9436df69b6a2b478470622da Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 10 Nov 2014 00:22:37 +0300 Subject: [PATCH 4/7] Improve documentation of Command-T support code --- docs/source/configuration/segments/vim.rst | 6 ++++++ powerline/segments/vim/plugin/commandt.py | 15 +++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/docs/source/configuration/segments/vim.rst b/docs/source/configuration/segments/vim.rst index cb7b3429..eeadd4f1 100644 --- a/docs/source/configuration/segments/vim.rst +++ b/docs/source/configuration/segments/vim.rst @@ -21,6 +21,12 @@ Ctrl-P segments .. automodule:: powerline.segments.vim.plugin.ctrlp :members: +Command-T segments +------------------ + +.. automodule:: powerline.segments.vim.plugin.commandt + :members: + Tagbar segments --------------- diff --git a/powerline/segments/vim/plugin/commandt.py b/powerline/segments/vim/plugin/commandt.py index e48a0d2f..c51a9146 100644 --- a/powerline/segments/vim/plugin/commandt.py +++ b/powerline/segments/vim/plugin/commandt.py @@ -46,8 +46,10 @@ initialized = False def finder(pl): '''Display Command-T finder name - Requires $command_t.active_finder and .path methods (code above may - monkey-patch $command_t to add them). + Requires $command_t.active_finder and methods (code above may monkey-patch + $command_t to add them). All Command-T finders have ``CommandT::`` module + prefix, but it is stripped out (actually, any ``CommandT::`` substring will + be stripped out). ''' initialize() vim.command('ruby $powerline.commandt_set_active_finder') @@ -66,6 +68,15 @@ FINDERS_WITHOUT_PATH = set(( def path(pl): + '''Display path used by Command-T + + Requires $command_t.active_finder and .path methods (code above may + monkey-patch $command_t to add them). + + $command_t.active_finder is required in order to omit displaying path for + finders ``MRUBufferFinder``, ``BufferFinder``, ``TagFinder`` and + ``JumpFinder`` (pretty much any finder, except ``FileFinder``). + ''' initialize() vim.command('ruby $powerline.commandt_set_active_finder') finder = vim.eval('g:powerline_commandt_reply') From c9cb856acd435456ba4b7685b433f3620537a7de Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 10 Nov 2014 00:35:40 +0300 Subject: [PATCH 5/7] Add support for vim_func_exists to tests/vim.py --- tests/vim.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/vim.py b/tests/vim.py index b25759ce..75404f6a 100644 --- a/tests/vim.py +++ b/tests/vim.py @@ -288,6 +288,12 @@ def eval(expr): winnr = int(match.group(2)) varname = match.group(3) return tabpages[tabnr].windows[winnr].vars[varname] + elif expr.startswith('type(function('): + import re + match = re.match(r'^type\(function\("([^"]+)"\)\) == 2$', expr) + if not match: + raise NotImplementedError(expr) + return 0 raise NotImplementedError(expr) From 90ed328350edd1f2b993af73e2d21ba708955238 Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 10 Nov 2014 00:40:12 +0300 Subject: [PATCH 6/7] Change powerline.segments.vim to not import *from* csv One cannot really tell what are things like `Sniffer` or `reader`. It is better to use `csv` module directly rather than write `from csv import reader as csv_reader`. --- powerline/segments/vim/__init__.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/powerline/segments/vim/__init__.py b/powerline/segments/vim/__init__.py index 77a89864..91f93ea4 100644 --- a/powerline/segments/vim/__init__.py +++ b/powerline/segments/vim/__init__.py @@ -3,11 +3,9 @@ from __future__ import (unicode_literals, division, absolute_import, print_funct import os import re +import csv from collections import defaultdict -from csv import Sniffer, reader - -from csv import Error as CSVError try: import vim @@ -634,7 +632,7 @@ def winnr(pl, segment_info, show_current=True): csv_cache = None -sniffer = Sniffer() +sniffer = csv.Sniffer() def detect_text_csv_dialect(text, display_name, header_text=None): @@ -664,7 +662,7 @@ def process_csv_buffer(pl, buffer, line, col, display_name): text = vim.eval('join(map(getline(1, {0}), "strtrans(v:val)"), "\\n")'.format(CSV_SNIFF_LINES)) try: dialect, has_header = detect_text_csv_dialect(text, display_name) - except CSVError as e: + except csv.Error as e: pl.warn('Failed to detect csv format: {0}', str(e)) # Try detecting using three lines only: if line == 1: @@ -679,18 +677,18 @@ def process_csv_buffer(pl, buffer, line, col, display_name): display_name, header_text='\n'.join(buffer[:4]), ) - except CSVError as e: + except csv.Error as e: pl.error('Failed to detect csv format: {0}', str(e)) return None, None if len(buffer) > 2: csv_cache[buffer.number] = dialect, has_header, cur_first_line - column_number = len(list(reader( + column_number = len(list(csv.reader( buffer[max(0, line - CSV_PARSE_LINES):line - 1] + [buffer[line - 1][:col]], dialect=dialect))[-1]) or 1 if has_header: try: - header = next(reader(buffer[0:1], dialect=dialect)) + header = next(csv.reader(buffer[0:1], dialect=dialect)) except UnicodeDecodeError: - header = next(reader([vim.eval('strtrans(getline(1))')], dialect=dialect)) + header = next(csv.reader([vim.eval('strtrans(getline(1))')], dialect=dialect)) column_name = header[column_number - 1] else: column_name = None From b845cc25b49279b5b596a534589dd099ee3a53c2 Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 10 Nov 2014 01:08:37 +0300 Subject: [PATCH 7/7] Fix tests on python-2.6 csv module does not appear to work will with multiline strings in csv, especially incomplete. --- powerline/segments/vim/__init__.py | 28 ++++++++++++++++++++++++---- tests/test_segments.py | 2 ++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/powerline/segments/vim/__init__.py b/powerline/segments/vim/__init__.py index 91f93ea4..1dcfe9a9 100644 --- a/powerline/segments/vim/__init__.py +++ b/powerline/segments/vim/__init__.py @@ -4,6 +4,7 @@ from __future__ import (unicode_literals, division, absolute_import, print_funct import os import re import csv +import sys from collections import defaultdict @@ -646,6 +647,22 @@ CSV_SNIFF_LINES = 100 CSV_PARSE_LINES = 10 +if sys.version_info < (2, 7): + def read_csv(l, dialect, fin=next): + try: + return fin(csv.reader(l, dialect)) + except csv.Error as e: + if str(e) == 'newline inside string' and dialect.quotechar: + # Maybe we are inside an unfinished quoted string. Python-2.6 + # does not handle this fine + return fin(csv.reader(l[:-1] + [l[-1] + dialect.quotechar])) + else: + raise +else: + def read_csv(l, dialect, fin=next): + return fin(csv.reader(l, dialect)) + + def process_csv_buffer(pl, buffer, line, col, display_name): global csv_cache if csv_cache is None: @@ -682,13 +699,16 @@ def process_csv_buffer(pl, buffer, line, col, display_name): return None, None if len(buffer) > 2: csv_cache[buffer.number] = dialect, has_header, cur_first_line - column_number = len(list(csv.reader( - buffer[max(0, line - CSV_PARSE_LINES):line - 1] + [buffer[line - 1][:col]], dialect=dialect))[-1]) or 1 + column_number = len(read_csv( + buffer[max(0, line - CSV_PARSE_LINES):line - 1] + [buffer[line - 1][:col]], + dialect=dialect, + fin=list, + )[-1]) or 1 if has_header: try: - header = next(csv.reader(buffer[0:1], dialect=dialect)) + header = read_csv(buffer[0:1], dialect=dialect) except UnicodeDecodeError: - header = next(csv.reader([vim.eval('strtrans(getline(1))')], dialect=dialect)) + header = read_csv([vim.eval('strtrans(getline(1))')], dialect=dialect) column_name = header[column_number - 1] else: column_name = None diff --git a/tests/test_segments.py b/tests/test_segments.py index d533f495..a814ac32 100644 --- a/tests/test_segments.py +++ b/tests/test_segments.py @@ -1231,6 +1231,8 @@ class TestVim(TestCase): }, { 'contents': ' (Bar)', 'highlight_group': ['csv:column_name', 'csv'] }]) + if sys.version_info < (2, 7): + raise SkipTest('csv module in Python-2.6 does not handle multiline csv files well') buffer[len(buffer):] = ['1;"bc', 'def', 'ghi', 'jkl";3'] vim_module._set_cursor(5, 1) self.assertEqual(csv_col_current(), [{