New conf for zsh (powerline)
This commit is contained in:
parent
16b4350cdb
commit
c98bf2e7a6
102 changed files with 9836 additions and 98 deletions
25
common/.local/bin/powerline
Executable file
25
common/.local/bin/powerline
Executable file
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/python
|
||||
# vim:fileencoding=utf-8:noet
|
||||
'''Powerline prompt and statusline script.'''
|
||||
import sys
|
||||
import os
|
||||
|
||||
try:
|
||||
from powerline.shell import ShellPowerline, get_argparser
|
||||
except ImportError:
|
||||
import os
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from powerline.shell import ShellPowerline, get_argparser # NOQA
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = get_argparser(description=__doc__).parse_args()
|
||||
powerline = ShellPowerline(args, run_once=True)
|
||||
rendered = powerline.render(
|
||||
width=args.width,
|
||||
side=args.side,
|
||||
segment_info={'args': args, 'environ': os.environ},
|
||||
)
|
||||
try:
|
||||
sys.stdout.write(rendered)
|
||||
except UnicodeEncodeError:
|
||||
sys.stdout.write(rendered.encode('utf-8'))
|
14
common/.local/bin/powerline-lint
Executable file
14
common/.local/bin/powerline-lint
Executable file
|
@ -0,0 +1,14 @@
|
|||
#!/usr/bin/python
|
||||
# vim:fileencoding=utf-8:noet
|
||||
'''Powerline configuration checker.'''
|
||||
import argparse
|
||||
from powerline.lint import check
|
||||
import sys
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('-p', '--config_path', metavar='PATH')
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = parser.parse_args()
|
||||
sys.exit(check(args.config_path))
|
|
@ -0,0 +1,63 @@
|
|||
Metadata-Version: 1.0
|
||||
Name: Powerline
|
||||
Version: beta
|
||||
Summary: The ultimate statusline/prompt utility.
|
||||
Home-page: https://github.com/Lokaltog/powerline
|
||||
Author: Kim Silkebækken
|
||||
Author-email: kim.silkebaekken+vim@gmail.com
|
||||
License: UNKNOWN
|
||||
Description: Powerline
|
||||
=========
|
||||
|
||||
:Author: Kim Silkebækken (kim.silkebaekken+vim@gmail.com)
|
||||
:Source: https://github.com/Lokaltog/powerline
|
||||
:Version: beta
|
||||
:Build status:
|
||||
.. image:: https://api.travis-ci.org/Lokaltog/powerline.png?branch=develop
|
||||
:target: `travis-build-status`_
|
||||
:alt: Build status
|
||||
|
||||
This is the upcoming version of Powerline, implemented in Python. The
|
||||
project is currently in a stable beta and almost ready for release.
|
||||
|
||||
* Consult the `documentation
|
||||
<https://powerline.readthedocs.org/en/latest/>`_ for more information and
|
||||
installation instructions.
|
||||
* Check out `powerline-fonts <https://github.com/Lokaltog/powerline-fonts>`_
|
||||
for pre-patched versions of popular coding fonts.
|
||||
|
||||
.. _travis-build-status: https://travis-ci.org/Lokaltog/powerline
|
||||
|
||||
Screenshots
|
||||
-----------
|
||||
|
||||
Vim statusline
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
**Mode-dependent highlighting**
|
||||
|
||||
* .. image:: https://raw.github.com/Lokaltog/powerline/develop/docs/source/_static/img/pl-mode-normal.png
|
||||
:alt: Normal mode
|
||||
* .. image:: https://raw.github.com/Lokaltog/powerline/develop/docs/source/_static/img/pl-mode-insert.png
|
||||
:alt: Insert mode
|
||||
* .. image:: https://raw.github.com/Lokaltog/powerline/develop/docs/source/_static/img/pl-mode-visual.png
|
||||
:alt: Visual mode
|
||||
* .. image:: https://raw.github.com/Lokaltog/powerline/develop/docs/source/_static/img/pl-mode-replace.png
|
||||
:alt: Replace mode
|
||||
|
||||
**Automatic truncation of segments in small windows**
|
||||
|
||||
* .. image:: https://raw.github.com/Lokaltog/powerline/develop/docs/source/_static/img/pl-truncate1.png
|
||||
:alt: Truncation illustration
|
||||
* .. image:: https://raw.github.com/Lokaltog/powerline/develop/docs/source/_static/img/pl-truncate2.png
|
||||
:alt: Truncation illustration
|
||||
* .. image:: https://raw.github.com/Lokaltog/powerline/develop/docs/source/_static/img/pl-truncate3.png
|
||||
:alt: Truncation illustration
|
||||
|
||||
----
|
||||
|
||||
The font in the screenshots is `Pragmata Pro`_ by Fabrizio Schiavi.
|
||||
|
||||
.. _`Pragmata Pro`: http://www.fsd.it/fonts/pragmatapro.htm
|
||||
|
||||
Platform: UNKNOWN
|
|
@ -0,0 +1,98 @@
|
|||
MANIFEST.in
|
||||
README.rst
|
||||
Powerline.egg-info/PKG-INFO
|
||||
Powerline.egg-info/SOURCES.txt
|
||||
Powerline.egg-info/dependency_links.txt
|
||||
Powerline.egg-info/not-zip-safe
|
||||
Powerline.egg-info/requires.txt
|
||||
Powerline.egg-info/top_level.txt
|
||||
powerline/__init__.py
|
||||
powerline/colorscheme.py
|
||||
powerline/ipython.py
|
||||
powerline/matcher.py
|
||||
powerline/renderer.py
|
||||
powerline/segment.py
|
||||
powerline/shell.py
|
||||
powerline/theme.py
|
||||
powerline/vim.py
|
||||
powerline/bindings/__init__.py
|
||||
powerline/bindings/awesome/powerline-awesome.py
|
||||
powerline/bindings/awesome/powerline.lua
|
||||
powerline/bindings/bash/powerline.sh
|
||||
powerline/bindings/ipython/__init__.py
|
||||
powerline/bindings/ipython/post_0_11.py
|
||||
powerline/bindings/ipython/pre_0_11.py
|
||||
powerline/bindings/qtile/__init__.py
|
||||
powerline/bindings/qtile/widget.py
|
||||
powerline/bindings/tmux/powerline.conf
|
||||
powerline/bindings/vim/__init__.py
|
||||
powerline/bindings/vim/plugin/powerline.vim
|
||||
powerline/bindings/zsh/__init__.py
|
||||
powerline/bindings/zsh/powerline.zsh
|
||||
powerline/config_files/colors.json
|
||||
powerline/config_files/config.json
|
||||
powerline/config_files/colorschemes/ipython/default.json
|
||||
powerline/config_files/colorschemes/shell/default.json
|
||||
powerline/config_files/colorschemes/shell/solarized.json
|
||||
powerline/config_files/colorschemes/tmux/default.json
|
||||
powerline/config_files/colorschemes/vim/default.json
|
||||
powerline/config_files/colorschemes/vim/solarized.json
|
||||
powerline/config_files/colorschemes/wm/default.json
|
||||
powerline/config_files/themes/ipython/in.json
|
||||
powerline/config_files/themes/ipython/in2.json
|
||||
powerline/config_files/themes/ipython/out.json
|
||||
powerline/config_files/themes/ipython/rewrite.json
|
||||
powerline/config_files/themes/shell/default.json
|
||||
powerline/config_files/themes/shell/default_leftonly.json
|
||||
powerline/config_files/themes/tmux/default.json
|
||||
powerline/config_files/themes/vim/cmdwin.json
|
||||
powerline/config_files/themes/vim/default.json
|
||||
powerline/config_files/themes/vim/help.json
|
||||
powerline/config_files/themes/vim/quickfix.json
|
||||
powerline/config_files/themes/wm/default.json
|
||||
powerline/lib/__init__.py
|
||||
powerline/lib/config.py
|
||||
powerline/lib/file_watcher.py
|
||||
powerline/lib/humanize_bytes.py
|
||||
powerline/lib/inotify.py
|
||||
powerline/lib/memoize.py
|
||||
powerline/lib/monotonic.py
|
||||
powerline/lib/threaded.py
|
||||
powerline/lib/tree_watcher.py
|
||||
powerline/lib/url.py
|
||||
powerline/lib/vcs/__init__.py
|
||||
powerline/lib/vcs/bzr.py
|
||||
powerline/lib/vcs/git.py
|
||||
powerline/lib/vcs/mercurial.py
|
||||
powerline/lint/__init__.py
|
||||
powerline/lint/inspect.py
|
||||
powerline/lint/markedjson/__init__.py
|
||||
powerline/lint/markedjson/composer.py
|
||||
powerline/lint/markedjson/constructor.py
|
||||
powerline/lint/markedjson/error.py
|
||||
powerline/lint/markedjson/events.py
|
||||
powerline/lint/markedjson/loader.py
|
||||
powerline/lint/markedjson/markedvalue.py
|
||||
powerline/lint/markedjson/nodes.py
|
||||
powerline/lint/markedjson/parser.py
|
||||
powerline/lint/markedjson/reader.py
|
||||
powerline/lint/markedjson/resolver.py
|
||||
powerline/lint/markedjson/scanner.py
|
||||
powerline/lint/markedjson/tokens.py
|
||||
powerline/matchers/__init__.py
|
||||
powerline/matchers/vim.py
|
||||
powerline/renderers/__init__.py
|
||||
powerline/renderers/bash_prompt.py
|
||||
powerline/renderers/ipython.py
|
||||
powerline/renderers/pango_markup.py
|
||||
powerline/renderers/shell.py
|
||||
powerline/renderers/tmux.py
|
||||
powerline/renderers/vim.py
|
||||
powerline/renderers/zsh_prompt.py
|
||||
powerline/segments/__init__.py
|
||||
powerline/segments/common.py
|
||||
powerline/segments/ipython.py
|
||||
powerline/segments/shell.py
|
||||
powerline/segments/vim.py
|
||||
scripts/powerline
|
||||
scripts/powerline-lint
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,159 @@
|
|||
../powerline/shell.py
|
||||
../powerline/colorscheme.py
|
||||
../powerline/ipython.py
|
||||
../powerline/theme.py
|
||||
../powerline/vim.py
|
||||
../powerline/__init__.py
|
||||
../powerline/matcher.py
|
||||
../powerline/renderer.py
|
||||
../powerline/segment.py
|
||||
../powerline/matchers/vim.py
|
||||
../powerline/matchers/__init__.py
|
||||
../powerline/bindings/__init__.py
|
||||
../powerline/lint/__init__.py
|
||||
../powerline/lint/inspect.py
|
||||
../powerline/segments/shell.py
|
||||
../powerline/segments/ipython.py
|
||||
../powerline/segments/common.py
|
||||
../powerline/segments/vim.py
|
||||
../powerline/segments/__init__.py
|
||||
../powerline/renderers/shell.py
|
||||
../powerline/renderers/ipython.py
|
||||
../powerline/renderers/bash_prompt.py
|
||||
../powerline/renderers/zsh_prompt.py
|
||||
../powerline/renderers/vim.py
|
||||
../powerline/renderers/__init__.py
|
||||
../powerline/renderers/pango_markup.py
|
||||
../powerline/renderers/tmux.py
|
||||
../powerline/lib/memoize.py
|
||||
../powerline/lib/monotonic.py
|
||||
../powerline/lib/config.py
|
||||
../powerline/lib/humanize_bytes.py
|
||||
../powerline/lib/__init__.py
|
||||
../powerline/lib/inotify.py
|
||||
../powerline/lib/url.py
|
||||
../powerline/lib/threaded.py
|
||||
../powerline/lib/file_watcher.py
|
||||
../powerline/lib/tree_watcher.py
|
||||
../powerline/bindings/ipython/post_0_11.py
|
||||
../powerline/bindings/ipython/pre_0_11.py
|
||||
../powerline/bindings/ipython/__init__.py
|
||||
../powerline/bindings/qtile/__init__.py
|
||||
../powerline/bindings/qtile/widget.py
|
||||
../powerline/bindings/vim/__init__.py
|
||||
../powerline/bindings/zsh/__init__.py
|
||||
../powerline/lint/markedjson/composer.py
|
||||
../powerline/lint/markedjson/constructor.py
|
||||
../powerline/lint/markedjson/loader.py
|
||||
../powerline/lint/markedjson/nodes.py
|
||||
../powerline/lint/markedjson/resolver.py
|
||||
../powerline/lint/markedjson/scanner.py
|
||||
../powerline/lint/markedjson/reader.py
|
||||
../powerline/lint/markedjson/__init__.py
|
||||
../powerline/lint/markedjson/parser.py
|
||||
../powerline/lint/markedjson/markedvalue.py
|
||||
../powerline/lint/markedjson/events.py
|
||||
../powerline/lint/markedjson/tokens.py
|
||||
../powerline/lint/markedjson/error.py
|
||||
../powerline/lib/vcs/git.py
|
||||
../powerline/lib/vcs/mercurial.py
|
||||
../powerline/lib/vcs/__init__.py
|
||||
../powerline/lib/vcs/bzr.py
|
||||
../powerline/config_files/colors.json
|
||||
../powerline/config_files/config.json
|
||||
../powerline/config_files/colorschemes/ipython/default.json
|
||||
../powerline/config_files/colorschemes/shell/default.json
|
||||
../powerline/config_files/colorschemes/shell/solarized.json
|
||||
../powerline/config_files/colorschemes/tmux/default.json
|
||||
../powerline/config_files/colorschemes/vim/default.json
|
||||
../powerline/config_files/colorschemes/vim/solarized.json
|
||||
../powerline/config_files/colorschemes/wm/default.json
|
||||
../powerline/config_files/themes/ipython/in.json
|
||||
../powerline/config_files/themes/ipython/in2.json
|
||||
../powerline/config_files/themes/ipython/out.json
|
||||
../powerline/config_files/themes/ipython/rewrite.json
|
||||
../powerline/config_files/themes/shell/default.json
|
||||
../powerline/config_files/themes/shell/default_leftonly.json
|
||||
../powerline/config_files/themes/tmux/default.json
|
||||
../powerline/config_files/themes/vim/cmdwin.json
|
||||
../powerline/config_files/themes/vim/default.json
|
||||
../powerline/config_files/themes/vim/help.json
|
||||
../powerline/config_files/themes/vim/quickfix.json
|
||||
../powerline/config_files/themes/wm/default.json
|
||||
../powerline/bindings/awesome/powerline-awesome.py
|
||||
../powerline/bindings/awesome/powerline.lua
|
||||
../powerline/bindings/bash/powerline.sh
|
||||
../powerline/bindings/tmux/powerline.conf
|
||||
../powerline/bindings/vim/plugin/powerline.vim
|
||||
../powerline/bindings/zsh/powerline.zsh
|
||||
../powerline/shell.pyc
|
||||
../powerline/colorscheme.pyc
|
||||
../powerline/ipython.pyc
|
||||
../powerline/theme.pyc
|
||||
../powerline/vim.pyc
|
||||
../powerline/__init__.pyc
|
||||
../powerline/matcher.pyc
|
||||
../powerline/renderer.pyc
|
||||
../powerline/segment.pyc
|
||||
../powerline/matchers/vim.pyc
|
||||
../powerline/matchers/__init__.pyc
|
||||
../powerline/bindings/__init__.pyc
|
||||
../powerline/lint/__init__.pyc
|
||||
../powerline/lint/inspect.pyc
|
||||
../powerline/segments/shell.pyc
|
||||
../powerline/segments/ipython.pyc
|
||||
../powerline/segments/common.pyc
|
||||
../powerline/segments/vim.pyc
|
||||
../powerline/segments/__init__.pyc
|
||||
../powerline/renderers/shell.pyc
|
||||
../powerline/renderers/ipython.pyc
|
||||
../powerline/renderers/bash_prompt.pyc
|
||||
../powerline/renderers/zsh_prompt.pyc
|
||||
../powerline/renderers/vim.pyc
|
||||
../powerline/renderers/__init__.pyc
|
||||
../powerline/renderers/pango_markup.pyc
|
||||
../powerline/renderers/tmux.pyc
|
||||
../powerline/lib/memoize.pyc
|
||||
../powerline/lib/monotonic.pyc
|
||||
../powerline/lib/config.pyc
|
||||
../powerline/lib/humanize_bytes.pyc
|
||||
../powerline/lib/__init__.pyc
|
||||
../powerline/lib/inotify.pyc
|
||||
../powerline/lib/url.pyc
|
||||
../powerline/lib/threaded.pyc
|
||||
../powerline/lib/file_watcher.pyc
|
||||
../powerline/lib/tree_watcher.pyc
|
||||
../powerline/bindings/ipython/post_0_11.pyc
|
||||
../powerline/bindings/ipython/pre_0_11.pyc
|
||||
../powerline/bindings/ipython/__init__.pyc
|
||||
../powerline/bindings/qtile/__init__.pyc
|
||||
../powerline/bindings/qtile/widget.pyc
|
||||
../powerline/bindings/vim/__init__.pyc
|
||||
../powerline/bindings/zsh/__init__.pyc
|
||||
../powerline/lint/markedjson/composer.pyc
|
||||
../powerline/lint/markedjson/constructor.pyc
|
||||
../powerline/lint/markedjson/loader.pyc
|
||||
../powerline/lint/markedjson/nodes.pyc
|
||||
../powerline/lint/markedjson/resolver.pyc
|
||||
../powerline/lint/markedjson/scanner.pyc
|
||||
../powerline/lint/markedjson/reader.pyc
|
||||
../powerline/lint/markedjson/__init__.pyc
|
||||
../powerline/lint/markedjson/parser.pyc
|
||||
../powerline/lint/markedjson/markedvalue.pyc
|
||||
../powerline/lint/markedjson/events.pyc
|
||||
../powerline/lint/markedjson/tokens.pyc
|
||||
../powerline/lint/markedjson/error.pyc
|
||||
../powerline/lib/vcs/git.pyc
|
||||
../powerline/lib/vcs/mercurial.pyc
|
||||
../powerline/lib/vcs/__init__.pyc
|
||||
../powerline/lib/vcs/bzr.pyc
|
||||
../powerline/bindings/awesome/powerline-awesome.pyc
|
||||
./
|
||||
SOURCES.txt
|
||||
PKG-INFO
|
||||
not-zip-safe
|
||||
dependency_links.txt
|
||||
top_level.txt
|
||||
requires.txt
|
||||
../../../../bin/powerline
|
||||
../../../../bin/powerline-lint
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
|
||||
[docs]
|
||||
Sphinx
|
|
@ -0,0 +1 @@
|
|||
powerline
|
409
common/.local/lib/python2.7/site-packages/powerline/__init__.py
Normal file
409
common/.local/lib/python2.7/site-packages/powerline/__init__.py
Normal file
|
@ -0,0 +1,409 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
|
||||
from powerline.colorscheme import Colorscheme
|
||||
from powerline.lib.config import ConfigLoader
|
||||
|
||||
from threading import Lock, Event
|
||||
|
||||
|
||||
DEFAULT_SYSTEM_CONFIG_DIR = None
|
||||
|
||||
|
||||
def find_config_file(search_paths, config_file):
|
||||
config_file += '.json'
|
||||
for path in search_paths:
|
||||
config_file_path = os.path.join(path, config_file)
|
||||
if os.path.isfile(config_file_path):
|
||||
return config_file_path
|
||||
raise IOError('Config file not found in search path: {0}'.format(config_file))
|
||||
|
||||
|
||||
class PowerlineLogger(object):
|
||||
def __init__(self, use_daemon_threads, logger, ext):
|
||||
self.logger = logger
|
||||
self.ext = ext
|
||||
self.use_daemon_threads = use_daemon_threads
|
||||
self.prefix = ''
|
||||
self.last_msgs = {}
|
||||
|
||||
def _log(self, attr, msg, *args, **kwargs):
|
||||
prefix = kwargs.get('prefix') or self.prefix
|
||||
prefix = self.ext + ((':' + prefix) if prefix else '')
|
||||
if args or kwargs:
|
||||
msg = msg.format(*args, **kwargs)
|
||||
msg = prefix + ':' + msg
|
||||
key = attr + ':' + prefix
|
||||
if msg != self.last_msgs.get(key):
|
||||
getattr(self.logger, attr)(msg)
|
||||
self.last_msgs[key] = msg
|
||||
|
||||
def critical(self, msg, *args, **kwargs):
|
||||
self._log('critical', msg, *args, **kwargs)
|
||||
|
||||
def exception(self, msg, *args, **kwargs):
|
||||
self._log('exception', msg, *args, **kwargs)
|
||||
|
||||
def info(self, msg, *args, **kwargs):
|
||||
self._log('info', msg, *args, **kwargs)
|
||||
|
||||
def error(self, msg, *args, **kwargs):
|
||||
self._log('error', msg, *args, **kwargs)
|
||||
|
||||
def warn(self, msg, *args, **kwargs):
|
||||
self._log('warning', msg, *args, **kwargs)
|
||||
|
||||
def debug(self, msg, *args, **kwargs):
|
||||
self._log('debug', msg, *args, **kwargs)
|
||||
|
||||
|
||||
class Powerline(object):
|
||||
'''Main powerline class, entrance point for all powerline uses. Sets
|
||||
powerline up and loads the configuration.
|
||||
|
||||
:param str ext:
|
||||
extension used. Determines where configuration files will
|
||||
searched and what renderer module will be used. Affected: used ``ext``
|
||||
dictionary from :file:`powerline/config.json`, location of themes and
|
||||
colorschemes, render module (``powerline.renders.{ext}``).
|
||||
:param str renderer_module:
|
||||
Overrides renderer module (defaults to ``ext``). Should be the name of
|
||||
the package imported like this: ``powerline.renders.{render_module}``.
|
||||
If this parameter contains a dot, ``powerline.renderers.`` is not
|
||||
prepended. There is also a special case for renderers defined in
|
||||
toplevel modules: ``foo.`` (note: dot at the end) tries to get renderer
|
||||
from module ``foo`` (because ``foo`` (without dot) tries to get renderer
|
||||
from module ``powerline.renderers.foo``).
|
||||
:param bool run_once:
|
||||
Determines whether .renderer.render() method will be run only once
|
||||
during python session.
|
||||
:param Logger logger:
|
||||
If present, no new logger will be created and this logger will be used.
|
||||
:param bool use_daemon_threads:
|
||||
Use daemon threads for.
|
||||
:param Event shutdown_event:
|
||||
Use this Event as shutdown_event.
|
||||
:param ConfigLoader config_loader:
|
||||
Class that manages (re)loading of configuration.
|
||||
'''
|
||||
|
||||
def __init__(self,
|
||||
ext,
|
||||
renderer_module=None,
|
||||
run_once=False,
|
||||
logger=None,
|
||||
use_daemon_threads=True,
|
||||
shutdown_event=None,
|
||||
config_loader=None):
|
||||
self.ext = ext
|
||||
self.renderer_module = renderer_module or ext
|
||||
self.run_once = run_once
|
||||
self.logger = logger
|
||||
self.use_daemon_threads = use_daemon_threads
|
||||
|
||||
if '.' not in self.renderer_module:
|
||||
self.renderer_module = 'powerline.renderers.' + self.renderer_module
|
||||
elif self.renderer_module[-1] == '.':
|
||||
self.renderer_module = self.renderer_module[:-1]
|
||||
|
||||
config_paths = self.get_config_paths()
|
||||
self.find_config_file = lambda cfg_path: find_config_file(config_paths, cfg_path)
|
||||
|
||||
self.cr_kwargs_lock = Lock()
|
||||
self.create_renderer_kwargs = {
|
||||
'load_main': True,
|
||||
'load_colors': True,
|
||||
'load_colorscheme': True,
|
||||
'load_theme': True,
|
||||
}
|
||||
self.shutdown_event = shutdown_event or Event()
|
||||
self.config_loader = config_loader or ConfigLoader(shutdown_event=self.shutdown_event)
|
||||
self.run_loader_update = False
|
||||
|
||||
self.renderer_options = {}
|
||||
|
||||
self.prev_common_config = None
|
||||
self.prev_ext_config = None
|
||||
self.pl = None
|
||||
|
||||
def create_renderer(self, load_main=False, load_colors=False, load_colorscheme=False, load_theme=False):
|
||||
'''(Re)create renderer object. Can be used after Powerline object was
|
||||
successfully initialized. If any of the below parameters except
|
||||
``load_main`` is True renderer object will be recreated.
|
||||
|
||||
:param bool load_main:
|
||||
Determines whether main configuration file (:file:`config.json`)
|
||||
should be loaded. If appropriate configuration changes implies
|
||||
``load_colorscheme`` and ``load_theme`` and recreation of renderer
|
||||
object. Won’t trigger recreation if only unrelated configuration
|
||||
changed.
|
||||
:param bool load_colors:
|
||||
Determines whether colors configuration from :file:`colors.json`
|
||||
should be (re)loaded.
|
||||
:param bool load_colorscheme:
|
||||
Determines whether colorscheme configuration should be (re)loaded.
|
||||
:param bool load_theme:
|
||||
Determines whether theme configuration should be reloaded.
|
||||
'''
|
||||
common_config_differs = False
|
||||
ext_config_differs = False
|
||||
if load_main:
|
||||
self._purge_configs('main')
|
||||
config = self.load_main_config()
|
||||
self.common_config = config['common']
|
||||
if self.common_config != self.prev_common_config:
|
||||
common_config_differs = True
|
||||
self.prev_common_config = self.common_config
|
||||
self.common_config['paths'] = [os.path.expanduser(path) for path in self.common_config.get('paths', [])]
|
||||
self.import_paths = self.common_config['paths']
|
||||
|
||||
if not self.logger:
|
||||
log_format = self.common_config.get('log_format', '%(asctime)s:%(levelname)s:%(message)s')
|
||||
formatter = logging.Formatter(log_format)
|
||||
|
||||
level = getattr(logging, self.common_config.get('log_level', 'WARNING'))
|
||||
handler = self.get_log_handler()
|
||||
handler.setLevel(level)
|
||||
handler.setFormatter(formatter)
|
||||
|
||||
self.logger = logging.getLogger('powerline')
|
||||
self.logger.setLevel(level)
|
||||
self.logger.addHandler(handler)
|
||||
|
||||
if not self.pl:
|
||||
self.pl = PowerlineLogger(self.use_daemon_threads, self.logger, self.ext)
|
||||
if not self.config_loader.pl:
|
||||
self.config_loader.pl = self.pl
|
||||
|
||||
self.renderer_options.update(
|
||||
pl=self.pl,
|
||||
term_truecolor=self.common_config.get('term_truecolor', False),
|
||||
ambiwidth=self.common_config.get('ambiwidth', 1),
|
||||
tmux_escape=self.common_config.get('additional_escapes') == 'tmux',
|
||||
screen_escape=self.common_config.get('additional_escapes') == 'screen',
|
||||
theme_kwargs={
|
||||
'ext': self.ext,
|
||||
'common_config': self.common_config,
|
||||
'run_once': self.run_once,
|
||||
'shutdown_event': self.shutdown_event,
|
||||
},
|
||||
)
|
||||
|
||||
if not self.run_once and self.common_config.get('reload_config', True):
|
||||
interval = self.common_config.get('interval', None)
|
||||
self.config_loader.set_interval(interval)
|
||||
self.run_loader_update = (interval is None)
|
||||
if interval is not None and not self.config_loader.is_alive():
|
||||
self.config_loader.start()
|
||||
|
||||
self.ext_config = config['ext'][self.ext]
|
||||
if self.ext_config != self.prev_ext_config:
|
||||
ext_config_differs = True
|
||||
if not self.prev_ext_config or self.ext_config.get('local_themes') != self.prev_ext_config.get('local_themes'):
|
||||
self.renderer_options['local_themes'] = self.get_local_themes(self.ext_config.get('local_themes'))
|
||||
load_colorscheme = (load_colorscheme
|
||||
or not self.prev_ext_config
|
||||
or self.prev_ext_config['colorscheme'] != self.ext_config['colorscheme'])
|
||||
load_theme = (load_theme
|
||||
or not self.prev_ext_config
|
||||
or self.prev_ext_config['theme'] != self.ext_config['theme'])
|
||||
self.prev_ext_config = self.ext_config
|
||||
|
||||
create_renderer = load_colors or load_colorscheme or load_theme or common_config_differs or ext_config_differs
|
||||
|
||||
if load_colors:
|
||||
self._purge_configs('colors')
|
||||
self.colors_config = self.load_colors_config()
|
||||
|
||||
if load_colorscheme or load_colors:
|
||||
self._purge_configs('colorscheme')
|
||||
if load_colorscheme:
|
||||
self.colorscheme_config = self.load_colorscheme_config(self.ext_config['colorscheme'])
|
||||
self.renderer_options['colorscheme'] = Colorscheme(self.colorscheme_config, self.colors_config)
|
||||
|
||||
if load_theme:
|
||||
self._purge_configs('theme')
|
||||
self.renderer_options['theme_config'] = self.load_theme_config(self.ext_config.get('theme', 'default'))
|
||||
|
||||
if create_renderer:
|
||||
try:
|
||||
Renderer = __import__(self.renderer_module, fromlist=['renderer']).renderer
|
||||
except Exception as e:
|
||||
self.pl.exception('Failed to import renderer module: {0}', str(e))
|
||||
sys.exit(1)
|
||||
|
||||
# Renderer updates configuration file via segments’ .startup thus it
|
||||
# should be locked to prevent state when configuration was updated,
|
||||
# but .render still uses old renderer.
|
||||
try:
|
||||
renderer = Renderer(**self.renderer_options)
|
||||
except Exception as e:
|
||||
self.pl.exception('Failed to construct renderer object: {0}', str(e))
|
||||
if not hasattr(self, 'renderer'):
|
||||
raise
|
||||
else:
|
||||
self.renderer = renderer
|
||||
|
||||
def get_log_handler(self):
|
||||
'''Get log handler.
|
||||
|
||||
:param dict common_config:
|
||||
Common configuration.
|
||||
|
||||
:return: logging.Handler subclass.
|
||||
'''
|
||||
log_file = self.common_config.get('log_file', None)
|
||||
if log_file:
|
||||
log_file = os.path.expanduser(log_file)
|
||||
log_dir = os.path.dirname(log_file)
|
||||
if not os.path.isdir(log_dir):
|
||||
os.mkdir(log_dir)
|
||||
return logging.FileHandler(log_file)
|
||||
else:
|
||||
return logging.StreamHandler()
|
||||
|
||||
@staticmethod
|
||||
def get_config_paths():
|
||||
'''Get configuration paths.
|
||||
|
||||
:return: list of paths
|
||||
'''
|
||||
config_home = os.environ.get('XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config'))
|
||||
config_path = os.path.join(config_home, 'powerline')
|
||||
config_paths = [config_path]
|
||||
config_dirs = os.environ.get('XDG_CONFIG_DIRS', DEFAULT_SYSTEM_CONFIG_DIR)
|
||||
if config_dirs is not None:
|
||||
config_paths.extend([os.path.join(d, 'powerline') for d in config_dirs.split(':')])
|
||||
plugin_path = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'config_files')
|
||||
config_paths.append(plugin_path)
|
||||
return config_paths
|
||||
|
||||
def _load_config(self, cfg_path, type):
|
||||
'''Load configuration and setup watches.'''
|
||||
function = getattr(self, 'on_' + type + '_change')
|
||||
try:
|
||||
path = self.find_config_file(cfg_path)
|
||||
except IOError:
|
||||
self.config_loader.register_missing(self.find_config_file, function, cfg_path)
|
||||
raise
|
||||
self.config_loader.register(function, path)
|
||||
return self.config_loader.load(path)
|
||||
|
||||
def _purge_configs(self, type):
|
||||
function = getattr(self, 'on_' + type + '_change')
|
||||
self.config_loader.unregister_functions(set((function,)))
|
||||
self.config_loader.unregister_missing(set(((self.find_config_file, function),)))
|
||||
|
||||
def load_theme_config(self, name):
|
||||
'''Get theme configuration.
|
||||
|
||||
:param str name:
|
||||
Name of the theme to load.
|
||||
|
||||
:return: dictionary with :ref:`theme configuration <config-themes>`
|
||||
'''
|
||||
return self._load_config(os.path.join('themes', self.ext, name), 'theme')
|
||||
|
||||
def load_main_config(self):
|
||||
'''Get top-level configuration.
|
||||
|
||||
:return: dictionary with :ref:`top-level configuration <config-main>`.
|
||||
'''
|
||||
return self._load_config('config', 'main')
|
||||
|
||||
def load_colorscheme_config(self, name):
|
||||
'''Get colorscheme.
|
||||
|
||||
:param str name:
|
||||
Name of the colorscheme to load.
|
||||
|
||||
:return: dictionary with :ref:`colorscheme configuration <config-colorschemes>`.
|
||||
'''
|
||||
return self._load_config(os.path.join('colorschemes', self.ext, name), 'colorscheme')
|
||||
|
||||
def load_colors_config(self):
|
||||
'''Get colorscheme.
|
||||
|
||||
:return: dictionary with :ref:`colors configuration <config-colors>`.
|
||||
'''
|
||||
return self._load_config('colors', 'colors')
|
||||
|
||||
@staticmethod
|
||||
def get_local_themes(local_themes):
|
||||
'''Get local themes. No-op here, to be overridden in subclasses if
|
||||
required.
|
||||
|
||||
:param dict local_themes:
|
||||
Usually accepts ``{matcher_name : theme_name}``. May also receive
|
||||
None in case there is no local_themes configuration.
|
||||
|
||||
:return:
|
||||
anything accepted by ``self.renderer.get_theme`` and processable by
|
||||
``self.renderer.add_local_theme``. Renderer module is determined by
|
||||
``__init__`` arguments, refer to its documentation.
|
||||
'''
|
||||
return None
|
||||
|
||||
def update_renderer(self):
|
||||
'''Updates/creates a renderer if needed.'''
|
||||
if self.run_loader_update:
|
||||
self.config_loader.update()
|
||||
create_renderer_kwargs = None
|
||||
with self.cr_kwargs_lock:
|
||||
if self.create_renderer_kwargs:
|
||||
create_renderer_kwargs = self.create_renderer_kwargs.copy()
|
||||
if create_renderer_kwargs:
|
||||
try:
|
||||
self.create_renderer(**create_renderer_kwargs)
|
||||
except Exception as e:
|
||||
self.pl.exception('Failed to create renderer: {0}', str(e))
|
||||
finally:
|
||||
self.create_renderer_kwargs.clear()
|
||||
|
||||
def render(self, *args, **kwargs):
|
||||
'''Update/create renderer if needed and pass all arguments further to
|
||||
``self.renderer.render()``.
|
||||
'''
|
||||
self.update_renderer()
|
||||
return self.renderer.render(*args, **kwargs)
|
||||
|
||||
def shutdown(self):
|
||||
'''Shut down all background threads. Must be run only prior to exiting
|
||||
current application.
|
||||
'''
|
||||
self.shutdown_event.set()
|
||||
self.renderer.shutdown()
|
||||
functions = (
|
||||
self.on_main_change,
|
||||
self.on_colors_change,
|
||||
self.on_colorscheme_change,
|
||||
self.on_theme_change,
|
||||
)
|
||||
self.config_loader.unregister_functions(set(functions))
|
||||
self.config_loader.unregister_missing(set(((find_config_file, function) for function in functions)))
|
||||
|
||||
def on_main_change(self, path):
|
||||
with self.cr_kwargs_lock:
|
||||
self.create_renderer_kwargs['load_main'] = True
|
||||
|
||||
def on_colors_change(self, path):
|
||||
with self.cr_kwargs_lock:
|
||||
self.create_renderer_kwargs['load_colors'] = True
|
||||
|
||||
def on_colorscheme_change(self, path):
|
||||
with self.cr_kwargs_lock:
|
||||
self.create_renderer_kwargs['load_colorscheme'] = True
|
||||
|
||||
def on_theme_change(self, path):
|
||||
with self.cr_kwargs_lock:
|
||||
self.create_renderer_kwargs['load_theme'] = True
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
self.shutdown()
|
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env python
|
||||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from powerline import Powerline
|
||||
import sys
|
||||
from time import sleep
|
||||
from powerline.lib.monotonic import monotonic
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
powerline = Powerline('wm', renderer_module='pango_markup')
|
||||
powerline.update_renderer()
|
||||
|
||||
try:
|
||||
interval = float(sys.argv[1])
|
||||
except IndexError:
|
||||
interval = 2
|
||||
|
||||
|
||||
def read_to_log(pl, client):
|
||||
for line in client.stdout:
|
||||
if line:
|
||||
pl.info(line, prefix='awesome-client')
|
||||
for line in client.stderr:
|
||||
if line:
|
||||
pl.error(line, prefix='awesome-client')
|
||||
if client.wait():
|
||||
pl.error('Client exited with {0}', client.returncode, prefix='awesome')
|
||||
|
||||
|
||||
while True:
|
||||
start_time = monotonic()
|
||||
s = powerline.render(side='right')
|
||||
request = "powerline_widget:set_markup('" + s.replace('\\', '\\\\').replace("'", "\\'") + "')\n"
|
||||
client = Popen(['awesome-client'], shell=False, stdout=PIPE, stderr=PIPE, stdin=PIPE)
|
||||
client.stdin.write(request.encode('utf-8'))
|
||||
client.stdin.close()
|
||||
read_to_log(powerline.pl, client)
|
||||
sleep(max(interval - (monotonic() - start_time), 0.1))
|
|
@ -0,0 +1,11 @@
|
|||
local wibox = require('wibox')
|
||||
local awful = require('awful')
|
||||
|
||||
powerline_widget = wibox.widget.textbox()
|
||||
powerline_widget:set_align('right')
|
||||
|
||||
function powerline(mode, widget) end
|
||||
|
||||
bindings_path = string.gsub(debug.getinfo(1).source:match('@(.*)$'), '/[^/]+$', '')
|
||||
powerline_cmd = bindings_path .. '/powerline-awesome.py'
|
||||
awful.util.spawn_with_shell('ps -C powerline-awesome.py || ' .. powerline_cmd)
|
|
@ -0,0 +1,28 @@
|
|||
_powerline_tmux_setenv() {
|
||||
if [[ -n "$TMUX" ]]; then
|
||||
tmux setenv TMUX_"$1"_$(tmux display -p "#D" | tr -d %) "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
_powerline_tmux_set_pwd() {
|
||||
_powerline_tmux_setenv PWD "$PWD"
|
||||
}
|
||||
|
||||
_powerline_tmux_set_columns() {
|
||||
_powerline_tmux_setenv COLUMNS "$COLUMNS"
|
||||
}
|
||||
|
||||
_powerline_prompt() {
|
||||
local last_exit_code=$?
|
||||
[[ -z "$POWERLINE_OLD_PROMPT_COMMAND" ]] ||
|
||||
eval $POWERLINE_OLD_PROMPT_COMMAND
|
||||
PS1="$(powerline shell left -r bash_prompt --last_exit_code=$last_exit_code)"
|
||||
_powerline_tmux_set_pwd
|
||||
}
|
||||
|
||||
trap "_powerline_tmux_set_columns" SIGWINCH
|
||||
_powerline_tmux_set_columns
|
||||
|
||||
[[ "$PROMPT_COMMAND" == "_powerline_prompt" ]] ||
|
||||
POWERLINE_OLD_PROMPT_COMMAND="$PROMPT_COMMAND"
|
||||
export PROMPT_COMMAND="_powerline_prompt"
|
|
@ -0,0 +1,61 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
from powerline.ipython import IpythonPowerline
|
||||
|
||||
from IPython.core.prompts import PromptManager
|
||||
from IPython.core.hooks import TryNext
|
||||
|
||||
|
||||
class IpythonInfo(object):
|
||||
def __init__(self, shell):
|
||||
self._shell = shell
|
||||
|
||||
@property
|
||||
def prompt_count(self):
|
||||
return self._shell.execution_count
|
||||
|
||||
|
||||
class PowerlinePromptManager(PromptManager):
|
||||
powerline = None
|
||||
|
||||
def __init__(self, powerline, shell):
|
||||
self.powerline = powerline
|
||||
self.powerline_segment_info = IpythonInfo(shell)
|
||||
self.shell = shell
|
||||
|
||||
def render(self, name, color=True, *args, **kwargs):
|
||||
width = None if name == 'in' else self.width
|
||||
res, res_nocolor = self.powerline.render(output_raw=True, width=width, matcher_info=name, segment_info=self.powerline_segment_info)
|
||||
self.txtwidth = len(res_nocolor)
|
||||
self.width = self.txtwidth
|
||||
return res if color else res_nocolor
|
||||
|
||||
|
||||
class ConfigurableIpythonPowerline(IpythonPowerline):
|
||||
def __init__(self, ip):
|
||||
config = ip.config.Powerline
|
||||
self.config_overrides = config.get('config_overrides')
|
||||
self.theme_overrides = config.get('theme_overrides', {})
|
||||
self.path = config.get('path')
|
||||
super(ConfigurableIpythonPowerline, self).__init__()
|
||||
|
||||
|
||||
old_prompt_manager = None
|
||||
|
||||
|
||||
def load_ipython_extension(ip):
|
||||
global old_prompt_manager
|
||||
|
||||
old_prompt_manager = ip.prompt_manager
|
||||
powerline = ConfigurableIpythonPowerline(ip)
|
||||
|
||||
ip.prompt_manager = PowerlinePromptManager(powerline=powerline, shell=ip.prompt_manager.shell)
|
||||
|
||||
def shutdown_hook():
|
||||
powerline.shutdown()
|
||||
raise TryNext()
|
||||
|
||||
ip.hooks.shutdown_hook.add(shutdown_hook)
|
||||
|
||||
|
||||
def unload_ipython_extension(ip):
|
||||
ip.prompt_manager = old_prompt_manager
|
|
@ -0,0 +1,135 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
from powerline.ipython import IpythonPowerline
|
||||
from IPython.Prompts import BasePrompt
|
||||
from IPython.ipapi import get as get_ipython
|
||||
from IPython.ipapi import TryNext
|
||||
|
||||
import re
|
||||
|
||||
|
||||
def string(s):
|
||||
if type(s) is not str:
|
||||
return s.encode('utf-8')
|
||||
else:
|
||||
return s
|
||||
|
||||
|
||||
# HACK: ipython tries to only leave us with plain ASCII
|
||||
class RewriteResult(object):
|
||||
def __init__(self, prompt):
|
||||
self.prompt = string(prompt)
|
||||
|
||||
def __str__(self):
|
||||
return self.prompt
|
||||
|
||||
def __add__(self, s):
|
||||
if type(s) is not str:
|
||||
try:
|
||||
s = s.encode('utf-8')
|
||||
except AttributeError:
|
||||
raise NotImplementedError
|
||||
return RewriteResult(self.prompt + s)
|
||||
|
||||
|
||||
class IpythonInfo(object):
|
||||
def __init__(self, cache):
|
||||
self._cache = cache
|
||||
|
||||
@property
|
||||
def prompt_count(self):
|
||||
return self._cache.prompt_count
|
||||
|
||||
|
||||
class PowerlinePrompt(BasePrompt):
|
||||
def __init__(self, powerline, powerline_last_in, old_prompt):
|
||||
self.powerline = powerline
|
||||
self.powerline_last_in = powerline_last_in
|
||||
self.powerline_segment_info = IpythonInfo(old_prompt.cache)
|
||||
self.cache = old_prompt.cache
|
||||
if hasattr(old_prompt, 'sep'):
|
||||
self.sep = old_prompt.sep
|
||||
self.pad_left = False
|
||||
|
||||
def __str__(self):
|
||||
self.set_p_str()
|
||||
return string(self.p_str)
|
||||
|
||||
def set_p_str(self, width=None):
|
||||
self.p_str, self.p_str_nocolor = (
|
||||
self.powerline.render(output_raw=True,
|
||||
segment_info=self.powerline_segment_info,
|
||||
matcher_info=self.powerline_prompt_type,
|
||||
width=width)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def set_colors():
|
||||
pass
|
||||
|
||||
|
||||
class PowerlinePrompt1(PowerlinePrompt):
|
||||
powerline_prompt_type = 'in'
|
||||
rspace = re.compile(r'(\s*)$')
|
||||
|
||||
def __str__(self):
|
||||
self.cache.prompt_count += 1
|
||||
self.set_p_str()
|
||||
self.cache.last_prompt = self.p_str_nocolor.split('\n')[-1]
|
||||
return string(self.p_str)
|
||||
|
||||
def set_p_str(self):
|
||||
super(PowerlinePrompt1, self).set_p_str()
|
||||
self.nrspaces = len(self.rspace.search(self.p_str_nocolor).group())
|
||||
self.prompt_text_len = len(self.p_str_nocolor) - self.nrspaces
|
||||
self.powerline_last_in['nrspaces'] = self.nrspaces
|
||||
self.powerline_last_in['prompt_text_len'] = self.prompt_text_len
|
||||
|
||||
def auto_rewrite(self):
|
||||
return RewriteResult(self.powerline.render(matcher_info='rewrite', width=self.prompt_text_len, segment_info=self.powerline_segment_info)
|
||||
+ (' ' * self.nrspaces))
|
||||
|
||||
|
||||
class PowerlinePromptOut(PowerlinePrompt):
|
||||
powerline_prompt_type = 'out'
|
||||
|
||||
def set_p_str(self):
|
||||
super(PowerlinePromptOut, self).set_p_str(width=self.powerline_last_in['prompt_text_len'])
|
||||
spaces = ' ' * self.powerline_last_in['nrspaces']
|
||||
self.p_str += spaces
|
||||
self.p_str_nocolor += spaces
|
||||
|
||||
|
||||
class PowerlinePrompt2(PowerlinePromptOut):
|
||||
powerline_prompt_type = 'in2'
|
||||
|
||||
|
||||
class ConfigurableIpythonPowerline(IpythonPowerline):
|
||||
def __init__(self, config_overrides=None, theme_overrides={}, path=None):
|
||||
self.config_overrides = config_overrides
|
||||
self.theme_overrides = theme_overrides
|
||||
self.path = path
|
||||
super(ConfigurableIpythonPowerline, self).__init__()
|
||||
|
||||
|
||||
def setup(**kwargs):
|
||||
ip = get_ipython()
|
||||
|
||||
powerline = ConfigurableIpythonPowerline(**kwargs)
|
||||
|
||||
def late_startup_hook():
|
||||
last_in = {'nrspaces': 0, 'prompt_text_len': None}
|
||||
for attr, prompt_class in (
|
||||
('prompt1', PowerlinePrompt1),
|
||||
('prompt2', PowerlinePrompt2),
|
||||
('prompt_out', PowerlinePromptOut)
|
||||
):
|
||||
old_prompt = getattr(ip.IP.outputcache, attr)
|
||||
setattr(ip.IP.outputcache, attr, prompt_class(powerline, last_in, old_prompt))
|
||||
raise TryNext()
|
||||
|
||||
def shutdown_hook():
|
||||
powerline.shutdown()
|
||||
raise TryNext()
|
||||
|
||||
ip.IP.hooks.late_startup_hook.add(late_startup_hook)
|
||||
ip.IP.hooks.shutdown_hook.add(shutdown_hook)
|
|
@ -0,0 +1,36 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from libqtile import bar
|
||||
from libqtile.widget import base
|
||||
|
||||
from powerline import Powerline as PowerlineCore
|
||||
|
||||
|
||||
class Powerline(base._TextBox):
|
||||
def __init__(self, timeout=2, text=" ", width=bar.CALCULATED, **config):
|
||||
base._TextBox.__init__(self, text, width, **config)
|
||||
self.timeout_add(timeout, self.update)
|
||||
self.powerline = PowerlineCore(ext='wm', renderer_module='pango_markup')
|
||||
|
||||
def update(self):
|
||||
if not self.configured:
|
||||
return True
|
||||
self.text = self.powerline.render(side='right')
|
||||
self.bar.draw()
|
||||
return True
|
||||
|
||||
def cmd_update(self, text):
|
||||
self.update(text)
|
||||
|
||||
def cmd_get(self):
|
||||
return self.text
|
||||
|
||||
def _configure(self, qtile, bar):
|
||||
base._TextBox._configure(self, qtile, bar)
|
||||
self.layout = self.drawer.textlayout(
|
||||
self.text,
|
||||
self.foreground,
|
||||
self.font,
|
||||
self.fontsize,
|
||||
self.fontshadow,
|
||||
markup=True)
|
|
@ -0,0 +1,11 @@
|
|||
set -g status on
|
||||
set -g status-utf8 on
|
||||
set -g status-interval 2
|
||||
set -g status-fg colour231
|
||||
set -g status-bg colour234
|
||||
set -g status-left-length 20
|
||||
set -g status-left '#[fg=colour16,bg=colour254,bold] #S #[fg=colour254,bg=colour234,nobold]#(powerline tmux left)'
|
||||
set -g status-right '#(powerline tmux right)'
|
||||
set -g status-right-length 150
|
||||
set -g window-status-format "#[fg=colour244,bg=colour234]#I #[fg=colour240] #[fg=colour249]#W "
|
||||
set -g window-status-current-format "#[fg=colour234,bg=colour31]#[fg=colour117,bg=colour31] #I #[fg=colour231,bold]#W #[fg=colour31,bg=colour234,nobold]"
|
|
@ -0,0 +1,64 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
import sys
|
||||
|
||||
try:
|
||||
import vim
|
||||
except ImportError:
|
||||
vim = {}
|
||||
|
||||
try:
|
||||
_vim_globals = vim.bindeval('g:')
|
||||
|
||||
def vim_set_global_var(var, val):
|
||||
'''Set a global var in vim using bindeval().'''
|
||||
_vim_globals[var] = val
|
||||
|
||||
def vim_get_func(f, rettype=None):
|
||||
'''Return a vim function binding.'''
|
||||
try:
|
||||
func = vim.bindeval('function("' + f + '")')
|
||||
if sys.version_info >= (3,) and rettype is str:
|
||||
return (lambda *args, **kwargs: func(*args, **kwargs).decode('utf-8', errors='replace'))
|
||||
return func
|
||||
except vim.error:
|
||||
return None
|
||||
except AttributeError:
|
||||
import json
|
||||
|
||||
def vim_set_global_var(var, val): # NOQA
|
||||
'''Set a global var in vim using vim.command().
|
||||
|
||||
This is a fallback function for older vim versions.
|
||||
'''
|
||||
vim.command('let g:{0}={1}'.format(var, json.dumps(val)))
|
||||
|
||||
class VimFunc(object):
|
||||
'''Evaluate a vim function using vim.eval().
|
||||
|
||||
This is a fallback class for older vim versions.
|
||||
'''
|
||||
__slots__ = ('f', 'rettype')
|
||||
|
||||
def __init__(self, f, rettype=None):
|
||||
self.f = f
|
||||
self.rettype = rettype
|
||||
|
||||
def __call__(self, *args):
|
||||
r = vim.eval(self.f + '(' + json.dumps(args)[1:-1] + ')')
|
||||
if self.rettype:
|
||||
return self.rettype(r)
|
||||
return r
|
||||
|
||||
vim_get_func = VimFunc
|
||||
|
||||
if sys.version_info < (3,) or not hasattr(vim, 'bindeval'):
|
||||
getbufvar = vim_get_func('getbufvar')
|
||||
else:
|
||||
_getbufvar = vim_get_func('getbufvar')
|
||||
|
||||
def getbufvar(*args):
|
||||
r = _getbufvar(*args)
|
||||
if type(r) is bytes:
|
||||
return r.decode('utf-8')
|
||||
return r
|
|
@ -0,0 +1,95 @@
|
|||
if exists('g:powerline_loaded')
|
||||
finish
|
||||
endif
|
||||
let g:powerline_loaded = 1
|
||||
|
||||
function! s:CriticalError(message)
|
||||
echohl ErrorMsg
|
||||
echomsg a:message
|
||||
echohl None
|
||||
endfunction
|
||||
|
||||
if ! has('python') && ! has('python3')
|
||||
call s:CriticalError('You need vim compiled with Python 2.6+ or 3.2+ support
|
||||
\ for Powerline to work. Please consult the documentation for more details.')
|
||||
finish
|
||||
endif
|
||||
|
||||
let s:powerline_pycmd = substitute(get(g:, 'powerline_pycmd', has('python') ? 'py' : 'py3'),
|
||||
\'\v^(py)%[thon](3?)$', '\1\2', '')
|
||||
let s:powerline_pyeval = get(g:, 'powerline_pyeval', s:powerline_pycmd.'eval')
|
||||
|
||||
let s:import_cmd = 'from powerline.vim import VimPowerline'
|
||||
try
|
||||
exec s:powerline_pycmd "try:\n"
|
||||
\ ." ".s:import_cmd."\n"
|
||||
\ ."except ImportError:\n"
|
||||
\ ." import sys, vim\n"
|
||||
\ ." sys.path.append(vim.eval('expand(\"<sfile>:h:h:h:h:h\")'))\n"
|
||||
\ ." ".s:import_cmd
|
||||
let s:launched = 1
|
||||
finally
|
||||
if !exists('s:launched')
|
||||
call s:CriticalError('An error occurred while importing the Powerline package.
|
||||
\ This could be caused by an invalid sys.path setting, or by an incompatible
|
||||
\ Python version (Powerline requires Python 2.6+ or 3.2+ to work). Please consult
|
||||
\ the troubleshooting section in the documentation for possible solutions.')
|
||||
finish
|
||||
else
|
||||
unlet s:launched
|
||||
endif
|
||||
endtry
|
||||
|
||||
if !get(g:, 'powerline_debugging_pyeval') && exists('*'. s:powerline_pyeval)
|
||||
let s:pyeval = function(s:powerline_pyeval)
|
||||
else
|
||||
exec s:powerline_pycmd 'import json, vim'
|
||||
exec "function! s:pyeval(e)\n".
|
||||
\ s:powerline_pycmd." vim.command('return ' + json.dumps(eval(vim.eval('a:e'))))\n".
|
||||
\"endfunction"
|
||||
endif
|
||||
|
||||
let s:last_window_id = 0
|
||||
function! s:GetWinID(winnr)
|
||||
let r = getwinvar(a:winnr, 'window_id')
|
||||
if empty(r)
|
||||
let r = s:last_window_id
|
||||
let s:last_window_id += 1
|
||||
call setwinvar(a:winnr, 'window_id', r)
|
||||
endif
|
||||
" Without this condition it triggers unneeded statusline redraw
|
||||
if getwinvar(a:winnr, '&statusline') isnot# '%!Powerline('.r.')'
|
||||
call setwinvar(a:winnr, '&statusline', '%!Powerline('.r.')')
|
||||
endif
|
||||
return r
|
||||
endfunction
|
||||
|
||||
function! Powerline(window_id)
|
||||
let winidx = index(map(range(1, winnr('$')), 's:GetWinID(v:val)'), a:window_id)
|
||||
let current = w:window_id is# a:window_id
|
||||
return s:pyeval('powerline.render('. a:window_id .', '. winidx .', '. current .')')
|
||||
endfunction
|
||||
|
||||
function! PowerlineNew()
|
||||
call map(range(1, winnr('$')), 's:GetWinID(v:val)')
|
||||
endfunction
|
||||
|
||||
function! PowerlineRegisterCachePurgerEvent(event)
|
||||
exec s:powerline_pycmd 'from powerline.segments.vim import launchevent as powerline_launchevent'
|
||||
augroup Powerline
|
||||
exec 'autocmd' a:event '*' s:powerline_pycmd.' powerline_launchevent("'.a:event.'")'
|
||||
augroup END
|
||||
endfunction
|
||||
|
||||
augroup Powerline
|
||||
autocmd! ColorScheme * :exec s:powerline_pycmd 'powerline.reset_highlight()'
|
||||
autocmd! VimEnter * :redrawstatus!
|
||||
autocmd! VimLeavePre * :exec s:powerline_pycmd 'powerline.shutdown()'
|
||||
augroup END
|
||||
|
||||
exec s:powerline_pycmd 'powerline = VimPowerline()'
|
||||
exec s:powerline_pycmd 'del VimPowerline'
|
||||
" Is immediately changed when PowerlineNew() function is run. Good for global
|
||||
" value.
|
||||
set statusline=%!PowerlineNew()
|
||||
call PowerlineNew()
|
|
@ -0,0 +1,128 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
import zsh
|
||||
import atexit
|
||||
from powerline.shell import ShellPowerline
|
||||
from powerline.lib import parsedotval
|
||||
|
||||
|
||||
used_powerlines = []
|
||||
|
||||
|
||||
def shutdown():
|
||||
for powerline in used_powerlines:
|
||||
powerline.shutdown()
|
||||
|
||||
|
||||
def get_var_config(var):
|
||||
try:
|
||||
return [parsedotval(i) for i in zsh.getvalue(var).items()]
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
class Args(object):
|
||||
ext = ['shell']
|
||||
renderer_module = 'zsh_prompt'
|
||||
|
||||
@property
|
||||
def last_exit_code(self):
|
||||
return zsh.last_exit_code()
|
||||
|
||||
@property
|
||||
def last_pipe_status(self):
|
||||
return zsh.pipestatus()
|
||||
|
||||
@property
|
||||
def config(self):
|
||||
try:
|
||||
return get_var_config('POWERLINE_CONFIG')
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
@property
|
||||
def theme_option(self):
|
||||
try:
|
||||
return get_var_config('POWERLINE_THEME_CONFIG')
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
@property
|
||||
def config_path(self):
|
||||
try:
|
||||
return zsh.getvalue('POWERLINE_CONFIG_PATH')
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
|
||||
def string(s):
|
||||
if type(s) is bytes:
|
||||
return s.decode('utf-8', errors='replace')
|
||||
else:
|
||||
return str(s)
|
||||
|
||||
|
||||
class Environment(object):
|
||||
@staticmethod
|
||||
def __getitem__(key):
|
||||
try:
|
||||
return string(zsh.getvalue(key))
|
||||
except IndexError as e:
|
||||
raise KeyError(*e.args)
|
||||
|
||||
@staticmethod
|
||||
def get(key, default=None):
|
||||
try:
|
||||
return string(zsh.getvalue(key))
|
||||
except IndexError:
|
||||
return default
|
||||
|
||||
|
||||
environ = Environment()
|
||||
|
||||
|
||||
class Prompt(object):
|
||||
__slots__ = ('powerline', 'side', 'savedpsvar', 'savedps', 'args')
|
||||
|
||||
def __init__(self, powerline, side, savedpsvar=None, savedps=None):
|
||||
self.powerline = powerline
|
||||
self.side = side
|
||||
self.savedpsvar = savedpsvar
|
||||
self.savedps = savedps
|
||||
self.args = powerline.args
|
||||
|
||||
def __str__(self):
|
||||
r = self.powerline.render(
|
||||
width=zsh.columns(),
|
||||
side=self.side,
|
||||
segment_info={'args': self.args, 'environ': environ}
|
||||
)
|
||||
if type(r) is not str:
|
||||
if type(r) is bytes:
|
||||
return r.decode('utf-8')
|
||||
else:
|
||||
return r.encode('utf-8')
|
||||
return r
|
||||
|
||||
def __del__(self):
|
||||
if self.savedps:
|
||||
zsh.setvalue(self.savedpsvar, self.savedps)
|
||||
used_powerlines.remove(self.powerline)
|
||||
if self.powerline not in used_powerlines:
|
||||
self.powerline.shutdown()
|
||||
|
||||
|
||||
def set_prompt(powerline, psvar, side):
|
||||
savedps = zsh.getvalue(psvar)
|
||||
zpyvar = 'ZPYTHON_POWERLINE_' + psvar
|
||||
prompt = Prompt(powerline, side, psvar, savedps)
|
||||
zsh.set_special_string(zpyvar, prompt)
|
||||
zsh.setvalue(psvar, '${' + zpyvar + '}')
|
||||
|
||||
|
||||
def setup():
|
||||
powerline = ShellPowerline(Args())
|
||||
used_powerlines.append(powerline)
|
||||
used_powerlines.append(powerline)
|
||||
set_prompt(powerline, 'PS1', 'left')
|
||||
set_prompt(powerline, 'RPS1', 'right')
|
||||
atexit.register(shutdown)
|
|
@ -0,0 +1,39 @@
|
|||
_powerline_tmux_setenv() {
|
||||
emulate -L zsh
|
||||
if [[ -n "$TMUX" ]]; then
|
||||
tmux setenv TMUX_"$1"_$(tmux display -p "#D" | tr -d %) "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
_powerline_tmux_set_pwd() {
|
||||
_powerline_tmux_setenv PWD "$PWD"
|
||||
}
|
||||
|
||||
_powerline_tmux_set_columns() {
|
||||
_powerline_tmux_setenv COLUMNS "$COLUMNS"
|
||||
}
|
||||
|
||||
_powerline_install_precmd() {
|
||||
emulate zsh
|
||||
for f in "${precmd_functions[@]}"; do
|
||||
if [[ "$f" = "_powerline_precmd" ]]; then
|
||||
return
|
||||
fi
|
||||
done
|
||||
chpwd_functions+=( _powerline_tmux_set_pwd )
|
||||
setopt promptpercent
|
||||
setopt promptsubst
|
||||
if zmodload zsh/zpython &>/dev/null ; then
|
||||
zpython 'from powerline.bindings.zsh import setup as powerline_setup'
|
||||
zpython 'powerline_setup()'
|
||||
zpython 'del powerline_setup'
|
||||
else
|
||||
PS1='$(powerline shell left -r zsh_prompt --last_exit_code=$? --last_pipe_status="$pipestatus")'
|
||||
RPS1='$(powerline shell right -r zsh_prompt --last_exit_code=$? --last_pipe_status="$pipestatus")'
|
||||
fi
|
||||
}
|
||||
|
||||
trap "_powerline_tmux_set_columns" SIGWINCH
|
||||
_powerline_tmux_set_columns
|
||||
|
||||
_powerline_install_precmd
|
|
@ -0,0 +1,143 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from copy import copy
|
||||
|
||||
|
||||
DEFAULT_MODE_KEY = None
|
||||
ATTR_BOLD = 1
|
||||
ATTR_ITALIC = 2
|
||||
ATTR_UNDERLINE = 4
|
||||
|
||||
|
||||
def get_attr_flag(attributes):
|
||||
'''Convert an attribute array to a renderer flag.'''
|
||||
attr_flag = 0
|
||||
if 'bold' in attributes:
|
||||
attr_flag |= ATTR_BOLD
|
||||
if 'italic' in attributes:
|
||||
attr_flag |= ATTR_ITALIC
|
||||
if 'underline' in attributes:
|
||||
attr_flag |= ATTR_UNDERLINE
|
||||
return attr_flag
|
||||
|
||||
|
||||
def pick_gradient_value(grad_list, gradient_level):
|
||||
'''Given a list of colors and gradient percent, return a color that should be used.
|
||||
|
||||
Note: gradient level is not checked for being inside [0, 100] interval.
|
||||
'''
|
||||
return grad_list[int(round(gradient_level * (len(grad_list) - 1) / 100))]
|
||||
|
||||
|
||||
def hl_iter(value):
|
||||
if type(value) is list:
|
||||
for v in value:
|
||||
yield v
|
||||
else:
|
||||
yield value
|
||||
|
||||
|
||||
class Colorscheme(object):
|
||||
def __init__(self, colorscheme_config, colors_config):
|
||||
'''Initialize a colorscheme.'''
|
||||
self.colors = {}
|
||||
self.gradients = {}
|
||||
|
||||
self.groups = colorscheme_config['groups']
|
||||
self.translations = colorscheme_config.get('mode_translations', {})
|
||||
|
||||
# Create a dict of color tuples with both a cterm and hex value
|
||||
for color_name, color in colors_config['colors'].items():
|
||||
try:
|
||||
self.colors[color_name] = (color[0], int(color[1], 16))
|
||||
except TypeError:
|
||||
self.colors[color_name] = (color, cterm_to_hex[color])
|
||||
|
||||
# Create a dict of gradient names with two lists: for cterm and hex
|
||||
# values. Two lists in place of one list of pairs were chosen because
|
||||
# true colors allow more precise gradients.
|
||||
for gradient_name, gradient in colors_config['gradients'].items():
|
||||
if len(gradient) == 2:
|
||||
self.gradients[gradient_name] = (
|
||||
(gradient[0], [int(color, 16) for color in gradient[1]]))
|
||||
else:
|
||||
self.gradients[gradient_name] = (
|
||||
(gradient[0], [cterm_to_hex[color] for color in gradient[0]]))
|
||||
|
||||
def get_gradient(self, gradient, gradient_level):
|
||||
if gradient in self.gradients:
|
||||
return tuple((pick_gradient_value(grad_list, gradient_level) for grad_list in self.gradients[gradient]))
|
||||
else:
|
||||
return self.colors[gradient]
|
||||
|
||||
def get_highlighting(self, groups, mode, gradient_level=None):
|
||||
trans = self.translations.get(mode, {})
|
||||
for group in hl_iter(groups):
|
||||
if 'groups' in trans and group in trans['groups']:
|
||||
try:
|
||||
group_props = trans['groups'][group]
|
||||
except KeyError:
|
||||
continue
|
||||
break
|
||||
|
||||
else:
|
||||
try:
|
||||
group_props = copy(self.groups[group])
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
try:
|
||||
ctrans = trans['colors']
|
||||
for key in ('fg', 'bg'):
|
||||
try:
|
||||
group_props[key] = ctrans[group_props[key]]
|
||||
except KeyError:
|
||||
pass
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
break
|
||||
else:
|
||||
raise KeyError('Highlighting groups not found in colorscheme: ' + ', '.join(hl_iter(groups)))
|
||||
|
||||
if gradient_level is None:
|
||||
pick_color = self.colors.__getitem__
|
||||
else:
|
||||
pick_color = lambda gradient: self.get_gradient(gradient, gradient_level)
|
||||
|
||||
return {
|
||||
'fg': pick_color(group_props['fg']),
|
||||
'bg': pick_color(group_props['bg']),
|
||||
'attr': get_attr_flag(group_props.get('attr', [])),
|
||||
}
|
||||
|
||||
|
||||
# 0 1 2 3 4 5 6 7 8 9
|
||||
cterm_to_hex = (
|
||||
0x000000, 0xc00000, 0x008000, 0x804000, 0x0000c0, 0xc000c0, 0x008080, 0xc0c0c0, 0x808080, 0xff6060, # 0
|
||||
0x00ff00, 0xffff00, 0x8080ff, 0xff40ff, 0x00ffff, 0xffffff, 0x000000, 0x00005f, 0x000087, 0x0000af, # 1
|
||||
0x0000d7, 0x0000ff, 0x005f00, 0x005f5f, 0x005f87, 0x005faf, 0x005fd7, 0x005fff, 0x008700, 0x00875f, # 2
|
||||
0x008787, 0x0087af, 0x0087d7, 0x0087ff, 0x00af00, 0x00af5f, 0x00af87, 0x00afaf, 0x00afd7, 0x00afff, # 3
|
||||
0x00d700, 0x00d75f, 0x00d787, 0x00d7af, 0x00d7d7, 0x00d7ff, 0x00ff00, 0x00ff5f, 0x00ff87, 0x00ffaf, # 4
|
||||
0x00ffd7, 0x00ffff, 0x5f0000, 0x5f005f, 0x5f0087, 0x5f00af, 0x5f00d7, 0x5f00ff, 0x5f5f00, 0x5f5f5f, # 5
|
||||
0x5f5f87, 0x5f5faf, 0x5f5fd7, 0x5f5fff, 0x5f8700, 0x5f875f, 0x5f8787, 0x5f87af, 0x5f87d7, 0x5f87ff, # 6
|
||||
0x5faf00, 0x5faf5f, 0x5faf87, 0x5fafaf, 0x5fafd7, 0x5fafff, 0x5fd700, 0x5fd75f, 0x5fd787, 0x5fd7af, # 7
|
||||
0x5fd7d7, 0x5fd7ff, 0x5fff00, 0x5fff5f, 0x5fff87, 0x5fffaf, 0x5fffd7, 0x5fffff, 0x870000, 0x87005f, # 8
|
||||
0x870087, 0x8700af, 0x8700d7, 0x8700ff, 0x875f00, 0x875f5f, 0x875f87, 0x875faf, 0x875fd7, 0x875fff, # 9
|
||||
0x878700, 0x87875f, 0x878787, 0x8787af, 0x8787d7, 0x8787ff, 0x87af00, 0x87af5f, 0x87af87, 0x87afaf, # 10
|
||||
0x87afd7, 0x87afff, 0x87d700, 0x87d75f, 0x87d787, 0x87d7af, 0x87d7d7, 0x87d7ff, 0x87ff00, 0x87ff5f, # 11
|
||||
0x87ff87, 0x87ffaf, 0x87ffd7, 0x87ffff, 0xaf0000, 0xaf005f, 0xaf0087, 0xaf00af, 0xaf00d7, 0xaf00ff, # 12
|
||||
0xaf5f00, 0xaf5f5f, 0xaf5f87, 0xaf5faf, 0xaf5fd7, 0xaf5fff, 0xaf8700, 0xaf875f, 0xaf8787, 0xaf87af, # 13
|
||||
0xaf87d7, 0xaf87ff, 0xafaf00, 0xafaf5f, 0xafaf87, 0xafafaf, 0xafafd7, 0xafafff, 0xafd700, 0xafd75f, # 14
|
||||
0xafd787, 0xafd7af, 0xafd7d7, 0xafd7ff, 0xafff00, 0xafff5f, 0xafff87, 0xafffaf, 0xafffd7, 0xafffff, # 15
|
||||
0xd70000, 0xd7005f, 0xd70087, 0xd700af, 0xd700d7, 0xd700ff, 0xd75f00, 0xd75f5f, 0xd75f87, 0xd75faf, # 16
|
||||
0xd75fd7, 0xd75fff, 0xd78700, 0xd7875f, 0xd78787, 0xd787af, 0xd787d7, 0xd787ff, 0xd7af00, 0xd7af5f, # 17
|
||||
0xd7af87, 0xd7afaf, 0xd7afd7, 0xd7afff, 0xd7d700, 0xd7d75f, 0xd7d787, 0xd7d7af, 0xd7d7d7, 0xd7d7ff, # 18
|
||||
0xd7ff00, 0xd7ff5f, 0xd7ff87, 0xd7ffaf, 0xd7ffd7, 0xd7ffff, 0xff0000, 0xff005f, 0xff0087, 0xff00af, # 19
|
||||
0xff00d7, 0xff00ff, 0xff5f00, 0xff5f5f, 0xff5f87, 0xff5faf, 0xff5fd7, 0xff5fff, 0xff8700, 0xff875f, # 20
|
||||
0xff8787, 0xff87af, 0xff87d7, 0xff87ff, 0xffaf00, 0xffaf5f, 0xffaf87, 0xffafaf, 0xffafd7, 0xffafff, # 21
|
||||
0xffd700, 0xffd75f, 0xffd787, 0xffd7af, 0xffd7d7, 0xffd7ff, 0xffff00, 0xffff5f, 0xffff87, 0xffffaf, # 22
|
||||
0xffffd7, 0xffffff, 0x080808, 0x121212, 0x1c1c1c, 0x262626, 0x303030, 0x3a3a3a, 0x444444, 0x4e4e4e, # 23
|
||||
0x585858, 0x626262, 0x6c6c6c, 0x767676, 0x808080, 0x8a8a8a, 0x949494, 0x9e9e9e, 0xa8a8a8, 0xb2b2b2, # 24
|
||||
0xbcbcbc, 0xc6c6c6, 0xd0d0d0, 0xdadada, 0xe4e4e4, 0xeeeeee # 25
|
||||
)
|
|
@ -0,0 +1,106 @@
|
|||
{
|
||||
"colors": {
|
||||
"black": 16,
|
||||
"white": 231,
|
||||
|
||||
"darkestgreen": 22,
|
||||
"darkgreen": 28,
|
||||
"mediumgreen": 70,
|
||||
"brightgreen": 148,
|
||||
|
||||
"darkestcyan": 23,
|
||||
"darkcyan": 74,
|
||||
"mediumcyan": 117,
|
||||
"brightcyan": 159,
|
||||
|
||||
"darkestblue": 24,
|
||||
"darkblue": 31,
|
||||
|
||||
"darkestred": 52,
|
||||
"darkred": 88,
|
||||
"mediumred": 124,
|
||||
"brightred": 160,
|
||||
"brightestred": 196,
|
||||
|
||||
"darkestpurple": 55,
|
||||
"mediumpurple": 98,
|
||||
"brightpurple": 189,
|
||||
|
||||
"darkorange": 94,
|
||||
"mediumorange": 166,
|
||||
"brightorange": 208,
|
||||
"brightestorange": 214,
|
||||
|
||||
"brightyellow": 220,
|
||||
|
||||
"gray0": 233,
|
||||
"gray1": 235,
|
||||
"gray2": 236,
|
||||
"gray3": 239,
|
||||
"gray4": 240,
|
||||
"gray5": 241,
|
||||
"gray6": 244,
|
||||
"gray7": 245,
|
||||
"gray8": 247,
|
||||
"gray9": 250,
|
||||
"gray10": 252,
|
||||
|
||||
"gray61": [14, "93a1a1"],
|
||||
"gray13": [8, "002b36"],
|
||||
|
||||
"royalblue5": [0, "073642"],
|
||||
"darkgreencopper": [10, "586e75"],
|
||||
"lightskyblue4": [11, "657b83"],
|
||||
"azure4": [12, "839496"],
|
||||
"lightyellow": [7, "eee8d5"],
|
||||
"oldlace": [15, "fdf6e3"],
|
||||
|
||||
"green": [2, "719e07"],
|
||||
"cyan": [6, "2aa198"],
|
||||
"blue": [4, "268bd2"],
|
||||
"red": [1, "dc322f"],
|
||||
"magenta": [5, "d33682"],
|
||||
"violet": [13, "6c71c4"],
|
||||
"orange": [9, "cb4b16"],
|
||||
"yellow": [3, "b58900"],
|
||||
|
||||
"lightyellowgreen": 106,
|
||||
"gold3": 178,
|
||||
"orangered": 202,
|
||||
|
||||
"steelblue": 67,
|
||||
"darkorange3": 166,
|
||||
"skyblue1": 117,
|
||||
"khaki1": 228
|
||||
},
|
||||
"gradients": {
|
||||
"dark_GREEN_Orange_red": [
|
||||
[22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 94, 94, 94, 94, 94, 94, 94, 52],
|
||||
["005f00", "015f00", "025f00", "035f00", "045f00", "055f00", "065f00", "075f00", "085f00", "095f00", "0b5f00", "0c5f00", "0d5f00", "0e5f00", "0f5f00", "105f00", "115f00", "125f00", "135f00", "145f00", "165f00", "175f00", "185f00", "195f00", "1a5f00", "1b5f00", "1c5f00", "1d5f00", "1e5f00", "1f5f00", "215f00", "225f00", "235f00", "245f00", "255f00", "265f00", "275f00", "285f00", "295f00", "2a5f00", "2c5f00", "2d5f00", "2e5f00", "2f5f00", "305f00", "315f00", "325f00", "335f00", "345f00", "355f00", "375f00", "385f00", "395f00", "3a5f00", "3b5f00", "3c5f00", "3d5f00", "3e5f00", "3f5f00", "415f00", "425f00", "435f00", "445f00", "455f00", "465f00", "475f00", "485f00", "495f00", "4a5f00", "4c5f00", "4d5f00", "4e5f00", "4f5f00", "505f00", "515f00", "525f00", "535f00", "545f00", "555f00", "575f00", "585f00", "595f00", "5a5f00", "5b5f00", "5c5f00", "5d5f00", "5e5f00", "615f00", "655f00", "685f00", "6c5f00", "6f5f00", "735f00", "765f00", "7a5f00", "7d5f00", "815f00", "845f00", "815200", "702900"]
|
||||
],
|
||||
"GREEN_Orange_red": [
|
||||
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1],
|
||||
["005f00", "015f00", "025f00", "035f00", "045f00", "055f00", "065f00", "075f00", "085f00", "095f00", "0b5f00", "0c5f00", "0d5f00", "0e5f00", "0f5f00", "105f00", "115f00", "125f00", "135f00", "145f00", "165f00", "175f00", "185f00", "195f00", "1a5f00", "1b5f00", "1c5f00", "1d5f00", "1e5f00", "1f5f00", "215f00", "225f00", "235f00", "245f00", "255f00", "265f00", "275f00", "285f00", "295f00", "2a5f00", "2c5f00", "2d5f00", "2e5f00", "2f5f00", "305f00", "315f00", "325f00", "335f00", "345f00", "355f00", "375f00", "385f00", "395f00", "3a5f00", "3b5f00", "3c5f00", "3d5f00", "3e5f00", "3f5f00", "415f00", "425f00", "435f00", "445f00", "455f00", "465f00", "475f00", "485f00", "495f00", "4a5f00", "4c5f00", "4d5f00", "4e5f00", "4f5f00", "505f00", "515f00", "525f00", "535f00", "545f00", "555f00", "575f00", "585f00", "595f00", "5a5f00", "5b5f00", "5c5f00", "5d5f00", "5e5f00", "615f00", "655f00", "685f00", "6c5f00", "6f5f00", "735f00", "765f00", "7a5f00", "7d5f00", "815f00", "845f00", "815200", "702900"]
|
||||
],
|
||||
"green_yellow_red": [
|
||||
[190, 184, 178, 172, 166, 160],
|
||||
["8ae71c", "8ce71c", "8fe71c", "92e71c", "95e71d", "98e71d", "9ae71d", "9de71d", "a0e71e", "a3e71e", "a6e71e", "a8e71e", "abe71f", "aee71f", "b1e71f", "b4e71f", "b6e720", "b9e720", "bce720", "bfe720", "c2e821", "c3e721", "c5e621", "c7e521", "c9e522", "cbe422", "cde322", "cfe222", "d1e223", "d3e123", "d5e023", "d7df23", "d9df24", "dbde24", "dddd24", "dfdc24", "e1dc25", "e3db25", "e5da25", "e7d925", "e9d926", "e9d626", "e9d426", "e9d126", "e9cf27", "e9cc27", "e9ca27", "e9c727", "e9c528", "e9c228", "e9c028", "e9bd28", "e9bb29", "e9b829", "e9b629", "e9b329", "e9b12a", "e9ae2a", "e9ac2a", "e9a92a", "eaa72b", "eaa42b", "eaa22b", "ea9f2b", "ea9d2c", "ea9b2c", "ea982c", "ea962c", "ea942d", "ea912d", "ea8f2d", "ea8d2d", "ea8a2e", "ea882e", "ea862e", "ea832e", "ea812f", "ea7f2f", "ea7c2f", "ea7a2f", "eb7830", "eb7530", "eb7330", "eb7130", "eb6f31", "eb6c31", "eb6a31", "eb6831", "eb6632", "eb6332", "eb6132", "eb5f32", "eb5d33", "eb5a33", "eb5833", "eb5633", "eb5434", "eb5134", "eb4f34", "eb4d34", "ec4b35"]
|
||||
],
|
||||
"green_yellow_orange_red": [
|
||||
[2, 3, 9, 1],
|
||||
["719e07", "739d06", "759c06", "779c06", "799b06", "7b9a05", "7d9a05", "7f9905", "819805", "839805", "859704", "879704", "899604", "8b9504", "8d9504", "8f9403", "919303", "949303", "969203", "989102", "9a9102", "9c9002", "9e9002", "a08f02", "a28e01", "a48e01", "a68d01", "a88c01", "aa8c01", "ac8b00", "ae8a00", "b08a00", "b28900", "b58900", "b58700", "b68501", "b78302", "b78102", "b87f03", "b97d04", "b97b04", "ba7905", "bb7806", "bb7606", "bc7407", "bd7208", "bd7008", "be6e09", "bf6c0a", "bf6a0a", "c0690b", "c1670c", "c1650c", "c2630d", "c3610e", "c35f0e", "c45d0f", "c55b10", "c55a10", "c65811", "c75612", "c75412", "c85213", "c95014", "c94e14", "ca4c15", "cb4b16", "cb4a16", "cc4917", "cc4818", "cd4719", "cd4719", "ce461a", "ce451b", "cf441c", "cf441c", "d0431d", "d0421e", "d1411f", "d1411f", "d24020", "d23f21", "d33e22", "d33e22", "d43d23", "d43c24", "d53b25", "d53b25", "d63a26", "d63927", "d73828", "d73828", "d83729", "d8362a", "d9352b", "d9352b", "da342c", "da332d", "db322e", "dc322f"]
|
||||
],
|
||||
"yellow_red": [
|
||||
[220, 178, 172, 166, 160],
|
||||
["ffd700", "fdd500", "fbd300", "fad200", "f8d000", "f7cf00", "f5cd00", "f3cb00", "f2ca00", "f0c800", "efc700", "edc500", "ebc300", "eac200", "e8c000", "e7bf00", "e5bd00", "e3bb00", "e2ba00", "e0b800", "dfb700", "ddb500", "dbb300", "dab200", "d8b000", "d7af00", "d7ad00", "d7ab00", "d7aa00", "d7a800", "d7a700", "d7a500", "d7a300", "d7a200", "d7a000", "d79f00", "d79d00", "d79b00", "d79a00", "d79800", "d79700", "d79500", "d79300", "d79200", "d79000", "d78f00", "d78d00", "d78b00", "d78a00", "d78800", "d78700", "d78500", "d78300", "d78200", "d78000", "d77f00", "d77d00", "d77b00", "d77a00", "d77800", "d77700", "d77500", "d77300", "d77200", "d77000", "d76f00", "d76d00", "d76b00", "d76a00", "d76800", "d76700", "d76500", "d76300", "d76200", "d76000", "d75f00", "d75b00", "d75700", "d75300", "d74f00", "d74c00", "d74800", "d74400", "d74000", "d73c00", "d73900", "d73500", "d73100", "d72d00", "d72900", "d72600", "d72200", "d71e00", "d71a00", "d71600", "d71300", "d70f00", "d70b00", "d70700"]
|
||||
],
|
||||
"yellow_orange_red": [
|
||||
[3, 9, 1],
|
||||
["b58900", "b58700", "b58600", "b68501", "b68401", "b78202", "b78102", "b88003", "b87f03", "b87d03", "b97c04", "b97b04", "ba7a05", "ba7805", "bb7706", "bb7606", "bc7507", "bc7307", "bc7207", "bd7108", "bd7008", "be6e09", "be6d09", "bf6c0a", "bf6b0a", "c06a0b", "c0680b", "c0670b", "c1660c", "c1650c", "c2630d", "c2620d", "c3610e", "c3600e", "c35e0e", "c45d0f", "c45c0f", "c55b10", "c55910", "c65811", "c65711", "c75612", "c75412", "c75312", "c85213", "c85113", "c94f14", "c94e14", "ca4d15", "ca4c15", "cb4b16", "cb4a16", "cb4a17", "cc4917", "cc4918", "cc4818", "cd4819", "cd4719", "cd471a", "ce461a", "ce461b", "ce451b", "cf451c", "cf441c", "cf441d", "d0431d", "d0431e", "d0421e", "d1421f", "d1411f", "d14120", "d24020", "d24021", "d23f21", "d33f22", "d33e22", "d33e23", "d43d23", "d43d24", "d43c24", "d53c25", "d53b25", "d53b26", "d63a26", "d63a27", "d63927", "d73928", "d73828", "d73829", "d83729", "d8372a", "d8362a", "d9362b", "d9352b", "d9352c", "da342c", "da342d", "da332d", "db332e"]
|
||||
],
|
||||
"blue_red": [
|
||||
[39, 74, 68, 67, 103, 97, 96, 132, 131, 167, 203, 197],
|
||||
["19b4fe", "1bb2fc", "1db1fa", "1faff8", "22aef6", "24adf4", "26abf2", "29aaf0", "2ba9ee", "2da7ec", "30a6ea", "32a5e8", "34a3e6", "36a2e4", "39a0e2", "3b9fe1", "3d9edf", "409cdd", "429bdb", "449ad9", "4798d7", "4997d5", "4b96d3", "4d94d1", "5093cf", "5292cd", "5490cb", "578fc9", "598dc7", "5b8cc6", "5e8bc4", "6089c2", "6288c0", "6487be", "6785bc", "6984ba", "6b83b8", "6e81b6", "7080b4", "727eb2", "757db0", "777cae", "797aac", "7b79ab", "7e78a9", "8076a7", "8275a5", "8574a3", "8772a1", "89719f", "8c709d", "8e6e9b", "906d99", "926b97", "956a95", "976993", "996791", "9c668f", "9e658e", "a0638c", "a3628a", "a56188", "a75f86", "a95e84", "ac5c82", "ae5b80", "b05a7e", "b3587c", "b5577a", "b75678", "ba5476", "bc5374", "be5273", "c05071", "c34f6f", "c54e6d", "c74c6b", "ca4b69", "cc4967", "ce4865", "d14763", "d34561", "d5445f", "d7435d", "da415b", "dc4059", "de3f58", "e13d56", "e33c54", "e53a52", "e83950", "ea384e", "ec364c", "ee354a", "f13448", "f33246", "f53144", "f83042", "fa2e40"]
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "Default color scheme for IPython prompt",
|
||||
"groups": {
|
||||
"virtualenv": { "fg": "white", "bg": "darkcyan" },
|
||||
"prompt": { "fg": "gray9", "bg": "gray4" },
|
||||
"prompt_count": { "fg": "white", "bg": "gray4" }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "Default color scheme for shell prompts",
|
||||
"groups": {
|
||||
"user": { "fg": "white", "bg": "darkblue", "attr": ["bold"] },
|
||||
"superuser": { "fg": "white", "bg": "brightred", "attr": ["bold"] },
|
||||
"virtualenv": { "fg": "white", "bg": "darkcyan" },
|
||||
"branch": { "fg": "gray9", "bg": "gray2" },
|
||||
"branch_dirty": { "fg": "brightyellow", "bg": "gray2" },
|
||||
"branch_clean": { "fg": "gray9", "bg": "gray2" },
|
||||
"cwd": { "fg": "gray9", "bg": "gray4" },
|
||||
"cwd:current_folder": { "fg": "gray10", "bg": "gray4", "attr": ["bold"] },
|
||||
"cwd:divider": { "fg": "gray7", "bg": "gray4" },
|
||||
"hostname": { "fg": "brightyellow", "bg": "mediumorange" },
|
||||
"exit_fail": { "fg": "white", "bg": "darkestred" },
|
||||
"exit_success": { "fg": "white", "bg": "darkestgreen" }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "Solarized Dark",
|
||||
"groups": {
|
||||
"user": { "fg": "oldlace", "bg": "blue", "attr": ["bold"] },
|
||||
"superuser": { "fg": "oldlace", "bg": "red", "attr": ["bold"] },
|
||||
"virtualenv": { "fg": "oldlace", "bg": "green" },
|
||||
"branch": { "fg": "gray61", "bg": "royalblue5" },
|
||||
"branch_dirty": { "fg": "yellow", "bg": "royalblue5" },
|
||||
"branch_clean": { "fg": "gray61", "bg": "royalblue5" },
|
||||
"cwd": { "fg": "lightyellow", "bg": "darkgreencopper" },
|
||||
"cwd:current_folder": { "fg": "oldlace", "bg": "darkgreencopper", "attr": ["bold"] },
|
||||
"cwd:divider": { "fg": "gray61", "bg": "darkgreencopper" },
|
||||
"hostname": { "fg": "oldlace", "bg": "darkgreencopper" },
|
||||
"exit_fail": { "fg": "oldlace", "bg": "red" },
|
||||
"exit_success": { "fg": "oldlace", "bg": "green" }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "Default color scheme for terminal prompts",
|
||||
"groups": {
|
||||
"background:divider": { "fg": "gray5", "bg": "gray0" },
|
||||
"session": { "fg": "black", "bg": "gray10", "attr": ["bold"] },
|
||||
"date": { "fg": "gray8", "bg": "gray2" },
|
||||
"time": { "fg": "gray10", "bg": "gray2", "attr": ["bold"] },
|
||||
"time:divider": { "fg": "gray5", "bg": "gray2" },
|
||||
"email_alert": { "fg": "white", "bg": "brightred", "attr": ["bold"] },
|
||||
"email_alert_gradient": { "fg": "white", "bg": "yellow_orange_red", "attr": ["bold"] },
|
||||
"hostname": { "fg": "black", "bg": "gray10", "attr": ["bold"] },
|
||||
"weather": { "fg": "gray8", "bg": "gray0" },
|
||||
"weather_temp_gradient": { "fg": "blue_red", "bg": "gray0" },
|
||||
"weather_condition_hot": { "fg": "khaki1", "bg": "gray0" },
|
||||
"weather_condition_snowy": { "fg": "skyblue1", "bg": "gray0" },
|
||||
"weather_condition_rainy": { "fg": "skyblue1", "bg": "gray0" },
|
||||
"uptime": { "fg": "gray8", "bg": "gray0" },
|
||||
"external_ip": { "fg": "gray8", "bg": "gray0" },
|
||||
"network_load": { "fg": "gray8", "bg": "gray0" },
|
||||
"network_load_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0" },
|
||||
"system_load": { "fg": "gray8", "bg": "gray0" },
|
||||
"system_load_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0" }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
{
|
||||
"name": "Default color scheme",
|
||||
"groups": {
|
||||
"background": { "fg": "white", "bg": "gray2" },
|
||||
"background:divider": { "fg": "gray6", "bg": "gray2" },
|
||||
"mode": { "fg": "darkestgreen", "bg": "brightgreen", "attr": ["bold"] },
|
||||
"modified_indicator": { "fg": "brightyellow", "bg": "gray4", "attr": ["bold"] },
|
||||
"paste_indicator": { "fg": "white", "bg": "mediumorange", "attr": ["bold"] },
|
||||
"readonly_indicator": { "fg": "brightestred", "bg": "gray4" },
|
||||
"branch": { "fg": "gray9", "bg": "gray4" },
|
||||
"branch_dirty": { "fg": "brightyellow", "bg": "gray4" },
|
||||
"branch_clean": { "fg": "gray9", "bg": "gray4" },
|
||||
"branch:divider": { "fg": "gray7", "bg": "gray4" },
|
||||
"file_directory": { "fg": "gray9", "bg": "gray4" },
|
||||
"file_name": { "fg": "white", "bg": "gray4", "attr": ["bold"] },
|
||||
"file_size": { "fg": "gray8", "bg": "gray2" },
|
||||
"file_name_no_file": { "fg": "gray9", "bg": "gray4", "attr": ["bold"] },
|
||||
"file_name_empty": { "fg": "gray9", "bg": "gray4" },
|
||||
"file_format": { "fg": "gray8", "bg": "gray2" },
|
||||
"file_encoding": { "fg": "gray8", "bg": "gray2" },
|
||||
"file_type": { "fg": "gray8", "bg": "gray2" },
|
||||
"file_vcs_status": { "fg": "brightestred", "bg": "gray4" },
|
||||
"file_vcs_status_M": { "fg": "brightyellow", "bg": "gray4" },
|
||||
"file_vcs_status_A": { "fg": "brightgreen", "bg": "gray4" },
|
||||
"line_percent": { "fg": "gray9", "bg": "gray4" },
|
||||
"line_percent_gradient": { "fg": "green_yellow_red", "bg": "gray4" },
|
||||
"line_current": { "fg": "gray1", "bg": "gray10", "attr": ["bold"] },
|
||||
"line_current_symbol": { "fg": "gray1", "bg": "gray10" },
|
||||
"virtcol_current_gradient": { "fg": "dark_GREEN_Orange_red", "bg": "gray10" },
|
||||
"col_current": { "fg": "gray6", "bg": "gray10" },
|
||||
"modified_buffers": { "fg": "brightyellow", "bg": "gray2" }
|
||||
},
|
||||
"mode_translations": {
|
||||
"nc": {
|
||||
"colors": {
|
||||
"brightyellow": "darkorange",
|
||||
"brightestred": "darkred",
|
||||
"gray0": "gray0",
|
||||
"gray1": "gray0",
|
||||
"gray2": "gray0",
|
||||
"gray3": "gray1",
|
||||
"gray4": "gray1",
|
||||
"gray5": "gray1",
|
||||
"gray6": "gray1",
|
||||
"gray7": "gray4",
|
||||
"gray8": "gray4",
|
||||
"gray9": "gray4",
|
||||
"gray10": "gray5",
|
||||
"white": "gray6",
|
||||
"green_yellow_red": "gray5"
|
||||
}
|
||||
},
|
||||
"i": {
|
||||
"colors": {
|
||||
"gray0": "darkestblue",
|
||||
"gray1": "darkestblue",
|
||||
"gray2": "darkestblue",
|
||||
"gray3": "darkblue",
|
||||
"gray4": "darkblue",
|
||||
"gray5": "darkestcyan",
|
||||
"gray6": "darkestcyan",
|
||||
"gray7": "darkestcyan",
|
||||
"gray8": "mediumcyan",
|
||||
"gray9": "mediumcyan",
|
||||
"gray10": "mediumcyan",
|
||||
"green_yellow_red": "gray5"
|
||||
},
|
||||
"groups": {
|
||||
"mode": { "fg": "darkestcyan", "bg": "white", "attr": ["bold"] },
|
||||
"background:divider": { "fg": "darkcyan", "bg": "darkestblue" },
|
||||
"branch:divider": { "fg": "darkcyan", "bg": "darkblue" }
|
||||
}
|
||||
},
|
||||
"v": {
|
||||
"groups": {
|
||||
"mode": { "fg": "darkorange", "bg": "brightestorange", "attr": ["bold"] }
|
||||
}
|
||||
},
|
||||
"V": {
|
||||
"groups": {
|
||||
"mode": { "fg": "darkorange", "bg": "brightestorange", "attr": ["bold"] }
|
||||
}
|
||||
},
|
||||
"^V": {
|
||||
"groups": {
|
||||
"mode": { "fg": "darkorange", "bg": "brightestorange", "attr": ["bold"] }
|
||||
}
|
||||
},
|
||||
"R": {
|
||||
"groups": {
|
||||
"mode": { "fg": "white", "bg": "brightred", "attr": ["bold"] }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
{
|
||||
"name": "Solarized Dark",
|
||||
"groups": {
|
||||
"background": { "fg": "oldlace", "bg": "royalblue5" },
|
||||
"background:divider": { "fg": "lightskyblue4", "bg": "royalblue5" },
|
||||
"mode": { "fg": "oldlace", "bg": "green", "attr": ["bold"] },
|
||||
"modified_indicator": { "fg": "yellow", "bg": "darkgreencopper", "attr": ["bold"] },
|
||||
"paste_indicator": { "fg": "oldlace", "bg": "orange", "attr": ["bold"] },
|
||||
"readonly_indicator": { "fg": "red", "bg": "darkgreencopper" },
|
||||
"branch": { "fg": "lightyellow", "bg": "darkgreencopper" },
|
||||
"branch_dirty": { "fg": "yellow", "bg": "darkgreencopper" },
|
||||
"branch_clean": { "fg": "lightyellow", "bg": "darkgreencopper" },
|
||||
"branch:divider": { "fg": "gray61", "bg": "darkgreencopper" },
|
||||
"file_directory": { "fg": "lightyellow", "bg": "darkgreencopper" },
|
||||
"file_name": { "fg": "oldlace", "bg": "darkgreencopper", "attr": ["bold"] },
|
||||
"file_size": { "fg": "oldlace", "bg": "darkgreencopper" },
|
||||
"file_name_no_file": { "fg": "oldlace", "bg": "darkgreencopper", "attr": ["bold"] },
|
||||
"file_name_empty": { "fg": "oldlace", "bg": "darkgreencopper" },
|
||||
"file_format": { "fg": "gray61", "bg": "royalblue5" },
|
||||
"file_encoding": { "fg": "gray61", "bg": "royalblue5" },
|
||||
"file_type": { "fg": "gray61", "bg": "royalblue5" },
|
||||
"file_vcs_status": { "fg": "red", "bg": "darkgreencopper" },
|
||||
"file_vcs_status_M": { "fg": "yellow", "bg": "darkgreencopper" },
|
||||
"file_vcs_status_A": { "fg": "green", "bg": "darkgreencopper" },
|
||||
"line_percent": { "fg": "oldlace", "bg": "lightskyblue4" },
|
||||
"line_percent_gradient": { "fg": "green_yellow_orange_red", "bg": "lightskyblue4" },
|
||||
"line_current": { "fg": "gray13", "bg": "lightyellow", "attr": ["bold"] },
|
||||
"line_current_symbol": { "fg": "gray13", "bg": "lightyellow" },
|
||||
"virtcol_current_gradient": { "fg": "GREEN_Orange_red", "bg": "gray10" },
|
||||
"col_current": { "fg": "azure4", "bg": "lightyellow" }
|
||||
},
|
||||
"mode_translations": {
|
||||
"nc": {
|
||||
"colors": {
|
||||
"darkgreencopper": "royalblue5",
|
||||
"lightskyblue4": "royalblue5",
|
||||
"azure4": "darkgreencopper",
|
||||
"gray61": "lightskyblue4",
|
||||
"lightyellow": "azure4",
|
||||
"oldlace": "gray61"
|
||||
}
|
||||
},
|
||||
"i": {
|
||||
"groups": {
|
||||
"background": { "fg": "oldlace", "bg": "darkgreencopper" },
|
||||
"background:divider": { "fg": "lightyellow", "bg": "darkgreencopper" },
|
||||
"mode": { "fg": "oldlace", "bg": "blue", "attr": ["bold"] },
|
||||
"modified_indicator": { "fg": "yellow", "bg": "lightyellow", "attr": ["bold"] },
|
||||
"paste_indicator": { "fg": "oldlace", "bg": "orange", "attr": ["bold"] },
|
||||
"readonly_indicator": { "fg": "red", "bg": "lightyellow" },
|
||||
"branch": { "fg": "darkgreencopper", "bg": "lightyellow" },
|
||||
"branch:divider": { "fg": "lightskyblue4", "bg": "lightyellow" },
|
||||
"file_directory": { "fg": "darkgreencopper", "bg": "lightyellow" },
|
||||
"file_name": { "fg": "royalblue5", "bg": "lightyellow", "attr": ["bold"] },
|
||||
"file_size": { "fg": "royalblue5", "bg": "lightyellow" },
|
||||
"file_name_no_file": { "fg": "royalblue5", "bg": "lightyellow", "attr": ["bold"] },
|
||||
"file_name_empty": { "fg": "royalblue5", "bg": "lightyellow" },
|
||||
"file_format": { "fg": "lightyellow", "bg": "darkgreencopper" },
|
||||
"file_encoding": { "fg": "lightyellow", "bg": "darkgreencopper" },
|
||||
"file_type": { "fg": "lightyellow", "bg": "darkgreencopper" },
|
||||
"file_vcs_status": { "fg": "red", "bg": "lightyellow" },
|
||||
"file_vcs_status_M": { "fg": "yellow", "bg": "lightyellow" },
|
||||
"file_vcs_status_A": { "fg": "green", "bg": "lightyellow" },
|
||||
"line_percent": { "fg": "oldlace", "bg": "gray61" },
|
||||
"line_percent_gradient": { "fg": "oldlace", "bg": "gray61" },
|
||||
"line_current": { "fg": "gray13", "bg": "oldlace", "attr": ["bold"] },
|
||||
"line_current_symbol": { "fg": "gray13", "bg": "oldlace" },
|
||||
"col_current": { "fg": "azure4", "bg": "oldlace" }
|
||||
}
|
||||
},
|
||||
"v": {
|
||||
"groups": {
|
||||
"mode": { "fg": "oldlace", "bg": "orange", "attr": ["bold"] }
|
||||
}
|
||||
},
|
||||
"V": {
|
||||
"groups": {
|
||||
"mode": { "fg": "oldlace", "bg": "orange", "attr": ["bold"] }
|
||||
}
|
||||
},
|
||||
"^V": {
|
||||
"groups": {
|
||||
"mode": { "fg": "oldlace", "bg": "orange", "attr": ["bold"] }
|
||||
}
|
||||
},
|
||||
"R": {
|
||||
"groups": {
|
||||
"mode": { "fg": "oldlace", "bg": "red", "attr": ["bold"] }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "Default color scheme for window managers",
|
||||
"groups": {
|
||||
"background:divider": { "fg": "gray5", "bg": "gray0" },
|
||||
"session": { "fg": "black", "bg": "gray10", "attr": ["bold"] },
|
||||
"date": { "fg": "gray8", "bg": "gray2" },
|
||||
"time": { "fg": "gray10", "bg": "gray2", "attr": ["bold"] },
|
||||
"time:divider": { "fg": "gray5", "bg": "gray2" },
|
||||
"email_alert": { "fg": "white", "bg": "brightred", "attr": ["bold"] },
|
||||
"email_alert_gradient": { "fg": "white", "bg": "yellow_orange_red", "attr": ["bold"] },
|
||||
"hostname": { "fg": "black", "bg": "gray10", "attr": ["bold"] },
|
||||
"weather": { "fg": "gray8", "bg": "gray0" },
|
||||
"weather_temp_gradient": { "fg": "blue_red", "bg": "gray0" },
|
||||
"weather_condition_hot": { "fg": "khaki1", "bg": "gray0" },
|
||||
"weather_condition_snowy": { "fg": "skyblue1", "bg": "gray0" },
|
||||
"weather_condition_rainy": { "fg": "skyblue1", "bg": "gray0" },
|
||||
"uptime": { "fg": "gray8", "bg": "gray0" },
|
||||
"external_ip": { "fg": "gray8", "bg": "gray0" },
|
||||
"network_load": { "fg": "gray8", "bg": "gray0" },
|
||||
"system_load": { "fg": "gray8", "bg": "gray0" },
|
||||
"system_load_good": { "fg": "lightyellowgreen", "bg": "gray0" },
|
||||
"system_load_bad": { "fg": "gold3", "bg": "gray0" },
|
||||
"system_load_ugly": { "fg": "orangered", "bg": "gray0" }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"common": {
|
||||
"term_truecolor": false,
|
||||
"dividers": {
|
||||
"left": {
|
||||
"hard": " ",
|
||||
"soft": " "
|
||||
},
|
||||
"right": {
|
||||
"hard": " ",
|
||||
"soft": " "
|
||||
}
|
||||
},
|
||||
"spaces": 1
|
||||
},
|
||||
"ext": {
|
||||
"ipython": {
|
||||
"colorscheme": "default",
|
||||
"theme": "in",
|
||||
"local_themes": {
|
||||
"rewrite": "rewrite",
|
||||
"out": "out",
|
||||
"in2": "in2"
|
||||
}
|
||||
},
|
||||
"shell": {
|
||||
"colorscheme": "default",
|
||||
"theme": "default"
|
||||
},
|
||||
"tmux": {
|
||||
"colorscheme": "default",
|
||||
"theme": "default"
|
||||
},
|
||||
"vim": {
|
||||
"colorscheme": "default",
|
||||
"theme": "default",
|
||||
"local_themes": {
|
||||
"cmdwin": "cmdwin",
|
||||
"help": "help",
|
||||
"quickfix": "quickfix"
|
||||
}
|
||||
},
|
||||
"wm": {
|
||||
"colorscheme": "default",
|
||||
"theme": "default"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"default_module": "powerline.segments.common",
|
||||
"segments": {
|
||||
"left": [
|
||||
{
|
||||
"name": "virtualenv"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"contents": "In[",
|
||||
"draw_soft_divider": false,
|
||||
"highlight_group": ["prompt"]
|
||||
},
|
||||
{
|
||||
"name": "prompt_count",
|
||||
"module": "powerline.segments.ipython",
|
||||
"draw_soft_divider": false
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"contents": "]",
|
||||
"highlight_group": ["prompt"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"default_module": "powerline.segments.common",
|
||||
"segments": {
|
||||
"left": [
|
||||
{
|
||||
"type": "string",
|
||||
"contents": "",
|
||||
"width": "auto",
|
||||
"highlight_group": ["prompt"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"default_module": "powerline.segments.common",
|
||||
"segments": {
|
||||
"left": [
|
||||
{
|
||||
"type": "string",
|
||||
"contents": "Out[",
|
||||
"draw_soft_divider": false,
|
||||
"width": "auto",
|
||||
"align": "r",
|
||||
"highlight_group": ["prompt"]
|
||||
},
|
||||
{
|
||||
"name": "prompt_count",
|
||||
"module": "powerline.segments.ipython",
|
||||
"draw_soft_divider": false
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"contents": "]",
|
||||
"highlight_group": ["prompt"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"segments": {
|
||||
"left": [
|
||||
{
|
||||
"type": "string",
|
||||
"contents": "",
|
||||
"draw_soft_divider": false,
|
||||
"width": "auto",
|
||||
"highlight_group": ["prompt"]
|
||||
},
|
||||
{
|
||||
"name": "prompt_count",
|
||||
"module": "powerline.segments.ipython",
|
||||
"draw_soft_divider": false
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"contents": ">",
|
||||
"highlight_group": ["prompt"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"default_module": "powerline.segments.common",
|
||||
"segment_data": {
|
||||
"hostname": {
|
||||
"before": " ",
|
||||
"args": {
|
||||
"only_if_ssh": true
|
||||
}
|
||||
},
|
||||
"virtualenv": {
|
||||
"before": "ⓔ "
|
||||
},
|
||||
"branch": {
|
||||
"before": " "
|
||||
}
|
||||
},
|
||||
"segments": {
|
||||
"left": [
|
||||
{
|
||||
"name": "hostname"
|
||||
},
|
||||
{
|
||||
"name": "user"
|
||||
},
|
||||
{
|
||||
"name": "virtualenv"
|
||||
},
|
||||
{
|
||||
"name": "cwd",
|
||||
"args": {
|
||||
"dir_limit_depth": 3
|
||||
}
|
||||
}
|
||||
],
|
||||
"right": [
|
||||
{
|
||||
"module": "powerline.segments.shell",
|
||||
"name": "last_pipe_status"
|
||||
},
|
||||
{
|
||||
"name": "branch"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"default_module": "powerline.segments.common",
|
||||
"segment_data": {
|
||||
"hostname": {
|
||||
"before": " ",
|
||||
"args": {
|
||||
"only_if_ssh": true
|
||||
}
|
||||
},
|
||||
"virtualenv": {
|
||||
"before": "ⓔ "
|
||||
},
|
||||
"branch": {
|
||||
"before": " "
|
||||
}
|
||||
},
|
||||
"segments": {
|
||||
"left": [
|
||||
{
|
||||
"name": "hostname"
|
||||
},
|
||||
{
|
||||
"name": "user"
|
||||
},
|
||||
{
|
||||
"name": "virtualenv"
|
||||
},
|
||||
{
|
||||
"name": "branch"
|
||||
},
|
||||
{
|
||||
"name": "cwd",
|
||||
"args": {
|
||||
"dir_limit_depth": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "last_status",
|
||||
"module": "powerline.segments.shell"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"default_module": "powerline.segments.common",
|
||||
"segment_data": {
|
||||
"uptime": {
|
||||
"before": "⇑ "
|
||||
},
|
||||
"external_ip": {
|
||||
"before": "ⓦ "
|
||||
},
|
||||
"date": {
|
||||
"before": "⌚ "
|
||||
},
|
||||
"email_imap_alert": {
|
||||
"before": "✉ ",
|
||||
"args": {
|
||||
"username": "",
|
||||
"password": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"segments": {
|
||||
"right": [
|
||||
{
|
||||
"name": "uptime",
|
||||
"priority": 50
|
||||
},
|
||||
{
|
||||
"name": "external_ip",
|
||||
"priority": 50
|
||||
},
|
||||
{
|
||||
"name": "network_load",
|
||||
"priority": 50
|
||||
},
|
||||
{
|
||||
"name": "system_load",
|
||||
"priority": 50
|
||||
},
|
||||
{
|
||||
"name": "weather",
|
||||
"priority": 50
|
||||
},
|
||||
{
|
||||
"name": "date"
|
||||
},
|
||||
{
|
||||
"name": "date",
|
||||
"args": {
|
||||
"format": "%H:%M",
|
||||
"istime": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "email_imap_alert",
|
||||
"priority": 10
|
||||
},
|
||||
{
|
||||
"name": "hostname"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"segments": {
|
||||
"left": [
|
||||
{
|
||||
"type": "string",
|
||||
"contents": "Command Line",
|
||||
"highlight_group": ["file_name"]
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"highlight_group": ["background"],
|
||||
"draw_soft_divider": false,
|
||||
"draw_hard_divider": false,
|
||||
"width": "auto"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
{
|
||||
"segment_data": {
|
||||
"branch": {
|
||||
"before": " "
|
||||
},
|
||||
"modified_indicator": {
|
||||
"args": { "text": "+" }
|
||||
},
|
||||
"line_percent": {
|
||||
"args": { "gradient": true },
|
||||
"after": "%"
|
||||
},
|
||||
"line_current_symbol": {
|
||||
"contents": " "
|
||||
}
|
||||
},
|
||||
"segments": {
|
||||
"left": [
|
||||
{
|
||||
"name": "mode",
|
||||
"exclude_modes": ["nc"]
|
||||
},
|
||||
{
|
||||
"name": "paste_indicator",
|
||||
"exclude_modes": ["nc"],
|
||||
"priority": 10
|
||||
},
|
||||
{
|
||||
"name": "branch",
|
||||
"exclude_modes": ["nc"],
|
||||
"priority": 30
|
||||
},
|
||||
{
|
||||
"name": "readonly_indicator",
|
||||
"draw_soft_divider": false,
|
||||
"after": " "
|
||||
},
|
||||
{
|
||||
"name": "file_directory",
|
||||
"priority": 40,
|
||||
"draw_soft_divider": false
|
||||
},
|
||||
{
|
||||
"name": "file_name",
|
||||
"draw_soft_divider": false
|
||||
},
|
||||
{
|
||||
"name": "file_vcs_status",
|
||||
"before": " ",
|
||||
"draw_soft_divider": false
|
||||
},
|
||||
{
|
||||
"name": "modified_indicator",
|
||||
"before": " "
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"highlight_group": ["background"],
|
||||
"draw_soft_divider": false,
|
||||
"draw_hard_divider": false,
|
||||
"width": "auto"
|
||||
}
|
||||
],
|
||||
"right": [
|
||||
{
|
||||
"name": "file_format",
|
||||
"draw_soft_divider": false,
|
||||
"exclude_modes": ["nc"],
|
||||
"priority": 60
|
||||
},
|
||||
{
|
||||
"name": "file_encoding",
|
||||
"exclude_modes": ["nc"],
|
||||
"priority": 60
|
||||
},
|
||||
{
|
||||
"name": "file_type",
|
||||
"exclude_modes": ["nc"],
|
||||
"priority": 60
|
||||
},
|
||||
{
|
||||
"name": "line_percent",
|
||||
"priority": 50,
|
||||
"width": 4,
|
||||
"align": "r"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "line_current_symbol",
|
||||
"highlight_group": ["line_current_symbol", "line_current"]
|
||||
},
|
||||
{
|
||||
"name": "line_current",
|
||||
"draw_soft_divider": false,
|
||||
"width": 3,
|
||||
"align": "r"
|
||||
},
|
||||
{
|
||||
"name": "virtcol_current",
|
||||
"draw_soft_divider": false,
|
||||
"priority": 20,
|
||||
"before": ":",
|
||||
"width": 3,
|
||||
"align": "l"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"segments": {
|
||||
"left": [
|
||||
{
|
||||
"name": "file_name",
|
||||
"draw_soft_divider": false
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"highlight_group": ["background"],
|
||||
"draw_soft_divider": false,
|
||||
"draw_hard_divider": false,
|
||||
"width": "auto"
|
||||
}
|
||||
],
|
||||
"right": [
|
||||
{
|
||||
"name": "line_percent",
|
||||
"priority": 30,
|
||||
"width": 4,
|
||||
"align": "r"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "line_current_symbol",
|
||||
"highlight_group": ["line_current_symbol", "line_current"]
|
||||
},
|
||||
{
|
||||
"name": "line_current",
|
||||
"draw_soft_divider": false,
|
||||
"width": 3,
|
||||
"align": "r"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"segment_data": {
|
||||
"buffer_name": {
|
||||
"contents": "Location List"
|
||||
}
|
||||
},
|
||||
"segments": {
|
||||
"left": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "buffer_name",
|
||||
"highlight_group": ["file_name"],
|
||||
"draw_soft_divider": false
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"highlight_group": ["background"],
|
||||
"draw_soft_divider": false,
|
||||
"draw_hard_divider": false,
|
||||
"width": "auto"
|
||||
}
|
||||
],
|
||||
"right": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "line_current_symbol",
|
||||
"highlight_group": ["line_current_symbol", "line_current"]
|
||||
},
|
||||
{
|
||||
"name": "line_current",
|
||||
"draw_soft_divider": false,
|
||||
"width": 3,
|
||||
"align": "r"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"default_module": "powerline.segments.common",
|
||||
"segments": {
|
||||
"right": [
|
||||
{
|
||||
"name": "weather",
|
||||
"priority": 50
|
||||
},
|
||||
{
|
||||
"name": "date"
|
||||
},
|
||||
{
|
||||
"name": "date",
|
||||
"args": {
|
||||
"format": "%H:%M",
|
||||
"istime": true
|
||||
},
|
||||
"before": "⌚ "
|
||||
},
|
||||
{
|
||||
"name": "email_imap_alert",
|
||||
"before": "✉ ",
|
||||
"priority": 10,
|
||||
"args": {
|
||||
"username": "",
|
||||
"password": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from powerline import Powerline
|
||||
from powerline.lib import mergedicts
|
||||
|
||||
|
||||
class IpythonPowerline(Powerline):
|
||||
def __init__(self):
|
||||
super(IpythonPowerline, self).__init__('ipython', use_daemon_threads=True)
|
||||
|
||||
def get_config_paths(self):
|
||||
if self.path:
|
||||
return [self.path]
|
||||
else:
|
||||
return super(IpythonPowerline, self).get_config_paths()
|
||||
|
||||
def get_local_themes(self, local_themes):
|
||||
return dict(((type, {'config': self.load_theme_config(name)}) for type, name in local_themes.items()))
|
||||
|
||||
def load_main_config(self):
|
||||
r = super(IpythonPowerline, self).load_main_config()
|
||||
if self.config_overrides:
|
||||
mergedicts(r, self.config_overrides)
|
||||
return r
|
||||
|
||||
def load_theme_config(self, name):
|
||||
r = super(IpythonPowerline, self).load_theme_config(name)
|
||||
if name in self.theme_overrides:
|
||||
mergedicts(r, self.theme_overrides[name])
|
||||
return r
|
|
@ -0,0 +1,67 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
from functools import wraps
|
||||
import json
|
||||
|
||||
|
||||
def wraps_saveargs(wrapped):
|
||||
def dec(wrapper):
|
||||
r = wraps(wrapped)(wrapper)
|
||||
r.powerline_origin = getattr(wrapped, 'powerline_origin', wrapped)
|
||||
return r
|
||||
return dec
|
||||
|
||||
|
||||
def mergedicts(d1, d2):
|
||||
'''Recursively merge two dictionaries. First dictionary is modified in-place.
|
||||
'''
|
||||
for k in d2:
|
||||
if k in d1 and type(d1[k]) is dict and type(d2[k]) is dict:
|
||||
mergedicts(d1[k], d2[k])
|
||||
else:
|
||||
d1[k] = d2[k]
|
||||
|
||||
|
||||
def add_divider_highlight_group(highlight_group):
|
||||
def dec(func):
|
||||
@wraps_saveargs(func)
|
||||
def f(**kwargs):
|
||||
r = func(**kwargs)
|
||||
if r:
|
||||
return [{
|
||||
'contents': r,
|
||||
'divider_highlight_group': highlight_group,
|
||||
}]
|
||||
else:
|
||||
return None
|
||||
return f
|
||||
return dec
|
||||
|
||||
|
||||
def keyvaluesplit(s):
|
||||
if '=' not in s:
|
||||
raise TypeError('Option must look like option=json_value')
|
||||
if s[0] == '_':
|
||||
raise ValueError('Option names must not start with `_\'')
|
||||
idx = s.index('=')
|
||||
o = s[:idx]
|
||||
val = json.loads(s[idx + 1:])
|
||||
return (o, val)
|
||||
|
||||
|
||||
def parsedotval(s):
|
||||
if type(s) is tuple:
|
||||
o, val = s
|
||||
else:
|
||||
o, val = keyvaluesplit(s)
|
||||
|
||||
keys = o.split('.')
|
||||
if len(keys) > 1:
|
||||
r = (keys[0], {})
|
||||
rcur = r[1]
|
||||
for key in keys[1:-1]:
|
||||
rcur[key] = {}
|
||||
rcur = rcur[key]
|
||||
rcur[keys[-1]] = val
|
||||
return r
|
||||
else:
|
||||
return (o, val)
|
|
@ -0,0 +1,156 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from powerline.lib.threaded import MultiRunnedThread
|
||||
from powerline.lib.file_watcher import create_file_watcher
|
||||
|
||||
from threading import Event, Lock
|
||||
from collections import defaultdict
|
||||
|
||||
import json
|
||||
|
||||
|
||||
def open_file(path):
|
||||
return open(path, 'r')
|
||||
|
||||
|
||||
def load_json_config(config_file_path, load=json.load, open_file=open_file):
|
||||
with open_file(config_file_path) as config_file_fp:
|
||||
return load(config_file_fp)
|
||||
|
||||
|
||||
class ConfigLoader(MultiRunnedThread):
|
||||
def __init__(self, shutdown_event=None, watcher=None, load=load_json_config):
|
||||
super(ConfigLoader, self).__init__()
|
||||
self.shutdown_event = shutdown_event or Event()
|
||||
self.watcher = watcher or create_file_watcher()
|
||||
self._load = load
|
||||
|
||||
self.pl = None
|
||||
self.interval = None
|
||||
|
||||
self.lock = Lock()
|
||||
|
||||
self.watched = defaultdict(set)
|
||||
self.missing = defaultdict(set)
|
||||
self.loaded = {}
|
||||
|
||||
def set_pl(self, pl):
|
||||
self.pl = pl
|
||||
|
||||
def set_interval(self, interval):
|
||||
self.interval = interval
|
||||
|
||||
def register(self, function, path):
|
||||
'''Register function that will be run when file changes.
|
||||
|
||||
:param function function:
|
||||
Function that will be called when file at the given path changes.
|
||||
:param str path:
|
||||
Path that will be watched for.
|
||||
'''
|
||||
with self.lock:
|
||||
self.watched[path].add(function)
|
||||
self.watcher.watch(path)
|
||||
|
||||
def register_missing(self, condition_function, function, key):
|
||||
'''Register any function that will be called with given key each
|
||||
interval seconds (interval is defined at __init__). Its result is then
|
||||
passed to ``function``, but only if the result is true.
|
||||
|
||||
:param function condition_function:
|
||||
Function which will be called each ``interval`` seconds. All
|
||||
exceptions from it will be ignored.
|
||||
:param function function:
|
||||
Function which will be called if condition_function returns
|
||||
something that is true. Accepts result of condition_function as an
|
||||
argument.
|
||||
:param str key:
|
||||
Any value, it will be passed to condition_function on each call.
|
||||
|
||||
Note: registered functions will be automatically removed if
|
||||
condition_function results in something true.
|
||||
'''
|
||||
with self.lock:
|
||||
self.missing[key].add((condition_function, function))
|
||||
|
||||
def unregister_functions(self, removed_functions):
|
||||
'''Unregister files handled by these functions.
|
||||
|
||||
:param set removed_functions:
|
||||
Set of functions previously passed to ``.register()`` method.
|
||||
'''
|
||||
with self.lock:
|
||||
for path, functions in list(self.watched.items()):
|
||||
functions -= removed_functions
|
||||
if not functions:
|
||||
self.watched.pop(path)
|
||||
self.loaded.pop(path, None)
|
||||
|
||||
def unregister_missing(self, removed_functions):
|
||||
'''Unregister files handled by these functions.
|
||||
|
||||
:param set removed_functions:
|
||||
Set of pairs (2-tuples) representing ``(condition_function,
|
||||
function)`` function pairs previously passed as an arguments to
|
||||
``.register_missing()`` method.
|
||||
'''
|
||||
with self.lock:
|
||||
for key, functions in list(self.missing.items()):
|
||||
functions -= removed_functions
|
||||
if not functions:
|
||||
self.missing.pop(key)
|
||||
|
||||
def load(self, path):
|
||||
try:
|
||||
# No locks: GIL does what we need
|
||||
return self.loaded[path]
|
||||
except KeyError:
|
||||
r = self._load(path)
|
||||
self.loaded[path] = r
|
||||
return r
|
||||
|
||||
def update(self):
|
||||
toload = []
|
||||
with self.lock:
|
||||
for path, functions in self.watched.items():
|
||||
for function in functions:
|
||||
try:
|
||||
modified = self.watcher(path)
|
||||
except OSError as e:
|
||||
modified = True
|
||||
self.exception('Error while running watcher for path {0}: {1}', path, str(e))
|
||||
else:
|
||||
if modified:
|
||||
toload.append(path)
|
||||
if modified:
|
||||
function(path)
|
||||
with self.lock:
|
||||
for key, functions in list(self.missing.items()):
|
||||
for condition_function, function in list(functions):
|
||||
try:
|
||||
path = condition_function(key)
|
||||
except Exception as e:
|
||||
self.exception('Error while running condition function for key {0}: {1}', key, str(e))
|
||||
else:
|
||||
if path:
|
||||
toload.append(path)
|
||||
function(path)
|
||||
functions.remove((condition_function, function))
|
||||
if not functions:
|
||||
self.missing.pop(key)
|
||||
for path in toload:
|
||||
try:
|
||||
self.loaded[path] = self._load(path)
|
||||
except Exception as e:
|
||||
self.exception('Error while loading {0}: {1}', path, str(e))
|
||||
|
||||
def run(self):
|
||||
while self.interval is not None and not self.shutdown_event.is_set():
|
||||
self.update()
|
||||
self.shutdown_event.wait(self.interval)
|
||||
|
||||
def exception(self, msg, *args, **kwargs):
|
||||
if self.pl:
|
||||
self.pl.exception(msg, prefix='config_loader', *args, **kwargs)
|
||||
else:
|
||||
raise
|
|
@ -0,0 +1,181 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os
|
||||
import sys
|
||||
from time import sleep
|
||||
from threading import RLock
|
||||
|
||||
from powerline.lib.monotonic import monotonic
|
||||
from powerline.lib.inotify import INotify, INotifyError
|
||||
|
||||
|
||||
class INotifyWatch(INotify):
|
||||
is_stat_based = False
|
||||
|
||||
def __init__(self, expire_time=10):
|
||||
super(INotifyWatch, self).__init__()
|
||||
self.watches = {}
|
||||
self.modified = {}
|
||||
self.last_query = {}
|
||||
self.lock = RLock()
|
||||
self.expire_time = expire_time * 60
|
||||
|
||||
def expire_watches(self):
|
||||
now = monotonic()
|
||||
for path, last_query in tuple(self.last_query.items()):
|
||||
if last_query - now > self.expire_time:
|
||||
self.unwatch(path)
|
||||
|
||||
def process_event(self, wd, mask, cookie, name):
|
||||
if wd == -1 and (mask & self.Q_OVERFLOW):
|
||||
# We missed some INOTIFY events, so we dont
|
||||
# know the state of any tracked files.
|
||||
for path in tuple(self.modified):
|
||||
if os.path.exists(path):
|
||||
self.modified[path] = True
|
||||
else:
|
||||
self.watches.pop(path, None)
|
||||
self.modified.pop(path, None)
|
||||
self.last_query.pop(path, None)
|
||||
return
|
||||
|
||||
for path, num in tuple(self.watches.items()):
|
||||
if num == wd:
|
||||
if mask & self.IGNORED:
|
||||
self.watches.pop(path, None)
|
||||
self.modified.pop(path, None)
|
||||
self.last_query.pop(path, None)
|
||||
else:
|
||||
self.modified[path] = True
|
||||
|
||||
def unwatch(self, path):
|
||||
''' Remove the watch for path. Raises an OSError if removing the watch
|
||||
fails for some reason. '''
|
||||
path = self.os.path.abspath(path)
|
||||
with self.lock:
|
||||
self.modified.pop(path, None)
|
||||
self.last_query.pop(path, None)
|
||||
wd = self.watches.pop(path, None)
|
||||
if wd is not None:
|
||||
if self._rm_watch(self._inotify_fd, wd) != 0:
|
||||
self.handle_error()
|
||||
|
||||
def watch(self, path):
|
||||
''' Register a watch for the file named path. Raises an OSError if path
|
||||
does not exist. '''
|
||||
import ctypes
|
||||
path = self.os.path.abspath(path)
|
||||
with self.lock:
|
||||
if path not in self.watches:
|
||||
bpath = path if isinstance(path, bytes) else path.encode(self.fenc)
|
||||
wd = self._add_watch(self._inotify_fd, ctypes.c_char_p(bpath),
|
||||
self.MODIFY | self.ATTRIB | self.MOVE_SELF | self.DELETE_SELF)
|
||||
if wd == -1:
|
||||
self.handle_error()
|
||||
self.watches[path] = wd
|
||||
self.modified[path] = False
|
||||
|
||||
def __call__(self, path):
|
||||
''' Return True if path has been modified since the last call. Can
|
||||
raise OSError if the path does not exist. '''
|
||||
path = self.os.path.abspath(path)
|
||||
with self.lock:
|
||||
self.last_query[path] = monotonic()
|
||||
self.expire_watches()
|
||||
if path not in self.watches:
|
||||
# Try to re-add the watch, it will fail if the file does not
|
||||
# exist/you dont have permission
|
||||
self.watch(path)
|
||||
return True
|
||||
self.read(get_name=False)
|
||||
if path not in self.modified:
|
||||
# An ignored event was received which means the path has been
|
||||
# automatically unwatched
|
||||
return True
|
||||
ans = self.modified[path]
|
||||
if ans:
|
||||
self.modified[path] = False
|
||||
return ans
|
||||
|
||||
def close(self):
|
||||
with self.lock:
|
||||
for path in tuple(self.watches):
|
||||
try:
|
||||
self.unwatch(path)
|
||||
except OSError:
|
||||
pass
|
||||
super(INotifyWatch, self).close()
|
||||
|
||||
|
||||
class StatWatch(object):
|
||||
is_stat_based = True
|
||||
|
||||
def __init__(self):
|
||||
self.watches = {}
|
||||
self.lock = RLock()
|
||||
|
||||
def watch(self, path):
|
||||
path = os.path.abspath(path)
|
||||
with self.lock:
|
||||
self.watches[path] = os.path.getmtime(path)
|
||||
|
||||
def unwatch(self, path):
|
||||
path = os.path.abspath(path)
|
||||
with self.lock:
|
||||
self.watches.pop(path, None)
|
||||
|
||||
def __call__(self, path):
|
||||
path = os.path.abspath(path)
|
||||
with self.lock:
|
||||
if path not in self.watches:
|
||||
self.watches[path] = os.path.getmtime(path)
|
||||
return True
|
||||
mtime = os.path.getmtime(path)
|
||||
if mtime != self.watches[path]:
|
||||
self.watches[path] = mtime
|
||||
return True
|
||||
return False
|
||||
|
||||
def close(self):
|
||||
with self.lock:
|
||||
self.watches.clear()
|
||||
|
||||
|
||||
def create_file_watcher(use_stat=False, expire_time=10):
|
||||
'''
|
||||
Create an object that can watch for changes to specified files. To use:
|
||||
|
||||
watcher = create_file_watcher()
|
||||
watcher(path1) # Will return True if path1 has changed since the last time this was called. Always returns True the first time.
|
||||
watcher.unwatch(path1)
|
||||
|
||||
Uses inotify if available, otherwise tracks mtimes. expire_time is the
|
||||
number of minutes after the last query for a given path for the inotify
|
||||
watch for that path to be automatically removed. This conserves kernel
|
||||
resources.
|
||||
'''
|
||||
if use_stat:
|
||||
return StatWatch()
|
||||
try:
|
||||
return INotifyWatch(expire_time=expire_time)
|
||||
except INotifyError:
|
||||
pass
|
||||
return StatWatch()
|
||||
|
||||
if __name__ == '__main__':
|
||||
watcher = create_file_watcher()
|
||||
print ('Using watcher: %s' % watcher.__class__.__name__)
|
||||
print ('Watching %s, press Ctrl-C to quit' % sys.argv[-1])
|
||||
watcher.watch(sys.argv[-1])
|
||||
try:
|
||||
while True:
|
||||
if watcher(sys.argv[-1]):
|
||||
print ('%s has changed' % sys.argv[-1])
|
||||
sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
watcher.close()
|
|
@ -0,0 +1,22 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from math import log
|
||||
unit_list = tuple(zip(['', 'k', 'M', 'G', 'T', 'P'], [0, 0, 1, 2, 2, 2]))
|
||||
|
||||
|
||||
def humanize_bytes(num, suffix='B', si_prefix=False):
|
||||
'''Return a human friendly byte representation.
|
||||
|
||||
Modified version from http://stackoverflow.com/questions/1094841
|
||||
'''
|
||||
if num == 0:
|
||||
return '0 ' + suffix
|
||||
div = 1000 if si_prefix else 1024
|
||||
exponent = min(int(log(num, div)) if num else 0, len(unit_list) - 1)
|
||||
quotient = float(num) / div ** exponent
|
||||
unit, decimals = unit_list[exponent]
|
||||
if unit and not si_prefix:
|
||||
unit = unit.upper() + 'i'
|
||||
return '{{quotient:.{decimals}f}} {{unit}}{{suffix}}'\
|
||||
.format(decimals=decimals)\
|
||||
.format(quotient=quotient, unit=unit, suffix=suffix)
|
|
@ -0,0 +1,178 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import sys
|
||||
import os
|
||||
import errno
|
||||
|
||||
|
||||
class INotifyError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
_inotify = None
|
||||
|
||||
|
||||
def load_inotify():
|
||||
''' Initialize the inotify library '''
|
||||
global _inotify
|
||||
if _inotify is None:
|
||||
if hasattr(sys, 'getwindowsversion'):
|
||||
# On windows abort before loading the C library. Windows has
|
||||
# multiple, incompatible C runtimes, and we have no way of knowing
|
||||
# if the one chosen by ctypes is compatible with the currently
|
||||
# loaded one.
|
||||
raise INotifyError('INotify not available on windows')
|
||||
import ctypes
|
||||
if not hasattr(ctypes, 'c_ssize_t'):
|
||||
raise INotifyError('You need python >= 2.7 to use inotify')
|
||||
from ctypes.util import find_library
|
||||
name = find_library('c')
|
||||
if not name:
|
||||
raise INotifyError('Cannot find C library')
|
||||
libc = ctypes.CDLL(name, use_errno=True)
|
||||
for function in ("inotify_add_watch", "inotify_init1", "inotify_rm_watch"):
|
||||
if not hasattr(libc, function):
|
||||
raise INotifyError('libc is too old')
|
||||
# inotify_init1()
|
||||
prototype = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, use_errno=True)
|
||||
init1 = prototype(('inotify_init1', libc), ((1, "flags", 0),))
|
||||
|
||||
# inotify_add_watch()
|
||||
prototype = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_char_p, ctypes.c_uint32, use_errno=True)
|
||||
add_watch = prototype(('inotify_add_watch', libc), (
|
||||
(1, "fd"), (1, "pathname"), (1, "mask")), use_errno=True)
|
||||
|
||||
# inotify_rm_watch()
|
||||
prototype = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int, use_errno=True)
|
||||
rm_watch = prototype(('inotify_rm_watch', libc), (
|
||||
(1, "fd"), (1, "wd")), use_errno=True)
|
||||
|
||||
# read()
|
||||
prototype = ctypes.CFUNCTYPE(ctypes.c_ssize_t, ctypes.c_int, ctypes.c_void_p, ctypes.c_size_t, use_errno=True)
|
||||
read = prototype(('read', libc), (
|
||||
(1, "fd"), (1, "buf"), (1, "count")), use_errno=True)
|
||||
_inotify = (init1, add_watch, rm_watch, read)
|
||||
return _inotify
|
||||
|
||||
|
||||
class INotify(object):
|
||||
# See <sys/inotify.h> for the flags defined below
|
||||
|
||||
# Supported events suitable for MASK parameter of INOTIFY_ADD_WATCH.
|
||||
ACCESS = 0x00000001 # File was accessed.
|
||||
MODIFY = 0x00000002 # File was modified.
|
||||
ATTRIB = 0x00000004 # Metadata changed.
|
||||
CLOSE_WRITE = 0x00000008 # Writtable file was closed.
|
||||
CLOSE_NOWRITE = 0x00000010 # Unwrittable file closed.
|
||||
OPEN = 0x00000020 # File was opened.
|
||||
MOVED_FROM = 0x00000040 # File was moved from X.
|
||||
MOVED_TO = 0x00000080 # File was moved to Y.
|
||||
CREATE = 0x00000100 # Subfile was created.
|
||||
DELETE = 0x00000200 # Subfile was deleted.
|
||||
DELETE_SELF = 0x00000400 # Self was deleted.
|
||||
MOVE_SELF = 0x00000800 # Self was moved.
|
||||
|
||||
# Events sent by the kernel.
|
||||
UNMOUNT = 0x00002000 # Backing fs was unmounted.
|
||||
Q_OVERFLOW = 0x00004000 # Event queued overflowed.
|
||||
IGNORED = 0x00008000 # File was ignored.
|
||||
|
||||
# Helper events.
|
||||
CLOSE = (CLOSE_WRITE | CLOSE_NOWRITE) # Close.
|
||||
MOVE = (MOVED_FROM | MOVED_TO) # Moves.
|
||||
|
||||
# Special flags.
|
||||
ONLYDIR = 0x01000000 # Only watch the path if it is a directory.
|
||||
DONT_FOLLOW = 0x02000000 # Do not follow a sym link.
|
||||
EXCL_UNLINK = 0x04000000 # Exclude events on unlinked objects.
|
||||
MASK_ADD = 0x20000000 # Add to the mask of an already existing watch.
|
||||
ISDIR = 0x40000000 # Event occurred against dir.
|
||||
ONESHOT = 0x80000000 # Only send event once.
|
||||
|
||||
# All events which a program can wait on.
|
||||
ALL_EVENTS = (ACCESS | MODIFY | ATTRIB | CLOSE_WRITE | CLOSE_NOWRITE |
|
||||
OPEN | MOVED_FROM | MOVED_TO | CREATE | DELETE |
|
||||
DELETE_SELF | MOVE_SELF)
|
||||
|
||||
# See <bits/inotify.h>
|
||||
CLOEXEC = 0x80000
|
||||
NONBLOCK = 0x800
|
||||
|
||||
def __init__(self, cloexec=True, nonblock=True):
|
||||
import ctypes
|
||||
import struct
|
||||
self._init1, self._add_watch, self._rm_watch, self._read = load_inotify()
|
||||
flags = 0
|
||||
if cloexec:
|
||||
flags |= self.CLOEXEC
|
||||
if nonblock:
|
||||
flags |= self.NONBLOCK
|
||||
self._inotify_fd = self._init1(flags)
|
||||
if self._inotify_fd == -1:
|
||||
raise INotifyError(os.strerror(ctypes.get_errno()))
|
||||
|
||||
self._buf = ctypes.create_string_buffer(5000)
|
||||
self.fenc = sys.getfilesystemencoding() or 'utf-8'
|
||||
self.hdr = struct.Struct(b'iIII')
|
||||
if self.fenc == 'ascii':
|
||||
self.fenc = 'utf-8'
|
||||
# We keep a reference to os to prevent it from being deleted
|
||||
# during interpreter shutdown, which would lead to errors in the
|
||||
# __del__ method
|
||||
self.os = os
|
||||
|
||||
def handle_error(self):
|
||||
import ctypes
|
||||
eno = ctypes.get_errno()
|
||||
raise OSError(eno, self.os.strerror(eno))
|
||||
|
||||
def __del__(self):
|
||||
# This method can be called during interpreter shutdown, which means we
|
||||
# must do the absolute minimum here. Note that there could be running
|
||||
# daemon threads that are trying to call other methods on this object.
|
||||
try:
|
||||
self.os.close(self._inotify_fd)
|
||||
except (AttributeError, TypeError):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
if hasattr(self, '_inotify_fd'):
|
||||
self.os.close(self._inotify_fd)
|
||||
del self.os
|
||||
del self._add_watch
|
||||
del self._rm_watch
|
||||
del self._inotify_fd
|
||||
|
||||
def read(self, get_name=True):
|
||||
import ctypes
|
||||
buf = []
|
||||
while True:
|
||||
num = self._read(self._inotify_fd, self._buf, len(self._buf))
|
||||
if num == 0:
|
||||
break
|
||||
if num < 0:
|
||||
en = ctypes.get_errno()
|
||||
if en == errno.EAGAIN:
|
||||
break # No more data
|
||||
if en == errno.EINTR:
|
||||
continue # Interrupted, try again
|
||||
raise OSError(en, self.os.strerror(en))
|
||||
buf.append(self._buf.raw[:num])
|
||||
raw = b''.join(buf)
|
||||
pos = 0
|
||||
lraw = len(raw)
|
||||
while lraw - pos >= self.hdr.size:
|
||||
wd, mask, cookie, name_len = self.hdr.unpack_from(raw, pos)
|
||||
pos += self.hdr.size
|
||||
name = None
|
||||
if get_name:
|
||||
name = raw[pos:pos + name_len].rstrip(b'\0').decode(self.fenc)
|
||||
pos += name_len
|
||||
self.process_event(wd, mask, cookie, name)
|
||||
|
||||
def process_event(self, *args):
|
||||
raise NotImplementedError()
|
|
@ -0,0 +1,40 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from functools import wraps
|
||||
from powerline.lib.monotonic import monotonic
|
||||
|
||||
|
||||
def default_cache_key(**kwargs):
|
||||
return frozenset(kwargs.items())
|
||||
|
||||
|
||||
class memoize(object):
|
||||
'''Memoization decorator with timeout.'''
|
||||
def __init__(self, timeout, cache_key=default_cache_key, cache_reg_func=None):
|
||||
self.timeout = timeout
|
||||
self.cache_key = cache_key
|
||||
self.cache = {}
|
||||
self.cache_reg_func = cache_reg_func
|
||||
|
||||
def __call__(self, func):
|
||||
@wraps(func)
|
||||
def decorated_function(**kwargs):
|
||||
if self.cache_reg_func:
|
||||
self.cache_reg_func(self.cache)
|
||||
self.cache_reg_func = None
|
||||
|
||||
key = self.cache_key(**kwargs)
|
||||
try:
|
||||
cached = self.cache.get(key, None)
|
||||
except TypeError:
|
||||
return func(**kwargs)
|
||||
# Handle case when time() appears to be less then cached['time'] due
|
||||
# to clock updates. Not applicable for monotonic clock, but this
|
||||
# case is currently rare.
|
||||
if cached is None or not (cached['time'] < monotonic() < cached['time'] + self.timeout):
|
||||
cached = self.cache[key] = {
|
||||
'result': func(**kwargs),
|
||||
'time': monotonic(),
|
||||
}
|
||||
return cached['result']
|
||||
return decorated_function
|
|
@ -0,0 +1,103 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from __future__ import division, absolute_import
|
||||
|
||||
try:
|
||||
try:
|
||||
# >=python-3.3, Unix
|
||||
from time import clock_gettime
|
||||
try:
|
||||
# >={kernel}-sources-2.6.28
|
||||
from time import CLOCK_MONOTONIC_RAW as CLOCK_ID
|
||||
except ImportError:
|
||||
from time import CLOCK_MONOTONIC as CLOCK_ID # NOQA
|
||||
|
||||
monotonic = lambda: clock_gettime(CLOCK_ID)
|
||||
|
||||
except ImportError:
|
||||
# >=python-3.3
|
||||
from time import monotonic # NOQA
|
||||
|
||||
except ImportError:
|
||||
import ctypes
|
||||
import sys
|
||||
|
||||
try:
|
||||
if sys.platform == 'win32':
|
||||
# Windows only
|
||||
GetTickCount64 = ctypes.windll.kernel32.GetTickCount64
|
||||
GetTickCount64.restype = ctypes.c_ulonglong
|
||||
|
||||
def monotonic(): # NOQA
|
||||
return GetTickCount64() / 1000
|
||||
|
||||
elif sys.platform == 'darwin':
|
||||
# Mac OS X
|
||||
from ctypes.util import find_library
|
||||
|
||||
libc_name = find_library('c')
|
||||
if not libc_name:
|
||||
raise OSError
|
||||
|
||||
libc = ctypes.CDLL(libc_name, use_errno=True)
|
||||
|
||||
mach_absolute_time = libc.mach_absolute_time
|
||||
mach_absolute_time.argtypes = ()
|
||||
mach_absolute_time.restype = ctypes.c_uint64
|
||||
|
||||
class mach_timebase_info_data_t(ctypes.Structure):
|
||||
_fields_ = (
|
||||
('numer', ctypes.c_uint32),
|
||||
('denom', ctypes.c_uint32),
|
||||
)
|
||||
mach_timebase_info_data_p = ctypes.POINTER(mach_timebase_info_data_t)
|
||||
|
||||
_mach_timebase_info = libc.mach_timebase_info
|
||||
_mach_timebase_info.argtypes = (mach_timebase_info_data_p,)
|
||||
_mach_timebase_info.restype = ctypes.c_int
|
||||
|
||||
def mach_timebase_info():
|
||||
timebase = mach_timebase_info_data_t()
|
||||
_mach_timebase_info(ctypes.byref(timebase))
|
||||
return (timebase.numer, timebase.denom)
|
||||
|
||||
timebase = mach_timebase_info()
|
||||
factor = timebase[0] / timebase[1] * 1e-9
|
||||
|
||||
def monotonic(): # NOQA
|
||||
return mach_absolute_time() * factor
|
||||
else:
|
||||
# linux only (no librt on OS X)
|
||||
import os
|
||||
|
||||
# See <bits/time.h>
|
||||
CLOCK_MONOTONIC = 1
|
||||
CLOCK_MONOTONIC_RAW = 4
|
||||
|
||||
class timespec(ctypes.Structure):
|
||||
_fields_ = (
|
||||
('tv_sec', ctypes.c_long),
|
||||
('tv_nsec', ctypes.c_long)
|
||||
)
|
||||
tspec = timespec()
|
||||
|
||||
librt = ctypes.CDLL('librt.so.1', use_errno=True)
|
||||
clock_gettime = librt.clock_gettime
|
||||
clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)]
|
||||
|
||||
if clock_gettime(CLOCK_MONOTONIC_RAW, ctypes.pointer(tspec)) == 0:
|
||||
# >={kernel}-sources-2.6.28
|
||||
clock_id = CLOCK_MONOTONIC_RAW
|
||||
elif clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(tspec)) == 0:
|
||||
clock_id = CLOCK_MONOTONIC
|
||||
else:
|
||||
raise OSError
|
||||
|
||||
def monotonic(): # NOQA
|
||||
if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(tspec)) != 0:
|
||||
errno_ = ctypes.get_errno()
|
||||
raise OSError(errno_, os.strerror(errno_))
|
||||
return tspec.tv_sec + tspec.tv_nsec / 1e9
|
||||
|
||||
except:
|
||||
from time import time as monotonic # NOQA
|
|
@ -0,0 +1,204 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from powerline.lib.monotonic import monotonic
|
||||
|
||||
from threading import Thread, Lock, Event
|
||||
|
||||
|
||||
class MultiRunnedThread(object):
|
||||
daemon = True
|
||||
|
||||
def __init__(self):
|
||||
self.thread = None
|
||||
|
||||
def is_alive(self):
|
||||
return self.thread and self.thread.is_alive()
|
||||
|
||||
def start(self):
|
||||
self.shutdown_event.clear()
|
||||
self.thread = Thread(target=self.run)
|
||||
self.thread.daemon = self.daemon
|
||||
self.thread.start()
|
||||
|
||||
def join(self, *args, **kwargs):
|
||||
if self.thread:
|
||||
return self.thread.join(*args, **kwargs)
|
||||
return None
|
||||
|
||||
|
||||
class ThreadedSegment(MultiRunnedThread):
|
||||
min_sleep_time = 0.1
|
||||
update_first = True
|
||||
interval = 1
|
||||
daemon = False
|
||||
|
||||
def __init__(self):
|
||||
super(ThreadedSegment, self).__init__()
|
||||
self.run_once = True
|
||||
self.skip = False
|
||||
self.crashed_value = None
|
||||
self.update_value = None
|
||||
self.updated = False
|
||||
|
||||
def __call__(self, pl, update_first=True, **kwargs):
|
||||
if self.run_once:
|
||||
self.pl = pl
|
||||
self.set_state(**kwargs)
|
||||
update_value = self.get_update_value(True)
|
||||
elif not self.is_alive():
|
||||
# Without this we will not have to wait long until receiving bug “I
|
||||
# opened vim, but branch information is only shown after I move
|
||||
# cursor”.
|
||||
#
|
||||
# If running once .update() is called in __call__.
|
||||
update_value = self.get_update_value(update_first and self.update_first)
|
||||
self.start()
|
||||
elif not self.updated:
|
||||
update_value = self.get_update_value(True)
|
||||
self.updated = True
|
||||
else:
|
||||
update_value = self.update_value
|
||||
|
||||
if self.skip:
|
||||
return self.crashed_value
|
||||
|
||||
return self.render(update_value, update_first=update_first, pl=pl, **kwargs)
|
||||
|
||||
def get_update_value(self, update=False):
|
||||
if update:
|
||||
self.update_value = self.update(self.update_value)
|
||||
return self.update_value
|
||||
|
||||
def run(self):
|
||||
while not self.shutdown_event.is_set():
|
||||
start_time = monotonic()
|
||||
try:
|
||||
self.update_value = self.update(self.update_value)
|
||||
except Exception as e:
|
||||
self.exception('Exception while updating: {0}', str(e))
|
||||
self.skip = True
|
||||
except KeyboardInterrupt:
|
||||
self.warn('Caught keyboard interrupt while updating')
|
||||
self.skip = True
|
||||
else:
|
||||
self.skip = False
|
||||
self.shutdown_event.wait(max(self.interval - (monotonic() - start_time), self.min_sleep_time))
|
||||
|
||||
def shutdown(self):
|
||||
self.shutdown_event.set()
|
||||
if self.daemon and self.is_alive():
|
||||
# Give the worker thread a chance to shutdown, but don't block for
|
||||
# too long
|
||||
self.join(0.01)
|
||||
|
||||
def set_interval(self, interval=None):
|
||||
# Allowing “interval” keyword in configuration.
|
||||
# Note: Here **kwargs is needed to support foreign data, in subclasses
|
||||
# it can be seen in a number of places in order to support
|
||||
# .set_interval().
|
||||
interval = interval or getattr(self, 'interval')
|
||||
self.interval = interval
|
||||
|
||||
def set_state(self, interval=None, update_first=True, shutdown_event=None, **kwargs):
|
||||
self.set_interval(interval)
|
||||
self.shutdown_event = shutdown_event or Event()
|
||||
self.updated = self.updated or (not (update_first and self.update_first))
|
||||
|
||||
def startup(self, pl, **kwargs):
|
||||
self.run_once = False
|
||||
self.pl = pl
|
||||
self.daemon = pl.use_daemon_threads
|
||||
|
||||
self.set_state(**kwargs)
|
||||
|
||||
if not self.is_alive():
|
||||
self.start()
|
||||
|
||||
def critical(self, *args, **kwargs):
|
||||
self.pl.critical(prefix=self.__class__.__name__, *args, **kwargs)
|
||||
|
||||
def exception(self, *args, **kwargs):
|
||||
self.pl.exception(prefix=self.__class__.__name__, *args, **kwargs)
|
||||
|
||||
def info(self, *args, **kwargs):
|
||||
self.pl.info(prefix=self.__class__.__name__, *args, **kwargs)
|
||||
|
||||
def error(self, *args, **kwargs):
|
||||
self.pl.error(prefix=self.__class__.__name__, *args, **kwargs)
|
||||
|
||||
def warn(self, *args, **kwargs):
|
||||
self.pl.warn(prefix=self.__class__.__name__, *args, **kwargs)
|
||||
|
||||
def debug(self, *args, **kwargs):
|
||||
self.pl.debug(prefix=self.__class__.__name__, *args, **kwargs)
|
||||
|
||||
|
||||
class KwThreadedSegment(ThreadedSegment):
|
||||
drop_interval = 10 * 60
|
||||
update_first = True
|
||||
|
||||
def __init__(self):
|
||||
super(KwThreadedSegment, self).__init__()
|
||||
self.updated = True
|
||||
self.update_value = ({}, set())
|
||||
self.write_lock = Lock()
|
||||
self.new_queries = {}
|
||||
|
||||
@staticmethod
|
||||
def key(**kwargs):
|
||||
return frozenset(kwargs.items())
|
||||
|
||||
def render(self, update_value, update_first, **kwargs):
|
||||
queries, crashed = update_value
|
||||
key = self.key(**kwargs)
|
||||
if key in crashed:
|
||||
return self.crashed_value
|
||||
|
||||
try:
|
||||
update_state = queries[key][1]
|
||||
except KeyError:
|
||||
# Allow only to forbid to compute missing values: in either user
|
||||
# configuration or in subclasses.
|
||||
update_state = self.compute_state(key) if ((update_first and self.update_first) or self.run_once) else None
|
||||
|
||||
with self.write_lock:
|
||||
self.new_queries[key] = (monotonic(), update_state)
|
||||
return self.render_one(update_state, **kwargs)
|
||||
|
||||
def update(self, old_update_value):
|
||||
updates = {}
|
||||
crashed = set()
|
||||
update_value = (updates, crashed)
|
||||
queries = old_update_value[0]
|
||||
with self.write_lock:
|
||||
if self.new_queries:
|
||||
queries.update(self.new_queries)
|
||||
self.new_queries.clear()
|
||||
|
||||
for key, (last_query_time, state) in queries.items():
|
||||
if last_query_time < monotonic() < last_query_time + self.drop_interval:
|
||||
try:
|
||||
updates[key] = (last_query_time, self.compute_state(key))
|
||||
except Exception as e:
|
||||
self.exception('Exception while computing state for {0!r}: {1}', key, str(e))
|
||||
crashed.add(key)
|
||||
except KeyboardInterrupt:
|
||||
self.warn('Interrupt while computing state for {0!r}', key)
|
||||
crashed.add(key)
|
||||
|
||||
return update_value
|
||||
|
||||
def set_state(self, interval=None, shutdown_event=None, **kwargs):
|
||||
self.set_interval(interval)
|
||||
self.shutdown_event = shutdown_event or Event()
|
||||
|
||||
@staticmethod
|
||||
def render_one(update_state, **kwargs):
|
||||
return update_state
|
||||
|
||||
|
||||
def with_docstring(instance, doc):
|
||||
instance.__doc__ = doc
|
||||
return instance
|
|
@ -0,0 +1,199 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
from __future__ import (unicode_literals, absolute_import, print_function)
|
||||
|
||||
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import sys
|
||||
import os
|
||||
import errno
|
||||
from time import sleep
|
||||
from powerline.lib.monotonic import monotonic
|
||||
|
||||
from powerline.lib.inotify import INotify, INotifyError
|
||||
|
||||
|
||||
class NoSuchDir(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
class DirTooLarge(ValueError):
|
||||
def __init__(self, bdir):
|
||||
ValueError.__init__(self, 'The directory {0} is too large to monitor. Try increasing the value in /proc/sys/fs/inotify/max_user_watches'.format(bdir))
|
||||
|
||||
|
||||
class INotifyTreeWatcher(INotify):
|
||||
is_dummy = False
|
||||
|
||||
def __init__(self, basedir):
|
||||
super(INotifyTreeWatcher, self).__init__()
|
||||
self.basedir = os.path.abspath(basedir)
|
||||
self.watch_tree()
|
||||
self.modified = True
|
||||
|
||||
def watch_tree(self):
|
||||
self.watched_dirs = {}
|
||||
self.watched_rmap = {}
|
||||
try:
|
||||
self.add_watches(self.basedir)
|
||||
except OSError as e:
|
||||
if e.errno == errno.ENOSPC:
|
||||
raise DirTooLarge(self.basedir)
|
||||
|
||||
def add_watches(self, base, top_level=True):
|
||||
''' Add watches for this directory and all its descendant directories,
|
||||
recursively. '''
|
||||
base = os.path.abspath(base)
|
||||
try:
|
||||
is_dir = self.add_watch(base)
|
||||
except OSError as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
# The entry could have been deleted between listdir() and
|
||||
# add_watch().
|
||||
if top_level:
|
||||
raise NoSuchDir('The dir {0} does not exist'.format(base))
|
||||
return
|
||||
if e.errno == errno.EACCES:
|
||||
# We silently ignore entries for which we dont have permission,
|
||||
# unless they are the top level dir
|
||||
if top_level:
|
||||
raise NoSuchDir('You do not have permission to monitor {0}'.format(base))
|
||||
return
|
||||
raise
|
||||
else:
|
||||
if is_dir:
|
||||
try:
|
||||
files = os.listdir(base)
|
||||
except OSError as e:
|
||||
if e.errno in (errno.ENOTDIR, errno.ENOENT):
|
||||
# The dir was deleted/replaced between the add_watch()
|
||||
# and listdir()
|
||||
if top_level:
|
||||
raise NoSuchDir('The dir {0} does not exist'.format(base))
|
||||
return
|
||||
raise
|
||||
for x in files:
|
||||
self.add_watches(os.path.join(base, x), top_level=False)
|
||||
elif top_level:
|
||||
# The top level dir is a file, not good.
|
||||
raise NoSuchDir('The dir {0} does not exist'.format(base))
|
||||
|
||||
def add_watch(self, path):
|
||||
import ctypes
|
||||
bpath = path if isinstance(path, bytes) else path.encode(self.fenc)
|
||||
wd = self._add_watch(self._inotify_fd, ctypes.c_char_p(bpath),
|
||||
# Ignore symlinks and watch only directories
|
||||
self.DONT_FOLLOW | self.ONLYDIR |
|
||||
|
||||
self.MODIFY | self.CREATE | self.DELETE |
|
||||
self.MOVE_SELF | self.MOVED_FROM | self.MOVED_TO |
|
||||
self.ATTRIB | self.MOVE_SELF | self.DELETE_SELF)
|
||||
if wd == -1:
|
||||
eno = ctypes.get_errno()
|
||||
if eno == errno.ENOTDIR:
|
||||
return False
|
||||
raise OSError(eno, 'Failed to add watch for: {0}: {1}'.format(path, self.os.strerror(eno)))
|
||||
self.watched_dirs[path] = wd
|
||||
self.watched_rmap[wd] = path
|
||||
return True
|
||||
|
||||
def process_event(self, wd, mask, cookie, name):
|
||||
if wd == -1 and (mask & self.Q_OVERFLOW):
|
||||
# We missed some INOTIFY events, so we dont
|
||||
# know the state of any tracked dirs.
|
||||
self.watch_tree()
|
||||
self.modified = True
|
||||
return
|
||||
path = self.watched_rmap.get(wd, None)
|
||||
if path is not None:
|
||||
self.modified = True
|
||||
if mask & self.CREATE:
|
||||
# A new sub-directory might have been created, monitor it.
|
||||
try:
|
||||
self.add_watch(os.path.join(path, name))
|
||||
except OSError as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
# Deleted before add_watch()
|
||||
pass
|
||||
elif e.errno == errno.ENOSPC:
|
||||
raise DirTooLarge(self.basedir)
|
||||
else:
|
||||
raise
|
||||
|
||||
def __call__(self):
|
||||
self.read()
|
||||
ret = self.modified
|
||||
self.modified = False
|
||||
return ret
|
||||
|
||||
|
||||
class DummyTreeWatcher(object):
|
||||
is_dummy = True
|
||||
|
||||
def __init__(self, basedir):
|
||||
self.basedir = os.path.abspath(basedir)
|
||||
|
||||
def __call__(self):
|
||||
return False
|
||||
|
||||
|
||||
class TreeWatcher(object):
|
||||
def __init__(self, expire_time=10):
|
||||
self.watches = {}
|
||||
self.last_query_times = {}
|
||||
self.expire_time = expire_time * 60
|
||||
|
||||
def watch(self, path, logger=None):
|
||||
path = os.path.abspath(path)
|
||||
try:
|
||||
w = INotifyTreeWatcher(path)
|
||||
except (INotifyError, DirTooLarge) as e:
|
||||
if logger is not None:
|
||||
logger.warn('Failed to watch path: {0} with error: {1}'.format(path, e))
|
||||
w = DummyTreeWatcher(path)
|
||||
self.watches[path] = w
|
||||
return w
|
||||
|
||||
def is_actually_watched(self, path):
|
||||
w = self.watches.get(path, None)
|
||||
return not getattr(w, 'is_dummy', True)
|
||||
|
||||
def expire_old_queries(self):
|
||||
pop = []
|
||||
now = monotonic()
|
||||
for path, lt in self.last_query_times.items():
|
||||
if now - lt > self.expire_time:
|
||||
pop.append(path)
|
||||
for path in pop:
|
||||
del self.last_query_times[path]
|
||||
|
||||
def __call__(self, path, logger=None):
|
||||
path = os.path.abspath(path)
|
||||
self.expire_old_queries()
|
||||
self.last_query_times[path] = monotonic()
|
||||
w = self.watches.get(path, None)
|
||||
if w is None:
|
||||
try:
|
||||
self.watch(path)
|
||||
except NoSuchDir:
|
||||
pass
|
||||
return True
|
||||
try:
|
||||
return w()
|
||||
except DirTooLarge as e:
|
||||
if logger is not None:
|
||||
logger.warn(str(e))
|
||||
self.watches[path] = DummyTreeWatcher(path)
|
||||
return False
|
||||
|
||||
if __name__ == '__main__':
|
||||
w = INotifyTreeWatcher(sys.argv[-1])
|
||||
w()
|
||||
print ('Monitoring', sys.argv[-1], 'press Ctrl-C to stop')
|
||||
try:
|
||||
while True:
|
||||
if w():
|
||||
print (sys.argv[-1], 'changed')
|
||||
sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
raise SystemExit(0)
|
|
@ -0,0 +1,16 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
try:
|
||||
from urllib.error import HTTPError
|
||||
from urllib.request import urlopen
|
||||
from urllib.parse import urlencode as urllib_urlencode # NOQA
|
||||
except ImportError:
|
||||
from urllib2 import urlopen, HTTPError # NOQA
|
||||
from urllib import urlencode as urllib_urlencode # NOQA
|
||||
|
||||
|
||||
def urllib_read(url):
|
||||
try:
|
||||
return urlopen(url, timeout=10).read().decode('utf-8')
|
||||
except HTTPError:
|
||||
return
|
|
@ -0,0 +1,33 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
|
||||
|
||||
vcs_props = (
|
||||
('git', '.git', os.path.exists),
|
||||
('mercurial', '.hg', os.path.isdir),
|
||||
('bzr', '.bzr', os.path.isdir),
|
||||
)
|
||||
|
||||
|
||||
def generate_directories(path):
|
||||
yield path
|
||||
while True:
|
||||
old_path = path
|
||||
path = os.path.dirname(path)
|
||||
if path == old_path or not path:
|
||||
break
|
||||
yield path
|
||||
|
||||
|
||||
def guess(path):
|
||||
for directory in generate_directories(path):
|
||||
for vcs, vcs_dir, check in vcs_props:
|
||||
if check(os.path.join(directory, vcs_dir)):
|
||||
try:
|
||||
if vcs not in globals():
|
||||
globals()[vcs] = getattr(__import__('powerline.lib.vcs', fromlist=[vcs]), vcs)
|
||||
return globals()[vcs].Repository(directory)
|
||||
except:
|
||||
pass
|
||||
return None
|
|
@ -0,0 +1,64 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
from __future__ import absolute_import, unicode_literals, division, print_function
|
||||
|
||||
import sys
|
||||
from io import StringIO
|
||||
|
||||
from bzrlib import (branch, workingtree, status, library_state, trace, ui)
|
||||
|
||||
|
||||
class CoerceIO(StringIO):
|
||||
def write(self, arg):
|
||||
if isinstance(arg, bytes):
|
||||
arg = arg.decode('utf-8', 'replace')
|
||||
return super(CoerceIO, self).write(arg)
|
||||
|
||||
|
||||
class Repository(object):
|
||||
def __init__(self, directory):
|
||||
if isinstance(directory, bytes):
|
||||
directory = directory.decode(sys.getfilesystemencoding() or sys.getdefaultencoding() or 'utf-8')
|
||||
self.directory = directory
|
||||
self.state = library_state.BzrLibraryState(ui=ui.SilentUIFactory, trace=trace.DefaultConfig())
|
||||
|
||||
def status(self, path=None):
|
||||
'''Return status of repository or file.
|
||||
|
||||
Without file argument: returns status of the repository:
|
||||
|
||||
:"D?": dirty (tracked modified files: added, removed, deleted, modified),
|
||||
:"?U": untracked-dirty (added, but not tracked files)
|
||||
:None: clean (status is empty)
|
||||
|
||||
With file argument: returns status of this file: The status codes are
|
||||
those returned by bzr status -S
|
||||
'''
|
||||
try:
|
||||
return self._status(path)
|
||||
except:
|
||||
pass
|
||||
|
||||
def _status(self, path):
|
||||
buf = CoerceIO()
|
||||
w = workingtree.WorkingTree.open(self.directory)
|
||||
status.show_tree_status(w, specific_files=[path] if path else None, to_file=buf, short=True)
|
||||
raw = buf.getvalue()
|
||||
if not raw.strip():
|
||||
return
|
||||
if path:
|
||||
return raw[:2]
|
||||
dirtied = untracked = ' '
|
||||
for line in raw.splitlines():
|
||||
if len(line) > 1 and line[1] in 'ACDMRIN':
|
||||
dirtied = 'D'
|
||||
elif line and line[0] == '?':
|
||||
untracked = 'U'
|
||||
ans = dirtied + untracked
|
||||
return ans if ans.strip() else None
|
||||
|
||||
def branch(self):
|
||||
try:
|
||||
b = branch.Branch.open(self.directory)
|
||||
return b._get_nick(local=True) or None
|
||||
except:
|
||||
pass
|
|
@ -0,0 +1,143 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
try:
|
||||
import pygit2 as git
|
||||
|
||||
class Repository(object):
|
||||
__slots__ = ('directory')
|
||||
|
||||
def __init__(self, directory):
|
||||
self.directory = directory
|
||||
|
||||
def _repo(self):
|
||||
return git.Repository(self.directory)
|
||||
|
||||
def status(self, path=None):
|
||||
'''Return status of repository or file.
|
||||
|
||||
Without file argument: returns status of the repository:
|
||||
|
||||
:First column: working directory status (D: dirty / space)
|
||||
:Second column: index status (I: index dirty / space)
|
||||
:Third column: presense of untracked files (U: untracked files / space)
|
||||
:None: repository clean
|
||||
|
||||
With file argument: returns status of this file. Output is
|
||||
equivalent to the first two columns of "git status --porcelain"
|
||||
(except for merge statuses as they are not supported by libgit2).
|
||||
'''
|
||||
if path:
|
||||
try:
|
||||
status = self._repo().status_file(path)
|
||||
except (KeyError, ValueError):
|
||||
return None
|
||||
|
||||
if status == git.GIT_STATUS_CURRENT:
|
||||
return None
|
||||
else:
|
||||
if status & git.GIT_STATUS_WT_NEW:
|
||||
return '??'
|
||||
if status & git.GIT_STATUS_IGNORED:
|
||||
return '!!'
|
||||
|
||||
if status & git.GIT_STATUS_INDEX_NEW:
|
||||
index_status = 'A'
|
||||
elif status & git.GIT_STATUS_INDEX_DELETED:
|
||||
index_status = 'D'
|
||||
elif status & git.GIT_STATUS_INDEX_MODIFIED:
|
||||
index_status = 'M'
|
||||
else:
|
||||
index_status = ' '
|
||||
|
||||
if status & git.GIT_STATUS_WT_DELETED:
|
||||
wt_status = 'D'
|
||||
elif status & git.GIT_STATUS_WT_MODIFIED:
|
||||
wt_status = 'M'
|
||||
else:
|
||||
wt_status = ' '
|
||||
|
||||
return index_status + wt_status
|
||||
else:
|
||||
wt_column = ' '
|
||||
index_column = ' '
|
||||
untracked_column = ' '
|
||||
for status in self._repo().status().values():
|
||||
if status & git.GIT_STATUS_WT_NEW:
|
||||
untracked_column = 'U'
|
||||
continue
|
||||
|
||||
if status & (git.GIT_STATUS_WT_DELETED
|
||||
| git.GIT_STATUS_WT_MODIFIED):
|
||||
wt_column = 'D'
|
||||
|
||||
if status & (git.GIT_STATUS_INDEX_NEW
|
||||
| git.GIT_STATUS_INDEX_MODIFIED
|
||||
| git.GIT_STATUS_INDEX_DELETED):
|
||||
index_column = 'I'
|
||||
r = wt_column + index_column + untracked_column
|
||||
return r if r != ' ' else None
|
||||
|
||||
def branch(self):
|
||||
try:
|
||||
ref = self._repo().lookup_reference('HEAD')
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
try:
|
||||
target = ref.target
|
||||
except ValueError:
|
||||
return '[DETACHED HEAD]'
|
||||
|
||||
if target.startswith('refs/heads/'):
|
||||
return target[11:]
|
||||
else:
|
||||
return '[DETACHED HEAD]'
|
||||
except ImportError:
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
def readlines(cmd, cwd):
|
||||
p = Popen(cmd, shell=False, stdout=PIPE, stderr=PIPE, cwd=cwd)
|
||||
p.stderr.close()
|
||||
with p.stdout:
|
||||
for line in p.stdout:
|
||||
yield line[:-1].decode('utf-8')
|
||||
|
||||
class Repository(object):
|
||||
__slots__ = ('directory',)
|
||||
|
||||
def __init__(self, directory):
|
||||
self.directory = directory
|
||||
|
||||
def _gitcmd(self, *args):
|
||||
return readlines(('git',) + args, self.directory)
|
||||
|
||||
def status(self, path=None):
|
||||
if path:
|
||||
try:
|
||||
return next(self._gitcmd('status', '--porcelain', '--ignored', '--', path))[:2]
|
||||
except StopIteration:
|
||||
return None
|
||||
else:
|
||||
wt_column = ' '
|
||||
index_column = ' '
|
||||
untracked_column = ' '
|
||||
for line in self._gitcmd('status', '--porcelain'):
|
||||
if line[0] == '?':
|
||||
untracked_column = 'U'
|
||||
continue
|
||||
elif line[0] == '!':
|
||||
continue
|
||||
|
||||
if line[0] != ' ':
|
||||
index_column = 'I'
|
||||
|
||||
if line[1] != ' ':
|
||||
wt_column = 'D'
|
||||
|
||||
r = wt_column + index_column + untracked_column
|
||||
return r if r != ' ' else None
|
||||
|
||||
def branch(self):
|
||||
for line in self._gitcmd('branch', '-l'):
|
||||
if line[0] == '*':
|
||||
return line[2:]
|
||||
return None
|
|
@ -0,0 +1,51 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
from __future__ import absolute_import
|
||||
from mercurial import hg, ui, match
|
||||
|
||||
|
||||
class Repository(object):
|
||||
__slots__ = ('directory', 'ui')
|
||||
|
||||
statuses = 'MARDUI'
|
||||
repo_statuses = (1, 1, 1, 1, 2)
|
||||
repo_statuses_str = (None, 'D ', ' U', 'DU')
|
||||
|
||||
def __init__(self, directory):
|
||||
self.directory = directory
|
||||
self.ui = ui.ui()
|
||||
|
||||
def _repo(self):
|
||||
# Cannot create this object once and use always: when repository updates
|
||||
# functions emit invalid results
|
||||
return hg.repository(self.ui, self.directory)
|
||||
|
||||
def status(self, path=None):
|
||||
'''Return status of repository or file.
|
||||
|
||||
Without file argument: returns status of the repository:
|
||||
|
||||
:"D?": dirty (tracked modified files: added, removed, deleted, modified),
|
||||
:"?U": untracked-dirty (added, but not tracked files)
|
||||
:None: clean (status is empty)
|
||||
|
||||
With file argument: returns status of this file: "M"odified, "A"dded,
|
||||
"R"emoved, "D"eleted (removed from filesystem, but still tracked),
|
||||
"U"nknown, "I"gnored, (None)Clean.
|
||||
'''
|
||||
repo = self._repo()
|
||||
if path:
|
||||
m = match.match(None, None, [path], exact=True)
|
||||
statuses = repo.status(match=m, unknown=True, ignored=True)
|
||||
for status, paths in zip(self.statuses, statuses):
|
||||
if paths:
|
||||
return status
|
||||
return None
|
||||
else:
|
||||
resulting_status = 0
|
||||
for status, paths in zip(self.repo_statuses, repo.status(unknown=True)):
|
||||
if paths:
|
||||
resulting_status |= status
|
||||
return self.repo_statuses_str[resulting_status]
|
||||
|
||||
def branch(self):
|
||||
return self._repo().dirstate.branch()
|
1108
common/.local/lib/python2.7/site-packages/powerline/lint/__init__.py
Normal file
1108
common/.local/lib/python2.7/site-packages/powerline/lint/__init__.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,59 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
from __future__ import absolute_import
|
||||
from inspect import ArgSpec, getargspec
|
||||
from powerline.lib.threaded import ThreadedSegment, KwThreadedSegment
|
||||
from itertools import count
|
||||
|
||||
def getconfigargspec(obj):
|
||||
if isinstance(obj, ThreadedSegment):
|
||||
args = ['interval']
|
||||
defaults = [getattr(obj, 'interval', 1)]
|
||||
if obj.update_first:
|
||||
args.append('update_first')
|
||||
defaults.append(True)
|
||||
methods = ['render', 'set_state']
|
||||
if isinstance(obj, KwThreadedSegment):
|
||||
methods += ['key', 'render_one']
|
||||
|
||||
for method in methods:
|
||||
if hasattr(obj, method):
|
||||
# Note: on <python-2.6 it may return simple tuple, not
|
||||
# ArgSpec instance.
|
||||
argspec = getargspec(getattr(obj, method))
|
||||
for i, arg in zip(count(1), reversed(argspec.args)):
|
||||
if (arg == 'self' or
|
||||
(arg == 'segment_info' and
|
||||
getattr(obj, 'powerline_requires_segment_info', None)) or
|
||||
(arg == 'pl') or
|
||||
(method.startswith('render') and (1 if argspec.args[0] == 'self' else 0) + i == len(argspec.args)) or
|
||||
arg in args):
|
||||
continue
|
||||
if argspec.defaults and len(argspec.defaults) >= i:
|
||||
default = argspec.defaults[-i]
|
||||
defaults.append(default)
|
||||
args.append(arg)
|
||||
else:
|
||||
args.insert(0, arg)
|
||||
argspec = ArgSpec(args=args, varargs=None, keywords=None, defaults=tuple(defaults))
|
||||
else:
|
||||
if hasattr(obj, 'powerline_origin'):
|
||||
obj = obj.powerline_origin
|
||||
else:
|
||||
obj = obj
|
||||
|
||||
argspec = getargspec(obj)
|
||||
args = []
|
||||
defaults = []
|
||||
for i, arg in zip(count(1), reversed(argspec.args)):
|
||||
if ((arg == 'segment_info' and getattr(obj, 'powerline_requires_segment_info', None)) or
|
||||
arg == 'pl'):
|
||||
continue
|
||||
if argspec.defaults and len(argspec.defaults) >= i:
|
||||
default = argspec.defaults[-i]
|
||||
defaults.append(default)
|
||||
args.append(arg)
|
||||
else:
|
||||
args.insert(0, arg)
|
||||
argspec = ArgSpec(args=args, varargs=argspec.varargs, keywords=argspec.keywords, defaults=tuple(defaults))
|
||||
|
||||
return argspec
|
|
@ -0,0 +1,17 @@
|
|||
__version__ = '3.10'
|
||||
|
||||
|
||||
from .loader import Loader
|
||||
|
||||
|
||||
def load(stream, Loader=Loader):
|
||||
"""
|
||||
Parse the first YAML document in a stream
|
||||
and produce the corresponding Python object.
|
||||
"""
|
||||
loader = Loader(stream)
|
||||
try:
|
||||
r = loader.get_single_data()
|
||||
return r, loader.haserrors
|
||||
finally:
|
||||
loader.dispose()
|
|
@ -0,0 +1,117 @@
|
|||
__all__ = ['Composer', 'ComposerError']
|
||||
|
||||
from .error import MarkedError
|
||||
from .events import * # NOQA
|
||||
from .nodes import * # NOQA
|
||||
|
||||
|
||||
class ComposerError(MarkedError):
|
||||
pass
|
||||
|
||||
|
||||
class Composer:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def check_node(self):
|
||||
# Drop the STREAM-START event.
|
||||
if self.check_event(StreamStartEvent):
|
||||
self.get_event()
|
||||
|
||||
# If there are more documents available?
|
||||
return not self.check_event(StreamEndEvent)
|
||||
|
||||
def get_node(self):
|
||||
# Get the root node of the next document.
|
||||
if not self.check_event(StreamEndEvent):
|
||||
return self.compose_document()
|
||||
|
||||
def get_single_node(self):
|
||||
# Drop the STREAM-START event.
|
||||
self.get_event()
|
||||
|
||||
# Compose a document if the stream is not empty.
|
||||
document = None
|
||||
if not self.check_event(StreamEndEvent):
|
||||
document = self.compose_document()
|
||||
|
||||
# Ensure that the stream contains no more documents.
|
||||
if not self.check_event(StreamEndEvent):
|
||||
event = self.get_event()
|
||||
raise ComposerError("expected a single document in the stream",
|
||||
document.start_mark, "but found another document",
|
||||
event.start_mark)
|
||||
|
||||
# Drop the STREAM-END event.
|
||||
self.get_event()
|
||||
|
||||
return document
|
||||
|
||||
def compose_document(self):
|
||||
# Drop the DOCUMENT-START event.
|
||||
self.get_event()
|
||||
|
||||
# Compose the root node.
|
||||
node = self.compose_node(None, None)
|
||||
|
||||
# Drop the DOCUMENT-END event.
|
||||
self.get_event()
|
||||
|
||||
return node
|
||||
|
||||
def compose_node(self, parent, index):
|
||||
self.descend_resolver(parent, index)
|
||||
if self.check_event(ScalarEvent):
|
||||
node = self.compose_scalar_node()
|
||||
elif self.check_event(SequenceStartEvent):
|
||||
node = self.compose_sequence_node()
|
||||
elif self.check_event(MappingStartEvent):
|
||||
node = self.compose_mapping_node()
|
||||
self.ascend_resolver()
|
||||
return node
|
||||
|
||||
def compose_scalar_node(self):
|
||||
event = self.get_event()
|
||||
tag = event.tag
|
||||
if tag is None or tag == '!':
|
||||
tag = self.resolve(ScalarNode, event.value, event.implicit, event.start_mark)
|
||||
node = ScalarNode(tag, event.value,
|
||||
event.start_mark, event.end_mark, style=event.style)
|
||||
return node
|
||||
|
||||
def compose_sequence_node(self):
|
||||
start_event = self.get_event()
|
||||
tag = start_event.tag
|
||||
if tag is None or tag == '!':
|
||||
tag = self.resolve(SequenceNode, None, start_event.implicit)
|
||||
node = SequenceNode(tag, [],
|
||||
start_event.start_mark, None,
|
||||
flow_style=start_event.flow_style)
|
||||
index = 0
|
||||
while not self.check_event(SequenceEndEvent):
|
||||
node.value.append(self.compose_node(node, index))
|
||||
index += 1
|
||||
end_event = self.get_event()
|
||||
node.end_mark = end_event.end_mark
|
||||
return node
|
||||
|
||||
def compose_mapping_node(self):
|
||||
start_event = self.get_event()
|
||||
tag = start_event.tag
|
||||
if tag is None or tag == '!':
|
||||
tag = self.resolve(MappingNode, None, start_event.implicit)
|
||||
node = MappingNode(tag, [],
|
||||
start_event.start_mark, None,
|
||||
flow_style=start_event.flow_style)
|
||||
while not self.check_event(MappingEndEvent):
|
||||
#key_event = self.peek_event()
|
||||
item_key = self.compose_node(node, None)
|
||||
#if item_key in node.value:
|
||||
# raise ComposerError("while composing a mapping", start_event.start_mark,
|
||||
# "found duplicate key", key_event.start_mark)
|
||||
item_value = self.compose_node(node, item_key)
|
||||
#node.value[item_key] = item_value
|
||||
node.value.append((item_key, item_value))
|
||||
end_event = self.get_event()
|
||||
node.end_mark = end_event.end_mark
|
||||
return node
|
|
@ -0,0 +1,274 @@
|
|||
__all__ = ['BaseConstructor', 'Constructor', 'ConstructorError']
|
||||
|
||||
from .error import MarkedError
|
||||
from .nodes import * # NOQA
|
||||
from .markedvalue import gen_marked_value
|
||||
|
||||
import collections
|
||||
import types
|
||||
|
||||
from functools import wraps
|
||||
|
||||
|
||||
try:
|
||||
from __builtin__ import unicode
|
||||
except ImportError:
|
||||
unicode = str # NOQA
|
||||
|
||||
|
||||
def marked(func):
|
||||
@wraps(func)
|
||||
def f(self, node, *args, **kwargs):
|
||||
return gen_marked_value(func(self, node, *args, **kwargs), node.start_mark)
|
||||
return f
|
||||
|
||||
|
||||
class ConstructorError(MarkedError):
|
||||
pass
|
||||
|
||||
|
||||
class BaseConstructor:
|
||||
yaml_constructors = {}
|
||||
|
||||
def __init__(self):
|
||||
self.constructed_objects = {}
|
||||
self.state_generators = []
|
||||
self.deep_construct = False
|
||||
|
||||
def check_data(self):
|
||||
# If there are more documents available?
|
||||
return self.check_node()
|
||||
|
||||
def get_data(self):
|
||||
# Construct and return the next document.
|
||||
if self.check_node():
|
||||
return self.construct_document(self.get_node())
|
||||
|
||||
def get_single_data(self):
|
||||
# Ensure that the stream contains a single document and construct it.
|
||||
node = self.get_single_node()
|
||||
if node is not None:
|
||||
return self.construct_document(node)
|
||||
return None
|
||||
|
||||
def construct_document(self, node):
|
||||
data = self.construct_object(node)
|
||||
while self.state_generators:
|
||||
state_generators = self.state_generators
|
||||
self.state_generators = []
|
||||
for generator in state_generators:
|
||||
for dummy in generator:
|
||||
pass
|
||||
self.constructed_objects = {}
|
||||
self.deep_construct = False
|
||||
return data
|
||||
|
||||
def construct_object(self, node, deep=False):
|
||||
if node in self.constructed_objects:
|
||||
return self.constructed_objects[node]
|
||||
if deep:
|
||||
old_deep = self.deep_construct
|
||||
self.deep_construct = True
|
||||
constructor = None
|
||||
tag_suffix = None
|
||||
if node.tag in self.yaml_constructors:
|
||||
constructor = self.yaml_constructors[node.tag]
|
||||
else:
|
||||
raise ConstructorError(None, None, 'no constructor for tag %s' % node.tag)
|
||||
if tag_suffix is None:
|
||||
data = constructor(self, node)
|
||||
else:
|
||||
data = constructor(self, tag_suffix, node)
|
||||
if isinstance(data, types.GeneratorType):
|
||||
generator = data
|
||||
data = next(generator)
|
||||
if self.deep_construct:
|
||||
for dummy in generator:
|
||||
pass
|
||||
else:
|
||||
self.state_generators.append(generator)
|
||||
self.constructed_objects[node] = data
|
||||
if deep:
|
||||
self.deep_construct = old_deep
|
||||
return data
|
||||
|
||||
@marked
|
||||
def construct_scalar(self, node):
|
||||
if not isinstance(node, ScalarNode):
|
||||
raise ConstructorError(None, None,
|
||||
"expected a scalar node, but found %s" % node.id,
|
||||
node.start_mark)
|
||||
return node.value
|
||||
|
||||
def construct_sequence(self, node, deep=False):
|
||||
if not isinstance(node, SequenceNode):
|
||||
raise ConstructorError(None, None,
|
||||
"expected a sequence node, but found %s" % node.id,
|
||||
node.start_mark)
|
||||
return [self.construct_object(child, deep=deep)
|
||||
for child in node.value]
|
||||
|
||||
@marked
|
||||
def construct_mapping(self, node, deep=False):
|
||||
if not isinstance(node, MappingNode):
|
||||
raise ConstructorError(None, None,
|
||||
"expected a mapping node, but found %s" % node.id,
|
||||
node.start_mark)
|
||||
mapping = {}
|
||||
for key_node, value_node in node.value:
|
||||
key = self.construct_object(key_node, deep=deep)
|
||||
if not isinstance(key, collections.Hashable):
|
||||
self.echoerr('While constructing a mapping', node.start_mark,
|
||||
'found unhashable key', key_node.start_mark)
|
||||
continue
|
||||
elif type(key.value) != unicode:
|
||||
self.echoerr('Error while constructing a mapping', node.start_mark,
|
||||
'found key that is not a string', key_node.start_mark)
|
||||
continue
|
||||
elif key in mapping:
|
||||
self.echoerr('Error while constructing a mapping', node.start_mark,
|
||||
'found duplicate key', key_node.start_mark)
|
||||
continue
|
||||
value = self.construct_object(value_node, deep=deep)
|
||||
mapping[key] = value
|
||||
return mapping
|
||||
|
||||
@classmethod
|
||||
def add_constructor(cls, tag, constructor):
|
||||
if not 'yaml_constructors' in cls.__dict__:
|
||||
cls.yaml_constructors = cls.yaml_constructors.copy()
|
||||
cls.yaml_constructors[tag] = constructor
|
||||
|
||||
|
||||
class Constructor(BaseConstructor):
|
||||
def construct_scalar(self, node):
|
||||
if isinstance(node, MappingNode):
|
||||
for key_node, value_node in node.value:
|
||||
if key_node.tag == 'tag:yaml.org,2002:value':
|
||||
return self.construct_scalar(value_node)
|
||||
return BaseConstructor.construct_scalar(self, node)
|
||||
|
||||
def flatten_mapping(self, node):
|
||||
merge = []
|
||||
index = 0
|
||||
while index < len(node.value):
|
||||
key_node, value_node = node.value[index]
|
||||
if key_node.tag == 'tag:yaml.org,2002:merge':
|
||||
del node.value[index]
|
||||
if isinstance(value_node, MappingNode):
|
||||
self.flatten_mapping(value_node)
|
||||
merge.extend(value_node.value)
|
||||
elif isinstance(value_node, SequenceNode):
|
||||
submerge = []
|
||||
for subnode in value_node.value:
|
||||
if not isinstance(subnode, MappingNode):
|
||||
raise ConstructorError("while constructing a mapping",
|
||||
node.start_mark,
|
||||
"expected a mapping for merging, but found %s"
|
||||
% subnode.id, subnode.start_mark)
|
||||
self.flatten_mapping(subnode)
|
||||
submerge.append(subnode.value)
|
||||
submerge.reverse()
|
||||
for value in submerge:
|
||||
merge.extend(value)
|
||||
else:
|
||||
raise ConstructorError("while constructing a mapping", node.start_mark,
|
||||
"expected a mapping or list of mappings for merging, but found %s"
|
||||
% value_node.id, value_node.start_mark)
|
||||
elif key_node.tag == 'tag:yaml.org,2002:value':
|
||||
key_node.tag = 'tag:yaml.org,2002:str'
|
||||
index += 1
|
||||
else:
|
||||
index += 1
|
||||
if merge:
|
||||
node.value = merge + node.value
|
||||
|
||||
def construct_mapping(self, node, deep=False):
|
||||
if isinstance(node, MappingNode):
|
||||
self.flatten_mapping(node)
|
||||
return BaseConstructor.construct_mapping(self, node, deep=deep)
|
||||
|
||||
@marked
|
||||
def construct_yaml_null(self, node):
|
||||
self.construct_scalar(node)
|
||||
return None
|
||||
|
||||
@marked
|
||||
def construct_yaml_bool(self, node):
|
||||
value = self.construct_scalar(node).value
|
||||
return bool(value)
|
||||
|
||||
@marked
|
||||
def construct_yaml_int(self, node):
|
||||
value = self.construct_scalar(node).value
|
||||
sign = +1
|
||||
if value[0] == '-':
|
||||
sign = -1
|
||||
if value[0] in '+-':
|
||||
value = value[1:]
|
||||
if value == '0':
|
||||
return 0
|
||||
else:
|
||||
return sign * int(value)
|
||||
|
||||
@marked
|
||||
def construct_yaml_float(self, node):
|
||||
value = self.construct_scalar(node).value
|
||||
sign = +1
|
||||
if value[0] == '-':
|
||||
sign = -1
|
||||
if value[0] in '+-':
|
||||
value = value[1:]
|
||||
else:
|
||||
return sign * float(value)
|
||||
|
||||
def construct_yaml_str(self, node):
|
||||
return self.construct_scalar(node)
|
||||
|
||||
def construct_yaml_seq(self, node):
|
||||
data = gen_marked_value([], node.start_mark)
|
||||
yield data
|
||||
data.extend(self.construct_sequence(node))
|
||||
|
||||
def construct_yaml_map(self, node):
|
||||
data = gen_marked_value({}, node.start_mark)
|
||||
yield data
|
||||
value = self.construct_mapping(node)
|
||||
data.update(value)
|
||||
|
||||
def construct_undefined(self, node):
|
||||
raise ConstructorError(None, None,
|
||||
"could not determine a constructor for the tag %r" % node.tag,
|
||||
node.start_mark)
|
||||
|
||||
|
||||
Constructor.add_constructor(
|
||||
'tag:yaml.org,2002:null',
|
||||
Constructor.construct_yaml_null)
|
||||
|
||||
Constructor.add_constructor(
|
||||
'tag:yaml.org,2002:bool',
|
||||
Constructor.construct_yaml_bool)
|
||||
|
||||
Constructor.add_constructor(
|
||||
'tag:yaml.org,2002:int',
|
||||
Constructor.construct_yaml_int)
|
||||
|
||||
Constructor.add_constructor(
|
||||
'tag:yaml.org,2002:float',
|
||||
Constructor.construct_yaml_float)
|
||||
|
||||
Constructor.add_constructor(
|
||||
'tag:yaml.org,2002:str',
|
||||
Constructor.construct_yaml_str)
|
||||
|
||||
Constructor.add_constructor(
|
||||
'tag:yaml.org,2002:seq',
|
||||
Constructor.construct_yaml_seq)
|
||||
|
||||
Constructor.add_constructor(
|
||||
'tag:yaml.org,2002:map',
|
||||
Constructor.construct_yaml_map)
|
||||
|
||||
Constructor.add_constructor(None,
|
||||
Constructor.construct_undefined)
|
|
@ -0,0 +1,99 @@
|
|||
__all__ = ['Mark', 'MarkedError', 'echoerr', 'NON_PRINTABLE']
|
||||
|
||||
|
||||
import sys
|
||||
import re
|
||||
|
||||
try:
|
||||
from __builtin__ import unichr
|
||||
except ImportError:
|
||||
unichr = chr # NOQA
|
||||
|
||||
|
||||
NON_PRINTABLE = re.compile('[^\t\n\x20-\x7E' + unichr(0x85) + (unichr(0xA0) + '-' + unichr(0xD7FF)) + (unichr(0xE000) + '-' + unichr(0xFFFD)) + ']')
|
||||
|
||||
|
||||
def repl(s):
|
||||
return '<x%04x>' % ord(s.group())
|
||||
|
||||
|
||||
def strtrans(s):
|
||||
return NON_PRINTABLE.sub(repl, s.replace('\t', '>---'))
|
||||
|
||||
|
||||
class Mark:
|
||||
def __init__(self, name, line, column, buffer, pointer):
|
||||
self.name = name
|
||||
self.line = line
|
||||
self.column = column
|
||||
self.buffer = buffer
|
||||
self.pointer = pointer
|
||||
|
||||
def copy(self):
|
||||
return Mark(self.name, self.line, self.column, self.buffer, self.pointer)
|
||||
|
||||
def get_snippet(self, indent=4, max_length=75):
|
||||
if self.buffer is None:
|
||||
return None
|
||||
head = ''
|
||||
start = self.pointer
|
||||
while start > 0 and self.buffer[start - 1] not in '\0\n':
|
||||
start -= 1
|
||||
if self.pointer - start > max_length / 2 - 1:
|
||||
head = ' ... '
|
||||
start += 5
|
||||
break
|
||||
tail = ''
|
||||
end = self.pointer
|
||||
while end < len(self.buffer) and self.buffer[end] not in '\0\n':
|
||||
end += 1
|
||||
if end - self.pointer > max_length / 2 - 1:
|
||||
tail = ' ... '
|
||||
end -= 5
|
||||
break
|
||||
snippet = [self.buffer[start:self.pointer], self.buffer[self.pointer], self.buffer[self.pointer + 1:end]]
|
||||
snippet = [strtrans(s) for s in snippet]
|
||||
return ' ' * indent + head + ''.join(snippet) + tail + '\n' \
|
||||
+ ' ' * (indent + len(head) + len(snippet[0])) + '^'
|
||||
|
||||
def __str__(self):
|
||||
snippet = self.get_snippet()
|
||||
where = " in \"%s\", line %d, column %d" \
|
||||
% (self.name, self.line + 1, self.column + 1)
|
||||
if snippet is not None:
|
||||
where += ":\n" + snippet
|
||||
if type(where) is str:
|
||||
return where
|
||||
else:
|
||||
return where.encode('utf-8')
|
||||
|
||||
|
||||
def echoerr(*args, **kwargs):
|
||||
sys.stderr.write('\n')
|
||||
sys.stderr.write(format_error(*args, **kwargs) + '\n')
|
||||
|
||||
|
||||
def format_error(context=None, context_mark=None, problem=None, problem_mark=None, note=None):
|
||||
lines = []
|
||||
if context is not None:
|
||||
lines.append(context)
|
||||
if context_mark is not None \
|
||||
and (problem is None or problem_mark is None
|
||||
or context_mark.name != problem_mark.name
|
||||
or context_mark.line != problem_mark.line
|
||||
or context_mark.column != problem_mark.column):
|
||||
lines.append(str(context_mark))
|
||||
if problem is not None:
|
||||
lines.append(problem)
|
||||
if problem_mark is not None:
|
||||
lines.append(str(problem_mark))
|
||||
if note is not None:
|
||||
lines.append(note)
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
class MarkedError(Exception):
|
||||
def __init__(self, context=None, context_mark=None,
|
||||
problem=None, problem_mark=None, note=None):
|
||||
Exception.__init__(self, format_error(context, context_mark, problem,
|
||||
problem_mark, note))
|
|
@ -0,0 +1,97 @@
|
|||
# Abstract classes.
|
||||
|
||||
|
||||
class Event(object):
|
||||
def __init__(self, start_mark=None, end_mark=None):
|
||||
self.start_mark = start_mark
|
||||
self.end_mark = end_mark
|
||||
|
||||
def __repr__(self):
|
||||
attributes = [key for key in ['implicit', 'value']
|
||||
if hasattr(self, key)]
|
||||
arguments = ', '.join(['%s=%r' % (key, getattr(self, key))
|
||||
for key in attributes])
|
||||
return '%s(%s)' % (self.__class__.__name__, arguments)
|
||||
|
||||
|
||||
class NodeEvent(Event):
|
||||
def __init__(self, start_mark=None, end_mark=None):
|
||||
self.start_mark = start_mark
|
||||
self.end_mark = end_mark
|
||||
|
||||
|
||||
class CollectionStartEvent(NodeEvent):
|
||||
def __init__(self, implicit, start_mark=None, end_mark=None,
|
||||
flow_style=None):
|
||||
self.tag = None
|
||||
self.implicit = implicit
|
||||
self.start_mark = start_mark
|
||||
self.end_mark = end_mark
|
||||
self.flow_style = flow_style
|
||||
|
||||
|
||||
class CollectionEndEvent(Event):
|
||||
pass
|
||||
|
||||
|
||||
# Implementations.
|
||||
|
||||
|
||||
class StreamStartEvent(Event):
|
||||
def __init__(self, start_mark=None, end_mark=None, encoding=None):
|
||||
self.start_mark = start_mark
|
||||
self.end_mark = end_mark
|
||||
self.encoding = encoding
|
||||
|
||||
|
||||
class StreamEndEvent(Event):
|
||||
pass
|
||||
|
||||
|
||||
class DocumentStartEvent(Event):
|
||||
def __init__(self, start_mark=None, end_mark=None,
|
||||
explicit=None, version=None, tags=None):
|
||||
self.start_mark = start_mark
|
||||
self.end_mark = end_mark
|
||||
self.explicit = explicit
|
||||
self.version = version
|
||||
self.tags = tags
|
||||
|
||||
|
||||
class DocumentEndEvent(Event):
|
||||
def __init__(self, start_mark=None, end_mark=None,
|
||||
explicit=None):
|
||||
self.start_mark = start_mark
|
||||
self.end_mark = end_mark
|
||||
self.explicit = explicit
|
||||
|
||||
|
||||
class AliasEvent(NodeEvent):
|
||||
pass
|
||||
|
||||
|
||||
class ScalarEvent(NodeEvent):
|
||||
def __init__(self, implicit, value,
|
||||
start_mark=None, end_mark=None, style=None):
|
||||
self.tag = None
|
||||
self.implicit = implicit
|
||||
self.value = value
|
||||
self.start_mark = start_mark
|
||||
self.end_mark = end_mark
|
||||
self.style = style
|
||||
|
||||
|
||||
class SequenceStartEvent(CollectionStartEvent):
|
||||
pass
|
||||
|
||||
|
||||
class SequenceEndEvent(CollectionEndEvent):
|
||||
pass
|
||||
|
||||
|
||||
class MappingStartEvent(CollectionStartEvent):
|
||||
pass
|
||||
|
||||
|
||||
class MappingEndEvent(CollectionEndEvent):
|
||||
pass
|
|
@ -0,0 +1,24 @@
|
|||
__all__ = ['Loader']
|
||||
|
||||
from .reader import Reader
|
||||
from .scanner import Scanner
|
||||
from .parser import Parser
|
||||
from .composer import Composer
|
||||
from .constructor import Constructor
|
||||
from .resolver import Resolver
|
||||
from .error import echoerr
|
||||
|
||||
|
||||
class Loader(Reader, Scanner, Parser, Composer, Constructor, Resolver):
|
||||
def __init__(self, stream):
|
||||
Reader.__init__(self, stream)
|
||||
Scanner.__init__(self)
|
||||
Parser.__init__(self)
|
||||
Composer.__init__(self)
|
||||
Constructor.__init__(self)
|
||||
Resolver.__init__(self)
|
||||
self.haserrors = False
|
||||
|
||||
def echoerr(self, *args, **kwargs):
|
||||
echoerr(*args, **kwargs)
|
||||
self.haserrors = True
|
|
@ -0,0 +1,83 @@
|
|||
__all__ = ['gen_marked_value', 'MarkedValue']
|
||||
|
||||
|
||||
try:
|
||||
from __builtin__ import unicode
|
||||
except ImportError:
|
||||
unicode = str
|
||||
|
||||
|
||||
def gen_new(cls):
|
||||
def __new__(arg_cls, value, mark):
|
||||
r = super(arg_cls, arg_cls).__new__(arg_cls, value)
|
||||
r.mark = mark
|
||||
r.value = value
|
||||
return r
|
||||
return __new__
|
||||
|
||||
|
||||
class MarkedUnicode(unicode):
|
||||
__new__ = gen_new(unicode)
|
||||
|
||||
def _proc_partition(self, part_result):
|
||||
pointdiff = 1
|
||||
r = []
|
||||
for s in part_result:
|
||||
mark = self.mark.copy()
|
||||
# XXX Does not work properly with escaped strings, but this requires
|
||||
# saving much more information in mark.
|
||||
mark.column += pointdiff
|
||||
mark.pointer += pointdiff
|
||||
r.append(MarkedUnicode(s, mark))
|
||||
pointdiff += len(s)
|
||||
return tuple(r)
|
||||
|
||||
def rpartition(self, sep):
|
||||
return self._proc_partition(super(MarkedUnicode, self).rpartition(sep))
|
||||
|
||||
def partition(self, sep):
|
||||
return self._proc_partition(super(MarkedUnicode, self).partition(sep))
|
||||
|
||||
|
||||
class MarkedInt(int):
|
||||
__new__ = gen_new(int)
|
||||
|
||||
|
||||
class MarkedFloat(float):
|
||||
__new__ = gen_new(float)
|
||||
|
||||
|
||||
class MarkedValue:
|
||||
def __init__(self, value, mark):
|
||||
self.mark = mark
|
||||
self.value = value
|
||||
|
||||
|
||||
specialclasses = {
|
||||
unicode: MarkedUnicode,
|
||||
int: MarkedInt,
|
||||
float: MarkedFloat,
|
||||
}
|
||||
|
||||
classcache = {}
|
||||
|
||||
|
||||
def gen_marked_value(value, mark, use_special_classes=True):
|
||||
if use_special_classes and value.__class__ in specialclasses:
|
||||
Marked = specialclasses[value.__class__]
|
||||
elif value.__class__ in classcache:
|
||||
Marked = classcache[value.__class__]
|
||||
else:
|
||||
class Marked(MarkedValue):
|
||||
for func in value.__class__.__dict__:
|
||||
if func not in set(('__init__', '__new__', '__getattribute__')):
|
||||
if func in set(('__eq__',)):
|
||||
# HACK to make marked dictionaries always work
|
||||
exec (('def {0}(self, *args):\n'
|
||||
' return self.value.{0}(*[arg.value if isinstance(arg, MarkedValue) else arg for arg in args])').format(func))
|
||||
else:
|
||||
exec (('def {0}(self, *args, **kwargs):\n'
|
||||
' return self.value.{0}(*args, **kwargs)\n').format(func))
|
||||
classcache[value.__class__] = Marked
|
||||
|
||||
return Marked(value, mark)
|
|
@ -0,0 +1,53 @@
|
|||
class Node(object):
|
||||
def __init__(self, tag, value, start_mark, end_mark):
|
||||
self.tag = tag
|
||||
self.value = value
|
||||
self.start_mark = start_mark
|
||||
self.end_mark = end_mark
|
||||
|
||||
def __repr__(self):
|
||||
value = self.value
|
||||
#if isinstance(value, list):
|
||||
# if len(value) == 0:
|
||||
# value = '<empty>'
|
||||
# elif len(value) == 1:
|
||||
# value = '<1 item>'
|
||||
# else:
|
||||
# value = '<%d items>' % len(value)
|
||||
#else:
|
||||
# if len(value) > 75:
|
||||
# value = repr(value[:70]+u' ... ')
|
||||
# else:
|
||||
# value = repr(value)
|
||||
value = repr(value)
|
||||
return '%s(tag=%r, value=%s)' % (self.__class__.__name__, self.tag, value)
|
||||
|
||||
|
||||
class ScalarNode(Node):
|
||||
id = 'scalar'
|
||||
|
||||
def __init__(self, tag, value,
|
||||
start_mark=None, end_mark=None, style=None):
|
||||
self.tag = tag
|
||||
self.value = value
|
||||
self.start_mark = start_mark
|
||||
self.end_mark = end_mark
|
||||
self.style = style
|
||||
|
||||
|
||||
class CollectionNode(Node):
|
||||
def __init__(self, tag, value,
|
||||
start_mark=None, end_mark=None, flow_style=None):
|
||||
self.tag = tag
|
||||
self.value = value
|
||||
self.start_mark = start_mark
|
||||
self.end_mark = end_mark
|
||||
self.flow_style = flow_style
|
||||
|
||||
|
||||
class SequenceNode(CollectionNode):
|
||||
id = 'sequence'
|
||||
|
||||
|
||||
class MappingNode(CollectionNode):
|
||||
id = 'mapping'
|
|
@ -0,0 +1,240 @@
|
|||
__all__ = ['Parser', 'ParserError']
|
||||
|
||||
from .error import MarkedError
|
||||
from .tokens import * # NOQA
|
||||
from .events import * # NOQA
|
||||
|
||||
|
||||
class ParserError(MarkedError):
|
||||
pass
|
||||
|
||||
|
||||
class Parser:
|
||||
def __init__(self):
|
||||
self.current_event = None
|
||||
self.yaml_version = None
|
||||
self.states = []
|
||||
self.marks = []
|
||||
self.state = self.parse_stream_start
|
||||
|
||||
def dispose(self):
|
||||
# Reset the state attributes (to clear self-references)
|
||||
self.states = []
|
||||
self.state = None
|
||||
|
||||
def check_event(self, *choices):
|
||||
# Check the type of the next event.
|
||||
if self.current_event is None:
|
||||
if self.state:
|
||||
self.current_event = self.state()
|
||||
if self.current_event is not None:
|
||||
if not choices:
|
||||
return True
|
||||
for choice in choices:
|
||||
if isinstance(self.current_event, choice):
|
||||
return True
|
||||
return False
|
||||
|
||||
def peek_event(self):
|
||||
# Get the next event.
|
||||
if self.current_event is None:
|
||||
if self.state:
|
||||
self.current_event = self.state()
|
||||
return self.current_event
|
||||
|
||||
def get_event(self):
|
||||
# Get the next event and proceed further.
|
||||
if self.current_event is None:
|
||||
if self.state:
|
||||
self.current_event = self.state()
|
||||
value = self.current_event
|
||||
self.current_event = None
|
||||
return value
|
||||
|
||||
# stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
|
||||
# implicit_document ::= block_node DOCUMENT-END*
|
||||
# explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
||||
|
||||
def parse_stream_start(self):
|
||||
# Parse the stream start.
|
||||
token = self.get_token()
|
||||
event = StreamStartEvent(token.start_mark, token.end_mark,
|
||||
encoding=token.encoding)
|
||||
|
||||
# Prepare the next state.
|
||||
self.state = self.parse_implicit_document_start
|
||||
|
||||
return event
|
||||
|
||||
def parse_implicit_document_start(self):
|
||||
# Parse an implicit document.
|
||||
if not self.check_token(StreamEndToken):
|
||||
token = self.peek_token()
|
||||
start_mark = end_mark = token.start_mark
|
||||
event = DocumentStartEvent(start_mark, end_mark, explicit=False)
|
||||
|
||||
# Prepare the next state.
|
||||
self.states.append(self.parse_document_end)
|
||||
self.state = self.parse_node
|
||||
|
||||
return event
|
||||
|
||||
else:
|
||||
return self.parse_document_start()
|
||||
|
||||
def parse_document_start(self):
|
||||
# Parse an explicit document.
|
||||
if not self.check_token(StreamEndToken):
|
||||
token = self.peek_token()
|
||||
self.echoerr(None, None,
|
||||
"expected '<stream end>', but found %r" % token.id,
|
||||
token.start_mark)
|
||||
return StreamEndEvent(token.start_mark, token.end_mark)
|
||||
else:
|
||||
# Parse the end of the stream.
|
||||
token = self.get_token()
|
||||
event = StreamEndEvent(token.start_mark, token.end_mark)
|
||||
assert not self.states
|
||||
assert not self.marks
|
||||
self.state = None
|
||||
return event
|
||||
|
||||
def parse_document_end(self):
|
||||
# Parse the document end.
|
||||
token = self.peek_token()
|
||||
start_mark = end_mark = token.start_mark
|
||||
explicit = False
|
||||
event = DocumentEndEvent(start_mark, end_mark, explicit=explicit)
|
||||
|
||||
# Prepare the next state.
|
||||
self.state = self.parse_document_start
|
||||
|
||||
return event
|
||||
|
||||
def parse_document_content(self):
|
||||
return self.parse_node()
|
||||
|
||||
def parse_node(self, indentless_sequence=False):
|
||||
start_mark = end_mark = None
|
||||
if start_mark is None:
|
||||
start_mark = end_mark = self.peek_token().start_mark
|
||||
event = None
|
||||
implicit = True
|
||||
if self.check_token(ScalarToken):
|
||||
token = self.get_token()
|
||||
end_mark = token.end_mark
|
||||
if token.plain:
|
||||
implicit = (True, False)
|
||||
else:
|
||||
implicit = (False, True)
|
||||
event = ScalarEvent(implicit, token.value,
|
||||
start_mark, end_mark, style=token.style)
|
||||
self.state = self.states.pop()
|
||||
elif self.check_token(FlowSequenceStartToken):
|
||||
end_mark = self.peek_token().end_mark
|
||||
event = SequenceStartEvent(implicit,
|
||||
start_mark, end_mark, flow_style=True)
|
||||
self.state = self.parse_flow_sequence_first_entry
|
||||
elif self.check_token(FlowMappingStartToken):
|
||||
end_mark = self.peek_token().end_mark
|
||||
event = MappingStartEvent(implicit,
|
||||
start_mark, end_mark, flow_style=True)
|
||||
self.state = self.parse_flow_mapping_first_key
|
||||
else:
|
||||
token = self.peek_token()
|
||||
raise ParserError("while parsing a flow node", start_mark,
|
||||
"expected the node content, but found %r" % token.id,
|
||||
token.start_mark)
|
||||
return event
|
||||
|
||||
def parse_flow_sequence_first_entry(self):
|
||||
token = self.get_token()
|
||||
self.marks.append(token.start_mark)
|
||||
return self.parse_flow_sequence_entry(first=True)
|
||||
|
||||
def parse_flow_sequence_entry(self, first=False):
|
||||
if not self.check_token(FlowSequenceEndToken):
|
||||
if not first:
|
||||
if self.check_token(FlowEntryToken):
|
||||
self.get_token()
|
||||
if self.check_token(FlowSequenceEndToken):
|
||||
token = self.peek_token()
|
||||
self.echoerr("While parsing a flow sequence", self.marks[-1],
|
||||
"expected sequence value, but got %r" % token.id, token.start_mark)
|
||||
else:
|
||||
token = self.peek_token()
|
||||
raise ParserError("while parsing a flow sequence", self.marks[-1],
|
||||
"expected ',' or ']', but got %r" % token.id, token.start_mark)
|
||||
|
||||
if not self.check_token(FlowSequenceEndToken):
|
||||
self.states.append(self.parse_flow_sequence_entry)
|
||||
return self.parse_node()
|
||||
token = self.get_token()
|
||||
event = SequenceEndEvent(token.start_mark, token.end_mark)
|
||||
self.state = self.states.pop()
|
||||
self.marks.pop()
|
||||
return event
|
||||
|
||||
def parse_flow_sequence_entry_mapping_end(self):
|
||||
self.state = self.parse_flow_sequence_entry
|
||||
token = self.peek_token()
|
||||
return MappingEndEvent(token.start_mark, token.start_mark)
|
||||
|
||||
def parse_flow_mapping_first_key(self):
|
||||
token = self.get_token()
|
||||
self.marks.append(token.start_mark)
|
||||
return self.parse_flow_mapping_key(first=True)
|
||||
|
||||
def parse_flow_mapping_key(self, first=False):
|
||||
if not self.check_token(FlowMappingEndToken):
|
||||
if not first:
|
||||
if self.check_token(FlowEntryToken):
|
||||
self.get_token()
|
||||
if self.check_token(FlowMappingEndToken):
|
||||
token = self.peek_token()
|
||||
self.echoerr("While parsing a flow mapping", self.marks[-1],
|
||||
"expected mapping key, but got %r" % token.id, token.start_mark)
|
||||
else:
|
||||
token = self.peek_token()
|
||||
raise ParserError("while parsing a flow mapping", self.marks[-1],
|
||||
"expected ',' or '}', but got %r" % token.id, token.start_mark)
|
||||
if self.check_token(KeyToken):
|
||||
token = self.get_token()
|
||||
if not self.check_token(ValueToken,
|
||||
FlowEntryToken, FlowMappingEndToken):
|
||||
self.states.append(self.parse_flow_mapping_value)
|
||||
return self.parse_node()
|
||||
else:
|
||||
token = self.peek_token()
|
||||
raise ParserError("while parsing a flow mapping", self.marks[-1],
|
||||
"expected value, but got %r" % token.id, token.start_mark)
|
||||
elif not self.check_token(FlowMappingEndToken):
|
||||
token = self.peek_token()
|
||||
expect_key = self.check_token(ValueToken, FlowEntryToken)
|
||||
if not expect_key:
|
||||
self.get_token()
|
||||
expect_key = self.check_token(ValueToken)
|
||||
|
||||
if expect_key:
|
||||
raise ParserError("while parsing a flow mapping", self.marks[-1],
|
||||
"expected string key, but got %r" % token.id, token.start_mark)
|
||||
else:
|
||||
token = self.peek_token()
|
||||
raise ParserError("while parsing a flow mapping", self.marks[-1],
|
||||
"expected ':', but got %r" % token.id, token.start_mark)
|
||||
token = self.get_token()
|
||||
event = MappingEndEvent(token.start_mark, token.end_mark)
|
||||
self.state = self.states.pop()
|
||||
self.marks.pop()
|
||||
return event
|
||||
|
||||
def parse_flow_mapping_value(self):
|
||||
if self.check_token(ValueToken):
|
||||
token = self.get_token()
|
||||
if not self.check_token(FlowEntryToken, FlowMappingEndToken):
|
||||
self.states.append(self.parse_flow_mapping_key)
|
||||
return self.parse_node()
|
||||
|
||||
token = self.peek_token()
|
||||
raise ParserError("while parsing a flow mapping", self.marks[-1],
|
||||
"expected mapping value, but got %r" % token.id, token.start_mark)
|
|
@ -0,0 +1,135 @@
|
|||
# This module contains abstractions for the input stream. You don't have to
|
||||
# looks further, there are no pretty code.
|
||||
|
||||
__all__ = ['Reader', 'ReaderError']
|
||||
|
||||
from .error import MarkedError, Mark, NON_PRINTABLE
|
||||
|
||||
import codecs
|
||||
|
||||
try:
|
||||
from __builtin__ import unicode
|
||||
except ImportError:
|
||||
unicode = str # NOQA
|
||||
|
||||
|
||||
class ReaderError(MarkedError):
|
||||
pass
|
||||
|
||||
|
||||
class Reader(object):
|
||||
# Reader:
|
||||
# - determines the data encoding and converts it to a unicode string,
|
||||
# - checks if characters are in allowed range,
|
||||
# - adds '\0' to the end.
|
||||
|
||||
# Reader accepts
|
||||
# - a file-like object with its `read` method returning `str`,
|
||||
|
||||
# Yeah, it's ugly and slow.
|
||||
def __init__(self, stream):
|
||||
self.name = None
|
||||
self.stream = None
|
||||
self.stream_pointer = 0
|
||||
self.eof = True
|
||||
self.buffer = ''
|
||||
self.pointer = 0
|
||||
self.full_buffer = unicode('')
|
||||
self.full_pointer = 0
|
||||
self.raw_buffer = None
|
||||
self.raw_decode = codecs.utf_8_decode
|
||||
self.encoding = 'utf-8'
|
||||
self.index = 0
|
||||
self.line = 0
|
||||
self.column = 0
|
||||
|
||||
self.stream = stream
|
||||
self.name = getattr(stream, 'name', "<file>")
|
||||
self.eof = False
|
||||
self.raw_buffer = None
|
||||
|
||||
while not self.eof and (self.raw_buffer is None or len(self.raw_buffer) < 2):
|
||||
self.update_raw()
|
||||
self.update(1)
|
||||
|
||||
def peek(self, index=0):
|
||||
try:
|
||||
return self.buffer[self.pointer + index]
|
||||
except IndexError:
|
||||
self.update(index + 1)
|
||||
return self.buffer[self.pointer + index]
|
||||
|
||||
def prefix(self, length=1):
|
||||
if self.pointer + length >= len(self.buffer):
|
||||
self.update(length)
|
||||
return self.buffer[self.pointer:self.pointer + length]
|
||||
|
||||
def update_pointer(self, length):
|
||||
while length:
|
||||
ch = self.buffer[self.pointer]
|
||||
self.pointer += 1
|
||||
self.full_pointer += 1
|
||||
self.index += 1
|
||||
if ch == '\n':
|
||||
self.line += 1
|
||||
self.column = 0
|
||||
else:
|
||||
self.column += 1
|
||||
length -= 1
|
||||
|
||||
def forward(self, length=1):
|
||||
if self.pointer + length + 1 >= len(self.buffer):
|
||||
self.update(length + 1)
|
||||
self.update_pointer(length)
|
||||
|
||||
def get_mark(self):
|
||||
return Mark(self.name, self.line, self.column, self.full_buffer, self.full_pointer)
|
||||
|
||||
def check_printable(self, data):
|
||||
match = NON_PRINTABLE.search(data)
|
||||
if match:
|
||||
self.update_pointer(match.start())
|
||||
raise ReaderError('while reading from stream', None,
|
||||
'found special characters which are not allowed',
|
||||
Mark(self.name, self.line, self.column, self.full_buffer, self.full_pointer))
|
||||
|
||||
def update(self, length):
|
||||
if self.raw_buffer is None:
|
||||
return
|
||||
self.buffer = self.buffer[self.pointer:]
|
||||
self.pointer = 0
|
||||
while len(self.buffer) < length:
|
||||
if not self.eof:
|
||||
self.update_raw()
|
||||
try:
|
||||
data, converted = self.raw_decode(self.raw_buffer,
|
||||
'strict', self.eof)
|
||||
except UnicodeDecodeError as exc:
|
||||
character = self.raw_buffer[exc.start]
|
||||
position = self.stream_pointer - len(self.raw_buffer) + exc.start
|
||||
data, converted = self.raw_decode(self.raw_buffer[:exc.start], 'strict', self.eof)
|
||||
self.buffer += data
|
||||
self.full_buffer += data + '<' + str(ord(character)) + '>'
|
||||
self.raw_buffer = self.raw_buffer[converted:]
|
||||
self.update_pointer(exc.start - 1)
|
||||
raise ReaderError('while reading from stream', None,
|
||||
'found character #x%04x that cannot be decoded by UTF-8 codec' % ord(character),
|
||||
Mark(self.name, self.line, self.column, self.full_buffer, position))
|
||||
self.buffer += data
|
||||
self.full_buffer += data
|
||||
self.raw_buffer = self.raw_buffer[converted:]
|
||||
self.check_printable(data)
|
||||
if self.eof:
|
||||
self.buffer += '\0'
|
||||
self.raw_buffer = None
|
||||
break
|
||||
|
||||
def update_raw(self, size=4096):
|
||||
data = self.stream.read(size)
|
||||
if self.raw_buffer is None:
|
||||
self.raw_buffer = data
|
||||
else:
|
||||
self.raw_buffer += data
|
||||
self.stream_pointer += len(data)
|
||||
if not data:
|
||||
self.eof = True
|
|
@ -0,0 +1,131 @@
|
|||
__all__ = ['BaseResolver', 'Resolver']
|
||||
|
||||
from .error import MarkedError
|
||||
from .nodes import * # NOQA
|
||||
|
||||
import re
|
||||
|
||||
|
||||
class ResolverError(MarkedError):
|
||||
pass
|
||||
|
||||
|
||||
class BaseResolver:
|
||||
DEFAULT_SCALAR_TAG = 'tag:yaml.org,2002:str'
|
||||
DEFAULT_SEQUENCE_TAG = 'tag:yaml.org,2002:seq'
|
||||
DEFAULT_MAPPING_TAG = 'tag:yaml.org,2002:map'
|
||||
|
||||
yaml_implicit_resolvers = {}
|
||||
yaml_path_resolvers = {}
|
||||
|
||||
def __init__(self):
|
||||
self.resolver_exact_paths = []
|
||||
self.resolver_prefix_paths = []
|
||||
|
||||
@classmethod
|
||||
def add_implicit_resolver(cls, tag, regexp, first):
|
||||
if not 'yaml_implicit_resolvers' in cls.__dict__:
|
||||
cls.yaml_implicit_resolvers = cls.yaml_implicit_resolvers.copy()
|
||||
if first is None:
|
||||
first = [None]
|
||||
for ch in first:
|
||||
cls.yaml_implicit_resolvers.setdefault(ch, []).append((tag, regexp))
|
||||
|
||||
def descend_resolver(self, current_node, current_index):
|
||||
if not self.yaml_path_resolvers:
|
||||
return
|
||||
exact_paths = {}
|
||||
prefix_paths = []
|
||||
if current_node:
|
||||
depth = len(self.resolver_prefix_paths)
|
||||
for path, kind in self.resolver_prefix_paths[-1]:
|
||||
if self.check_resolver_prefix(depth, path, kind,
|
||||
current_node, current_index):
|
||||
if len(path) > depth:
|
||||
prefix_paths.append((path, kind))
|
||||
else:
|
||||
exact_paths[kind] = self.yaml_path_resolvers[path, kind]
|
||||
else:
|
||||
for path, kind in self.yaml_path_resolvers:
|
||||
if not path:
|
||||
exact_paths[kind] = self.yaml_path_resolvers[path, kind]
|
||||
else:
|
||||
prefix_paths.append((path, kind))
|
||||
self.resolver_exact_paths.append(exact_paths)
|
||||
self.resolver_prefix_paths.append(prefix_paths)
|
||||
|
||||
def ascend_resolver(self):
|
||||
if not self.yaml_path_resolvers:
|
||||
return
|
||||
self.resolver_exact_paths.pop()
|
||||
self.resolver_prefix_paths.pop()
|
||||
|
||||
def check_resolver_prefix(self, depth, path, kind,
|
||||
current_node, current_index):
|
||||
node_check, index_check = path[depth - 1]
|
||||
if isinstance(node_check, str):
|
||||
if current_node.tag != node_check:
|
||||
return
|
||||
elif node_check is not None:
|
||||
if not isinstance(current_node, node_check):
|
||||
return
|
||||
if index_check is True and current_index is not None:
|
||||
return
|
||||
if (index_check is False or index_check is None) \
|
||||
and current_index is None:
|
||||
return
|
||||
if isinstance(index_check, str):
|
||||
if not (isinstance(current_index, ScalarNode)
|
||||
and index_check == current_index.value):
|
||||
return
|
||||
elif isinstance(index_check, int) and not isinstance(index_check, bool):
|
||||
if index_check != current_index:
|
||||
return
|
||||
return True
|
||||
|
||||
def resolve(self, kind, value, implicit, mark=None):
|
||||
if kind is ScalarNode and implicit[0]:
|
||||
if value == '':
|
||||
resolvers = self.yaml_implicit_resolvers.get('', [])
|
||||
else:
|
||||
resolvers = self.yaml_implicit_resolvers.get(value[0], [])
|
||||
resolvers += self.yaml_implicit_resolvers.get(None, [])
|
||||
for tag, regexp in resolvers:
|
||||
if regexp.match(value):
|
||||
return tag
|
||||
else:
|
||||
self.echoerr('While resolving plain scalar', None,
|
||||
'expected floating-point value, integer, null or boolean, but got %r' % value,
|
||||
mark)
|
||||
return self.DEFAULT_SCALAR_TAG
|
||||
if kind is ScalarNode:
|
||||
return self.DEFAULT_SCALAR_TAG
|
||||
elif kind is SequenceNode:
|
||||
return self.DEFAULT_SEQUENCE_TAG
|
||||
elif kind is MappingNode:
|
||||
return self.DEFAULT_MAPPING_TAG
|
||||
|
||||
|
||||
class Resolver(BaseResolver):
|
||||
pass
|
||||
|
||||
|
||||
Resolver.add_implicit_resolver(
|
||||
'tag:yaml.org,2002:bool',
|
||||
re.compile(r'''^(?:true|false)$''', re.X),
|
||||
list('yYnNtTfFoO'))
|
||||
|
||||
Resolver.add_implicit_resolver(
|
||||
'tag:yaml.org,2002:float',
|
||||
re.compile(r'^-?(?:0|[1-9]\d*)(?=[.eE])(?:\.\d+)?(?:[eE][-+]?\d+)?$', re.X),
|
||||
list('-0123456789'))
|
||||
|
||||
Resolver.add_implicit_resolver(
|
||||
'tag:yaml.org,2002:int',
|
||||
re.compile(r'^(?:0|-?[1-9]\d*)$', re.X),
|
||||
list('-0123456789'))
|
||||
|
||||
Resolver.add_implicit_resolver(
|
||||
'tag:yaml.org,2002:null',
|
||||
re.compile(r'^null$', re.X),
|
||||
['n'])
|
|
@ -0,0 +1,474 @@
|
|||
# Scanner produces tokens of the following types:
|
||||
# STREAM-START
|
||||
# STREAM-END
|
||||
# DOCUMENT-START
|
||||
# DOCUMENT-END
|
||||
# FLOW-SEQUENCE-START
|
||||
# FLOW-MAPPING-START
|
||||
# FLOW-SEQUENCE-END
|
||||
# FLOW-MAPPING-END
|
||||
# FLOW-ENTRY
|
||||
# KEY
|
||||
# VALUE
|
||||
# SCALAR(value, plain, style)
|
||||
#
|
||||
# Read comments in the Scanner code for more details.
|
||||
|
||||
__all__ = ['Scanner', 'ScannerError']
|
||||
|
||||
from .error import MarkedError
|
||||
from .tokens import * # NOQA
|
||||
|
||||
|
||||
class ScannerError(MarkedError):
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
from __builtin__ import unicode
|
||||
except ImportError:
|
||||
unicode = str # NOQA
|
||||
|
||||
|
||||
class SimpleKey:
|
||||
# See below simple keys treatment.
|
||||
def __init__(self, token_number, index, line, column, mark):
|
||||
self.token_number = token_number
|
||||
self.index = index
|
||||
self.line = line
|
||||
self.column = column
|
||||
self.mark = mark
|
||||
|
||||
|
||||
class Scanner:
|
||||
def __init__(self):
|
||||
"""Initialize the scanner."""
|
||||
# It is assumed that Scanner and Reader will have a common descendant.
|
||||
# Reader do the dirty work of checking for BOM and converting the
|
||||
# input data to Unicode. It also adds NUL to the end.
|
||||
#
|
||||
# Reader supports the following methods
|
||||
# self.peek(i=0) # peek the next i-th character
|
||||
# self.prefix(l=1) # peek the next l characters
|
||||
# self.forward(l=1) # read the next l characters and move the pointer.
|
||||
|
||||
# Had we reached the end of the stream?
|
||||
self.done = False
|
||||
|
||||
# The number of unclosed '{' and '['. `flow_level == 0` means block
|
||||
# context.
|
||||
self.flow_level = 0
|
||||
|
||||
# List of processed tokens that are not yet emitted.
|
||||
self.tokens = []
|
||||
|
||||
# Add the STREAM-START token.
|
||||
self.fetch_stream_start()
|
||||
|
||||
# Number of tokens that were emitted through the `get_token` method.
|
||||
self.tokens_taken = 0
|
||||
|
||||
# Variables related to simple keys treatment.
|
||||
|
||||
# A simple key is a key that is not denoted by the '?' indicator.
|
||||
# We emit the KEY token before all keys, so when we find a potential
|
||||
# simple key, we try to locate the corresponding ':' indicator.
|
||||
# Simple keys should be limited to a single line.
|
||||
|
||||
# Can a simple key start at the current position? A simple key may
|
||||
# start:
|
||||
# - after '{', '[', ',' (in the flow context),
|
||||
self.allow_simple_key = False
|
||||
|
||||
# Keep track of possible simple keys. This is a dictionary. The key
|
||||
# is `flow_level`; there can be no more that one possible simple key
|
||||
# for each level. The value is a SimpleKey record:
|
||||
# (token_number, index, line, column, mark)
|
||||
# A simple key may start with SCALAR(flow), '[', or '{' tokens.
|
||||
self.possible_simple_keys = {}
|
||||
|
||||
# Public methods.
|
||||
|
||||
def check_token(self, *choices):
|
||||
# Check if the next token is one of the given types.
|
||||
while self.need_more_tokens():
|
||||
self.fetch_more_tokens()
|
||||
if self.tokens:
|
||||
if not choices:
|
||||
return True
|
||||
for choice in choices:
|
||||
if isinstance(self.tokens[0], choice):
|
||||
return True
|
||||
return False
|
||||
|
||||
def peek_token(self):
|
||||
# Return the next token, but do not delete if from the queue.
|
||||
while self.need_more_tokens():
|
||||
self.fetch_more_tokens()
|
||||
if self.tokens:
|
||||
return self.tokens[0]
|
||||
|
||||
def get_token(self):
|
||||
# Return the next token.
|
||||
while self.need_more_tokens():
|
||||
self.fetch_more_tokens()
|
||||
if self.tokens:
|
||||
self.tokens_taken += 1
|
||||
return self.tokens.pop(0)
|
||||
|
||||
# Private methods.
|
||||
|
||||
def need_more_tokens(self):
|
||||
if self.done:
|
||||
return False
|
||||
if not self.tokens:
|
||||
return True
|
||||
# The current token may be a potential simple key, so we
|
||||
# need to look further.
|
||||
self.stale_possible_simple_keys()
|
||||
if self.next_possible_simple_key() == self.tokens_taken:
|
||||
return True
|
||||
|
||||
def fetch_more_tokens(self):
|
||||
|
||||
# Eat whitespaces and comments until we reach the next token.
|
||||
self.scan_to_next_token()
|
||||
|
||||
# Remove obsolete possible simple keys.
|
||||
self.stale_possible_simple_keys()
|
||||
|
||||
# Peek the next character.
|
||||
ch = self.peek()
|
||||
|
||||
# Is it the end of stream?
|
||||
if ch == '\0':
|
||||
return self.fetch_stream_end()
|
||||
|
||||
# Note: the order of the following checks is NOT significant.
|
||||
|
||||
# Is it the flow sequence start indicator?
|
||||
if ch == '[':
|
||||
return self.fetch_flow_sequence_start()
|
||||
|
||||
# Is it the flow mapping start indicator?
|
||||
if ch == '{':
|
||||
return self.fetch_flow_mapping_start()
|
||||
|
||||
# Is it the flow sequence end indicator?
|
||||
if ch == ']':
|
||||
return self.fetch_flow_sequence_end()
|
||||
|
||||
# Is it the flow mapping end indicator?
|
||||
if ch == '}':
|
||||
return self.fetch_flow_mapping_end()
|
||||
|
||||
# Is it the flow entry indicator?
|
||||
if ch == ',':
|
||||
return self.fetch_flow_entry()
|
||||
|
||||
# Is it the value indicator?
|
||||
if ch == ':' and self.flow_level:
|
||||
return self.fetch_value()
|
||||
|
||||
# Is it a double quoted scalar?
|
||||
if ch == '\"':
|
||||
return self.fetch_double()
|
||||
|
||||
# It must be a plain scalar then.
|
||||
if self.check_plain():
|
||||
return self.fetch_plain()
|
||||
|
||||
# No? It's an error. Let's produce a nice error message.
|
||||
raise ScannerError("while scanning for the next token", None,
|
||||
"found character %r that cannot start any token" % ch,
|
||||
self.get_mark())
|
||||
|
||||
# Simple keys treatment.
|
||||
|
||||
def next_possible_simple_key(self):
|
||||
# Return the number of the nearest possible simple key. Actually we
|
||||
# don't need to loop through the whole dictionary. We may replace it
|
||||
# with the following code:
|
||||
# if not self.possible_simple_keys:
|
||||
# return None
|
||||
# return self.possible_simple_keys[
|
||||
# min(self.possible_simple_keys.keys())].token_number
|
||||
min_token_number = None
|
||||
for level in self.possible_simple_keys:
|
||||
key = self.possible_simple_keys[level]
|
||||
if min_token_number is None or key.token_number < min_token_number:
|
||||
min_token_number = key.token_number
|
||||
return min_token_number
|
||||
|
||||
def stale_possible_simple_keys(self):
|
||||
# Remove entries that are no longer possible simple keys. According to
|
||||
# the YAML specification, simple keys
|
||||
# - should be limited to a single line,
|
||||
# Disabling this procedure will allow simple keys of any length and
|
||||
# height (may cause problems if indentation is broken though).
|
||||
for level in list(self.possible_simple_keys):
|
||||
key = self.possible_simple_keys[level]
|
||||
if key.line != self.line:
|
||||
del self.possible_simple_keys[level]
|
||||
|
||||
def save_possible_simple_key(self):
|
||||
# The next token may start a simple key. We check if it's possible
|
||||
# and save its position. This function is called for
|
||||
# SCALAR(flow), '[', and '{'.
|
||||
|
||||
# The next token might be a simple key. Let's save it's number and
|
||||
# position.
|
||||
if self.allow_simple_key:
|
||||
self.remove_possible_simple_key()
|
||||
token_number = self.tokens_taken + len(self.tokens)
|
||||
key = SimpleKey(token_number,
|
||||
self.index, self.line, self.column, self.get_mark())
|
||||
self.possible_simple_keys[self.flow_level] = key
|
||||
|
||||
def remove_possible_simple_key(self):
|
||||
# Remove the saved possible key position at the current flow level.
|
||||
if self.flow_level in self.possible_simple_keys:
|
||||
del self.possible_simple_keys[self.flow_level]
|
||||
|
||||
# Fetchers.
|
||||
|
||||
def fetch_stream_start(self):
|
||||
# We always add STREAM-START as the first token and STREAM-END as the
|
||||
# last token.
|
||||
|
||||
# Read the token.
|
||||
mark = self.get_mark()
|
||||
|
||||
# Add STREAM-START.
|
||||
self.tokens.append(StreamStartToken(mark, mark,
|
||||
encoding=self.encoding))
|
||||
|
||||
def fetch_stream_end(self):
|
||||
# Reset simple keys.
|
||||
self.remove_possible_simple_key()
|
||||
self.allow_simple_key = False
|
||||
self.possible_simple_keys = {}
|
||||
|
||||
# Read the token.
|
||||
mark = self.get_mark()
|
||||
|
||||
# Add STREAM-END.
|
||||
self.tokens.append(StreamEndToken(mark, mark))
|
||||
|
||||
# The steam is finished.
|
||||
self.done = True
|
||||
|
||||
def fetch_flow_sequence_start(self):
|
||||
self.fetch_flow_collection_start(FlowSequenceStartToken)
|
||||
|
||||
def fetch_flow_mapping_start(self):
|
||||
self.fetch_flow_collection_start(FlowMappingStartToken)
|
||||
|
||||
def fetch_flow_collection_start(self, TokenClass):
|
||||
|
||||
# '[' and '{' may start a simple key.
|
||||
self.save_possible_simple_key()
|
||||
|
||||
# Increase the flow level.
|
||||
self.flow_level += 1
|
||||
|
||||
# Simple keys are allowed after '[' and '{'.
|
||||
self.allow_simple_key = True
|
||||
|
||||
# Add FLOW-SEQUENCE-START or FLOW-MAPPING-START.
|
||||
start_mark = self.get_mark()
|
||||
self.forward()
|
||||
end_mark = self.get_mark()
|
||||
self.tokens.append(TokenClass(start_mark, end_mark))
|
||||
|
||||
def fetch_flow_sequence_end(self):
|
||||
self.fetch_flow_collection_end(FlowSequenceEndToken)
|
||||
|
||||
def fetch_flow_mapping_end(self):
|
||||
self.fetch_flow_collection_end(FlowMappingEndToken)
|
||||
|
||||
def fetch_flow_collection_end(self, TokenClass):
|
||||
|
||||
# Reset possible simple key on the current level.
|
||||
self.remove_possible_simple_key()
|
||||
|
||||
# Decrease the flow level.
|
||||
self.flow_level -= 1
|
||||
|
||||
# No simple keys after ']' or '}'.
|
||||
self.allow_simple_key = False
|
||||
|
||||
# Add FLOW-SEQUENCE-END or FLOW-MAPPING-END.
|
||||
start_mark = self.get_mark()
|
||||
self.forward()
|
||||
end_mark = self.get_mark()
|
||||
self.tokens.append(TokenClass(start_mark, end_mark))
|
||||
|
||||
def fetch_value(self):
|
||||
# Do we determine a simple key?
|
||||
if self.flow_level in self.possible_simple_keys:
|
||||
|
||||
# Add KEY.
|
||||
key = self.possible_simple_keys[self.flow_level]
|
||||
del self.possible_simple_keys[self.flow_level]
|
||||
self.tokens.insert(key.token_number - self.tokens_taken,
|
||||
KeyToken(key.mark, key.mark))
|
||||
|
||||
# There cannot be two simple keys one after another.
|
||||
self.allow_simple_key = False
|
||||
|
||||
# Add VALUE.
|
||||
start_mark = self.get_mark()
|
||||
self.forward()
|
||||
end_mark = self.get_mark()
|
||||
self.tokens.append(ValueToken(start_mark, end_mark))
|
||||
|
||||
def fetch_flow_entry(self):
|
||||
|
||||
# Simple keys are allowed after ','.
|
||||
self.allow_simple_key = True
|
||||
|
||||
# Reset possible simple key on the current level.
|
||||
self.remove_possible_simple_key()
|
||||
|
||||
# Add FLOW-ENTRY.
|
||||
start_mark = self.get_mark()
|
||||
self.forward()
|
||||
end_mark = self.get_mark()
|
||||
self.tokens.append(FlowEntryToken(start_mark, end_mark))
|
||||
|
||||
def fetch_double(self):
|
||||
# A flow scalar could be a simple key.
|
||||
self.save_possible_simple_key()
|
||||
|
||||
# No simple keys after flow scalars.
|
||||
self.allow_simple_key = False
|
||||
|
||||
# Scan and add SCALAR.
|
||||
self.tokens.append(self.scan_flow_scalar())
|
||||
|
||||
def fetch_plain(self):
|
||||
|
||||
self.save_possible_simple_key()
|
||||
|
||||
# No simple keys after plain scalars.
|
||||
self.allow_simple_key = False
|
||||
|
||||
# Scan and add SCALAR. May change `allow_simple_key`.
|
||||
self.tokens.append(self.scan_plain())
|
||||
|
||||
# Checkers.
|
||||
|
||||
def check_plain(self):
|
||||
return self.peek() in '0123456789-ntf'
|
||||
|
||||
# Scanners.
|
||||
|
||||
def scan_to_next_token(self):
|
||||
while self.peek() in ' \t\n':
|
||||
self.forward()
|
||||
|
||||
def scan_flow_scalar(self):
|
||||
# See the specification for details.
|
||||
# Note that we loose indentation rules for quoted scalars. Quoted
|
||||
# scalars don't need to adhere indentation because " and ' clearly
|
||||
# mark the beginning and the end of them. Therefore we are less
|
||||
# restrictive then the specification requires. We only need to check
|
||||
# that document separators are not included in scalars.
|
||||
chunks = []
|
||||
start_mark = self.get_mark()
|
||||
quote = self.peek()
|
||||
self.forward()
|
||||
chunks.extend(self.scan_flow_scalar_non_spaces(start_mark))
|
||||
while self.peek() != quote:
|
||||
chunks.extend(self.scan_flow_scalar_spaces(start_mark))
|
||||
chunks.extend(self.scan_flow_scalar_non_spaces(start_mark))
|
||||
self.forward()
|
||||
end_mark = self.get_mark()
|
||||
return ScalarToken(unicode().join(chunks), False, start_mark, end_mark, '"')
|
||||
|
||||
ESCAPE_REPLACEMENTS = {
|
||||
'b': '\x08',
|
||||
't': '\x09',
|
||||
'n': '\x0A',
|
||||
'f': '\x0C',
|
||||
'r': '\x0D',
|
||||
'\"': '\"',
|
||||
'\\': '\\',
|
||||
}
|
||||
|
||||
ESCAPE_CODES = {
|
||||
'u': 4,
|
||||
}
|
||||
|
||||
def scan_flow_scalar_non_spaces(self, start_mark):
|
||||
# See the specification for details.
|
||||
chunks = []
|
||||
while True:
|
||||
length = 0
|
||||
while self.peek(length) not in '\"\\\0 \t\n':
|
||||
length += 1
|
||||
if length:
|
||||
chunks.append(self.prefix(length))
|
||||
self.forward(length)
|
||||
ch = self.peek()
|
||||
if ch == '\\':
|
||||
self.forward()
|
||||
ch = self.peek()
|
||||
if ch in self.ESCAPE_REPLACEMENTS:
|
||||
chunks.append(self.ESCAPE_REPLACEMENTS[ch])
|
||||
self.forward()
|
||||
elif ch in self.ESCAPE_CODES:
|
||||
length = self.ESCAPE_CODES[ch]
|
||||
self.forward()
|
||||
for k in range(length):
|
||||
if self.peek(k) not in '0123456789ABCDEFabcdef':
|
||||
raise ScannerError("while scanning a double-quoted scalar", start_mark,
|
||||
"expected escape sequence of %d hexdecimal numbers, but found %r" %
|
||||
(length, self.peek(k)), self.get_mark())
|
||||
code = int(self.prefix(length), 16)
|
||||
chunks.append(chr(code))
|
||||
self.forward(length)
|
||||
else:
|
||||
raise ScannerError("while scanning a double-quoted scalar", start_mark,
|
||||
"found unknown escape character %r" % ch, self.get_mark())
|
||||
else:
|
||||
return chunks
|
||||
|
||||
def scan_flow_scalar_spaces(self, start_mark):
|
||||
# See the specification for details.
|
||||
chunks = []
|
||||
length = 0
|
||||
while self.peek(length) in ' \t':
|
||||
length += 1
|
||||
whitespaces = self.prefix(length)
|
||||
self.forward(length)
|
||||
ch = self.peek()
|
||||
if ch == '\0':
|
||||
raise ScannerError("while scanning a quoted scalar", start_mark,
|
||||
"found unexpected end of stream", self.get_mark())
|
||||
elif ch == '\n':
|
||||
raise ScannerError("while scanning a quoted scalar", start_mark,
|
||||
"found unexpected line end", self.get_mark())
|
||||
else:
|
||||
chunks.append(whitespaces)
|
||||
return chunks
|
||||
|
||||
def scan_plain(self):
|
||||
chunks = []
|
||||
start_mark = self.get_mark()
|
||||
spaces = []
|
||||
while True:
|
||||
length = 0
|
||||
while True:
|
||||
if self.peek(length) not in 'eE.0123456789nul-tr+fas':
|
||||
break
|
||||
length += 1
|
||||
if length == 0:
|
||||
break
|
||||
self.allow_simple_key = False
|
||||
chunks.extend(spaces)
|
||||
chunks.append(self.prefix(length))
|
||||
self.forward(length)
|
||||
end_mark = self.get_mark()
|
||||
return ScalarToken(''.join(chunks), True, start_mark, end_mark)
|
|
@ -0,0 +1,65 @@
|
|||
class Token(object):
|
||||
def __init__(self, start_mark, end_mark):
|
||||
self.start_mark = start_mark
|
||||
self.end_mark = end_mark
|
||||
|
||||
def __repr__(self):
|
||||
attributes = [key for key in self.__dict__
|
||||
if not key.endswith('_mark')]
|
||||
attributes.sort()
|
||||
arguments = ', '.join(['%s=%r' % (key, getattr(self, key))
|
||||
for key in attributes])
|
||||
return '%s(%s)' % (self.__class__.__name__, arguments)
|
||||
|
||||
|
||||
class StreamStartToken(Token):
|
||||
id = '<stream start>'
|
||||
|
||||
def __init__(self, start_mark=None, end_mark=None,
|
||||
encoding=None):
|
||||
self.start_mark = start_mark
|
||||
self.end_mark = end_mark
|
||||
self.encoding = encoding
|
||||
|
||||
|
||||
class StreamEndToken(Token):
|
||||
id = '<stream end>'
|
||||
|
||||
|
||||
class FlowSequenceStartToken(Token):
|
||||
id = '['
|
||||
|
||||
|
||||
class FlowMappingStartToken(Token):
|
||||
id = '{'
|
||||
|
||||
|
||||
class FlowSequenceEndToken(Token):
|
||||
id = ']'
|
||||
|
||||
|
||||
class FlowMappingEndToken(Token):
|
||||
id = '}'
|
||||
|
||||
|
||||
class KeyToken(Token):
|
||||
id = '?'
|
||||
|
||||
|
||||
class ValueToken(Token):
|
||||
id = ':'
|
||||
|
||||
|
||||
class FlowEntryToken(Token):
|
||||
id = ','
|
||||
|
||||
|
||||
class ScalarToken(Token):
|
||||
id = '<scalar>'
|
||||
|
||||
def __init__(self, value, plain, start_mark, end_mark, style=None):
|
||||
self.value = value
|
||||
self.plain = plain
|
||||
self.start_mark = start_mark
|
||||
self.end_mark = end_mark
|
||||
self.style = style
|
|
@ -0,0 +1,19 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from __future__ import absolute_import
|
||||
import sys
|
||||
|
||||
|
||||
def gen_matcher_getter(ext, import_paths):
|
||||
def get(match_name):
|
||||
match_module, separator, match_function = match_name.rpartition('.')
|
||||
if not separator:
|
||||
match_module = 'powerline.matchers.{0}'.format(ext)
|
||||
match_function = match_name
|
||||
oldpath = sys.path
|
||||
sys.path = import_paths + sys.path
|
||||
try:
|
||||
return getattr(__import__(match_module, fromlist=[match_function]), match_function)
|
||||
finally:
|
||||
sys.path = oldpath
|
||||
return get
|
|
@ -0,0 +1,19 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import os
|
||||
from powerline.bindings.vim import getbufvar
|
||||
|
||||
|
||||
def help(matcher_info):
|
||||
return str(getbufvar(matcher_info['bufnr'], '&buftype')) == 'help'
|
||||
|
||||
|
||||
def cmdwin(matcher_info):
|
||||
name = matcher_info['buffer'].name
|
||||
return name and os.path.basename(name) == '[Command Line]'
|
||||
|
||||
|
||||
def quickfix(matcher_info):
|
||||
return str(getbufvar(matcher_info['bufnr'], '&buftype')) == 'quickfix'
|
319
common/.local/lib/python2.7/site-packages/powerline/renderer.py
Normal file
319
common/.local/lib/python2.7/site-packages/powerline/renderer.py
Normal file
|
@ -0,0 +1,319 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from powerline.theme import Theme
|
||||
from unicodedata import east_asian_width, combining
|
||||
import os
|
||||
|
||||
|
||||
try:
|
||||
NBSP = unicode(' ', 'utf-8')
|
||||
except NameError:
|
||||
NBSP = ' '
|
||||
|
||||
|
||||
def construct_returned_value(rendered_highlighted, segments, output_raw):
|
||||
if output_raw:
|
||||
return rendered_highlighted, ''.join((segment['_rendered_raw'] for segment in segments))
|
||||
else:
|
||||
return rendered_highlighted
|
||||
|
||||
|
||||
class Renderer(object):
|
||||
'''Object that is responsible for generating the highlighted string.
|
||||
|
||||
:param dict theme_config:
|
||||
Main theme configuration.
|
||||
:param local_themes:
|
||||
Local themes. Is to be used by subclasses from ``.get_theme()`` method,
|
||||
base class only records this parameter to a ``.local_themes`` attribute.
|
||||
:param dict theme_kwargs:
|
||||
Keyword arguments for ``Theme`` class constructor.
|
||||
:param Colorscheme colorscheme:
|
||||
Colorscheme object that holds colors configuration.
|
||||
:param PowerlineLogger pl:
|
||||
Object used for logging.
|
||||
:param int ambiwidth:
|
||||
Width of the characters with east asian width unicode attribute equal to
|
||||
``A`` (Ambigious).
|
||||
:param dict options:
|
||||
Various options. Are normally not used by base renderer, but all options
|
||||
are recorded as attributes.
|
||||
'''
|
||||
|
||||
segment_info = {
|
||||
'environ': os.environ,
|
||||
'getcwd': getattr(os, 'getcwdu', os.getcwd),
|
||||
'home': os.environ.get('HOME'),
|
||||
}
|
||||
'''Basic segment info. Is merged with local segment information by
|
||||
``.get_segment_info()`` method. Keys:
|
||||
|
||||
``environ``
|
||||
Object containing environment variables. Must define at least the
|
||||
following methods: ``.__getitem__(var)`` that raises ``KeyError`` in
|
||||
case requested environment variable is not present, ``.get(var,
|
||||
default=None)`` that works like ``dict.get`` and be able to be passed to
|
||||
``Popen``.
|
||||
|
||||
``getcwd``
|
||||
Function that returns current working directory. Will be called without
|
||||
any arguments, should return ``unicode`` or (in python-2) regular
|
||||
string.
|
||||
|
||||
``home``
|
||||
String containing path to home directory. Should be ``unicode`` or (in
|
||||
python-2) regular string or ``None``.
|
||||
'''
|
||||
|
||||
def __init__(self,
|
||||
theme_config,
|
||||
local_themes,
|
||||
theme_kwargs,
|
||||
colorscheme,
|
||||
pl,
|
||||
ambiwidth=1,
|
||||
**options):
|
||||
self.__dict__.update(options)
|
||||
self.theme_config = theme_config
|
||||
theme_kwargs['pl'] = pl
|
||||
self.pl = pl
|
||||
self.theme = Theme(theme_config=theme_config, **theme_kwargs)
|
||||
self.local_themes = local_themes
|
||||
self.theme_kwargs = theme_kwargs
|
||||
self.colorscheme = colorscheme
|
||||
self.width_data = {
|
||||
'N': 1, # Neutral
|
||||
'Na': 1, # Narrow
|
||||
'A': ambiwidth, # Ambigious
|
||||
'H': 1, # Half-width
|
||||
'W': 2, # Wide
|
||||
'F': 2, # Fullwidth
|
||||
}
|
||||
|
||||
def strwidth(self, string):
|
||||
'''Function that returns string width.
|
||||
|
||||
Is used to calculate the place given string occupies when handling
|
||||
``width`` argument to ``.render()`` method. Must take east asian width
|
||||
into account.
|
||||
|
||||
:param unicode string:
|
||||
String whose width will be calculated.
|
||||
|
||||
:return: unsigned integer.
|
||||
'''
|
||||
return sum((0 if combining(symbol) else self.width_data[east_asian_width(symbol)] for symbol in string))
|
||||
|
||||
def get_theme(self, matcher_info):
|
||||
'''Get Theme object.
|
||||
|
||||
Is to be overridden by subclasses to support local themes, this variant
|
||||
only returns ``.theme`` attribute.
|
||||
|
||||
:param matcher_info:
|
||||
Parameter ``matcher_info`` that ``.render()`` method received.
|
||||
Unused.
|
||||
'''
|
||||
return self.theme
|
||||
|
||||
def shutdown(self):
|
||||
'''Prepare for interpreter shutdown. The only job it is supposed to do
|
||||
is calling ``.shutdown()`` method for all theme objects. Should be
|
||||
overridden by subclasses in case they support local themes.
|
||||
'''
|
||||
self.theme.shutdown()
|
||||
|
||||
def _get_highlighting(self, segment, mode):
|
||||
segment['highlight'] = self.colorscheme.get_highlighting(segment['highlight_group'], mode, segment.get('gradient_level'))
|
||||
if segment['divider_highlight_group']:
|
||||
segment['divider_highlight'] = self.colorscheme.get_highlighting(segment['divider_highlight_group'], mode)
|
||||
else:
|
||||
segment['divider_highlight'] = None
|
||||
return segment
|
||||
|
||||
def get_segment_info(self, segment_info):
|
||||
'''Get segment information.
|
||||
|
||||
Must return a dictionary containing at least ``home``, ``environ`` and
|
||||
``getcwd`` keys (see documentation for ``segment_info`` attribute). This
|
||||
implementation merges ``segment_info`` dictionary passed to
|
||||
``.render()`` method with ``.segment_info`` attribute, preferring keys
|
||||
from the former. It also replaces ``getcwd`` key with function returning
|
||||
``segment_info['environ']['PWD']`` in case ``PWD`` variable is
|
||||
available.
|
||||
|
||||
:param dict segment_info:
|
||||
Segment information that was passed to ``.render()`` method.
|
||||
|
||||
:return: dict with segment information.
|
||||
'''
|
||||
r = self.segment_info.copy()
|
||||
if segment_info:
|
||||
r.update(segment_info)
|
||||
if 'PWD' in r['environ']:
|
||||
r['getcwd'] = lambda: r['environ']['PWD']
|
||||
return r
|
||||
|
||||
def render(self, mode=None, width=None, side=None, output_raw=False, segment_info=None, matcher_info=None):
|
||||
'''Render all segments.
|
||||
|
||||
When a width is provided, low-priority segments are dropped one at
|
||||
a time until the line is shorter than the width, or only segments
|
||||
with a negative priority are left. If one or more filler segments are
|
||||
provided they will fill the remaining space until the desired width is
|
||||
reached.
|
||||
|
||||
:param str mode:
|
||||
Mode string. Affects contents (colors and the set of segments) of
|
||||
rendered string.
|
||||
:param int width:
|
||||
Maximum width text can occupy. May be exceeded if there are too much
|
||||
non-removable segments.
|
||||
:param str side:
|
||||
One of ``left``, ``right``. Determines which side will be rendered.
|
||||
If not present all sides are rendered.
|
||||
:param bool output_raw:
|
||||
Changes the output: if this parameter is ``True`` then in place of
|
||||
one string this method outputs a pair ``(colored_string,
|
||||
colorless_string)``.
|
||||
:param dict segment_info:
|
||||
Segment information. See also ``.get_segment_info()`` method.
|
||||
:param matcher_info:
|
||||
Matcher information. Is processed in ``.get_theme()`` method.
|
||||
'''
|
||||
theme = self.get_theme(matcher_info)
|
||||
segments = theme.get_segments(side, self.get_segment_info(segment_info))
|
||||
|
||||
# Handle excluded/included segments for the current mode
|
||||
segments = [self._get_highlighting(segment, mode) for segment in segments
|
||||
if mode not in segment['exclude_modes'] or (segment['include_modes'] and segment in segment['include_modes'])]
|
||||
|
||||
segments = [segment for segment in self._render_segments(theme, segments)]
|
||||
|
||||
if not width:
|
||||
# No width specified, so we don't need to crop or pad anything
|
||||
return construct_returned_value(''.join([segment['_rendered_hl'] for segment in segments]) + self.hlstyle(), segments, output_raw)
|
||||
|
||||
# Create an ordered list of segments that can be dropped
|
||||
segments_priority = sorted((segment for segment in segments if segment['priority'] is not None), key=lambda segment: segment['priority'], reverse=True)
|
||||
while sum([segment['_len'] for segment in segments]) > width and len(segments_priority):
|
||||
segments.remove(segments_priority[0])
|
||||
segments_priority.pop(0)
|
||||
|
||||
# Distribute the remaining space on spacer segments
|
||||
segments_spacers = [segment for segment in segments if segment['width'] == 'auto']
|
||||
if segments_spacers:
|
||||
distribute_len, distribute_len_remainder = divmod(width - sum([segment['_len'] for segment in segments]), len(segments_spacers))
|
||||
for segment in segments_spacers:
|
||||
if segment['align'] == 'l':
|
||||
segment['_space_right'] += distribute_len
|
||||
elif segment['align'] == 'r':
|
||||
segment['_space_left'] += distribute_len
|
||||
elif segment['align'] == 'c':
|
||||
space_side, space_side_remainder = divmod(distribute_len, 2)
|
||||
segment['_space_left'] += space_side + space_side_remainder
|
||||
segment['_space_right'] += space_side
|
||||
segments_spacers[0]['_space_right'] += distribute_len_remainder
|
||||
|
||||
rendered_highlighted = ''.join([segment['_rendered_hl'] for segment in self._render_segments(theme, segments)]) + self.hlstyle()
|
||||
|
||||
return construct_returned_value(rendered_highlighted, segments, output_raw)
|
||||
|
||||
def _render_segments(self, theme, segments, render_highlighted=True):
|
||||
'''Internal segment rendering method.
|
||||
|
||||
This method loops through the segment array and compares the
|
||||
foreground/background colors and divider properties and returns the
|
||||
rendered statusline as a string.
|
||||
|
||||
The method always renders the raw segment contents (i.e. without
|
||||
highlighting strings added), and only renders the highlighted
|
||||
statusline if render_highlighted is True.
|
||||
'''
|
||||
segments_len = len(segments)
|
||||
|
||||
for index, segment in enumerate(segments):
|
||||
segment['_rendered_raw'] = ''
|
||||
segment['_rendered_hl'] = ''
|
||||
|
||||
prev_segment = segments[index - 1] if index > 0 else theme.EMPTY_SEGMENT
|
||||
next_segment = segments[index + 1] if index < segments_len - 1 else theme.EMPTY_SEGMENT
|
||||
compare_segment = next_segment if segment['side'] == 'left' else prev_segment
|
||||
outer_padding = ' ' if (index == 0 and segment['side'] == 'left') or (index == segments_len - 1 and segment['side'] == 'right') else ''
|
||||
divider_type = 'soft' if compare_segment['highlight']['bg'] == segment['highlight']['bg'] else 'hard'
|
||||
|
||||
divider_raw = theme.get_divider(segment['side'], divider_type)
|
||||
divider_spaces = theme.get_spaces()
|
||||
divider_highlighted = ''
|
||||
contents_raw = segment['contents']
|
||||
contents_highlighted = ''
|
||||
draw_divider = segment['draw_' + divider_type + '_divider']
|
||||
|
||||
# Pad segments first
|
||||
if draw_divider:
|
||||
if segment['side'] == 'left':
|
||||
contents_raw = outer_padding + (segment['_space_left'] * ' ') + contents_raw + ((divider_spaces + segment['_space_right']) * ' ')
|
||||
else:
|
||||
contents_raw = ((divider_spaces + segment['_space_left']) * ' ') + contents_raw + (segment['_space_right'] * ' ') + outer_padding
|
||||
else:
|
||||
if segment['side'] == 'left':
|
||||
contents_raw = outer_padding + (segment['_space_left'] * ' ') + contents_raw + (segment['_space_right'] * ' ')
|
||||
else:
|
||||
contents_raw = (segment['_space_left'] * ' ') + contents_raw + (segment['_space_right'] * ' ') + outer_padding
|
||||
|
||||
# Replace spaces with no-break spaces
|
||||
contents_raw = contents_raw.replace(' ', NBSP)
|
||||
divider_raw = divider_raw.replace(' ', NBSP)
|
||||
|
||||
# Apply highlighting to padded dividers and contents
|
||||
if render_highlighted:
|
||||
if divider_type == 'soft':
|
||||
divider_highlight_group_key = 'highlight' if segment['divider_highlight_group'] is None else 'divider_highlight'
|
||||
divider_fg = segment[divider_highlight_group_key]['fg']
|
||||
divider_bg = segment[divider_highlight_group_key]['bg']
|
||||
else:
|
||||
divider_fg = segment['highlight']['bg']
|
||||
divider_bg = compare_segment['highlight']['bg']
|
||||
divider_highlighted = self.hl(divider_raw, divider_fg, divider_bg, False)
|
||||
contents_highlighted = self.hl(self.escape(contents_raw), **segment['highlight'])
|
||||
|
||||
# Append padded raw and highlighted segments to the rendered segment variables
|
||||
if draw_divider:
|
||||
if segment['side'] == 'left':
|
||||
segment['_rendered_raw'] += contents_raw + divider_raw
|
||||
segment['_rendered_hl'] += contents_highlighted + divider_highlighted
|
||||
else:
|
||||
segment['_rendered_raw'] += divider_raw + contents_raw
|
||||
segment['_rendered_hl'] += divider_highlighted + contents_highlighted
|
||||
else:
|
||||
if segment['side'] == 'left':
|
||||
segment['_rendered_raw'] += contents_raw
|
||||
segment['_rendered_hl'] += contents_highlighted
|
||||
else:
|
||||
segment['_rendered_raw'] += contents_raw
|
||||
segment['_rendered_hl'] += contents_highlighted
|
||||
segment['_len'] = self.strwidth(segment['_rendered_raw'])
|
||||
yield segment
|
||||
|
||||
@staticmethod
|
||||
def escape(string):
|
||||
'''Method that escapes segment contents.
|
||||
'''
|
||||
return string
|
||||
|
||||
def hlstyle(fg=None, bg=None, attr=None):
|
||||
'''Output highlight style string.
|
||||
|
||||
Assuming highlighted string looks like ``{style}{contents}`` this method
|
||||
should output ``{style}``. If it is called without arguments this method
|
||||
is supposed to reset style to its default.
|
||||
'''
|
||||
raise NotImplementedError
|
||||
|
||||
def hl(self, contents, fg=None, bg=None, attr=None):
|
||||
'''Output highlighted chunk.
|
||||
|
||||
This implementation just outputs ``.hlstyle()`` joined with
|
||||
``contents``.
|
||||
'''
|
||||
return self.hlstyle(fg, bg, attr) + (contents or '')
|
|
@ -0,0 +1,16 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from powerline.renderers.shell import ShellRenderer
|
||||
|
||||
|
||||
class BashPromptRenderer(ShellRenderer):
|
||||
'''Powerline bash prompt segment renderer.'''
|
||||
escape_hl_start = '\['
|
||||
escape_hl_end = '\]'
|
||||
|
||||
@staticmethod
|
||||
def escape(string):
|
||||
return string.replace('\\', '\\\\').replace('$', '\\$').replace('`', '\\`')
|
||||
|
||||
|
||||
renderer = BashPromptRenderer
|
|
@ -0,0 +1,35 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from powerline.renderers.shell import ShellRenderer
|
||||
from powerline.theme import Theme
|
||||
|
||||
|
||||
class IpythonRenderer(ShellRenderer):
|
||||
'''Powerline ipython segment renderer.'''
|
||||
escape_hl_start = '\x01'
|
||||
escape_hl_end = '\x02'
|
||||
|
||||
def get_segment_info(self, segment_info):
|
||||
r = self.segment_info.copy()
|
||||
r['ipython'] = segment_info
|
||||
return r
|
||||
|
||||
def get_theme(self, matcher_info):
|
||||
if matcher_info == 'in':
|
||||
return self.theme
|
||||
else:
|
||||
match = self.local_themes[matcher_info]
|
||||
try:
|
||||
return match['theme']
|
||||
except KeyError:
|
||||
match['theme'] = Theme(theme_config=match['config'], top_theme_config=self.theme_config, **self.theme_kwargs)
|
||||
return match['theme']
|
||||
|
||||
def shutdown(self):
|
||||
self.theme.shutdown()
|
||||
for match in self.local_themes.values():
|
||||
if 'theme' in match:
|
||||
match['theme'].shutdown()
|
||||
|
||||
|
||||
renderer = IpythonRenderer
|
|
@ -0,0 +1,38 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from powerline.renderer import Renderer
|
||||
from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
|
||||
|
||||
from xml.sax.saxutils import escape as _escape
|
||||
|
||||
|
||||
class PangoMarkupRenderer(Renderer):
|
||||
'''Powerline Pango markup segment renderer.'''
|
||||
|
||||
@staticmethod
|
||||
def hlstyle(*args, **kwargs):
|
||||
# We don't need to explicitly reset attributes, so skip those calls
|
||||
return ''
|
||||
|
||||
def hl(self, contents, fg=None, bg=None, attr=None):
|
||||
'''Highlight a segment.'''
|
||||
awesome_attr = []
|
||||
if fg is not None:
|
||||
if fg is not False and fg[1] is not False:
|
||||
awesome_attr += ['foreground="#{0:06x}"'.format(fg[1])]
|
||||
if bg is not None:
|
||||
if bg is not False and bg[1] is not False:
|
||||
awesome_attr += ['background="#{0:06x}"'.format(bg[1])]
|
||||
if attr is not None and attr is not False:
|
||||
if attr & ATTR_BOLD:
|
||||
awesome_attr += ['font_weight="bold"']
|
||||
if attr & ATTR_ITALIC:
|
||||
awesome_attr += ['font_style="italic"']
|
||||
if attr & ATTR_UNDERLINE:
|
||||
awesome_attr += ['underline="single"']
|
||||
return '<span ' + ' '.join(awesome_attr) + '>' + contents + '</span>'
|
||||
|
||||
escape = staticmethod(_escape)
|
||||
|
||||
|
||||
renderer = PangoMarkupRenderer
|
|
@ -0,0 +1,70 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from powerline.renderer import Renderer
|
||||
from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
|
||||
|
||||
|
||||
def int_to_rgb(num):
|
||||
r = (num >> 16) & 0xff
|
||||
g = (num >> 8) & 0xff
|
||||
b = num & 0xff
|
||||
return r, g, b
|
||||
|
||||
|
||||
class ShellRenderer(Renderer):
|
||||
'''Powerline shell segment renderer.'''
|
||||
escape_hl_start = ''
|
||||
escape_hl_end = ''
|
||||
term_truecolor = False
|
||||
tmux_escape = False
|
||||
screen_escape = False
|
||||
|
||||
def hlstyle(self, fg=None, bg=None, attr=None):
|
||||
'''Highlight a segment.
|
||||
|
||||
If an argument is None, the argument is ignored. If an argument is
|
||||
False, the argument is reset to the terminal defaults. If an argument
|
||||
is a valid color or attribute, it's added to the ANSI escape code.
|
||||
'''
|
||||
ansi = [0]
|
||||
if fg is not None:
|
||||
if fg is False or fg[0] is False:
|
||||
ansi += [39]
|
||||
else:
|
||||
if self.term_truecolor:
|
||||
ansi += [38, 2] + list(int_to_rgb(fg[1]))
|
||||
else:
|
||||
ansi += [38, 5, fg[0]]
|
||||
if bg is not None:
|
||||
if bg is False or bg[0] is False:
|
||||
ansi += [49]
|
||||
else:
|
||||
if self.term_truecolor:
|
||||
ansi += [48, 2] + list(int_to_rgb(bg[1]))
|
||||
else:
|
||||
ansi += [48, 5, bg[0]]
|
||||
if attr is not None:
|
||||
if attr is False:
|
||||
ansi += [22]
|
||||
else:
|
||||
if attr & ATTR_BOLD:
|
||||
ansi += [1]
|
||||
elif attr & ATTR_ITALIC:
|
||||
# Note: is likely not to work or even be inverse in place of
|
||||
# italic. Omit using this in colorschemes.
|
||||
ansi += [3]
|
||||
elif attr & ATTR_UNDERLINE:
|
||||
ansi += [4]
|
||||
r = '\033[{0}m'.format(';'.join(str(attr) for attr in ansi))
|
||||
if self.tmux_escape:
|
||||
r = '\033Ptmux;' + r.replace('\033', '\033\033') + '\033\\'
|
||||
elif self.screen_escape:
|
||||
r = '\033P' + r.replace('\033', '\033\033') + '\033\\'
|
||||
return self.escape_hl_start + r + self.escape_hl_end
|
||||
|
||||
@staticmethod
|
||||
def escape(string):
|
||||
return string.replace('\\', '\\\\')
|
||||
|
||||
|
||||
renderer = ShellRenderer
|
|
@ -0,0 +1,44 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from powerline.renderer import Renderer
|
||||
from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
|
||||
|
||||
|
||||
class TmuxRenderer(Renderer):
|
||||
'''Powerline tmux segment renderer.'''
|
||||
def hlstyle(self, fg=None, bg=None, attr=None):
|
||||
'''Highlight a segment.'''
|
||||
# We don't need to explicitly reset attributes, so skip those calls
|
||||
if not attr and not bg and not fg:
|
||||
return ''
|
||||
tmux_attr = []
|
||||
if fg is not None:
|
||||
if fg is False or fg[0] is False:
|
||||
tmux_attr += ['fg=default']
|
||||
else:
|
||||
tmux_attr += ['fg=colour' + str(fg[0])]
|
||||
if bg is not None:
|
||||
if bg is False or bg[0] is False:
|
||||
tmux_attr += ['bg=default']
|
||||
else:
|
||||
tmux_attr += ['bg=colour' + str(bg[0])]
|
||||
if attr is not None:
|
||||
if attr is False:
|
||||
tmux_attr += ['nobold', 'noitalics', 'nounderscore']
|
||||
else:
|
||||
if attr & ATTR_BOLD:
|
||||
tmux_attr += ['bold']
|
||||
else:
|
||||
tmux_attr += ['nobold']
|
||||
if attr & ATTR_ITALIC:
|
||||
tmux_attr += ['italics']
|
||||
else:
|
||||
tmux_attr += ['noitalics']
|
||||
if attr & ATTR_UNDERLINE:
|
||||
tmux_attr += ['underscore']
|
||||
else:
|
||||
tmux_attr += ['nounderscore']
|
||||
return '#[' + ','.join(tmux_attr) + ']'
|
||||
|
||||
|
||||
renderer = TmuxRenderer
|
|
@ -0,0 +1,154 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from powerline.bindings.vim import vim_get_func
|
||||
from powerline.renderer import Renderer
|
||||
from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
|
||||
from powerline.theme import Theme
|
||||
|
||||
import vim
|
||||
import sys
|
||||
|
||||
|
||||
vim_mode = vim_get_func('mode', rettype=str)
|
||||
mode_translations = {
|
||||
chr(ord('V') - 0x40): '^V',
|
||||
chr(ord('S') - 0x40): '^S',
|
||||
}
|
||||
|
||||
|
||||
class VimRenderer(Renderer):
|
||||
'''Powerline vim segment renderer.'''
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if not hasattr(vim, 'strwidth'):
|
||||
# Hope nobody want to change this at runtime
|
||||
if vim.eval('&ambiwidth') == 'double':
|
||||
kwargs = dict(**kwargs)
|
||||
kwargs['ambigious'] = 2
|
||||
super(VimRenderer, self).__init__(*args, **kwargs)
|
||||
self.hl_groups = {}
|
||||
|
||||
def shutdown(self):
|
||||
self.theme.shutdown()
|
||||
for match in self.local_themes.values():
|
||||
if 'theme' in match:
|
||||
match['theme'].shutdown()
|
||||
|
||||
def add_local_theme(self, matcher, theme):
|
||||
if matcher in self.local_themes:
|
||||
raise KeyError('There is already a local theme with given matcher')
|
||||
self.local_themes[matcher] = theme
|
||||
|
||||
def get_theme(self, matcher_info):
|
||||
for matcher in self.local_themes.keys():
|
||||
if matcher(matcher_info):
|
||||
match = self.local_themes[matcher]
|
||||
try:
|
||||
return match['theme']
|
||||
except KeyError:
|
||||
match['theme'] = Theme(theme_config=match['config'], top_theme_config=self.theme_config, **self.theme_kwargs)
|
||||
return match['theme']
|
||||
else:
|
||||
return self.theme
|
||||
|
||||
if hasattr(vim, 'strwidth'):
|
||||
if sys.version_info < (3,):
|
||||
@staticmethod
|
||||
def strwidth(string):
|
||||
# Does not work with tabs, but neither is strwidth from default
|
||||
# renderer
|
||||
return vim.strwidth(string.encode('utf-8'))
|
||||
else:
|
||||
@staticmethod # NOQA
|
||||
def strwidth(string):
|
||||
return vim.strwidth(string)
|
||||
|
||||
def get_segment_info(self, segment_info):
|
||||
return segment_info or self.segment_info
|
||||
|
||||
def render(self, window_id, winidx, current):
|
||||
'''Render all segments.'''
|
||||
if current:
|
||||
mode = vim_mode(1)
|
||||
mode = mode_translations.get(mode, mode)
|
||||
else:
|
||||
mode = 'nc'
|
||||
segment_info = {
|
||||
'window': vim.windows[winidx],
|
||||
'mode': mode,
|
||||
'window_id': window_id,
|
||||
}
|
||||
segment_info['buffer'] = segment_info['window'].buffer
|
||||
segment_info['bufnr'] = segment_info['buffer'].number
|
||||
segment_info.update(self.segment_info)
|
||||
winwidth = segment_info['window'].width
|
||||
statusline = super(VimRenderer, self).render(
|
||||
mode=mode,
|
||||
width=winwidth,
|
||||
segment_info=segment_info,
|
||||
matcher_info=segment_info,
|
||||
)
|
||||
return statusline
|
||||
|
||||
def reset_highlight(self):
|
||||
self.hl_groups.clear()
|
||||
|
||||
@staticmethod
|
||||
def escape(string):
|
||||
return string.replace('%', '%%')
|
||||
|
||||
def hlstyle(self, fg=None, bg=None, attr=None):
|
||||
'''Highlight a segment.
|
||||
|
||||
If an argument is None, the argument is ignored. If an argument is
|
||||
False, the argument is reset to the terminal defaults. If an argument
|
||||
is a valid color or attribute, it's added to the vim highlight group.
|
||||
'''
|
||||
# We don't need to explicitly reset attributes in vim, so skip those calls
|
||||
if not attr and not bg and not fg:
|
||||
return ''
|
||||
|
||||
if not (fg, bg, attr) in self.hl_groups:
|
||||
hl_group = {
|
||||
'ctermfg': 'NONE',
|
||||
'guifg': None,
|
||||
'ctermbg': 'NONE',
|
||||
'guibg': None,
|
||||
'attr': ['NONE'],
|
||||
'name': '',
|
||||
}
|
||||
if fg is not None and fg is not False:
|
||||
hl_group['ctermfg'] = fg[0]
|
||||
hl_group['guifg'] = fg[1]
|
||||
if bg is not None and bg is not False:
|
||||
hl_group['ctermbg'] = bg[0]
|
||||
hl_group['guibg'] = bg[1]
|
||||
if attr:
|
||||
hl_group['attr'] = []
|
||||
if attr & ATTR_BOLD:
|
||||
hl_group['attr'].append('bold')
|
||||
if attr & ATTR_ITALIC:
|
||||
hl_group['attr'].append('italic')
|
||||
if attr & ATTR_UNDERLINE:
|
||||
hl_group['attr'].append('underline')
|
||||
hl_group['name'] = 'Pl_' + \
|
||||
str(hl_group['ctermfg']) + '_' + \
|
||||
str(hl_group['guifg']) + '_' + \
|
||||
str(hl_group['ctermbg']) + '_' + \
|
||||
str(hl_group['guibg']) + '_' + \
|
||||
''.join(hl_group['attr'])
|
||||
self.hl_groups[(fg, bg, attr)] = hl_group
|
||||
vim.command('hi {group} ctermfg={ctermfg} guifg={guifg} guibg={guibg} ctermbg={ctermbg} cterm={attr} gui={attr}'.format(
|
||||
group=hl_group['name'],
|
||||
ctermfg=hl_group['ctermfg'],
|
||||
guifg='#{0:06x}'.format(hl_group['guifg']) if hl_group['guifg'] is not None else 'NONE',
|
||||
ctermbg=hl_group['ctermbg'],
|
||||
guibg='#{0:06x}'.format(hl_group['guibg']) if hl_group['guibg'] is not None else 'NONE',
|
||||
attr=','.join(hl_group['attr']),
|
||||
))
|
||||
return '%#' + self.hl_groups[(fg, bg, attr)]['name'] + '#'
|
||||
|
||||
|
||||
renderer = VimRenderer
|
|
@ -0,0 +1,16 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from powerline.renderers.shell import ShellRenderer
|
||||
|
||||
|
||||
class ZshPromptRenderer(ShellRenderer):
|
||||
'''Powerline zsh prompt segment renderer.'''
|
||||
escape_hl_start = '%{'
|
||||
escape_hl_end = '%}'
|
||||
|
||||
@staticmethod
|
||||
def escape(string):
|
||||
return string.replace('%', '%%').replace('\\', '\\\\')
|
||||
|
||||
|
||||
renderer = ZshPromptRenderer
|
104
common/.local/lib/python2.7/site-packages/powerline/segment.py
Normal file
104
common/.local/lib/python2.7/site-packages/powerline/segment.py
Normal file
|
@ -0,0 +1,104 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from __future__ import absolute_import
|
||||
import sys
|
||||
|
||||
|
||||
def get_segment_key(segment, theme_configs, key, module=None, default=None):
|
||||
try:
|
||||
return segment[key]
|
||||
except KeyError:
|
||||
if 'name' in segment:
|
||||
name = segment['name']
|
||||
for theme_config in theme_configs:
|
||||
if 'segment_data' in theme_config:
|
||||
for segment_key in ((module + '.' + name, name) if module else (name,)):
|
||||
try:
|
||||
return theme_config['segment_data'][segment_key][key]
|
||||
except KeyError:
|
||||
pass
|
||||
return default
|
||||
|
||||
|
||||
def get_function(data, segment):
|
||||
oldpath = sys.path
|
||||
sys.path = data['path'] + sys.path
|
||||
segment_module = str(segment.get('module', data['default_module']))
|
||||
try:
|
||||
return None, getattr(__import__(segment_module, fromlist=[segment['name']]), segment['name']), segment_module
|
||||
finally:
|
||||
sys.path = oldpath
|
||||
|
||||
|
||||
def get_string(data, segment):
|
||||
return data['get_key'](segment, None, 'contents'), None, None
|
||||
|
||||
|
||||
def get_filler(data, segment):
|
||||
return None, None, None
|
||||
|
||||
|
||||
segment_getters = {
|
||||
"function": get_function,
|
||||
"string": get_string,
|
||||
"filler": get_filler,
|
||||
}
|
||||
|
||||
|
||||
def gen_segment_getter(pl, ext, path, theme_configs, default_module=None):
|
||||
data = {
|
||||
'default_module': default_module or 'powerline.segments.' + ext,
|
||||
'path': path,
|
||||
}
|
||||
|
||||
def get_key(segment, module, key, default=None):
|
||||
return get_segment_key(segment, theme_configs, key, module, default)
|
||||
data['get_key'] = get_key
|
||||
|
||||
def get(segment, side):
|
||||
segment_type = segment.get('type', 'function')
|
||||
try:
|
||||
get_segment_info = segment_getters[segment_type]
|
||||
except KeyError:
|
||||
raise TypeError('Unknown segment type: {0}'.format(segment_type))
|
||||
|
||||
try:
|
||||
contents, contents_func, module = get_segment_info(data, segment)
|
||||
except Exception as e:
|
||||
pl.exception('Failed to generate segment from {0!r}: {1}', segment, str(e), prefix='segment_generator')
|
||||
return None
|
||||
|
||||
if segment_type == 'function':
|
||||
highlight_group = [module + '.' + segment['name'], segment['name']]
|
||||
else:
|
||||
highlight_group = segment.get('highlight_group') or segment.get('name')
|
||||
|
||||
return {
|
||||
'name': segment.get('name'),
|
||||
'type': segment_type,
|
||||
'highlight_group': highlight_group,
|
||||
'divider_highlight_group': None,
|
||||
'before': get_key(segment, module, 'before', ''),
|
||||
'after': get_key(segment, module, 'after', ''),
|
||||
'contents_func': contents_func,
|
||||
'contents': contents,
|
||||
'args': get_key(segment, module, 'args', {}) if segment_type == 'function' else {},
|
||||
'priority': segment.get('priority', None),
|
||||
'draw_hard_divider': segment.get('draw_hard_divider', True),
|
||||
'draw_soft_divider': segment.get('draw_soft_divider', True),
|
||||
'draw_inner_divider': segment.get('draw_inner_divider', False),
|
||||
'side': side,
|
||||
'exclude_modes': segment.get('exclude_modes', []),
|
||||
'include_modes': segment.get('include_modes', []),
|
||||
'width': segment.get('width'),
|
||||
'align': segment.get('align', 'l'),
|
||||
'shutdown': getattr(contents_func, 'shutdown', None),
|
||||
'startup': getattr(contents_func, 'startup', None),
|
||||
'_rendered_raw': '',
|
||||
'_rendered_hl': '',
|
||||
'_len': 0,
|
||||
'_space_left': 0,
|
||||
'_space_right': 0,
|
||||
}
|
||||
|
||||
return get
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,8 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from powerline.theme import requires_segment_info
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
def prompt_count(pl, segment_info):
|
||||
return str(segment_info['ipython'].prompt_count)
|
|
@ -0,0 +1,28 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from powerline.theme import requires_segment_info
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
def last_status(pl, segment_info):
|
||||
'''Return last exit code.
|
||||
|
||||
Highlight groups used: ``exit_fail``
|
||||
'''
|
||||
if not segment_info['args'].last_exit_code:
|
||||
return None
|
||||
return [{'contents': str(segment_info['args'].last_exit_code), 'highlight_group': 'exit_fail'}]
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
def last_pipe_status(pl, segment_info):
|
||||
'''Return last pipe status.
|
||||
|
||||
Highlight groups used: ``exit_fail``, ``exit_success``
|
||||
'''
|
||||
last_pipe_status = segment_info['args'].last_pipe_status
|
||||
if any(last_pipe_status):
|
||||
return [{'contents': str(status), 'highlight_group': 'exit_fail' if status else 'exit_success', 'draw_inner_divider': True}
|
||||
for status in last_pipe_status]
|
||||
else:
|
||||
return None
|
|
@ -0,0 +1,443 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from __future__ import absolute_import, division
|
||||
|
||||
import os
|
||||
try:
|
||||
import vim
|
||||
except ImportError:
|
||||
vim = {} # NOQA
|
||||
|
||||
from powerline.bindings.vim import vim_get_func, getbufvar
|
||||
from powerline.theme import requires_segment_info
|
||||
from powerline.lib import add_divider_highlight_group
|
||||
from powerline.lib.vcs import guess
|
||||
from powerline.lib.humanize_bytes import humanize_bytes
|
||||
from powerline.lib.threaded import KwThreadedSegment, with_docstring
|
||||
from powerline.lib import wraps_saveargs as wraps
|
||||
from collections import defaultdict
|
||||
|
||||
vim_funcs = {
|
||||
'virtcol': vim_get_func('virtcol', rettype=int),
|
||||
'fnamemodify': vim_get_func('fnamemodify', rettype=str),
|
||||
'expand': vim_get_func('expand', rettype=str),
|
||||
'bufnr': vim_get_func('bufnr', rettype=int),
|
||||
'line2byte': vim_get_func('line2byte', rettype=int),
|
||||
}
|
||||
|
||||
vim_modes = {
|
||||
'n': 'NORMAL',
|
||||
'no': 'N·OPER',
|
||||
'v': 'VISUAL',
|
||||
'V': 'V·LINE',
|
||||
'^V': 'V·BLCK',
|
||||
's': 'SELECT',
|
||||
'S': 'S·LINE',
|
||||
'^S': 'S·BLCK',
|
||||
'i': 'INSERT',
|
||||
'R': 'REPLACE',
|
||||
'Rv': 'V·RPLCE',
|
||||
'c': 'COMMND',
|
||||
'cv': 'VIM EX',
|
||||
'ce': 'EX',
|
||||
'r': 'PROMPT',
|
||||
'rm': 'MORE',
|
||||
'r?': 'CONFIRM',
|
||||
'!': 'SHELL',
|
||||
}
|
||||
|
||||
|
||||
eventfuncs = defaultdict(lambda: [])
|
||||
bufeventfuncs = defaultdict(lambda: [])
|
||||
defined_events = set()
|
||||
|
||||
|
||||
def purgeonevents_reg(func, events, is_buffer_event=False):
|
||||
if is_buffer_event:
|
||||
cureventfuncs = bufeventfuncs
|
||||
else:
|
||||
cureventfuncs = eventfuncs
|
||||
for event in events:
|
||||
if event not in defined_events:
|
||||
vim.eval('PowerlineRegisterCachePurgerEvent("' + event + '")')
|
||||
defined_events.add(event)
|
||||
cureventfuncs[event].append(func)
|
||||
|
||||
|
||||
def launchevent(event):
|
||||
global eventfuncs
|
||||
global bufeventfuncs
|
||||
for func in eventfuncs[event]:
|
||||
func()
|
||||
if bufeventfuncs[event]:
|
||||
buffer = vim.buffers[int(vim_funcs['expand']('<abuf>')) - 1]
|
||||
for func in bufeventfuncs[event]:
|
||||
func(buffer)
|
||||
|
||||
|
||||
# TODO Remove cache when needed
|
||||
def window_cached(func):
|
||||
cache = {}
|
||||
|
||||
@requires_segment_info
|
||||
@wraps(func)
|
||||
def ret(segment_info, **kwargs):
|
||||
window_id = segment_info['window_id']
|
||||
if segment_info['mode'] == 'nc':
|
||||
return cache.get(window_id)
|
||||
else:
|
||||
r = func(**kwargs)
|
||||
cache[window_id] = r
|
||||
return r
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
def mode(pl, segment_info, override=None):
|
||||
'''Return the current vim mode.
|
||||
|
||||
:param dict override:
|
||||
dict for overriding default mode strings, e.g. ``{ 'n': 'NORM' }``
|
||||
'''
|
||||
mode = segment_info['mode']
|
||||
if mode == 'nc':
|
||||
return None
|
||||
if not override:
|
||||
return vim_modes[mode]
|
||||
try:
|
||||
return override[mode]
|
||||
except KeyError:
|
||||
return vim_modes[mode]
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
def modified_indicator(pl, segment_info, text='+'):
|
||||
'''Return a file modified indicator.
|
||||
|
||||
:param string text:
|
||||
text to display if the current buffer is modified
|
||||
'''
|
||||
return text if int(getbufvar(segment_info['bufnr'], '&modified')) else None
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
def paste_indicator(pl, segment_info, text='PASTE'):
|
||||
'''Return a paste mode indicator.
|
||||
|
||||
:param string text:
|
||||
text to display if paste mode is enabled
|
||||
'''
|
||||
return text if int(vim.eval('&paste')) else None
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
def readonly_indicator(pl, segment_info, text=''):
|
||||
'''Return a read-only indicator.
|
||||
|
||||
:param string text:
|
||||
text to display if the current buffer is read-only
|
||||
'''
|
||||
return text if int(getbufvar(segment_info['bufnr'], '&readonly')) else None
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
def file_directory(pl, segment_info, shorten_user=True, shorten_cwd=True, shorten_home=False):
|
||||
'''Return file directory (head component of the file path).
|
||||
|
||||
:param bool shorten_user:
|
||||
shorten ``$HOME`` directory to :file:`~/`
|
||||
|
||||
:param bool shorten_cwd:
|
||||
shorten current directory to :file:`./`
|
||||
|
||||
:param bool shorten_home:
|
||||
shorten all directories in :file:`/home/` to :file:`~user/` instead of :file:`/home/user/`.
|
||||
'''
|
||||
name = segment_info['buffer'].name
|
||||
if not name:
|
||||
return None
|
||||
file_directory = vim_funcs['fnamemodify'](name, (':~' if shorten_user else '')
|
||||
+ (':.' if shorten_cwd else '') + ':h')
|
||||
if shorten_home and file_directory.startswith('/home/'):
|
||||
file_directory = '~' + file_directory[6:]
|
||||
return file_directory + os.sep if file_directory else None
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
def file_name(pl, segment_info, display_no_file=False, no_file_text='[No file]'):
|
||||
'''Return file name (tail component of the file path).
|
||||
|
||||
:param bool display_no_file:
|
||||
display a string if the buffer is missing a file name
|
||||
:param str no_file_text:
|
||||
the string to display if the buffer is missing a file name
|
||||
|
||||
Highlight groups used: ``file_name_no_file`` or ``file_name``, ``file_name``.
|
||||
'''
|
||||
name = segment_info['buffer'].name
|
||||
if not name:
|
||||
if display_no_file:
|
||||
return [{
|
||||
'contents': no_file_text,
|
||||
'highlight_group': ['file_name_no_file', 'file_name'],
|
||||
}]
|
||||
else:
|
||||
return None
|
||||
file_name = vim_funcs['fnamemodify'](name, ':~:.:t')
|
||||
return file_name
|
||||
|
||||
|
||||
@window_cached
|
||||
def file_size(pl, suffix='B', si_prefix=False):
|
||||
'''Return file size in &encoding.
|
||||
|
||||
:param str suffix:
|
||||
string appended to the file size
|
||||
:param bool si_prefix:
|
||||
use SI prefix, e.g. MB instead of MiB
|
||||
:return: file size or None if the file isn't saved or if the size is too big to fit in a number
|
||||
'''
|
||||
# Note: returns file size in &encoding, not in &fileencoding. But returned
|
||||
# size is updated immediately; and it is valid for any buffer
|
||||
file_size = vim_funcs['line2byte'](len(vim.current.buffer) + 1) - 1
|
||||
return humanize_bytes(file_size, suffix, si_prefix)
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
@add_divider_highlight_group('background:divider')
|
||||
def file_format(pl, segment_info):
|
||||
'''Return file format (i.e. line ending type).
|
||||
|
||||
:return: file format or None if unknown or missing file format
|
||||
|
||||
Divider highlight group used: ``background:divider``.
|
||||
'''
|
||||
return getbufvar(segment_info['bufnr'], '&fileformat') or None
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
@add_divider_highlight_group('background:divider')
|
||||
def file_encoding(pl, segment_info):
|
||||
'''Return file encoding/character set.
|
||||
|
||||
:return: file encoding/character set or None if unknown or missing file encoding
|
||||
|
||||
Divider highlight group used: ``background:divider``.
|
||||
'''
|
||||
return getbufvar(segment_info['bufnr'], '&fileencoding') or None
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
@add_divider_highlight_group('background:divider')
|
||||
def file_type(pl, segment_info):
|
||||
'''Return file type.
|
||||
|
||||
:return: file type or None if unknown file type
|
||||
|
||||
Divider highlight group used: ``background:divider``.
|
||||
'''
|
||||
return getbufvar(segment_info['bufnr'], '&filetype') or None
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
def line_percent(pl, segment_info, gradient=False):
|
||||
'''Return the cursor position in the file as a percentage.
|
||||
|
||||
:param bool gradient:
|
||||
highlight the percentage with a color gradient (by default a green to red gradient)
|
||||
|
||||
Highlight groups used: ``line_percent_gradient`` (gradient), ``line_percent``.
|
||||
'''
|
||||
line_current = segment_info['window'].cursor[0]
|
||||
line_last = len(segment_info['buffer'])
|
||||
percentage = line_current * 100.0 / line_last
|
||||
if not gradient:
|
||||
return str(int(round(percentage)))
|
||||
return [{
|
||||
'contents': str(int(round(percentage))),
|
||||
'highlight_group': ['line_percent_gradient', 'line_percent'],
|
||||
'gradient_level': percentage,
|
||||
}]
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
def line_current(pl, segment_info):
|
||||
'''Return the current cursor line.'''
|
||||
return str(segment_info['window'].cursor[0])
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
def col_current(pl, segment_info):
|
||||
'''Return the current cursor column.
|
||||
'''
|
||||
return str(segment_info['window'].cursor[1] + 1)
|
||||
|
||||
|
||||
# TODO Add &textwidth-based gradient
|
||||
@window_cached
|
||||
def virtcol_current(pl, gradient=True):
|
||||
'''Return current visual column with concealed characters ingored
|
||||
|
||||
:param bool gradient:
|
||||
Determines whether it should show textwidth-based gradient (gradient level is ``virtcol * 100 / textwidth``).
|
||||
|
||||
Highlight groups used: ``virtcol_current_gradient`` (gradient), ``virtcol_current`` or ``col_current``.
|
||||
'''
|
||||
col = vim_funcs['virtcol']('.')
|
||||
r = [{'contents': str(col), 'highlight_group': ['virtcol_current', 'col_current']}]
|
||||
if gradient:
|
||||
textwidth = int(getbufvar('%', '&textwidth'))
|
||||
r[-1]['gradient_level'] = min(col * 100 / textwidth, 100) if textwidth else 0
|
||||
r[-1]['highlight_group'].insert(0, 'virtcol_current_gradient')
|
||||
return r
|
||||
|
||||
|
||||
def modified_buffers(pl, text='+ ', join_str=','):
|
||||
'''Return a comma-separated list of modified buffers.
|
||||
|
||||
:param str text:
|
||||
text to display before the modified buffer list
|
||||
:param str join_str:
|
||||
string to use for joining the modified buffer list
|
||||
'''
|
||||
buffer_len = vim_funcs['bufnr']('$')
|
||||
buffer_mod = [str(bufnr) for bufnr in range(1, buffer_len + 1) if int(getbufvar(bufnr, '&modified') or 0)]
|
||||
if buffer_mod:
|
||||
return text + join_str.join(buffer_mod)
|
||||
return None
|
||||
|
||||
|
||||
class KwWindowThreadedSegment(KwThreadedSegment):
|
||||
def set_state(self, **kwargs):
|
||||
kwargs = kwargs.copy()
|
||||
for window in vim.windows:
|
||||
buffer = window.buffer
|
||||
kwargs['segment_info'] = {'bufnr': buffer.number, 'buffer': buffer}
|
||||
super(KwWindowThreadedSegment, self).set_state(**kwargs)
|
||||
|
||||
|
||||
class RepositorySegment(KwWindowThreadedSegment):
|
||||
def __init__(self):
|
||||
super(RepositorySegment, self).__init__()
|
||||
self.directories = {}
|
||||
|
||||
@staticmethod
|
||||
def key(segment_info, **kwargs):
|
||||
# FIXME os.getcwd() is not a proper variant for non-current buffers
|
||||
return segment_info['buffer'].name or os.getcwd()
|
||||
|
||||
def update(self, *args):
|
||||
# .compute_state() is running only in this method, and only in one
|
||||
# thread, thus operations with .directories do not need write locks
|
||||
# (.render() method is not using .directories). If this is changed
|
||||
# .directories needs redesigning
|
||||
self.directories.clear()
|
||||
return super(RepositorySegment, self).update(*args)
|
||||
|
||||
def compute_state(self, path):
|
||||
repo = guess(path=path)
|
||||
if repo:
|
||||
if repo.directory in self.directories:
|
||||
return self.directories[repo.directory]
|
||||
else:
|
||||
r = self.process_repo(repo)
|
||||
self.directories[repo.directory] = r
|
||||
return r
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
class RepositoryStatusSegment(RepositorySegment):
|
||||
interval = 2
|
||||
|
||||
@staticmethod
|
||||
def process_repo(repo):
|
||||
return repo.status()
|
||||
|
||||
|
||||
repository_status = with_docstring(RepositoryStatusSegment(),
|
||||
'''Return the status for the current repo.''')
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
class BranchSegment(RepositorySegment):
|
||||
interval = 0.2
|
||||
started_repository_status = False
|
||||
|
||||
@staticmethod
|
||||
def process_repo(repo):
|
||||
return repo.branch()
|
||||
|
||||
def render_one(self, branch, segment_info, status_colors=False, **kwargs):
|
||||
if not branch:
|
||||
return None
|
||||
|
||||
if status_colors:
|
||||
self.started_repository_status = True
|
||||
|
||||
return [{
|
||||
'contents': branch,
|
||||
'highlight_group': (['branch_dirty' if repository_status(segment_info=segment_info, **kwargs) else 'branch_clean']
|
||||
if status_colors else []) + ['branch'],
|
||||
'divider_highlight_group': 'branch:divider',
|
||||
}]
|
||||
|
||||
def startup(self, status_colors=False, **kwargs):
|
||||
super(BranchSegment, self).startup(**kwargs)
|
||||
if status_colors:
|
||||
self.started_repository_status = True
|
||||
repository_status.startup(**kwargs)
|
||||
|
||||
def shutdown(self):
|
||||
if self.started_repository_status:
|
||||
repository_status.shutdown()
|
||||
super(BranchSegment, self).shutdown()
|
||||
|
||||
|
||||
branch = with_docstring(BranchSegment(),
|
||||
'''Return the current working branch.
|
||||
|
||||
:param bool status_colors:
|
||||
determines whether repository status will be used to determine highlighting. Default: False.
|
||||
|
||||
Highlight groups used: ``branch_clean``, ``branch_dirty``, ``branch``.
|
||||
|
||||
Divider highlight group used: ``branch:divider``.
|
||||
''')
|
||||
|
||||
|
||||
@requires_segment_info
|
||||
class FileVCSStatusSegment(KwWindowThreadedSegment):
|
||||
interval = 0.2
|
||||
|
||||
@staticmethod
|
||||
def key(segment_info, **kwargs):
|
||||
name = segment_info['buffer'].name
|
||||
skip = not (name and (not getbufvar(segment_info['bufnr'], '&buftype')))
|
||||
return name, skip
|
||||
|
||||
@staticmethod
|
||||
def compute_state(key):
|
||||
name, skip = key
|
||||
if not skip:
|
||||
repo = guess(path=name)
|
||||
if repo:
|
||||
status = repo.status(os.path.relpath(name, repo.directory))
|
||||
if not status:
|
||||
return None
|
||||
status = status.strip()
|
||||
ret = []
|
||||
for status in status:
|
||||
ret.append({
|
||||
'contents': status,
|
||||
'highlight_group': ['file_vcs_status_' + status, 'file_vcs_status'],
|
||||
})
|
||||
return ret
|
||||
return None
|
||||
|
||||
|
||||
file_vcs_status = with_docstring(FileVCSStatusSegment(),
|
||||
'''Return the VCS status for this buffer.
|
||||
|
||||
Highlight groups used: ``file_vcs_status``.
|
||||
''')
|
55
common/.local/lib/python2.7/site-packages/powerline/shell.py
Normal file
55
common/.local/lib/python2.7/site-packages/powerline/shell.py
Normal file
|
@ -0,0 +1,55 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from powerline import Powerline
|
||||
from powerline.lib import mergedicts, parsedotval
|
||||
|
||||
|
||||
def mergeargs(argvalue):
|
||||
if not argvalue:
|
||||
return None
|
||||
r = dict([argvalue[0]])
|
||||
for subval in argvalue[1:]:
|
||||
mergedicts(r, dict([subval]))
|
||||
return r
|
||||
|
||||
|
||||
class ShellPowerline(Powerline):
|
||||
def __init__(self, args, **kwargs):
|
||||
self.args = args
|
||||
self.theme_option = mergeargs(args.theme_option) or {}
|
||||
super(ShellPowerline, self).__init__(args.ext[0], args.renderer_module, **kwargs)
|
||||
|
||||
def load_main_config(self):
|
||||
r = super(ShellPowerline, self).load_main_config()
|
||||
if self.args.config:
|
||||
mergedicts(r, mergeargs(self.args.config))
|
||||
return r
|
||||
|
||||
def load_theme_config(self, name):
|
||||
r = super(ShellPowerline, self).load_theme_config(name)
|
||||
if name in self.theme_option:
|
||||
mergedicts(r, self.theme_option[name])
|
||||
return r
|
||||
|
||||
def get_config_paths(self):
|
||||
if self.args.config_path:
|
||||
return [self.args.config_path]
|
||||
else:
|
||||
return super(ShellPowerline, self).get_config_paths()
|
||||
|
||||
|
||||
def get_argparser(parser=None, *args, **kwargs):
|
||||
if not parser:
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser
|
||||
p = parser(*args, **kwargs)
|
||||
p.add_argument('ext', nargs=1)
|
||||
p.add_argument('side', nargs='?', choices=('left', 'right'))
|
||||
p.add_argument('-r', '--renderer_module', metavar='MODULE', type=str)
|
||||
p.add_argument('-w', '--width', type=int)
|
||||
p.add_argument('--last_exit_code', metavar='INT', type=int)
|
||||
p.add_argument('--last_pipe_status', metavar='LIST', default='', type=lambda s: [int(status) for status in s.split()])
|
||||
p.add_argument('-c', '--config', metavar='KEY.KEY=VALUE', type=parsedotval, action='append')
|
||||
p.add_argument('-t', '--theme_option', metavar='THEME.KEY.KEY=VALUE', type=parsedotval, action='append')
|
||||
p.add_argument('-p', '--config_path', metavar='PATH')
|
||||
return p
|
148
common/.local/lib/python2.7/site-packages/powerline/theme.py
Normal file
148
common/.local/lib/python2.7/site-packages/powerline/theme.py
Normal file
|
@ -0,0 +1,148 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from .segment import gen_segment_getter
|
||||
|
||||
|
||||
try:
|
||||
from __builtin__ import unicode
|
||||
except ImportError:
|
||||
unicode = str # NOQA
|
||||
|
||||
|
||||
def u(s):
|
||||
if type(s) is unicode:
|
||||
return s
|
||||
else:
|
||||
return unicode(s, 'utf-8')
|
||||
|
||||
|
||||
def requires_segment_info(func):
|
||||
func.powerline_requires_segment_info = True
|
||||
return func
|
||||
|
||||
|
||||
class Theme(object):
|
||||
def __init__(self,
|
||||
ext,
|
||||
theme_config,
|
||||
common_config,
|
||||
pl,
|
||||
top_theme_config=None,
|
||||
run_once=False,
|
||||
shutdown_event=None):
|
||||
self.dividers = theme_config.get('dividers', common_config['dividers'])
|
||||
self.spaces = theme_config.get('spaces', common_config['spaces'])
|
||||
self.segments = {
|
||||
'left': [],
|
||||
'right': [],
|
||||
}
|
||||
self.EMPTY_SEGMENT = {
|
||||
'contents': None,
|
||||
'highlight': {'fg': False, 'bg': False, 'attr': 0}
|
||||
}
|
||||
self.pl = pl
|
||||
theme_configs = [theme_config]
|
||||
if top_theme_config:
|
||||
theme_configs.append(top_theme_config)
|
||||
get_segment = gen_segment_getter(pl, ext, common_config['paths'], theme_configs, theme_config.get('default_module'))
|
||||
for side in ['left', 'right']:
|
||||
for segment in theme_config['segments'].get(side, []):
|
||||
segment = get_segment(segment, side)
|
||||
if not run_once:
|
||||
if segment['startup']:
|
||||
try:
|
||||
segment['startup'](pl=pl, shutdown_event=shutdown_event, **segment['args'])
|
||||
except Exception as e:
|
||||
pl.error('Exception during {0} startup: {1}', segment['name'], str(e))
|
||||
continue
|
||||
self.segments[side].append(segment)
|
||||
|
||||
def shutdown(self):
|
||||
for segments in self.segments.values():
|
||||
for segment in segments:
|
||||
try:
|
||||
segment['shutdown']()
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
def get_divider(self, side='left', type='soft'):
|
||||
'''Return segment divider.'''
|
||||
return self.dividers[side][type]
|
||||
|
||||
def get_spaces(self):
|
||||
return self.spaces
|
||||
|
||||
def get_segments(self, side=None, segment_info=None):
|
||||
'''Return all segments.
|
||||
|
||||
Function segments are called, and all segments get their before/after
|
||||
and ljust/rjust properties applied.
|
||||
'''
|
||||
for side in [side] if side else ['left', 'right']:
|
||||
parsed_segments = []
|
||||
for segment in self.segments[side]:
|
||||
if segment['type'] == 'function':
|
||||
self.pl.prefix = segment['name']
|
||||
try:
|
||||
if (hasattr(segment['contents_func'], 'powerline_requires_segment_info')
|
||||
and segment['contents_func'].powerline_requires_segment_info):
|
||||
contents = segment['contents_func'](pl=self.pl, segment_info=segment_info, **segment['args'])
|
||||
else:
|
||||
contents = segment['contents_func'](pl=self.pl, **segment['args'])
|
||||
except Exception as e:
|
||||
self.pl.exception('Exception while computing segment: {0}', str(e))
|
||||
continue
|
||||
|
||||
if contents is None:
|
||||
continue
|
||||
if isinstance(contents, list):
|
||||
segment_base = segment.copy()
|
||||
if contents:
|
||||
draw_divider_position = -1 if side == 'left' else 0
|
||||
for key, i, newval in (
|
||||
('before', 0, ''),
|
||||
('after', -1, ''),
|
||||
('draw_soft_divider', draw_divider_position, True),
|
||||
('draw_hard_divider', draw_divider_position, True),
|
||||
):
|
||||
try:
|
||||
contents[i][key] = segment_base.pop(key)
|
||||
segment_base[key] = newval
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
draw_inner_divider = None
|
||||
if side == 'right':
|
||||
append = parsed_segments.append
|
||||
else:
|
||||
pslen = len(parsed_segments)
|
||||
append = lambda item: parsed_segments.insert(pslen, item)
|
||||
|
||||
for subsegment in (contents if side == 'right' else reversed(contents)):
|
||||
segment_copy = segment_base.copy()
|
||||
segment_copy.update(subsegment)
|
||||
if draw_inner_divider is not None:
|
||||
segment_copy['draw_soft_divider'] = draw_inner_divider
|
||||
draw_inner_divider = segment_copy.pop('draw_inner_divider', None)
|
||||
append(segment_copy)
|
||||
else:
|
||||
segment['contents'] = contents
|
||||
parsed_segments.append(segment)
|
||||
elif segment['width'] == 'auto' or (segment['type'] == 'string' and segment['contents'] is not None):
|
||||
parsed_segments.append(segment)
|
||||
else:
|
||||
continue
|
||||
for segment in parsed_segments:
|
||||
segment['contents'] = segment['before'] + u(segment['contents'] if segment['contents'] is not None else '') + segment['after']
|
||||
# Align segment contents
|
||||
if segment['width'] and segment['width'] != 'auto':
|
||||
if segment['align'] == 'l':
|
||||
segment['contents'] = segment['contents'].ljust(segment['width'])
|
||||
elif segment['align'] == 'r':
|
||||
segment['contents'] = segment['contents'].rjust(segment['width'])
|
||||
elif segment['align'] == 'c':
|
||||
segment['contents'] = segment['contents'].center(segment['width'])
|
||||
# We need to yield a copy of the segment, or else mode-dependent
|
||||
# segment contents can't be cached correctly e.g. when caching
|
||||
# non-current window contents for vim statuslines
|
||||
yield segment.copy()
|
95
common/.local/lib/python2.7/site-packages/powerline/vim.py
Normal file
95
common/.local/lib/python2.7/site-packages/powerline/vim.py
Normal file
|
@ -0,0 +1,95 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from powerline.bindings.vim import vim_get_func
|
||||
from powerline import Powerline
|
||||
from powerline.lib import mergedicts
|
||||
from powerline.matcher import gen_matcher_getter
|
||||
import vim
|
||||
|
||||
|
||||
vim_exists = vim_get_func('exists', rettype=int)
|
||||
|
||||
|
||||
def _override_from(config, override_varname):
|
||||
if vim_exists(override_varname):
|
||||
# FIXME vim.eval has problem with numeric types, vim.bindeval may be
|
||||
# absent (and requires converting values to python built-in types),
|
||||
# vim.eval with typed call like the one I implemented in frawor is slow.
|
||||
# Maybe eval(vime.eval('string({0})'.format(override_varname)))?
|
||||
overrides = vim.eval(override_varname)
|
||||
mergedicts(config, overrides)
|
||||
return config
|
||||
|
||||
|
||||
class VimPowerline(Powerline):
|
||||
def __init__(self):
|
||||
super(VimPowerline, self).__init__('vim')
|
||||
|
||||
def add_local_theme(self, key, config):
|
||||
'''Add local themes at runtime (during vim session).
|
||||
|
||||
:param str key:
|
||||
Matcher name (in format ``{matcher_module}.{module_attribute}`` or
|
||||
``{module_attribute}`` if ``{matcher_module}`` is
|
||||
``powerline.matchers.vim``). Function pointed by
|
||||
``{module_attribute}`` should be hashable and accept a dictionary
|
||||
with information about current buffer and return boolean value
|
||||
indicating whether current window matched conditions. See also
|
||||
:ref:`local_themes key description <config-ext-local_themes>`.
|
||||
|
||||
:param dict config:
|
||||
:ref:`Theme <config-themes>` dictionary.
|
||||
|
||||
:return:
|
||||
``True`` if theme was added successfully and ``False`` if theme with
|
||||
the same matcher already exists.
|
||||
'''
|
||||
self.update_renderer()
|
||||
key = self.get_matcher(key)
|
||||
try:
|
||||
self.renderer.add_local_theme(key, {'config': config})
|
||||
except KeyError:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def load_main_config(self):
|
||||
return _override_from(super(VimPowerline, self).load_main_config(), 'g:powerline_config_overrides')
|
||||
|
||||
def load_theme_config(self, name):
|
||||
# Note: themes with non-[a-zA-Z0-9_] names are impossible to override
|
||||
# (though as far as I know exists() won’t throw). Won’t fix, use proper
|
||||
# theme names.
|
||||
return _override_from(super(VimPowerline, self).load_theme_config(name),
|
||||
'g:powerline_theme_overrides__' + name)
|
||||
|
||||
def get_local_themes(self, local_themes):
|
||||
if not local_themes:
|
||||
return {}
|
||||
|
||||
self.get_matcher = gen_matcher_getter(self.ext, self.import_paths)
|
||||
return dict(((self.get_matcher(key), {'config': self.load_theme_config(val)})
|
||||
for key, val in local_themes.items()))
|
||||
|
||||
def get_config_paths(self):
|
||||
if vim_exists('g:powerline_config_path'):
|
||||
return [vim.eval('g:powerline_config_path')]
|
||||
else:
|
||||
return super(VimPowerline, self).get_config_paths()
|
||||
|
||||
@staticmethod
|
||||
def get_segment_info():
|
||||
return {}
|
||||
|
||||
def reset_highlight(self):
|
||||
try:
|
||||
self.renderer.reset_highlight()
|
||||
except AttributeError:
|
||||
# Renderer object appears only after first `.render()` call. Thus if
|
||||
# ColorScheme event happens before statusline is drawn for the first
|
||||
# time AttributeError will be thrown for the self.renderer. It is
|
||||
# fine to ignore it: no renderer == no colors to reset == no need to
|
||||
# do anything.
|
||||
pass
|
|
@ -1,11 +1,13 @@
|
|||
# Path to your oh-my-zsh configuration.
|
||||
ZSH=$HOME/.oh-my-zsh
|
||||
|
||||
export TERM="xterm-256color"
|
||||
|
||||
# Set name of the theme to load.
|
||||
# Look in ~/.oh-my-zsh/themes/
|
||||
# Optionally, if you set this to "random", it'll load a random theme each
|
||||
# time that oh-my-zsh is loaded.
|
||||
ZSH_THEME="robbyrussell"
|
||||
#ZSH_THEME="robbyrussell"
|
||||
|
||||
# Example aliases
|
||||
# alias zshconfig="mate ~/.zshrc"
|
||||
|
@ -24,23 +26,37 @@ ZSH_THEME="robbyrussell"
|
|||
# DISABLE_AUTO_TITLE="true"
|
||||
|
||||
# Uncomment following line if you want red dots to be displayed while waiting for completion
|
||||
# COMPLETION_WAITING_DOTS="true"
|
||||
COMPLETION_WAITING_DOTS="true"
|
||||
|
||||
# Which plugins would you like to load? (plugins can be found in ~/.oh-my-zsh/plugins/*)
|
||||
# Custom plugins may be added to ~/.oh-my-zsh/custom/plugins/
|
||||
# Example format: plugins=(rails git textmate ruby lighthouse)
|
||||
plugins=(git)
|
||||
plugins=(git mercurial battery colorize debian django go pip python svn tmux vi-mode command-not-found)
|
||||
|
||||
bindkey "^[[A" history-search-backward
|
||||
bindkey "^[[B" history-search-forward
|
||||
|
||||
source $ZSH/oh-my-zsh.sh
|
||||
source ~/.zshrc-local
|
||||
source ~/.zshrc-local-theme
|
||||
|
||||
autoload -Uz promptinit
|
||||
promptinit
|
||||
prompt fire
|
||||
|
||||
autoload -U zsh-mime-setup
|
||||
autoload -U zsh-mime-handler
|
||||
zsh-mime-setup
|
||||
|
||||
autoload -Uz vcs_info
|
||||
zstyle ':vcs_info:*' enable git svn hg bzr mtn
|
||||
precmd() {
|
||||
vcs_info
|
||||
}
|
||||
|
||||
zstyle ':vcs_info:*' actionformats
|
||||
zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat '%b%F{1}:%F{3}%r'
|
||||
|
||||
|
||||
|
||||
alias make='colormake'
|
||||
alias gcc='colorgcc'
|
||||
|
@ -70,7 +86,7 @@ function cd() {
|
|||
# Customize to your needs...
|
||||
export PATH=$PATH:/usr/sbin:/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/games
|
||||
|
||||
ssc() { ssh -XC -p ${3:-"22"} -t ${2:-`whoami`}@$1 tmux ${argv[4,-1]:-"attach-session"}; }
|
||||
ssc() { ssh -XC -p ${3:-"22"} -t ${2:-`whoami`}@$1 "tmux ${argv[4,-1]:-"attach-session"} || tmux ${argv[4,-1]} ;" }
|
||||
|
||||
senritsu() { ssc senritsu.kujiu.org ${argv[-1]:-`whoami`} 22 $argv[1,-2]; }
|
||||
gon() { ssc gon.kujiu.org ${argv[-1]:-`whoami`} 2208 $argv[1,-2]; }
|
||||
|
@ -78,7 +94,9 @@ kirua() { ssc kirua.kujiu.org ${argv[-1]:-`whoami`} 22 $argv[1,-2]; }
|
|||
kurapika() { ssc kurapika.kujiu.org ${argv[-1]:-`whoami`} 2242 $argv[1,-2]; }
|
||||
leorio() { ssc leorio.kujiu.org ${argv[-1]:-`whoami`} 22 $argv[1,-2]; }
|
||||
ellcrys() { ssc ellcrys.kujiu.org ${argv[-1]:-`whoami`} 22 $argv[1,-2]; }
|
||||
bisuke() { ssc bisuke.kujiu.org ${argv[-1]:-`whoami`} 22 $argv[1,-2]; }
|
||||
goreinu() { ssc goreinu.kujiu.org ${argv[-1]:-`whoami`} 22 $argv[1,-2]; }
|
||||
pakunoda() { ssc pakunoda.kujiu.org ${argv[-1]:-`whoami`} 22 $argv[1,-2]; }
|
||||
hisoka() { ssc hisoka.kujiu.org ${argv[-1]:-`whoami`} 22 $argv[1,-2]; }
|
||||
|
||||
DEBEMAIL="christophe@buffenoir.org"
|
||||
DEBFULLNAME="Christophe Buffenoir"
|
||||
export DEBEMAIL DEBFULLNAME
|
||||
hl() { highlight --out-format=xterm256 -l ${argv} | less -R; }
|
8
common/.zshrc-local
Normal file
8
common/.zshrc-local
Normal file
|
@ -0,0 +1,8 @@
|
|||
DEBEMAIL="christophe@buffenoir.org"
|
||||
DEBFULLNAME="Christophe Buffenoir"
|
||||
|
||||
export DEBEMAIL DEBFULLNAME
|
||||
|
||||
POWERLINE_DETECT_SSH="true"
|
||||
#POWERLINE_FULL_CURRENT_PATH="true"
|
||||
|
129
common/.zshrc-local-theme
Normal file
129
common/.zshrc-local-theme
Normal file
|
@ -0,0 +1,129 @@
|
|||
# FreeAgent puts the powerline style in zsh !
|
||||
|
||||
if [ "$POWERLINE_DATE_FORMAT" = "" ]; then
|
||||
POWERLINE_DATE_FORMAT=%D{%Y-%m-%d}
|
||||
fi
|
||||
|
||||
if [ "$POWERLINE_RIGHT_B" = "" ]; then
|
||||
POWERLINE_RIGHT_B=%D{%H:%M:%S}
|
||||
fi
|
||||
|
||||
if [ "$POWERLINE_RIGHT_A" = "mixed" ]; then
|
||||
POWERLINE_RIGHT_A=%(?."$POWERLINE_DATE_FORMAT".%F{red}✘ %?)
|
||||
elif [ "$POWERLINE_RIGHT_A" = "exit-status" ]; then
|
||||
POWERLINE_RIGHT_A=%(?.%F{green}✔ %?.%F{red}✘ %?)
|
||||
elif [ "$POWERLINE_RIGHT_A" = "date" ]; then
|
||||
POWERLINE_RIGHT_A="$POWERLINE_DATE_FORMAT"
|
||||
fi
|
||||
|
||||
if [ "$POWERLINE_HIDE_USER_NAME" = "" ] && [ "$POWERLINE_HIDE_HOST_NAME" = "" ]; then
|
||||
POWERLINE_USER_NAME="%n@%M"
|
||||
elif [ "$POWERLINE_HIDE_USER_NAME" != "" ] && [ "$POWERLINE_HIDE_HOST_NAME" = "" ]; then
|
||||
POWERLINE_USER_NAME="@%M"
|
||||
elif [ "$POWERLINE_HIDE_USER_NAME" = "" ] && [ "$POWERLINE_HIDE_HOST_NAME" != "" ]; then
|
||||
POWERLINE_USER_NAME="%n"
|
||||
else
|
||||
POWERLINE_USER_NAME=""
|
||||
fi
|
||||
|
||||
POWERLINE_CURRENT_PATH="%d"
|
||||
|
||||
if [ "$POWERLINE_FULL_CURRENT_PATH" = "" ]; then
|
||||
POWERLINE_CURRENT_PATH="%1~"
|
||||
fi
|
||||
|
||||
if [ "$POWERLINE_GIT_CLEAN" = "" ]; then
|
||||
POWERLINE_GIT_CLEAN="✔"
|
||||
fi
|
||||
|
||||
if [ "$POWERLINE_GIT_DIRTY" = "" ]; then
|
||||
POWERLINE_GIT_DIRTY="✘"
|
||||
fi
|
||||
|
||||
if [ "$POWERLINE_GIT_ADDED" = "" ]; then
|
||||
POWERLINE_GIT_ADDED="%F{green}✚%F{black}"
|
||||
fi
|
||||
|
||||
if [ "$POWERLINE_GIT_MODIFIED" = "" ]; then
|
||||
POWERLINE_GIT_MODIFIED="%F{blue}✹%F{black}"
|
||||
fi
|
||||
|
||||
if [ "$POWERLINE_GIT_DELETED" = "" ]; then
|
||||
POWERLINE_GIT_DELETED="%F{red}✖%F{black}"
|
||||
fi
|
||||
|
||||
if [ "$POWERLINE_GIT_UNTRACKED" = "" ]; then
|
||||
POWERLINE_GIT_UNTRACKED="%F{yellow}✭%F{black}"
|
||||
fi
|
||||
|
||||
if [ "$POWERLINE_GIT_RENAMED" = "" ]; then
|
||||
POWERLINE_GIT_RENAMED="➜"
|
||||
fi
|
||||
|
||||
if [ "$POWERLINE_GIT_UNMERGED" = "" ]; then
|
||||
POWERLINE_GIT_UNMERGED="═"
|
||||
fi
|
||||
|
||||
ZSH_THEME_GIT_PROMPT_PREFIX=" \ue0a0 "
|
||||
ZSH_THEME_GIT_PROMPT_SUFFIX=""
|
||||
ZSH_THEME_GIT_PROMPT_DIRTY=" $POWERLINE_GIT_DIRTY"
|
||||
ZSH_THEME_GIT_PROMPT_CLEAN=" $POWERLINE_GIT_CLEAN"
|
||||
|
||||
ZSH_THEME_GIT_PROMPT_ADDED=" $POWERLINE_GIT_ADDED"
|
||||
ZSH_THEME_GIT_PROMPT_MODIFIED=" $POWERLINE_GIT_MODIFIED"
|
||||
ZSH_THEME_GIT_PROMPT_DELETED=" $POWERLINE_GIT_DELETED"
|
||||
ZSH_THEME_GIT_PROMPT_UNTRACKED=" $POWERLINE_GIT_UNTRACKED"
|
||||
ZSH_THEME_GIT_PROMPT_RENAMED=" $POWERLINE_GIT_RENAMED"
|
||||
ZSH_THEME_GIT_PROMPT_UNMERGED=" $POWERLINE_GIT_UNMERGED"
|
||||
ZSH_THEME_GIT_PROMPT_AHEAD=" ⬆"
|
||||
ZSH_THEME_GIT_PROMPT_BEHIND=" ⬇"
|
||||
ZSH_THEME_GIT_PROMPT_DIVERGED=" ⬍"
|
||||
|
||||
# if [ "${vcs_info_msg_0_}" = "" ]; then
|
||||
# POWERLINE_GIT_INFO_LEFT=""
|
||||
# POWERLINE_GIT_INFO_RIGHT=""
|
||||
# else
|
||||
if [ "$POWERLINE_SHOW_GIT_ON_RIGHT" = "" ]; then
|
||||
if [ "$POWERLINE_HIDE_GIT_PROMPT_STATUS" = "" ]; then
|
||||
POWERLINE_GIT_INFO_LEFT=" %F{blue}%K{white}"$'\ue0b0'"%F{white}%F{black}%K{white}"$'${vcs_info_msg_0_}$(git_prompt_status)%F{white}'
|
||||
else
|
||||
POWERLINE_GIT_INFO_LEFT=" %F{blue}%K{white}"$'\ue0b0'"%F{white}%F{black}%K{white}"$'${vcs_info_msg_0_}%F{white}'
|
||||
fi
|
||||
POWERLINE_GIT_INFO_RIGHT=""
|
||||
else
|
||||
POWERLINE_GIT_INFO_LEFT=""
|
||||
POWERLINE_GIT_INFO_RIGHT="%F{white}"$'\ue0b2'"%F{black}%K{white}"$'${vcs_info_msg_0_}'" %K{white}"
|
||||
fi
|
||||
# fi
|
||||
|
||||
if [ $(id -u) -eq 0 ]; then
|
||||
POWERLINE_SEC1_BG=%K{red}
|
||||
POWERLINE_SEC1_FG=%F{red}
|
||||
else
|
||||
POWERLINE_SEC1_BG=%K{green}
|
||||
POWERLINE_SEC1_FG=%F{green}
|
||||
fi
|
||||
POWERLINE_SEC1_TXT=%F{black}
|
||||
if [ "$POWERLINE_DETECT_SSH" != "" ]; then
|
||||
if [ -n "$SSH_CLIENT" ]; then
|
||||
POWERLINE_SEC1_BG=%K{red}
|
||||
POWERLINE_SEC1_FG=%F{red}
|
||||
POWERLINE_SEC1_TXT=%F{white}
|
||||
fi
|
||||
fi
|
||||
PROMPT="$POWERLINE_SEC1_BG$POWERLINE_SEC1_TXT $POWERLINE_USER_NAME %k%f$POWERLINE_SEC1_FG%K{blue}"$'\ue0b0'"%k%f%F{white}%K{blue} "$POWERLINE_CURRENT_PATH"%F{blue}"$POWERLINE_GIT_INFO_LEFT" %k"$'\ue0b0'"%f "
|
||||
|
||||
if [ "$POWERLINE_NO_BLANK_LINE" = "" ]; then
|
||||
PROMPT="
|
||||
"$PROMPT
|
||||
fi
|
||||
|
||||
if [ "$POWERLINE_DISABLE_RPROMPT" = "" ]; then
|
||||
if [ "$POWERLINE_RIGHT_A" = "" ]; then
|
||||
RPROMPT="$POWERLINE_GIT_INFO_RIGHT%F{white}"$'\ue0b2'"%k%F{black}%K{white} $POWERLINE_RIGHT_B %f%k"
|
||||
else
|
||||
RPROMPT="$POWERLINE_GIT_INFO_RIGHT%F{white}"$'\ue0b2'"%k%F{black}%K{white} $POWERLINE_RIGHT_B %f%F{240}"$'\ue0b2'"%f%k%K{240}%F{255} $POWERLINE_RIGHT_A %f%k"
|
||||
fi
|
||||
fi
|
||||
|
||||
zstyle ':vcs_info:*' formats "$ZSH_THEME_GIT_PROMPT_PREFIX${ref#refs/heads/}%s %r/%S %b %m%u%c$ZSH_THEME_GIT_PROMPT_SUFFIX"
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue