Merge pull request #1144 from ZyX-I/vim-plugins
Add support for csv and capslock and Command-T vim plugins
This commit is contained in:
commit
a6ba63a8e5
|
@ -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
|
||||
---------------
|
||||
|
||||
|
@ -32,3 +38,9 @@ NERDTree segments
|
|||
|
||||
.. automodule:: powerline.segments.vim.plugin.nerdtree
|
||||
:members:
|
||||
|
||||
Capslock segments
|
||||
-----------------
|
||||
|
||||
.. automodule:: powerline.segments.vim.plugin.capslock
|
||||
:members:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -398,3 +414,16 @@ def on_bwipe():
|
|||
|
||||
|
||||
environ = VimEnviron()
|
||||
|
||||
|
||||
def create_ruby_dpowerline():
|
||||
vim.command((
|
||||
'''
|
||||
ruby
|
||||
if $powerline == nil
|
||||
class Powerline
|
||||
end
|
||||
$powerline = Powerline.new
|
||||
end
|
||||
'''
|
||||
))
|
||||
|
|
|
@ -1,23 +1,27 @@
|
|||
{
|
||||
"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",
|
||||
|
||||
"tab_nc:file_directory": "information:unimportant",
|
||||
"tab_nc:file_name": "tab_nc:file_directory",
|
||||
|
@ -26,6 +30,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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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"],
|
||||
|
@ -95,6 +100,10 @@
|
|||
"width": 4,
|
||||
"align": "r"
|
||||
},
|
||||
{
|
||||
"function": "csv_col_current",
|
||||
"priority": 30
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "line_current_symbol",
|
||||
|
|
|
@ -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": [
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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'
|
|
@ -3,6 +3,8 @@ from __future__ import (unicode_literals, division, absolute_import, print_funct
|
|||
|
||||
import os
|
||||
import re
|
||||
import csv
|
||||
import sys
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
|
@ -22,6 +24,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 +630,118 @@ 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 = csv.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
|
||||
|
||||
|
||||
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:
|
||||
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 csv.Error 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 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(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 = read_csv(buffer[0:1], dialect=dialect)
|
||||
except UnicodeDecodeError:
|
||||
header = read_csv([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 [])
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,89 @@
|
|||
# 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 and @active_finder.class.name or ''
|
||||
end
|
||||
end
|
||||
if (not ($command_t.respond_to? 'path'))
|
||||
def $command_t.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 or '').gsub(/'/, "''")}'"
|
||||
end
|
||||
'''
|
||||
))
|
||||
|
||||
|
||||
initialized = False
|
||||
|
||||
|
||||
def finder(pl):
|
||||
'''Display Command-T finder name
|
||||
|
||||
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')
|
||||
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):
|
||||
'''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')
|
||||
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')
|
||||
}]
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1196,6 +1196,75 @@ 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']
|
||||
}])
|
||||
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(), [{
|
||||
'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')))
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue