summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2019-09-14 17:20:05 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2019-09-14 17:20:05 +0000
commitfd3ca6bbda3af8e65e51d4c0ff0336884c906be8 (patch)
tree5d263b4543e10940f5e9a79a8fe981c5a3414bd7
parentInitial commit. (diff)
downloadpowerline-fd3ca6bbda3af8e65e51d4c0ff0336884c906be8.tar.xz
powerline-fd3ca6bbda3af8e65e51d4c0ff0336884c906be8.zip
Adding upstream version 2.7.upstream/2.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r--.editorconfig20
-rw-r--r--.gitattributes1
-rw-r--r--.gitignore16
-rw-r--r--.local.vimrc11
-rw-r--r--.travis.yml42
-rw-r--r--CONTRIBUTING.rst138
-rw-r--r--LICENSE21
-rw-r--r--MANIFEST.in7
-rw-r--r--README.rst95
-rw-r--r--client/powerline.c164
-rwxr-xr-xclient/powerline.py104
-rwxr-xr-xclient/powerline.sh53
-rw-r--r--docs/.gitignore1
-rw-r--r--docs/Makefile39
-rw-r--r--docs/source/_static/css/theme_overrides.css6
-rw-r--r--docs/source/_static/img/icons/cross.pngbin0 -> 473 bytes
-rw-r--r--docs/source/_static/img/icons/error.pngbin0 -> 543 bytes
-rw-r--r--docs/source/_static/img/icons/tick.pngbin0 -> 451 bytes
-rw-r--r--docs/source/_static/img/pl-mode-insert.pngbin0 -> 6894 bytes
-rw-r--r--docs/source/_static/img/pl-mode-normal.pngbin0 -> 6879 bytes
-rw-r--r--docs/source/_static/img/pl-mode-replace.pngbin0 -> 6949 bytes
-rw-r--r--docs/source/_static/img/pl-mode-visual.pngbin0 -> 6868 bytes
-rw-r--r--docs/source/_static/img/pl-truncate1.pngbin0 -> 6882 bytes
-rw-r--r--docs/source/_static/img/pl-truncate2.pngbin0 -> 5541 bytes
-rw-r--r--docs/source/_static/img/pl-truncate3.pngbin0 -> 3093 bytes
-rw-r--r--docs/source/commands.rst9
-rw-r--r--docs/source/commands/config.rst12
-rw-r--r--docs/source/commands/daemon.rst12
-rw-r--r--docs/source/commands/lint.rst14
-rw-r--r--docs/source/commands/main.rst12
-rw-r--r--docs/source/conf.py70
-rw-r--r--docs/source/configuration.rst146
-rw-r--r--docs/source/configuration/listers.rst35
-rw-r--r--docs/source/configuration/local.rst260
-rw-r--r--docs/source/configuration/reference.rst602
-rw-r--r--docs/source/configuration/segments.rst28
-rw-r--r--docs/source/configuration/segments/common.rst57
-rw-r--r--docs/source/configuration/segments/i3wm.rst6
-rw-r--r--docs/source/configuration/segments/pdb.rst7
-rw-r--r--docs/source/configuration/segments/shell.rst6
-rw-r--r--docs/source/configuration/segments/tmux.rst6
-rw-r--r--docs/source/configuration/segments/vim.rst46
-rw-r--r--docs/source/configuration/selectors.rst17
-rw-r--r--docs/source/configuration/selectors/vim.rst6
-rw-r--r--docs/source/develop.rst13
-rw-r--r--docs/source/develop/extensions.rst47
-rw-r--r--docs/source/develop/listers.rst49
-rw-r--r--docs/source/develop/local-themes.rst59
-rw-r--r--docs/source/develop/segments.rst547
-rw-r--r--docs/source/develop/tips-and-tricks.rst21
-rw-r--r--docs/source/index.rst28
-rw-r--r--docs/source/installation.rst132
-rw-r--r--docs/source/installation/linux.rst110
-rw-r--r--docs/source/installation/osx.rst67
-rw-r--r--docs/source/license-and-credits.rst31
-rw-r--r--docs/source/overview.rst67
-rw-r--r--docs/source/powerline_autodoc.py64
-rw-r--r--docs/source/powerline_automan.py408
-rw-r--r--docs/source/tips-and-tricks.rst94
-rw-r--r--docs/source/troubleshooting.rst329
-rw-r--r--docs/source/troubleshooting/linux.rst78
-rw-r--r--docs/source/troubleshooting/osx.rst71
-rw-r--r--docs/source/usage.rst88
-rw-r--r--docs/source/usage/other.rst209
-rw-r--r--docs/source/usage/shell-prompts.rst144
-rw-r--r--docs/source/usage/wm-widgets.rst102
-rw-r--r--font/10-powerline-symbols.conf105
-rw-r--r--font/PowerlineSymbols.otfbin0 -> 2264 bytes
-rw-r--r--powerline/__init__.py991
-rw-r--r--powerline/bindings/__init__.py0
-rwxr-xr-xpowerline/bindings/awesome/powerline-awesome.py20
-rw-r--r--powerline/bindings/awesome/powerline.lua15
-rwxr-xr-xpowerline/bindings/bar/powerline-bar.py60
-rw-r--r--powerline/bindings/bash/powerline.sh153
-rw-r--r--powerline/bindings/config.py286
-rw-r--r--powerline/bindings/fish/powerline-setup.fish109
-rwxr-xr-xpowerline/bindings/i3/powerline-i3.py52
-rw-r--r--powerline/bindings/ipython/__init__.py0
-rw-r--r--powerline/bindings/ipython/post_0_11.py123
-rw-r--r--powerline/bindings/ipython/pre_0_11.py146
-rw-r--r--powerline/bindings/ipython/since_5.py81
-rwxr-xr-xpowerline/bindings/lemonbar/powerline-lemonbar.py61
-rw-r--r--powerline/bindings/pdb/__init__.py183
-rwxr-xr-xpowerline/bindings/pdb/__main__.py9
-rw-r--r--powerline/bindings/qtile/__init__.py0
-rw-r--r--powerline/bindings/qtile/widget.py61
-rw-r--r--powerline/bindings/rc/powerline.rc92
-rw-r--r--powerline/bindings/shell/powerline.sh239
-rw-r--r--powerline/bindings/tcsh/powerline.tcsh60
-rw-r--r--powerline/bindings/tmux/__init__.py84
-rw-r--r--powerline/bindings/tmux/powerline-base.conf11
-rw-r--r--powerline/bindings/tmux/powerline.conf2
-rw-r--r--powerline/bindings/tmux/powerline_tmux_1.7_plus.conf3
-rw-r--r--powerline/bindings/tmux/powerline_tmux_1.8.conf5
-rw-r--r--powerline/bindings/tmux/powerline_tmux_1.8_minus.conf11
-rw-r--r--powerline/bindings/tmux/powerline_tmux_1.8_plus.conf5
-rw-r--r--powerline/bindings/tmux/powerline_tmux_1.9_plus.conf8
-rw-r--r--powerline/bindings/tmux/powerline_tmux_2.1_plus.conf3
-rw-r--r--powerline/bindings/vim/__init__.py482
-rw-r--r--powerline/bindings/vim/autoload/powerline/debug.vim20
-rw-r--r--powerline/bindings/vim/plugin/powerline.vim169
-rw-r--r--powerline/bindings/wm/__init__.py85
-rw-r--r--powerline/bindings/wm/awesome.py59
-rw-r--r--powerline/bindings/zsh/__init__.py228
-rw-r--r--powerline/bindings/zsh/powerline.zsh216
-rw-r--r--powerline/colorscheme.py147
-rw-r--r--powerline/commands/__init__.py0
-rw-r--r--powerline/commands/config.py109
-rw-r--r--powerline/commands/daemon.py24
-rw-r--r--powerline/commands/lemonbar.py35
-rwxr-xr-xpowerline/commands/lint.py21
-rw-r--r--powerline/commands/main.py190
-rw-r--r--powerline/config.py10
-rw-r--r--powerline/config_files/colors.json124
-rw-r--r--powerline/config_files/colorschemes/default.json56
-rw-r--r--powerline/config_files/colorschemes/ipython/__main__.json6
-rw-r--r--powerline/config_files/colorschemes/pdb/__main__.json8
-rw-r--r--powerline/config_files/colorschemes/pdb/default.json5
-rw-r--r--powerline/config_files/colorschemes/pdb/solarized.json5
-rw-r--r--powerline/config_files/colorschemes/shell/__main__.json10
-rw-r--r--powerline/config_files/colorschemes/shell/default.json16
-rw-r--r--powerline/config_files/colorschemes/shell/solarized.json13
-rw-r--r--powerline/config_files/colorschemes/solarized.json40
-rw-r--r--powerline/config_files/colorschemes/tmux/default.json14
-rw-r--r--powerline/config_files/colorschemes/tmux/solarized.json14
-rw-r--r--powerline/config_files/colorschemes/vim/__main__.json50
-rw-r--r--powerline/config_files/colorschemes/vim/default.json154
-rw-r--r--powerline/config_files/colorschemes/vim/solarized.json121
-rw-r--r--powerline/config_files/colorschemes/vim/solarizedlight.json122
-rw-r--r--powerline/config_files/config.json53
-rw-r--r--powerline/config_files/themes/ascii.json153
-rw-r--r--powerline/config_files/themes/ipython/in.json25
-rw-r--r--powerline/config_files/themes/ipython/in2.json12
-rw-r--r--powerline/config_files/themes/ipython/out.json24
-rw-r--r--powerline/config_files/themes/ipython/rewrite.json23
-rw-r--r--powerline/config_files/themes/pdb/default.json27
-rw-r--r--powerline/config_files/themes/powerline.json151
-rw-r--r--powerline/config_files/themes/powerline_terminus.json151
-rw-r--r--powerline/config_files/themes/powerline_unicode7.json165
-rw-r--r--powerline/config_files/themes/shell/__main__.json14
-rw-r--r--powerline/config_files/themes/shell/continuation.json12
-rw-r--r--powerline/config_files/themes/shell/default.json43
-rw-r--r--powerline/config_files/themes/shell/default_leftonly.json34
-rw-r--r--powerline/config_files/themes/shell/select.json13
-rw-r--r--powerline/config_files/themes/tmux/default.json28
-rw-r--r--powerline/config_files/themes/unicode.json151
-rw-r--r--powerline/config_files/themes/unicode_terminus.json151
-rw-r--r--powerline/config_files/themes/unicode_terminus_condensed.json151
-rw-r--r--powerline/config_files/themes/vim/__main__.json10
-rw-r--r--powerline/config_files/themes/vim/cmdwin.json18
-rw-r--r--powerline/config_files/themes/vim/default.json128
-rw-r--r--powerline/config_files/themes/vim/help.json36
-rw-r--r--powerline/config_files/themes/vim/plugin_commandt.json26
-rw-r--r--powerline/config_files/themes/vim/plugin_gundo-preview.json18
-rw-r--r--powerline/config_files/themes/vim/plugin_gundo.json18
-rw-r--r--powerline/config_files/themes/vim/plugin_nerdtree.json17
-rw-r--r--powerline/config_files/themes/vim/quickfix.json40
-rw-r--r--powerline/config_files/themes/vim/tabline.json93
-rw-r--r--powerline/config_files/themes/wm/default.json29
-rw-r--r--powerline/dist/systemd/powerline-daemon.service10
-rw-r--r--powerline/ipython.py68
-rw-r--r--powerline/lemonbar.py21
-rw-r--r--powerline/lib/__init__.py28
-rw-r--r--powerline/lib/config.py218
-rwxr-xr-xpowerline/lib/debug.py97
-rw-r--r--powerline/lib/dict.py88
-rw-r--r--powerline/lib/encoding.py125
-rw-r--r--powerline/lib/humanize_bytes.py25
-rw-r--r--powerline/lib/inotify.py184
-rw-r--r--powerline/lib/memoize.py42
-rw-r--r--powerline/lib/monotonic.py100
-rw-r--r--powerline/lib/overrides.py80
-rw-r--r--powerline/lib/path.py18
-rw-r--r--powerline/lib/shell.py133
-rw-r--r--powerline/lib/threaded.py262
-rw-r--r--powerline/lib/unicode.py283
-rw-r--r--powerline/lib/url.py17
-rw-r--r--powerline/lib/vcs/__init__.py276
-rw-r--r--powerline/lib/vcs/bzr.py108
-rw-r--r--powerline/lib/vcs/git.py208
-rw-r--r--powerline/lib/vcs/mercurial.py88
-rw-r--r--powerline/lib/watcher/__init__.py76
-rw-r--r--powerline/lib/watcher/inotify.py268
-rw-r--r--powerline/lib/watcher/stat.py44
-rw-r--r--powerline/lib/watcher/tree.py90
-rw-r--r--powerline/lib/watcher/uv.py207
-rw-r--r--powerline/lint/__init__.py625
-rw-r--r--powerline/lint/checks.py866
-rw-r--r--powerline/lint/context.py68
-rw-r--r--powerline/lint/imp.py56
-rw-r--r--powerline/lint/inspect.py63
-rw-r--r--powerline/lint/markedjson/__init__.py19
-rw-r--r--powerline/lint/markedjson/composer.py119
-rw-r--r--powerline/lint/markedjson/constructor.py285
-rw-r--r--powerline/lint/markedjson/error.py241
-rw-r--r--powerline/lint/markedjson/events.py97
-rw-r--r--powerline/lint/markedjson/loader.py25
-rw-r--r--powerline/lint/markedjson/markedvalue.py151
-rw-r--r--powerline/lint/markedjson/nodes.py55
-rw-r--r--powerline/lint/markedjson/parser.py255
-rw-r--r--powerline/lint/markedjson/reader.py141
-rw-r--r--powerline/lint/markedjson/resolver.py131
-rw-r--r--powerline/lint/markedjson/scanner.py499
-rw-r--r--powerline/lint/markedjson/tokens.py72
-rw-r--r--powerline/lint/selfcheck.py16
-rw-r--r--powerline/lint/spec.py759
-rw-r--r--powerline/listers/__init__.py0
-rw-r--r--powerline/listers/i3wm.py68
-rw-r--r--powerline/listers/pdb.py37
-rw-r--r--powerline/listers/vim.py123
-rw-r--r--powerline/matchers/__init__.py6
-rw-r--r--powerline/matchers/vim/__init__.py19
-rw-r--r--powerline/matchers/vim/plugin/__init__.py6
-rw-r--r--powerline/matchers/vim/plugin/commandt.py14
-rw-r--r--powerline/matchers/vim/plugin/gundo.py16
-rw-r--r--powerline/matchers/vim/plugin/nerdtree.py15
-rw-r--r--powerline/pdb.py48
-rw-r--r--powerline/renderer.py594
-rw-r--r--powerline/renderers/__init__.py0
-rw-r--r--powerline/renderers/i3bar.py36
-rw-r--r--powerline/renderers/ipython/__init__.py34
-rw-r--r--powerline/renderers/ipython/pre_5.py56
-rw-r--r--powerline/renderers/ipython/since_5.py130
-rw-r--r--powerline/renderers/lemonbar.py61
-rw-r--r--powerline/renderers/pango_markup.py39
-rw-r--r--powerline/renderers/pdb.py50
-rw-r--r--powerline/renderers/shell/__init__.py182
-rw-r--r--powerline/renderers/shell/bash.py18
-rw-r--r--powerline/renderers/shell/ksh.py19
-rw-r--r--powerline/renderers/shell/rcsh.py7
-rw-r--r--powerline/renderers/shell/readline.py14
-rw-r--r--powerline/renderers/shell/tcsh.py31
-rw-r--r--powerline/renderers/shell/zsh.py16
-rw-r--r--powerline/renderers/tmux.py79
-rw-r--r--powerline/renderers/vim.py188
-rw-r--r--powerline/segment.py450
-rw-r--r--powerline/segments/__init__.py63
-rw-r--r--powerline/segments/common/__init__.py0
-rw-r--r--powerline/segments/common/bat.py302
-rw-r--r--powerline/segments/common/env.py197
-rw-r--r--powerline/segments/common/mail.py78
-rw-r--r--powerline/segments/common/net.py315
-rw-r--r--powerline/segments/common/players.py607
-rw-r--r--powerline/segments/common/sys.py183
-rw-r--r--powerline/segments/common/time.py94
-rw-r--r--powerline/segments/common/vcs.py89
-rw-r--r--powerline/segments/common/wthr.py235
-rw-r--r--powerline/segments/i3wm.py155
-rw-r--r--powerline/segments/ipython.py9
-rw-r--r--powerline/segments/pdb.py61
-rw-r--r--powerline/segments/shell.py174
-rw-r--r--powerline/segments/tmux.py22
-rw-r--r--powerline/segments/vim/__init__.py793
-rw-r--r--powerline/segments/vim/plugin/__init__.py6
-rw-r--r--powerline/segments/vim/plugin/ale.py52
-rw-r--r--powerline/segments/vim/plugin/capslock.py30
-rw-r--r--powerline/segments/vim/plugin/commandt.py97
-rw-r--r--powerline/segments/vim/plugin/nerdtree.py25
-rw-r--r--powerline/segments/vim/plugin/syntastic.py43
-rw-r--r--powerline/segments/vim/plugin/tagbar.py51
-rw-r--r--powerline/selectors/__init__.py0
-rw-r--r--powerline/selectors/vim.py10
-rw-r--r--powerline/shell.py38
-rw-r--r--powerline/theme.py182
-rw-r--r--powerline/vim.py347
-rw-r--r--scripts/.gitignore1
-rwxr-xr-xscripts/powerline-config22
-rwxr-xr-xscripts/powerline-daemon495
-rwxr-xr-xscripts/powerline-lint13
-rwxr-xr-xscripts/powerline-release.py242
-rwxr-xr-xscripts/powerline-render31
-rw-r--r--setup.py135
-rw-r--r--tests/__init__.py0
-rwxr-xr-xtests/install.sh81
-rw-r--r--tests/modules/__init__.py94
-rw-r--r--tests/modules/lib/__init__.py183
-rw-r--r--tests/modules/lib/config_mock.py230
-rw-r--r--tests/modules/lib/fsconfig.py83
-rw-r--r--tests/modules/lib/terminal.py307
-rw-r--r--tests/modules/lib/vterm.py193
-rw-r--r--tests/modules/matchers.py6
-rw-r--r--tests/modules/vim.py927
-rw-r--r--tests/shlib/common.sh150
-rw-r--r--tests/shlib/vim.sh33
-rw-r--r--tests/shlib/vterm.sh17
-rw-r--r--tests/terminfo/s/screenbin0 -> 1564 bytes
-rw-r--r--tests/terminfo/s/st-256colorbin0 -> 2324 bytes
-rwxr-xr-xtests/test.sh42
-rwxr-xr-xtests/test_awesome/path/awesome-client3
-rw-r--r--tests/test_awesome/powerline/config.json7
-rw-r--r--tests/test_awesome/powerline/themes/wm/default.json18
-rw-r--r--tests/test_awesome/powerline/themes/wm/dvi.json18
-rwxr-xr-xtests/test_awesome/test.sh188
-rwxr-xr-xtests/test_bar/path/lemonbar11
-rwxr-xr-xtests/test_bar/path/xrandr31
-rw-r--r--tests/test_bar/powerline/config.json9
-rw-r--r--tests/test_bar/powerline/themes/wm/default.json18
-rw-r--r--tests/test_bar/powerline/themes/wm/dvi.json18
-rwxr-xr-xtests/test_bar/test.sh195
-rwxr-xr-xtests/test_daemon/test.sh41
-rw-r--r--tests/test_in_vterm/shell/inits/dash16
-rwxr-xr-xtests/test_in_vterm/test.sh13
-rwxr-xr-xtests/test_in_vterm/test_shells.py162
-rwxr-xr-xtests/test_in_vterm/test_shells.sh119
-rwxr-xr-xtests/test_in_vterm/test_tmux.py251
-rwxr-xr-xtests/test_in_vterm/test_tmux.sh44
-rwxr-xr-xtests/test_in_vterm/test_vim.py73
-rwxr-xr-xtests/test_in_vterm/test_vim.sh39
-rwxr-xr-xtests/test_lint/test.sh10
-rw-r--r--tests/test_python/empty0
-rwxr-xr-xtests/test_python/test.sh13
-rw-r--r--tests/test_python/test_cmdline.py149
-rw-r--r--tests/test_python/test_config_merging.py270
-rw-r--r--tests/test_python/test_config_reload.py319
-rw-r--r--tests/test_python/test_configuration.py877
-rw-r--r--tests/test_python/test_lib.py733
-rw-r--r--tests/test_python/test_lib_config.py52
-rw-r--r--tests/test_python/test_listers.py227
-rw-r--r--tests/test_python/test_logging.py467
-rw-r--r--tests/test_python/test_provided_config_files.py201
-rw-r--r--tests/test_python/test_segments.py1711
-rw-r--r--tests/test_python/test_selectors.py36
-rw-r--r--tests/test_python/test_watcher.py245
-rwxr-xr-xtests/test_shells/bgscript.sh5
-rw-r--r--tests/test_shells/inputs/bash69
-rw-r--r--tests/test_shells/inputs/busybox37
-rw-r--r--tests/test_shells/inputs/dash37
-rw-r--r--tests/test_shells/inputs/fish69
-rw-r--r--tests/test_shells/inputs/ipython7
-rw-r--r--tests/test_shells/inputs/mksh38
-rw-r--r--tests/test_shells/inputs/pdb89
-rw-r--r--tests/test_shells/inputs/rc33
-rw-r--r--tests/test_shells/inputs/tcsh24
-rw-r--r--tests/test_shells/inputs/zsh90
-rw-r--r--tests/test_shells/ipython_home/profile_default/ipython_config.py19
-rw-r--r--tests/test_shells/outputs/bash.daemon.ok42
-rw-r--r--tests/test_shells/outputs/bash.nodaemon.ok42
-rw-r--r--tests/test_shells/outputs/busybox.daemon.ok29
-rw-r--r--tests/test_shells/outputs/busybox.nodaemon.ok29
-rw-r--r--tests/test_shells/outputs/dash.daemon.ok28
-rw-r--r--tests/test_shells/outputs/dash.nodaemon.ok28
-rw-r--r--tests/test_shells/outputs/fish.ok52
-rw-r--r--tests/test_shells/outputs/ipython.ok14
-rw-r--r--tests/test_shells/outputs/mksh.daemon.ok32
-rw-r--r--tests/test_shells/outputs/mksh.nodaemon.ok32
-rw-r--r--tests/test_shells/outputs/pdb.module.ok222
-rw-r--r--tests/test_shells/outputs/pdb.subclass.ok217
-rw-r--r--tests/test_shells/outputs/rc.daemon.ok24
-rw-r--r--tests/test_shells/outputs/rc.nodaemon.ok24
-rw-r--r--tests/test_shells/outputs/tcsh.ok17
-rw-r--r--tests/test_shells/outputs/zsh.daemon.ok52
-rw-r--r--tests/test_shells/outputs/zsh.nodaemon.ok52
-rw-r--r--tests/test_shells/outputs/zsh.zpython.ok52
-rw-r--r--tests/test_shells/pdb-main.py24
-rw-r--r--tests/test_shells/pdb-script.py38
-rwxr-xr-xtests/test_shells/postproc.py130
-rwxr-xr-xtests/test_shells/run_script.py125
-rwxr-xr-xtests/test_shells/test.sh491
-rwxr-xr-xtests/test_shells/waitpid.sh4
-rw-r--r--tests/test_shells/zsh_test_script.zsh11
-rw-r--r--tests/test_vim/pyfiles/setup_statusline_catcher.py18
-rwxr-xr-xtests/test_vim/test.sh60
-rwxr-xr-xtests/test_vim/tests/commandt_plugin.vim17
-rwxr-xr-xtests/test_vim/tests/empty_encoding.old.vim32
-rw-r--r--tests/test_vim/tests/foreign_stl_override.vim22
-rw-r--r--tests/test_vim/tests/invalid_unicode.vim19
-rwxr-xr-xtests/test_vim/tests/local_overrides.vim48
-rwxr-xr-xtests/test_vim/tests/nerdtree_plugin.vim11
-rwxr-xr-xtests/test_vim/tests/plugin_file.vim22
-rwxr-xr-xtests/test_vim/tests/tabline.vim56
-rw-r--r--tests/test_vim/vim_utils.vim88
-rw-r--r--tests/vim_sys_path/vim.py7
-rw-r--r--tools/colors.map646
-rwxr-xr-xtools/colors_find.py63
-rwxr-xr-xtools/generate_gradients.py217
-rwxr-xr-xtools/purge-PRs.py27
376 files changed, 40043 insertions, 0 deletions
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..94eab89
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,20 @@
+# editorconfig ini file
+# Check out http://editorconfig.org for a list of plugins for different
+# IDEs/text editors that support this file. Vim plugin to support this:
+#
+# http://www.vim.org/scripts/script.php?script_id=3934
+# https://github.com/editorconfig/editorconfig-vim
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+indent_style = tab
+# Despite promise somewhere alignment is done only using tabs. Thus setting
+# indent_size and tab_width is a requirement.
+indent_size = 4
+tab_width = 4
+charset = utf-8
+
+[*.rst]
+indent_style = space
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..e307485
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.rst whitespace=-blank-at-eol
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6491a77
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,16 @@
+tags
+
+*.py[co]
+__pycache__
+
+*.egg
+*.egg-info
+dist
+build
+
+message.fail
+
+/client/powerline
+
+/tests/tmp
+/tests/status
diff --git a/.local.vimrc b/.local.vimrc
new file mode 100644
index 0000000..c8e1ef3
--- /dev/null
+++ b/.local.vimrc
@@ -0,0 +1,11 @@
+" Project vimrc file. To be sourced each time you open any file in this
+" repository. You may use [vimscript #3393][1] [(homepage)][2] to do this
+" automatically.
+"
+" [1]: http://www.vim.org/scripts/script.php?script_id=3393
+" [2]: https://github.com/thinca/vim-localrc
+let g:syntastic_python_flake8_args = '--ignore=W191,E501,E128,W291,E126,E101'
+let b:syntastic_checkers = ['flake8']
+unlet! g:python_space_error_highlight
+let g:pymode_syntax_indent_errors = 0
+let g:pymode_syntax_space_errors = 0
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..cf7c407
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,42 @@
+sudo: false
+dist: trusty
+cache:
+ directories:
+ - $HOME/.cache/pip
+ - tests/bot-ci
+addons:
+ apt:
+ packages:
+ - libssl1.0.0
+ - zsh
+ - tcsh
+ - mksh
+ - busybox
+ # - rc
+ - socat
+ - bc
+language: python
+install: tests/install.sh
+script: tests/test.sh
+jobs:
+ include:
+ - stage: UCS2 python
+ python: "2.7"
+ env: >-
+ USE_UCS2_PYTHON=1
+ UCS2_PYTHON_VARIANT="2.7"
+ - stage: Old Python
+ python: "2.6"
+ - python: "3.2"
+ - stage: PyPy
+ python: "pypy"
+ - python: "pypy3"
+ - stage: Latest Python
+ python: "2.7"
+ - python: "3.6"
+ - stage: Intermediate versions
+ python: "3.3"
+ - python: "3.4"
+ - python: "3.5"
+
+# vim: et
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
new file mode 100644
index 0000000..3792b70
--- /dev/null
+++ b/CONTRIBUTING.rst
@@ -0,0 +1,138 @@
+*****************
+How to contribute
+*****************
+
+So you want to contribute to the Powerline project? Awesome! This document
+describes the guidelines you should follow when making contributions to the
+project.
+
+**Please note that these guidelines aren't mandatory in any way, but your
+pull request will be merged a lot faster if you follow them.**
+
+Getting started
+===============
+
+* Make sure you have a `GitHub account <https://github.com/signup/free>`_.
+* Submit an `issue on GitHub <https://github.com/powerline/powerline/issues>`_,
+ assuming one does not already exist.
+
+ * Clearly describe the issue.
+ * If the issue is a bug: make sure you include steps to reproduce, and
+ include the earliest revision that you know has the issue.
+
+* Fork the repository on GitHub.
+
+Making changes
+==============
+
+* Create a topic branch from where you want to base your work.
+
+ * Powerline uses the `Git Flow
+ <http://nvie.com/posts/a-successful-git-branching-model/>`_ branching
+ model.
+ * Most contributions should be based off the ``develop`` branch.
+ * Prefix your branch with ``feature/`` if you're working on a new feature.
+ * Include the issue number in your topic branch, e.g.
+ ``321-fix-some-error`` or ``feature/123-a-cool-feature``.
+
+* Make commits of logical units.
+* Run your code through ``flake8`` and fix any programming style errors. Use
+ common sense regarding whitespace warnings, not all warnings need to be
+ fixed.
+* Make sure your commit messages are in the `proper format
+ <http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html>`_.
+ The summary must be no longer than 70 characters. Refer to any related
+ issues with e.g. ``Ref #123`` or ``Fixes #234`` at the bottom of the
+ commit message. Commit messages can use Markdown with the following
+ exceptions:
+
+ * No HTML extensions.
+ * Only indented code blocks (no ``````` blocks).
+ * Long links should be moved to the bottom if they make the text wrap or
+ extend past 72 columns.
+
+* Make sure you have added the necessary tests for your changes.
+* Run *all* the tests to assure nothing else was accidentally broken.
+
+Programming style
+-----------------
+
+* The project uses *tabs for indentation* and *spaces for alignment*, this
+ is also included in a vim modeline on top of every script file.
+* Run your code through ``flake8 --ignore=W191,E501,E128,W291,E126,E101`` to fix
+ any style errors. Use common sense regarding whitespace warnings, not all
+ ``flake8`` warnings need to be fixed.
+* Trailing whitespace to indicate a continuing paragraph is OK in comments,
+ documentation and commit messages.
+* It is allowed to have too long lines. It is advised though to avoid lines
+ wider then a hundred of characters.
+* Imports have the following structure:
+
+ 1. Shebang and modeline in a form
+
+ .. code-block:: python
+
+ #!/usr/bin/env python
+ # vim:fileencoding=utf-8:noet
+
+ . Modeline is required, shebang is not. If shebang is present file must end
+ with
+
+ .. code-block:: python
+
+ if __name__ == '__main__':
+ # Actual script here
+
+ 2. Module docstring.
+ 3. ``__future__`` import exactly in a form
+
+ .. code-block:: python
+
+ from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+ (powerline.shell is the only exception due to problems with argparse). It
+ is not separated by newline with shebang and modeline, but is with
+ docstring.
+ 4. Standard python library imports in a form ``import X``.
+ 5. Standard python library imports in a form ``from X import Y``.
+ 6. Third-party (non-python and non-powerline) library imports in a form
+ ``import X``.
+ 7. Third-party library imports in a form ``from X import Y``.
+ 8. Powerline non-test imports in a form ``from powerline.X import Y``.
+ 9. Powerline test imports in a form ``import tests.vim as vim_module``.
+ 10. Powerline test imports in a form ``from tests.X import Y``.
+
+ Each entry is separated by newline from another entry. Any entry except for
+ the first and third ones is optional. Example with all entries:
+
+ .. code-block:: python
+
+ #!/usr/bin/env python
+ # vim:fileencoding=utf-8:noet
+
+ '''Powerline super module'''
+
+ from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+ import sys
+
+ from argparse import ArgumentParser
+
+ import psutil
+
+ from colormath.color_diff import delta_e_cie2000
+
+ from powerline.lib.unicode import u
+
+ import tests.vim as vim_module
+
+ from tests import TestCase
+
+Submitting changes
+==================
+
+* Push your changes to a topic branch in your fork of the repository.
+* If necessary, use ``git rebase -i <revision>`` to squash or reword commits
+ before submitting a pull request.
+* Submit a pull request to `powerline repository
+ <https://github.com/powerline/powerline>`_.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..23b2ab2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+Copyright 2013 Kim Silkebækken and other contributors
+https://github.com/powerline/powerline
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..14acc93
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,7 @@
+recursive-include powerline *.json *.vim
+recursive-include powerline/bindings *.*
+recursive-exclude powerline/bindings *.pyc *.pyo
+recursive-include powerline/dist *.*
+recursive-include client *.*
+recursive-include docs/source *.rst *.py
+include docs/Makefile
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..8500db3
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,95 @@
+Powerline
+=========
+
+:Author: Kim Silkebækken (kim.silkebaekken+vim@gmail.com)
+:Source: https://github.com/powerline/powerline
+:Version: beta
+
+**Powerline is a statusline plugin for vim, and provides statuslines and
+prompts for several other applications, including zsh, bash, fish, tmux,
+IPython, Awesome, i3 and Qtile.**
+
+* `Support forum`_ (powerline-support@googlegroups.com)
+* `Development discussion`_ (powerline-dev@googlegroups.com)
+
+.. image:: https://api.travis-ci.org/powerline/powerline.svg?branch=develop
+ :target: `travis-build-status`_
+ :alt: Build status
+
+.. _travis-build-status: https://travis-ci.org/powerline/powerline
+.. _`Support forum`: https://groups.google.com/forum/#!forum/powerline-support
+.. _`Development discussion`: https://groups.google.com/forum/#!forum/powerline-dev
+
+Features
+--------
+
+* **Extensible and feature rich, written in Python.** Powerline was
+ completely rewritten in Python to get rid of as much vimscript as
+ possible. This has allowed much better extensibility, leaner and better
+ config files, and a structured, object-oriented codebase with no mandatory
+ third-party dependencies other than a Python interpreter.
+* **Stable and testable code base.** Using Python has allowed unit testing
+ of all the project code. The code is tested to work in Python 2.6+ and
+ Python 3.
+* **Support for prompts and statuslines in many applications.** Originally
+ created exclusively for vim statuslines, the project has evolved to
+ provide statuslines in tmux and several WMs, and prompts for shells like
+ bash/zsh and other applications. It’s simple to write renderers for any
+ other applications that Powerline doesn’t yet support.
+* **Configuration and colorschemes written in JSON.** JSON is
+ a standardized, simple and easy to use file format that allows for easy
+ user configuration across all of Powerline’s supported applications.
+* **Fast and lightweight, with daemon support for even better performance.**
+ Although the code base spans a couple of thousand lines of code with no
+ goal of “less than X lines of code”, the main focus is on good performance
+ and as little code as possible while still providing a rich set of
+ features. The new daemon also ensures that only one Python instance is
+ launched for prompts and statuslines, which provides excellent
+ performance.
+
+*But I hate Python / I don’t need shell prompts / this is just too much
+hassle for me / what happened to the original vim-powerline project / …*
+
+You should check out some of the Powerline derivatives. The most lightweight
+and feature-rich alternative is currently Bailey Ling’s `vim-airline
+<https://github.com/vim-airline/vim-airline>`_ project.
+
+------
+
+* Consult the `documentation
+ <https://powerline.readthedocs.org/en/latest/>`_ for more information and
+ installation instructions.
+* Check out `powerline-fonts <https://github.com/powerline/fonts>`_ for
+ pre-patched versions of popular, open source coding fonts.
+
+Screenshots
+-----------
+
+Vim statusline
+^^^^^^^^^^^^^^
+
+**Mode-dependent highlighting**
+
+* .. image:: https://raw.github.com/powerline/powerline/develop/docs/source/_static/img/pl-mode-normal.png
+ :alt: Normal mode
+* .. image:: https://raw.github.com/powerline/powerline/develop/docs/source/_static/img/pl-mode-insert.png
+ :alt: Insert mode
+* .. image:: https://raw.github.com/powerline/powerline/develop/docs/source/_static/img/pl-mode-visual.png
+ :alt: Visual mode
+* .. image:: https://raw.github.com/powerline/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/powerline/powerline/develop/docs/source/_static/img/pl-truncate1.png
+ :alt: Truncation illustration
+* .. image:: https://raw.github.com/powerline/powerline/develop/docs/source/_static/img/pl-truncate2.png
+ :alt: Truncation illustration
+* .. image:: https://raw.github.com/powerline/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/shop/fonts/pragmatapro
diff --git a/client/powerline.c b/client/powerline.c
new file mode 100644
index 0000000..ff107ec
--- /dev/null
+++ b/client/powerline.c
@@ -0,0 +1,164 @@
+/* vim:fileencoding=utf-8:noet
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#define HANDLE_ERROR(msg) \
+ do { \
+ perror(msg); \
+ exit(EXIT_FAILURE); \
+ } while (0)
+
+#define TEMP_FAILURE_RETRY(var, expression) \
+ do { \
+ ptrdiff_t __result; \
+ do { \
+ __result = (expression); \
+ } while (__result == -1L && errno == EINTR); \
+ var = __result; \
+ } while (0)
+
+extern char **environ;
+
+void do_write(int sd, const char *raw, size_t len) {
+ size_t written = 0;
+ ptrdiff_t n = -1;
+
+ while (written < len) {
+ TEMP_FAILURE_RETRY(n, write(sd, raw + written, len - written));
+ if (n == -1) {
+ close(sd);
+ HANDLE_ERROR("write() failed");
+ }
+ written += (size_t) n;
+ }
+}
+
+static inline size_t true_sun_len(const struct sockaddr_un *ptr) {
+#ifdef __linux__
+ /* Because SUN_LEN uses strlen and abstract namespace paths begin
+ * with a null byte, SUN_LEN is broken for these. Passing the full
+ * struct size also fails on Linux, so compute manually. The
+ * abstract namespace is Linux-only. */
+ if (ptr->sun_path[0] == '\0') {
+ return sizeof(ptr->sun_family) + strlen(ptr->sun_path + 1) + 1;
+ }
+#endif
+#ifdef SUN_LEN
+ /* If the vendor provided SUN_LEN, we may as well use it. */
+ return SUN_LEN(ptr);
+#else
+ /* SUN_LEN is not POSIX, so if it was not provided, use the struct
+ * size as a fallback. */
+ return sizeof(struct sockaddr_un);
+#endif
+}
+
+#ifdef __linux__
+# define ADDRESS_TEMPLATE "powerline-ipc-%d"
+# define A +1
+#else
+# define ADDRESS_TEMPLATE "/tmp/powerline-ipc-%d"
+# define A
+#endif
+
+#define ADDRESS_SIZE sizeof(ADDRESS_TEMPLATE) + (sizeof(uid_t) * 4)
+#define NUM_ARGS_SIZE (sizeof(int) * 2 + 1)
+#define BUF_SIZE 4096
+#define NEW_ARGV_SIZE 200
+
+int main(int argc, char *argv[]) {
+ int sd = -1;
+ int i;
+ ptrdiff_t read_size;
+ struct sockaddr_un server;
+ char address_buf[ADDRESS_SIZE];
+ const char eof[2] = "\0\0";
+ char num_args[NUM_ARGS_SIZE];
+ char buf[BUF_SIZE];
+ char *newargv[NEW_ARGV_SIZE];
+ char *wd = NULL;
+ char **envp;
+ const char *address;
+ int len;
+
+ if (argc < 2) {
+ printf("Must provide at least one argument.\n");
+ return EXIT_FAILURE;
+ }
+
+ if (argc > 3 && strcmp(argv[1], "--socket") == 0) {
+ address = argv[2];
+ argv += 2;
+ argc -= 2;
+ } else {
+ snprintf(address_buf, ADDRESS_SIZE, ADDRESS_TEMPLATE, getuid());
+ address = &(address_buf[0]);
+ }
+
+ sd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sd == -1)
+ HANDLE_ERROR("socket() failed");
+
+ memset(&server, 0, sizeof(struct sockaddr_un));
+ server.sun_family = AF_UNIX;
+ strncpy(server.sun_path A, address, strlen(address));
+
+ if (connect(sd, (struct sockaddr *) &server, true_sun_len(&server)) < 0) {
+ close(sd);
+ /* We failed to connect to the daemon, execute powerline instead */
+ argc = (argc < NEW_ARGV_SIZE - 1) ? argc : NEW_ARGV_SIZE - 1;
+ for (i = 1; i < argc; i++)
+ newargv[i] = argv[i];
+ newargv[0] = "powerline-render";
+ newargv[argc] = NULL;
+ execvp("powerline-render", newargv);
+ }
+
+ len = snprintf(num_args, NUM_ARGS_SIZE, "%x", argc - 1);
+ do_write(sd, num_args, len);
+ do_write(sd, eof, 1);
+
+ for (i = 1; i < argc; i++) {
+ do_write(sd, argv[i], strlen(argv[i]));
+ do_write(sd, eof, 1);
+ }
+
+ wd = getcwd(NULL, 0);
+ if (wd != NULL) {
+ do_write(sd, wd, strlen(wd));
+ free(wd);
+ wd = NULL;
+ }
+ do_write(sd, eof, 1);
+
+ for(envp=environ; *envp; envp++) {
+ do_write(sd, *envp, strlen(*envp));
+ do_write(sd, eof, 1);
+ }
+
+ do_write(sd, eof, 2);
+
+ read_size = -1;
+ while (read_size != 0) {
+ TEMP_FAILURE_RETRY(read_size, read(sd, buf, BUF_SIZE));
+ if (read_size == -1) {
+ close(sd);
+ HANDLE_ERROR("read() failed");
+ } else if (read_size > 0) {
+ do_write(STDOUT_FILENO, buf, (size_t) read_size);
+ }
+ }
+
+ close(sd);
+
+ return 0;
+}
diff --git a/client/powerline.py b/client/powerline.py
new file mode 100755
index 0000000..28492c1
--- /dev/null
+++ b/client/powerline.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import sys
+import socket
+import errno
+import os
+
+try:
+ from posix import environ
+except ImportError:
+ from os import environ
+
+# XXX Hack for importing powerline modules to work.
+sys.path.pop(0)
+
+try:
+ from powerline.lib.encoding import get_preferred_output_encoding
+except ImportError:
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(os.path.realpath(__file__)))))
+ from powerline.lib.encoding import get_preferred_output_encoding
+
+
+if len(sys.argv) < 2:
+ print('Must provide at least one argument.', file=sys.stderr)
+ raise SystemExit(1)
+
+use_filesystem = not sys.platform.lower().startswith('linux')
+
+if sys.argv[1] == '--socket':
+ address = sys.argv[2]
+ if not use_filesystem:
+ address = '\0' + address
+ del sys.argv[1:3]
+else:
+ address = ('/tmp/powerline-ipc-%d' if use_filesystem else '\0powerline-ipc-%d') % os.getuid()
+
+sock = socket.socket(family=socket.AF_UNIX)
+
+
+def eintr_retry_call(func, *args, **kwargs):
+ while True:
+ try:
+ return func(*args, **kwargs)
+ except EnvironmentError as e:
+ if getattr(e, 'errno', None) == errno.EINTR:
+ continue
+ raise
+
+
+try:
+ eintr_retry_call(sock.connect, address)
+except Exception:
+ # Run the powerline renderer
+ args = ['powerline-render'] + sys.argv[1:]
+ os.execvp('powerline-render', args)
+
+fenc = get_preferred_output_encoding()
+
+
+def tobytes(s):
+ if isinstance(s, bytes):
+ return s
+ else:
+ return s.encode(fenc)
+
+
+args = [tobytes('%x' % (len(sys.argv) - 1))]
+args.extend((tobytes(s) for s in sys.argv[1:]))
+
+
+try:
+ cwd = os.getcwd()
+except EnvironmentError:
+ pass
+else:
+ if not isinstance(cwd, bytes):
+ cwd = cwd.encode(fenc)
+ args.append(cwd)
+
+
+args.extend((tobytes(k) + b'=' + tobytes(v) for k, v in environ.items()))
+
+EOF = b'\0\0'
+
+for a in args:
+ eintr_retry_call(sock.sendall, a + b'\0')
+
+eintr_retry_call(sock.sendall, EOF)
+
+received = []
+while True:
+ r = sock.recv(4096)
+ if not r:
+ break
+ received.append(r)
+
+sock.close()
+
+if sys.version_info < (3,):
+ sys.stdout.write(b''.join(received))
+else:
+ sys.stdout.buffer.write(b''.join(received))
diff --git a/client/powerline.sh b/client/powerline.sh
new file mode 100755
index 0000000..8bcec22
--- /dev/null
+++ b/client/powerline.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+use_filesystem=1
+darwin=
+if test -n "$OSTYPE" ; then
+ # OSTYPE variable is a shell feature. supported by bash and zsh, but not
+ # dash, busybox or (m)ksh.
+ if test "${OSTYPE#linux}" '!=' "${OSTYPE}" ; then
+ use_filesystem=
+ elif test "${OSTYPE#darwin}" ; then
+ darwin=1
+ fi
+elif which uname >/dev/null ; then
+ if uname -o | grep -iqF linux ; then
+ use_filesystem=
+ elif uname -o | grep -iqF darwin ; then
+ darwin=1
+ fi
+fi
+
+if test "$1" = "--socket" ; then
+ shift
+ ADDRESS="$1"
+ shift
+else
+ ADDRESS="powerline-ipc-${UID:-`id -u`}"
+ test -n "$use_filesystem" && ADDRESS="/tmp/$ADDRESS"
+fi
+
+if test -n "$darwin" ; then
+ ENV=genv
+else
+ ENV=env
+fi
+
+if test -z "$use_filesystem" ; then
+ ADDRESS="abstract-client:$ADDRESS"
+fi
+
+# Warning: env -0 does not work in busybox. Consider switching to parsing
+# `set` output in this case
+(
+ printf '%x\0' "$#"
+ for argv in "$@" ; do
+ printf '%s\0' "$argv"
+ done
+ printf '%s\0' "$PWD"
+ $ENV -0
+) 2>/dev/null | socat -lf/dev/null -t 10 - "$ADDRESS"
+
+if test $? -ne 0 ; then
+ powerline-render "$@"
+fi
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 0000000..e35d885
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1 @@
+_build
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..3b41221
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,39 @@
+# Makefile for Sphinx documentation
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -T -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
+
+GH_PAGES_SOURCES = source Makefile
+GH_SOURCE_BRANCH = develop
+
+.PHONY: html clean html latexpdf
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
diff --git a/docs/source/_static/css/theme_overrides.css b/docs/source/_static/css/theme_overrides.css
new file mode 100644
index 0000000..7e39e34
--- /dev/null
+++ b/docs/source/_static/css/theme_overrides.css
@@ -0,0 +1,6 @@
+.wy-table-responsive > table > tbody > tr > td {
+ white-space: unset;
+}
+.wy-table-responsive > table > tbody > tr > td:first-child {
+ vertical-align: top;
+}
diff --git a/docs/source/_static/img/icons/cross.png b/docs/source/_static/img/icons/cross.png
new file mode 100644
index 0000000..33a3837
--- /dev/null
+++ b/docs/source/_static/img/icons/cross.png
Binary files differ
diff --git a/docs/source/_static/img/icons/error.png b/docs/source/_static/img/icons/error.png
new file mode 100644
index 0000000..dbfda22
--- /dev/null
+++ b/docs/source/_static/img/icons/error.png
Binary files differ
diff --git a/docs/source/_static/img/icons/tick.png b/docs/source/_static/img/icons/tick.png
new file mode 100644
index 0000000..c277e6b
--- /dev/null
+++ b/docs/source/_static/img/icons/tick.png
Binary files differ
diff --git a/docs/source/_static/img/pl-mode-insert.png b/docs/source/_static/img/pl-mode-insert.png
new file mode 100644
index 0000000..9b09e18
--- /dev/null
+++ b/docs/source/_static/img/pl-mode-insert.png
Binary files differ
diff --git a/docs/source/_static/img/pl-mode-normal.png b/docs/source/_static/img/pl-mode-normal.png
new file mode 100644
index 0000000..29d3716
--- /dev/null
+++ b/docs/source/_static/img/pl-mode-normal.png
Binary files differ
diff --git a/docs/source/_static/img/pl-mode-replace.png b/docs/source/_static/img/pl-mode-replace.png
new file mode 100644
index 0000000..d7c89a4
--- /dev/null
+++ b/docs/source/_static/img/pl-mode-replace.png
Binary files differ
diff --git a/docs/source/_static/img/pl-mode-visual.png b/docs/source/_static/img/pl-mode-visual.png
new file mode 100644
index 0000000..d654763
--- /dev/null
+++ b/docs/source/_static/img/pl-mode-visual.png
Binary files differ
diff --git a/docs/source/_static/img/pl-truncate1.png b/docs/source/_static/img/pl-truncate1.png
new file mode 100644
index 0000000..c687502
--- /dev/null
+++ b/docs/source/_static/img/pl-truncate1.png
Binary files differ
diff --git a/docs/source/_static/img/pl-truncate2.png b/docs/source/_static/img/pl-truncate2.png
new file mode 100644
index 0000000..1630f1d
--- /dev/null
+++ b/docs/source/_static/img/pl-truncate2.png
Binary files differ
diff --git a/docs/source/_static/img/pl-truncate3.png b/docs/source/_static/img/pl-truncate3.png
new file mode 100644
index 0000000..83e5b21
--- /dev/null
+++ b/docs/source/_static/img/pl-truncate3.png
Binary files differ
diff --git a/docs/source/commands.rst b/docs/source/commands.rst
new file mode 100644
index 0000000..a35d05f
--- /dev/null
+++ b/docs/source/commands.rst
@@ -0,0 +1,9 @@
+**************************************
+Powerline shell commands’ manual pages
+**************************************
+
+.. toctree::
+ :maxdepth: 1
+ :glob:
+
+ commands/*
diff --git a/docs/source/commands/config.rst b/docs/source/commands/config.rst
new file mode 100644
index 0000000..3fc25aa
--- /dev/null
+++ b/docs/source/commands/config.rst
@@ -0,0 +1,12 @@
+:orphan:
+
+powerline-config manual page
+============================
+
+.. automan:: powerline.commands.config
+ :prog: powerline-config
+
+See also
+--------
+
+:manpage:`powerline(1)`
diff --git a/docs/source/commands/daemon.rst b/docs/source/commands/daemon.rst
new file mode 100644
index 0000000..d899c73
--- /dev/null
+++ b/docs/source/commands/daemon.rst
@@ -0,0 +1,12 @@
+:orphan:
+
+powerline-daemon manual page
+============================
+
+.. automan:: powerline.commands.daemon
+ :prog: powerline-daemon
+
+See also
+--------
+
+:manpage:`powerline(1)`
diff --git a/docs/source/commands/lint.rst b/docs/source/commands/lint.rst
new file mode 100644
index 0000000..92d676d
--- /dev/null
+++ b/docs/source/commands/lint.rst
@@ -0,0 +1,14 @@
+:orphan:
+
+.. _command-powerline-lint:
+
+powerline-lint manual page
+==========================
+
+.. automan:: powerline.commands.lint
+ :prog: powerline-lint
+
+See also
+--------
+
+:manpage:`powerline(1)`, :manpage:`powerline-config(1)`
diff --git a/docs/source/commands/main.rst b/docs/source/commands/main.rst
new file mode 100644
index 0000000..178bcb9
--- /dev/null
+++ b/docs/source/commands/main.rst
@@ -0,0 +1,12 @@
+:orphan:
+
+powerline manual page
+=====================
+
+.. automan:: powerline.commands.main
+ :prog: powerline
+
+See also
+--------
+
+:manpage:`powerline-daemon(1)`, :manpage:`powerline-config(1)`
diff --git a/docs/source/conf.py b/docs/source/conf.py
new file mode 100644
index 0000000..5577ef6
--- /dev/null
+++ b/docs/source/conf.py
@@ -0,0 +1,70 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import os
+import sys
+
+
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(os.getcwd()))))
+sys.path.insert(0, os.path.abspath(os.getcwd()))
+
+extensions = [
+ 'powerline_autodoc', 'powerline_automan',
+ 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode',
+]
+source_suffix = '.rst'
+master_doc = 'index'
+project = 'Powerline'
+version = 'beta'
+release = 'beta'
+exclude_patterns = ['_build']
+pygments_style = 'sphinx'
+
+html_theme = 'default'
+html_static_path = ['_static']
+html_show_copyright = False
+
+latex_show_urls = 'footnote'
+latex_elements = {
+ 'preamble': '''
+ \\DeclareUnicodeCharacter{22EF}{$\\cdots$} % Dots
+ \\DeclareUnicodeCharacter{2665}{\\ding{170}} % Heart
+ \\DeclareUnicodeCharacter{2746}{\\ding{105}} % Snow
+ \\usepackage{pifont}
+ ''',
+}
+
+man_pages = []
+for doc in os.listdir(os.path.join(os.path.dirname(__file__), 'commands')):
+ if doc.endswith('.rst'):
+ name = doc[:-4]
+ module = 'powerline.commands.{0}'.format(name)
+ get_argparser = __import__(str(module), fromlist=[str('get_argparser')]).get_argparser
+ parser = get_argparser()
+ description = parser.description
+ man_pages.append([
+ 'commands/' + name,
+ 'powerline' if name == 'main' else 'powerline-' + name,
+ description,
+ '',
+ 1
+ ])
+
+on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
+
+if not on_rtd: # only import and set the theme if we’re building docs locally
+ try:
+ import sphinx_rtd_theme
+ html_theme = 'sphinx_rtd_theme'
+ html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
+ except ImportError:
+ pass
+
+if on_rtd or html_theme == 'sphinx_rtd_theme':
+ html_context = {
+ 'css_files': [
+ 'https://media.readthedocs.org/css/sphinx_rtd_theme.css',
+ 'https://media.readthedocs.org/css/readthedocs-doc-embed.css',
+ '_static/css/theme_overrides.css',
+ ],
+ }
diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst
new file mode 100644
index 0000000..412fb6a
--- /dev/null
+++ b/docs/source/configuration.rst
@@ -0,0 +1,146 @@
+*******************************
+Configuration and customization
+*******************************
+
+.. note::
+ **Forking the main GitHub repo is not needed to personalize Powerline
+ configuration!** Please read through the :ref:`quick-guide` for a quick
+ introduction to user configuration.
+
+Powerline is configured with one main configuration file, and with separate
+configuration files for themes and colorschemes. All configuration files are
+written in JSON, with the exception of segment definitions, which are
+written in Python.
+
+Powerline provides default configurations in the following locations:
+
+:ref:`Main configuration <config-main>`
+ :file:`{powerline}/config.json`
+:ref:`Colorschemes <config-colorschemes>`
+ :file:`{powerline}/colorschemes/{name}.json`,
+ :file:`{powerline}/colorschemes/{extension}/__main__.json`,
+ :file:`{powerline}/colorschemes/{extension}/{name}.json`
+:ref:`Themes <config-themes>`
+ :file:`{powerline}/themes/{top_theme}.json`,
+ :file:`{powerline}/themes/{extension}/__main__.json`,
+ :file:`{powerline}/themes/{extension}/default.json`
+
+Here `{powerline}` is one of the following:
+
+#. The default configuration directory located in the main package:
+ :file:`{powerline_root}/powerline/config_files`. May be absent in some
+ packages (e.g. when installing via Gentoo ebuilds).
+#. If variable ``$XDG_CONFIG_DIRS`` is set and non-empty then to any
+ :file:`{directory}/powerline` where `{directory}` is a directory listed in
+ a colon-separated ``$XDG_CONFIG_DIRS`` list. Directories are checked in
+ reverse order.
+#. User configuration directory located in :file:`$XDG_CONFIG_HOME/powerline`.
+ This usually corresponds to :file:`~/.config/powerline` on all platforms.
+
+If per-instance configuration is needed please refer to :ref:`Local
+configuration overrides <local-configuration-overrides>`.
+
+.. _configuration-merging:
+
+.. note::
+ Existing multiple configuration files that have the same name, but are placed
+ in different directories, will be merged. Merging happens in the order given
+ in the above list of possible `{powerline}` meanings.
+
+ When merging configuration only dictionaries are merged and they are merged
+ recursively: keys from next file overrule those from the previous unless
+ corresponding values are both dictionaries in which case these dictionaries
+ are merged and key is assigned the result of the merge.
+
+.. note:: Some configuration files (i.e. themes and colorschemes) have two level
+ of merging: first happens merging described above, second theme- or
+ colorscheme-specific merging happens.
+
+.. _quick-guide:
+
+Quick setup guide
+=================
+
+This guide will help you with the initial configuration of Powerline.
+
+Look at configuration in :file:`{powerline_root}/powerline/config_files`. If you
+want to modify some file you can create :file:`~/.config/powerline` directory
+and put modifications there: all configuration files are :ref:`merged
+<configuration-merging>` with each other.
+
+Each extension (vim, tmux, etc.) has its own theme, and they are located in
+:file:`{config directory}/themes/{extension}/default.json`. Best way to modify
+it is to copy this theme as a whole, remove ``segment_data`` key with
+corresponding value if present (unless you need to modify it, in which case only
+modifications must be left) and do necessary modifications in the list of
+segments (lists are not subject to merging: this is why you need a copy).
+
+If you want to move, remove or customize any of the provided segments in the
+copy, you can do that by updating the segment dictionary in the theme you want
+to customize. A segment dictionary looks like this:
+
+.. code-block:: javascript
+
+ {
+ "name": "segment_name"
+ ...
+ }
+
+You can move the segment dictionaries around to change the segment
+positions, or remove the entire dictionary to remove the segment from the
+prompt or statusline.
+
+.. note:: It’s essential that the contents of all your configuration files
+ is valid JSON! It’s strongly recommended that you run your configuration
+ files through ``jsonlint`` after changing them.
+
+.. note::
+ If your modifications appear not to work, run :ref:`powerline-lint script
+ <command-powerline-lint>`. This script should show you the location of the
+ error.
+
+Some segments need a user configuration to work properly. Here’s a couple of
+segments that you may want to customize right away:
+
+**E-mail alert segment**
+ You have to set your username and password (and possibly server/port)
+ for the e-mail alert segment. If you’re using GMail it’s recommended
+ that you `generate an application-specific password
+ <https://accounts.google.com/IssuedAuthSubTokens>`_ for this purpose.
+
+ Open a theme file, scroll down to the ``email_imap_alert`` segment and
+ set your ``username`` and ``password``. The server defaults to GMail’s
+ IMAP server, but you can set the server/port by adding a ``server`` and
+ a ``port`` argument.
+**Weather segment**
+ The weather segment will try to find your location using a GeoIP lookup,
+ so unless you’re on a VPN you probably won’t have to change the location
+ query.
+
+ If you want to change the location query or the temperature unit you’ll
+ have to update the segment arguments. Open a theme file, scroll down to
+ the weather segment and update it to include unit/location query
+ arguments:
+
+ .. code-block:: javascript
+
+ {
+ "name": "weather",
+ "priority": 50,
+ "args": {
+ "unit": "F",
+ "location_query": "oslo, norway"
+ }
+ },
+
+References
+==========
+
+.. toctree::
+ :glob:
+
+ configuration/reference
+ configuration/segments
+ configuration/listers
+ configuration/selectors
+ configuration/local
diff --git a/docs/source/configuration/listers.rst b/docs/source/configuration/listers.rst
new file mode 100644
index 0000000..7aaaabc
--- /dev/null
+++ b/docs/source/configuration/listers.rst
@@ -0,0 +1,35 @@
+.. _config-listers:
+
+****************
+Lister reference
+****************
+
+Listers are special segment collections which allow to show some list of
+segments for each entity in the list of entities (multiply their segments list
+by a list of entities). E.g. ``powerline.listers.vim.tablister`` presented with
+``powerline.segments.vim.tabnr`` and ``….file_name`` as segments will emit
+segments with buffer names and tabpage numbers for each tabpage shown by vim.
+
+Listers appear in configuration as irregular segments having ``segment_list`` as
+their type and ``segments`` key with a list of segments (a bit more details in
+:ref:`Themes section of configuration reference <config-themes-segments>`).
+
+More information in :ref:`Writing listers <dev-listers>` section.
+
+Vim listers
+-----------
+
+.. automodule:: powerline.listers.vim
+ :members:
+
+Pdb listers
+-----------
+
+.. automodule:: powerline.listers.pdb
+ :members:
+
+i3wm listers
+------------
+
+.. automodule:: powerline.listers.i3wm
+ :members:
diff --git a/docs/source/configuration/local.rst b/docs/source/configuration/local.rst
new file mode 100644
index 0000000..0f3d110
--- /dev/null
+++ b/docs/source/configuration/local.rst
@@ -0,0 +1,260 @@
+.. _local-configuration-overrides:
+
+*****************************
+Local configuration overrides
+*****************************
+
+Depending on the application used it is possible to override configuration. Here
+is the list:
+
+Vim overrides
+=============
+
+Vim configuration can be overridden using the following options:
+
+.. _local-configuration-overrides-vim-config:
+
+``g:powerline_config_overrides``
+ Dictionary, recursively merged with contents of
+ :file:`powerline/config.json`.
+
+``g:powerline_theme_overrides``
+ Dictionary mapping theme names to theme overrides, recursively merged with
+ contents of :file:`powerline/themes/vim/{key}.json`. Note that this way some
+ value (e.g. segment) in a list cannot be redefined, only the whole list
+ itself: only dictionaries are merged recursively.
+
+``g:powerline_config_paths``
+ Paths list (each path must be expanded, ``~`` shortcut is not supported).
+ Points to the list of directories which will be searched for configuration.
+ When this option is present, none of the other locations are searched.
+
+``g:powerline_no_python_error``
+ If this variable is set to a true value it will prevent Powerline from reporting
+ an error when loaded in a copy of vim without the necessary Python support.
+
+``g:powerline_use_var_handler``
+ This variable may be set to either 0 or 1. If it is set to 1 then Vim will
+ save log in ``g:powerline_log_messages`` variable in addition to whatever
+ was configured in :ref:`log_* options <config-common-log>`. Level is always
+ :ref:`log_level <config-common-log_level>`, same for format.
+
+ .. warning::
+ This variable is deprecated. Use :ref:`log_file option
+ <config-common-log>` in conjunction with
+ :py:class:`powerline.vim.VimVarHandler` class and :ref:`Vim config
+ overrides variable <local-configuration-overrides-vim-config>`. Using
+ this is also the only variant to make saving into the environment
+ variable the *only* place where log is saved or save into different
+ variable.
+
+ .. autoclass:: powerline.vim.VimVarHandler
+
+.. _local-configuration-overrides-script:
+
+Powerline script overrides
+==========================
+
+Powerline script has a number of options controlling powerline behavior. Here
+``VALUE`` always means “some JSON object”.
+
+``-c KEY.NESTED_KEY=VALUE`` or ``--config-override=KEY.NESTED_KEY=VALUE``
+ Overrides options from :file:`powerline/config.json`.
+ ``KEY.KEY2.KEY3=VALUE`` is a shortcut for ``KEY={"KEY2": {"KEY3": VALUE}}``.
+ Multiple options (i.e. ``-c K1=V1 -c K2=V2``) are allowed, result (in the
+ example: ``{"K1": V1, "K2": V2}``) is recursively merged with the contents
+ of the file.
+
+ If ``VALUE`` is omitted then corresponding key will be removed from the
+ configuration (if it was present).
+
+``-t THEME_NAME.KEY.NESTED_KEY=VALUE`` or ``--theme-override=THEME_NAME.KEY.NESTED_KEY=VALUE``
+ Overrides options from :file:`powerline/themes/{ext}/{THEME_NAME}.json`.
+ ``KEY.NESTED_KEY=VALUE`` is processed like described above, ``{ext}`` is the
+ first argument to powerline script. May be passed multiple times.
+
+ If ``VALUE`` is omitted then corresponding key will be removed from the
+ configuration (if it was present).
+
+``-p PATH`` or ``--config-path=PATH``
+ Sets directory where configuration should be read from. If present, no
+ default locations are searched for configuration. No expansions are
+ performed by powerline script itself, but ``-p ~/.powerline`` will likely be
+ expanded by the shell to something like ``-p /home/user/.powerline``.
+
+.. warning::
+ Such overrides are suggested for testing purposes only. Use
+ :ref:`Environment variables overrides <local-configuration-overrides-env>`
+ for other purposes.
+
+.. _local-configuration-overrides-env:
+
+Environment variables overrides
+===============================
+
+All bindings that use ``POWERLINE_COMMAND`` environment variable support taking
+overrides from environment variables. In this case overrides should look like
+the following::
+
+ OVERRIDE='key1.key2.key3=value;key4.key5={"value":1};key6=true;key1.key7=10'
+
+. This will be parsed into
+
+.. code-block:: Python
+
+ {
+ "key1": {
+ "key2": {
+ "key3": "value"
+ },
+ "key7": 10,
+ },
+ "key4": {
+ "key5": {
+ "value": 1,
+ },
+ },
+ "key6": True,
+ }
+
+. Rules:
+
+#. Environment variable must form a semicolon-separated list of key-value pairs:
+ ``key=value;key2=value2``.
+#. Keys are always dot-separated strings that must not contain equals sign (as
+ well as semicolon) or start with an underscore. They are interpreted
+ literally and create a nested set of dictionaries: ``k1.k2.k3`` creates
+ ``{"k1":{"k2":{}}}`` and inside the innermost dictionary last key (``k3`` in
+ the example) is contained with its value.
+#. Value may be empty in which case they are interpreted as an order to remove
+ some value: ``k1.k2=`` will form ``{"k1":{"k2":REMOVE_THIS_KEY}}`` nested
+ dictionary where ``k2`` value is a special value that tells
+ dictionary-merging function to remove ``k2`` rather then replace it with
+ something.
+#. Value may be a JSON strings like ``{"a":1}`` (JSON dictionary), ``["a",1]``
+ (JSON list), ``1`` or ``-1`` (JSON number), ``"abc"`` (JSON string) or
+ ``true``, ``false`` and ``null`` (JSON boolean objects and ``Null`` object
+ from JSON). General rule is that anything starting with a digit (U+0030 till
+ U+0039, inclusive), a hyphenminus (U+002D), a quotation mark (U+0022), a left
+ curly bracket (U+007B) or a left square bracket (U+005B) is considered to be
+ some JSON object, same for *exact* values ``true``, ``false`` and ``null``.
+#. Any other value is considered to be literal string: ``k1=foo:bar`` parses to
+ ``{"k1": "foo:bar"}``.
+
+The following environment variables may be used for overrides according to the
+above rules:
+
+``POWERLINE_CONFIG_OVERRIDES``
+ Overrides values from :file:`powerline/config.json`.
+
+``POWERLINE_THEME_OVERRIDES``
+ Overrides values from :file:`powerline/themes/{ext}/{key}.json`. Top-level
+ key is treated as a name of the theme for which overrides are used: e.g. to
+ disable cwd segment defined in :file:`powerline/themes/shell/default.json`
+ one needs to use::
+
+ POWERLINE_THEME_OVERRIDES=default.segment_data.cwd.display=false
+
+Additionally one environment variable is a usual *colon*-separated list of
+directories: ``POWERLINE_CONFIG_PATHS``. This one defines paths which will be
+searched for configuration. Empty paths in ``POWERLINE_CONFIG_PATHS`` are
+ignored.
+
+.. note::
+ Overrides from environment variables have lower priority then
+ :ref:`Powerline script overrides <local-configuration-overrides-script>`.
+ Latter are suggested for tests only.
+
+Zsh/zpython overrides
+=====================
+
+Here overrides are controlled by similarly to the powerline script, but values
+are taken from zsh variables. :ref:`Environment variable overrides
+<local-configuration-overrides-env>` are also supported: if variable is a string
+this variant is used.
+
+``POWERLINE_CONFIG_OVERRIDES``
+ Overrides options from :file:`powerline/config.json`. Should be a zsh
+ associative array with keys equal to ``KEY.NESTED_KEY`` and values being
+ JSON strings. Pair ``KEY.KEY1 VALUE`` is equivalent to ``{"KEY": {"KEY1":
+ VALUE}}``. All pairs are then recursively merged into one dictionary and
+ this dictionary is recursively merged with the contents of the file.
+
+``POWERLINE_THEME_OVERRIDES``
+ Overrides options from :file:`powerline/themes/shell/*.json`. Should be
+ a zsh associative array with keys equal to ``THEME_NAME.KEY.NESTED_KEY`` and
+ values being JSON strings. Is processed like the above
+ ``POWERLINE_CONFIG_OVERRIDES``, but only subdictionaries for ``THEME_NAME``
+ key are merged with theme configuration when theme with given name is
+ requested.
+
+``POWERLINE_CONFIG_PATHS``
+ Sets directories where configuration should be read from. If present, no
+ default locations are searched for configuration. No expansions are
+ performed by powerline script itself, but zsh usually performs them on its
+ own if variable without is set without quotes: ``POWERLINE_CONFIG_PATHS=(
+ ~/example )``. In addition to arrays usual colon-separated “array” string
+ can be used: ``POWERLINE_CONFIG_PATHS=$HOME/path1:$HOME/path2``.
+
+Ipython overrides
+=================
+
+Ipython overrides depend on ipython version. Before ipython-0.11 additional
+keyword arguments should be passed to setup() function. After ipython-0.11
+``c.Powerline.KEY`` should be used. Supported ``KEY`` strings or keyword
+argument names:
+
+``config_overrides``
+ Overrides options from :file:`powerline/config.json`. Should be a dictionary
+ that will be recursively merged with the contents of the file.
+
+``theme_overrides``
+ Overrides options from :file:`powerline/themes/ipython/*.json`. Should be
+ a dictionary where keys are theme names and values are dictionaries which
+ will be recursively merged with the contents of the given theme.
+
+``config_paths``
+ Sets directories where configuration should be read from. If present, no
+ default locations are searched for configuration. No expansions are
+ performed thus paths starting with ``~/`` cannot be used: use
+ :py:func:`os.path.expanduser`.
+
+Prompt command
+==============
+
+In addition to the above configuration options ``$POWERLINE_COMMAND``
+environment variable can be used to tell shell or tmux to use specific powerline
+implementation and ``$POWERLINE_CONFIG_COMMAND`` to tell zsh or tmux where
+``powerline-config`` script is located. This is mostly useful for putting
+powerline into different directory.
+
+.. note::
+
+ ``$POWERLINE_COMMAND`` is always treated as one path in shell bindings, so
+ path with spaces in it may be used. To specify additional arguments one may
+ use ``$POWERLINE_COMMAND_ARGS``, but note that this variable exists for
+ testing purposes only and may be removed. One should use :ref:`Environment
+ variable overrides <local-configuration-overrides-env>` instead.
+
+To disable prompt in shell, but still have tmux support or to disable tmux
+support environment variables ``$POWERLINE_NO_{SHELL}_PROMPT`` and
+``$POWERLINE_NO_{SHELL}_TMUX_SUPPORT`` can be used (substitute ``{SHELL}`` with
+the name of the shell (all-caps) that should be affected (e.g. ``BASH``) or use
+all-inclusive ``SHELL`` that will disable support for all shells). These
+variables have no effect after configuration script was sourced (in fish case:
+after ``powerline-setup`` function was run). To disable specific feature support
+set one of these variables to some non-empty value.
+
+In order to keep shell prompt, but avoid launching Python twice to get unused
+:ref:`above <config-themes-above>` lines in tcsh ``$POWERLINE_NO_TCSH_ABOVE`` or
+``$POWERLINE_NO_SHELL_ABOVE`` variable should be set.
+
+In order to remove additional space from the end of the right prompt in fish
+that was added in order to support multiline prompt ``$POWERLINE_NO_FISH_ABOVE``
+or ``$POWERLINE_NO_SHELL_ABOVE`` variable should be set.
+
+PDB overrides
+=============
+
+Like shell bindings :ref:`PDB bindings <pdb-prompt>` take overrides from
+:ref:`environment variables <local-configuration-overrides-env>`.
diff --git a/docs/source/configuration/reference.rst b/docs/source/configuration/reference.rst
new file mode 100644
index 0000000..9ea60fc
--- /dev/null
+++ b/docs/source/configuration/reference.rst
@@ -0,0 +1,602 @@
+***********************
+Configuration reference
+***********************
+
+.. _config-main:
+
+Main configuration
+==================
+
+:Location: :file:`powerline/config.json`
+
+The main configuration file defines some common options that applies to all
+extensions, as well as some extension-specific options like themes and
+colorschemes.
+
+Common configuration
+--------------------
+
+Common configuration is a subdictionary that is a value of ``common`` key in
+:file:`powerline/config.json` file.
+
+.. _config-common-term_truecolor:
+
+``term_truecolor``
+ Defines whether to output cterm indices (8-bit) or RGB colors (24-bit)
+ to the terminal emulator. See the :ref:`term-feature-support-matrix` for
+ information on whether used terminal emulator supports 24-bit colors.
+
+ This variable is forced to be ``false`` if :ref:`term_escape_style
+ <config-common-term_escape_style>` option is set to ``"fbterm"`` or if it is
+ set to ``"auto"`` and powerline detected fbterm.
+
+.. _config-common-term_escape_style:
+
+``term_escape_style``
+ Defines what escapes sequences should be used. Accepts three variants:
+
+ ======= ===================================================================
+ Variant Description
+ ======= ===================================================================
+ auto ``xterm`` or ``fbterm`` depending on ``$TERM`` variable value:
+ ``TERM=fbterm`` implies ``fbterm`` escaping style, all other values
+ select ``xterm`` escaping.
+ xterm Uses ``\e[{fb};5;{color}m`` for colors (``{fb}`` is either ``38``
+ (foreground) or ``48`` (background)). Should be used for most
+ terminals.
+ fbterm Uses ``\e[{fb};{color}}`` for colors (``{fb}`` is either ``1``
+ (foreground) or ``2`` (background)). Should be used for fbterm:
+ framebuffer terminal.
+ ======= ===================================================================
+
+.. _config-common-ambiwidth:
+
+``ambiwidth``
+ Tells powerline what to do with characters with East Asian Width Class
+ Ambigious (such as Euro, Registered Sign, Copyright Sign, Greek
+ letters, Cyrillic letters). Valid values: any positive integer; it is
+ suggested that this option is only set it to 1 (default) or 2.
+
+.. _config-common-watcher:
+
+``watcher``
+ Select filesystem watcher. Variants are
+
+ ======= ===================================
+ Variant Description
+ ======= ===================================
+ auto Selects most performant watcher.
+ inotify Select inotify watcher. Linux only.
+ stat Select stat-based polling watcher.
+ uv Select libuv-based watcher.
+ ======= ===================================
+
+ Default is ``auto``.
+
+.. _config-common-additional_escapes:
+
+``additional_escapes``
+ Valid for shell extensions, makes sense only if :ref:`term_truecolor
+ <config-common-term_truecolor>` is enabled. Is to be set from command-line.
+ Controls additional escaping that is needed for tmux/screen to work with
+ terminal true color escape codes: normally tmux/screen prevent terminal
+ emulator from receiving these control codes thus rendering powerline prompt
+ colorless. Valid values: ``"tmux"``, ``"screen"``, ``null`` (default).
+
+.. _config-common-paths:
+
+``paths``
+ Defines additional paths which will be searched for modules when using
+ :ref:`function segment option <config-themes-seg-function>` or :ref:`Vim
+ local_themes option <config-ext-local_themes>`. Paths defined here have
+ priority when searching for modules.
+
+.. _config-common-log:
+
+``log_file``
+ Defines how logs will be handled. There are three variants here:
+
+ #. Absent. In this case logging will be done to stderr: equivalent to
+ ``[["logging.StreamHandler", []]]`` or ``[null]``.
+ #. Plain string. In this case logging will be done to the given file:
+ ``"/file/name"`` is equivalent to ``[["logging.FileHandler",
+ [["/file/name"]]]]`` or ``["/file/name"]``. Leading ``~/`` is expanded in
+ the file name, so using ``"~/.log/foo"`` is permitted. If directory
+ pointed by the option is absent, it will be created, but not its parent.
+ #. List of handler definitions. Handler definition may either be ``null``,
+ a string or a list with two or three elements:
+
+ #. Logging class name and module. If module name is absent, it is
+ equivalent to ``logging.handlers``.
+ #. Class constructor arguments in a form ``[[args[, kwargs]]]``: accepted
+ variants are ``[]`` (no arguments), ``[args]`` (e.g.
+ ``[["/file/name"]]``: only positional arguments) or ``[args, kwargs]``
+ (e.g. ``[[], {"host": "localhost", "port": 6666}]``: positional and
+ keyword arguments, but no positional arguments in the example).
+ #. Optional logging level. Overrides :ref:`log_level key
+ <config-common-log_level>` and has the same format.
+ #. Optional format string. Partially overrides :ref:`log_format key
+ <config-common-log_format>` and has the same format. “Partially” here
+ means that it may only specify more critical level.
+
+.. _config-common-log_level:
+
+``log_level``
+ String, determines logging level. Defaults to ``WARNING``.
+
+.. _config-common-log_format:
+
+``log_format``
+ String, determines format of the log messages. Defaults to
+ ``'%(asctime)s:%(level)s:%(message)s'``.
+
+``interval``
+ Number, determines time (in seconds) between checks for changed
+ configuration. Checks are done in a seprate thread. Use ``null`` to check
+ for configuration changes on ``.render()`` call in main thread.
+ Defaults to ``None``.
+
+``reload_config``
+ Boolean, determines whether configuration should be reloaded at all.
+ Defaults to ``True``.
+
+.. _config-common-default_top_theme:
+
+``default_top_theme``
+ String, determines which top-level theme will be used as the default.
+ Defaults to ``powerline_terminus`` in unicode locales and ``ascii`` in
+ non-unicode locales. See `Themes`_ section for more details.
+
+Extension-specific configuration
+--------------------------------
+
+Common configuration is a subdictionary that is a value of ``ext`` key in
+:file:`powerline/config.json` file.
+
+``colorscheme``
+ Defines the colorscheme used for this extension.
+
+.. _config-ext-theme:
+
+``theme``
+ Defines the theme used for this extension.
+
+.. _config-ext-top_theme:
+
+``top_theme``
+ Defines the top-level theme used for this extension. See `Themes`_ section
+ for more details.
+
+.. _config-ext-local_themes:
+
+``local_themes``
+ Defines themes used when certain conditions are met, e.g. for
+ buffer-specific statuslines in vim. Value depends on extension used. For vim
+ it is a dictionary ``{matcher_name : theme_name}``, where ``matcher_name``
+ is either ``matcher_module.module_attribute`` or ``module_attribute``
+ (``matcher_module`` defaults to ``powerline.matchers.vim``) and
+ ``module_attribute`` should point to a function that returns boolean value
+ indicating that current buffer has (not) matched conditions. There is an
+ exception for ``matcher_name`` though: if it is ``__tabline__`` no functions
+ are loaded. This special theme is used for ``tabline`` Vim option.
+
+ For shell and ipython it is a simple ``{prompt_type : theme_name}``, where
+ ``prompt_type`` is a string with no special meaning (specifically it does
+ not refer to any Python function). Shell has ``continuation``, and
+ ``select`` prompts with rather self-explanatory names, IPython has ``in2``,
+ ``out`` and ``rewrite`` prompts (refer to IPython documentation for more
+ details) while ``in`` prompt is the default.
+
+ For wm (:ref:`lemonbar <lemonbar-usage>` only) it is a dictionary
+ ``{output : theme_name}`` that maps the ``xrandr`` output names to the
+ local themes to use on that output.
+
+.. _config-ext-components:
+
+``components``
+ Determines which extension components should be enabled. This key is highly
+ extension-specific, here is the table of extensions and corresponding
+ components:
+
+ +---------+----------+-----------------------------------------------------+
+ |Extension|Component |Description |
+ +---------+----------+-----------------------------------------------------+
+ |vim |statusline|Makes Vim use powerline statusline. |
+ | +----------+-----------------------------------------------------+
+ | |tabline |Makes Vim use powerline tabline. |
+ +---------+----------+-----------------------------------------------------+
+ |shell |prompt |Makes shell display powerline prompt. |
+ | +----------+-----------------------------------------------------+
+ | |tmux |Makes shell report its current working directory |
+ | | |and screen width to tmux for tmux powerline |
+ | | |bindings. |
+ | | |  |
+ +---------+----------+-----------------------------------------------------+
+
+ All components are enabled by default.
+
+.. _config-ext-update_interval:
+
+``update_interval``
+ Determines how often WM status bars need to be updated, in seconds. Only
+ valid for WM extensions which use ``powerline-daemon``. Defaults to
+ 2 seconds.
+
+.. _config-colors:
+
+Color definitions
+=================
+
+:Location: :file:`powerline/colors.json`
+
+.. _config-colors-colors:
+
+``colors``
+ Color definitions, consisting of a dict where the key is the name of the
+ color, and the value is one of the following:
+
+ * A cterm color index.
+ * A list with a cterm color index and a hex color string (e.g. ``[123,
+ "aabbcc"]``). This is useful for colorschemes that use colors that
+ aren’t available in color terminals.
+
+``gradients``
+ Gradient definitions, consisting of a dict where the key is the name of the
+ gradient, and the value is a list containing one or two items, second item
+ is optional:
+
+ * A list of cterm color indicies.
+ * A list of hex color strings.
+
+ It is expected that gradients are defined from least alert color to most
+ alert or non-alert colors are used.
+
+.. _config-colorschemes:
+
+Colorschemes
+============
+
+:Location: :file:`powerline/colorschemes/{name}.json`,
+ :file:`powerline/colorschemes/__main__.json`,
+ :file:`powerline/colorschemes/{extension}/{name}.json`
+
+Colorscheme files are processed in order given: definitions from each next file
+override those from each previous file. It is required that either
+:file:`powerline/colorschemes/{name}.json`, or
+:file:`powerline/colorschemes/{extension}/{name}.json` exists.
+
+``name``
+ Name of the colorscheme.
+
+.. _config-colorschemes-groups:
+
+``groups``
+ Segment highlighting groups, consisting of a dict where the key is the
+ name of the highlighting group (usually the function name for function
+ segments), and the value is either
+
+ #) a dict that defines the foreground color, background color and
+ attributes:
+
+ ``fg``
+ Foreground color. Must be defined in :ref:`colors
+ <config-colors-colors>`.
+
+ ``bg``
+ Background color. Must be defined in :ref:`colors
+ <config-colors-colors>`.
+
+ ``attrs``
+ List of attributes. Valid values are one or more of ``bold``,
+ ``italic`` and ``underline``. Note that some attributes may be
+ unavailable in some applications or terminal emulators. If no
+ attributes are needed this list should be left empty.
+
+ #) a string (an alias): a name of existing group. This group’s definition
+ will be used when this color is requested.
+
+``mode_translations``
+ Mode-specific highlighting for extensions that support it (e.g. the vim
+ extension). It’s an easy way of changing a color in a specific mode.
+ Consists of a dict where the key is the mode and the value is a dict
+ with the following options:
+
+ ``colors``
+ A dict where the key is the color to be translated in this mode, and
+ the value is the new color. Both the key and the value must be defined
+ in :ref:`colors <config-colors-colors>`.
+
+ ``groups``
+ Segment highlighting groups for this mode. Same syntax as the main
+ :ref:`groups <config-colorschemes-groups>` option.
+
+.. _config-themes:
+
+Themes
+======
+
+:Location: :file:`powerline/themes/{top_theme}.json`,
+ :file:`powerline/themes/{extension}/__main__.json`,
+ :file:`powerline/themes/{extension}/{name}.json`
+
+Theme files are processed in order given: definitions from each next file
+override those from each previous file. It is required that file
+:file:`powerline/themes/{extension}/{name}.json` exists.
+
+`{top_theme}` component of the file name is obtained either from :ref:`top_theme
+extension-specific key <config-ext-top_theme>` or from :ref:`default_top_theme
+common configuration key <config-common-default_top_theme>`. Powerline ships
+with the following top themes:
+
+.. _config-top_themes-list:
+
+========================== ====================================================
+Theme Description
+========================== ====================================================
+powerline Default powerline theme with fancy powerline symbols
+powerline_unicode7 Theme with powerline dividers and unicode-7 symbols
+unicode Theme without any symbols from private use area
+unicode_terminus Theme containing only symbols from terminus PCF font
+unicode_terminus_condensed Like above, but occupies as less space as possible
+powerline_terminus Like unicode_terminus, but with powerline symbols
+ascii Theme without any unicode characters at all
+========================== ====================================================
+
+``name``
+ Name of the theme.
+
+.. _config-themes-default_module:
+
+``default_module``
+ Python module where segments will be looked by default. Defaults to
+ ``powerline.segments.{ext}``.
+
+``spaces``
+ Defines number of spaces just before the divider (on the right side) or just
+ after it (on the left side). These spaces will not be added if divider is
+ not drawn.
+
+``use_non_breaking_spaces``
+ Determines whether non-breaking spaces should be used in place of the
+ regular ones. This option is needed because regular spaces are not displayed
+ properly when using powerline with some font configuration. Defaults to
+ ``True``.
+
+ .. note::
+ Unlike all other options this one is only checked once at startup using
+ whatever theme is :ref:`the default <config-ext-theme>`. If this option
+ is set in the local themes it will be ignored. This option may also be
+ ignored in some bindings.
+
+``outer_padding``
+ Defines number of spaces at the end of output (on the right side) or at
+ the start of output (on the left side). Defaults to ``1``.
+
+
+``dividers``
+ Defines the dividers used in all Powerline extensions.
+
+ The ``hard`` dividers are used to divide segments with different
+ background colors, while the ``soft`` dividers are used to divide
+ segments with the same background color.
+
+.. _config-themes-cursor_space:
+
+``cursor_space``
+ Space reserved for user input in shell bindings. It is measured in per
+ cents.
+
+``cursor_columns``
+ Space reserved for user input in shell bindings. Unlike :ref:`cursor_space
+ <config-themes-cursor_space>` it is measured in absolute amout of columns.
+
+.. _config-themes-segment_data:
+
+``segment_data``
+ A dict where keys are segment names or strings ``{module}.{function}``. Used
+ to specify default values for various keys:
+ :ref:`after <config-themes-seg-after>`,
+ :ref:`before <config-themes-seg-before>`,
+ :ref:`contents <config-themes-seg-contents>` (only for string segments
+ if :ref:`name <config-themes-seg-name>` is defined),
+ :ref:`display <config-themes-seg-display>`.
+
+ Key :ref:`args <config-themes-seg-args>` (only for function and
+ segment_list segments) is handled specially: unlike other values it is
+ merged with all other values, except that a single ``{module}.{function}``
+ key if found prevents merging all ``{function}`` values.
+
+ When using :ref:`local themes <config-ext-local_themes>` values of these
+ keys are first searched in the segment description, then in ``segment_data``
+ key of a local theme, then in ``segment_data`` key of a :ref:`default theme
+ <config-ext-theme>`. For the :ref:`default theme <config-ext-theme>` itself
+ step 2 is obviously avoided.
+
+ .. note:: Top-level themes are out of equation here: they are merged
+ before the above merging process happens.
+
+.. _config-themes-segments:
+
+``segments``
+ A dict with a ``left`` and a ``right`` lists, consisting of segment
+ dictionaries. Shell themes may also contain ``above`` list of dictionaries.
+ Each item in ``above`` list may have ``left`` and ``right`` keys like this
+ dictionary, but no ``above`` key.
+
+ .. _config-themes-above:
+
+ ``above`` list is used for multiline shell configurations.
+
+ ``left`` and ``right`` lists are used for segments that should be put on the
+ left or right side in the output. Actual mechanizm of putting segments on
+ the left or the right depends on used renderer, but most renderers require
+ one to specify segment with :ref:`width <config-themes-seg-width>` ``auto``
+ on either side to make generated line fill all of the available width.
+
+ Each segment dictionary has the following options:
+
+ .. _config-themes-seg-type:
+
+ ``type``
+ The segment type. Can be one of ``function`` (default), ``string`` or
+ ``segment_list``:
+
+ ``function``
+ The segment contents is the return value of the function defined in
+ the :ref:`function option <config-themes-seg-function>`.
+
+ List of function segments is available in :ref:`Segment reference
+ <config-segments>` section.
+
+ ``string``
+ A static string segment where the contents is defined in the
+ :ref:`contents option <config-themes-seg-contents>`, and the
+ highlighting group is defined in the :ref:`highlight_groups option
+ <config-themes-seg-highlight_groups>`.
+
+ ``segment_list``
+ Sub-list of segments. This list only allows :ref:`function
+ <config-themes-seg-function>`, :ref:`segments
+ <config-themes-seg-segments>` and :ref:`args
+ <config-themes-seg-args>` options.
+
+ List of lister segments is available in :ref:`Lister reference
+ <config-listers>` section.
+
+ .. _config-themes-seg-name:
+
+ ``name``
+ Segment name. If present allows referring to this segment in
+ :ref:`segment_data <config-themes-segment_data>` dictionary by this
+ name. If not ``string`` segments may not be referred there at all and
+ ``function`` and ``segment_list`` segments may be referred there using
+ either ``{module}.{function_name}`` or ``{function_name}``, whichever
+ will be found first. Function name is taken from :ref:`function key
+ <config-themes-seg-function>`.
+
+ .. note::
+ If present prevents ``function`` key from acting as a segment name.
+
+ .. _config-themes-seg-function:
+
+ ``function``
+ Function used to get segment contents, in format ``{module}.{function}``
+ or ``{function}``. If ``{module}`` is omitted :ref:`default_module
+ option <config-themes-default_module>` is used.
+
+ .. _config-themes-seg-highlight_groups:
+
+ ``highlight_groups``
+ Highlighting group for this segment. Consists of a prioritized list of
+ highlighting groups, where the first highlighting group that is
+ available in the colorscheme is used.
+
+ Ignored for segments that have ``function`` type.
+
+ .. _config-themes-seg-before:
+
+ ``before``
+ A string which will be prepended to the segment contents.
+
+ .. _config-themes-seg-after:
+
+ ``after``
+ A string which will be appended to the segment contents.
+
+ .. _config-themes-seg-contents:
+
+ ``contents``
+ Segment contents, only required for ``string`` segments.
+
+ .. _config-themes-seg-args:
+
+ ``args``
+ A dict of arguments to be passed to a ``function`` segment.
+
+ .. _config-themes-seg-align:
+
+ ``align``
+ Aligns the segments contents to the left (``l``), center (``c``) or
+ right (``r``). Has no sense if ``width`` key was not specified or if
+ segment provides its own function for ``auto`` ``width`` handling and
+ does not care about this option.
+
+ .. _config-themes-seg-width:
+
+ ``width``
+ Enforces a specific width for this segment.
+
+ This segment will work as a spacer if the width is set to ``auto``.
+ Several spacers may be used, and the space will be distributed
+ equally among all the spacer segments. Spacers may have contents,
+ either returned by a function or a static string, and the contents
+ can be aligned with the ``align`` property.
+
+ .. _config-themes-seg-priority:
+
+ ``priority``
+ Optional segment priority. Segments with priority ``None`` (the default
+ priority, represented by ``null`` in json) will always be included,
+ regardless of the width of the prompt/statusline.
+
+ If the priority is any number, the segment may be removed if the
+ prompt/statusline width is too small for all the segments to be
+ rendered. A lower number means that the segment has a higher priority.
+
+ Segments are removed according to their priority, with low priority
+ segments (i.e. with a greater priority number) being removed first.
+
+ .. _config-themes-seg-draw_divider:
+
+ ``draw_hard_divider``, ``draw_soft_divider``
+ Whether to draw a divider between this and the adjacent segment. The
+ adjacent segment is to the *right* for segments on the *left* side, and
+ vice versa. Hard dividers are used between segments with different
+ background colors, soft ones are used between segments with same
+ background. Both options default to ``True``.
+
+ .. _config-themes-seg-draw_inner_divider:
+
+ ``draw_inner_divider``
+ Determines whether inner soft dividers are to be drawn for function
+ segments. Only applicable for functions returning multiple segments.
+ Defaults to ``False``.
+
+ .. _config-themes-seg-exclude_modes:
+
+ ``exclude_modes``, ``include_modes``
+ A list of modes where this segment will be excluded: the segment is not
+ included or is included in all modes, *except* for the modes in one of
+ these lists respectively. If ``exclude_modes`` is not present then it
+ acts like an empty list (segment is not excluded from any modes).
+ Without ``include_modes`` it acts like a list with all possible modes
+ (segment is included in all modes). When there are both
+ ``exclude_modes`` overrides ``include_modes``.
+
+ .. _config-themes-seg-exclude_function:
+
+ ``exclude_function``, ``include_function``
+ Function name in a form ``{name}`` or ``{module}.{name}`` (in the first
+ form ``{module}`` defaults to ``powerline.selectors.{ext}``). Determines
+ under which condition specific segment will be included or excluded. By
+ default segment is always included and never excluded.
+ ``exclude_function`` overrides ``include_function``.
+
+ .. note::
+ Options :ref:`exclude_/include_modes
+ <config-themes-seg-exclude_modes>` complement
+ ``exclude_/include_functions``: segment will be included if it is
+ included by either ``include_mode`` or ``include_function`` and will
+ be excluded if it is excluded by either ``exclude_mode`` or
+ ``exclude_function``.
+
+ .. _config-themes-seg-display:
+
+ ``display``
+ Boolean. If false disables displaying of the segment.
+ Defaults to ``True``.
+
+ .. _config-themes-seg-segments:
+
+ ``segments``
+ A list of subsegments.
diff --git a/docs/source/configuration/segments.rst b/docs/source/configuration/segments.rst
new file mode 100644
index 0000000..63b4975
--- /dev/null
+++ b/docs/source/configuration/segments.rst
@@ -0,0 +1,28 @@
+.. _config-segments:
+
+*****************
+Segment reference
+*****************
+
+Segments
+========
+
+Segments are written in Python, and the default segments provided with
+Powerline are located in :file:`powerline/segments/{extension}.py`.
+User-defined segments can be defined in any module in ``sys.path`` or
+:ref:`paths common configuration option <config-common-paths>`, import is
+always absolute.
+
+Segments are regular Python functions, and they may accept arguments. All
+arguments should have a default value which will be used for themes that
+don’t provide an ``args`` dict.
+
+More information is available in :ref:`Writing segments <dev-segments>` section.
+
+Available segments
+==================
+
+.. toctree::
+ :glob:
+
+ segments/*
diff --git a/docs/source/configuration/segments/common.rst b/docs/source/configuration/segments/common.rst
new file mode 100644
index 0000000..5d52d69
--- /dev/null
+++ b/docs/source/configuration/segments/common.rst
@@ -0,0 +1,57 @@
+***************
+Common segments
+***************
+
+VCS submodule
+=============
+
+.. automodule:: powerline.segments.common.vcs
+ :members:
+
+System properties
+=================
+
+.. automodule:: powerline.segments.common.sys
+ :members:
+
+Network
+=======
+
+.. automodule:: powerline.segments.common.net
+ :members:
+
+Current environment
+===================
+
+.. automodule:: powerline.segments.common.env
+ :members:
+
+Battery
+=======
+
+.. automodule:: powerline.segments.common.bat
+ :members:
+
+Weather
+=======
+
+.. automodule:: powerline.segments.common.wthr
+ :members:
+
+Date and time
+=============
+
+.. automodule:: powerline.segments.common.time
+ :members:
+
+Mail
+====
+
+.. automodule:: powerline.segments.common.mail
+ :members:
+
+Media players
+=============
+
+.. automodule:: powerline.segments.common.players
+ :members:
diff --git a/docs/source/configuration/segments/i3wm.rst b/docs/source/configuration/segments/i3wm.rst
new file mode 100644
index 0000000..d103374
--- /dev/null
+++ b/docs/source/configuration/segments/i3wm.rst
@@ -0,0 +1,6 @@
+*************
+i3wm segments
+*************
+
+.. automodule:: powerline.segments.i3wm
+ :members:
diff --git a/docs/source/configuration/segments/pdb.rst b/docs/source/configuration/segments/pdb.rst
new file mode 100644
index 0000000..b9a104b
--- /dev/null
+++ b/docs/source/configuration/segments/pdb.rst
@@ -0,0 +1,7 @@
+************
+PDB segments
+************
+
+.. automodule:: powerline.segments.pdb
+ :members:
+
diff --git a/docs/source/configuration/segments/shell.rst b/docs/source/configuration/segments/shell.rst
new file mode 100644
index 0000000..fb3c804
--- /dev/null
+++ b/docs/source/configuration/segments/shell.rst
@@ -0,0 +1,6 @@
+**************
+Shell segments
+**************
+
+.. automodule:: powerline.segments.shell
+ :members:
diff --git a/docs/source/configuration/segments/tmux.rst b/docs/source/configuration/segments/tmux.rst
new file mode 100644
index 0000000..1a4a78f
--- /dev/null
+++ b/docs/source/configuration/segments/tmux.rst
@@ -0,0 +1,6 @@
+*************
+Tmux segments
+*************
+
+.. automodule:: powerline.segments.tmux
+ :members:
diff --git a/docs/source/configuration/segments/vim.rst b/docs/source/configuration/segments/vim.rst
new file mode 100644
index 0000000..5df70d6
--- /dev/null
+++ b/docs/source/configuration/segments/vim.rst
@@ -0,0 +1,46 @@
+************
+Vim segments
+************
+
+.. automodule:: powerline.segments.vim
+ :members:
+
+
+Plugin-specific segments
+========================
+
+Asynchronous Linter Engine (ALE) segments
+-----------------------------------------
+
+.. automodule:: powerline.segments.vim.plugin.ale
+ :members:
+
+Syntastic segments
+------------------
+
+.. automodule:: powerline.segments.vim.plugin.syntastic
+ :members:
+
+Command-T segments
+------------------
+
+.. automodule:: powerline.segments.vim.plugin.commandt
+ :members:
+
+Tagbar segments
+---------------
+
+.. automodule:: powerline.segments.vim.plugin.tagbar
+ :members:
+
+NERDTree segments
+-----------------
+
+.. automodule:: powerline.segments.vim.plugin.nerdtree
+ :members:
+
+Capslock segments
+-----------------
+
+.. automodule:: powerline.segments.vim.plugin.capslock
+ :members:
diff --git a/docs/source/configuration/selectors.rst b/docs/source/configuration/selectors.rst
new file mode 100644
index 0000000..f9367b2
--- /dev/null
+++ b/docs/source/configuration/selectors.rst
@@ -0,0 +1,17 @@
+.. _config-selectors:
+
+******************
+Selector functions
+******************
+
+Selector functions are functions that return ``True`` or ``False`` depending on
+application state. They are used for :ref:`exclude_function and include_function
+segment options <config-themes-seg-exclude_function>`.
+
+Available selectors
+===================
+
+.. toctree::
+ :glob:
+
+ selectors/*
diff --git a/docs/source/configuration/selectors/vim.rst b/docs/source/configuration/selectors/vim.rst
new file mode 100644
index 0000000..5097320
--- /dev/null
+++ b/docs/source/configuration/selectors/vim.rst
@@ -0,0 +1,6 @@
+*************
+Vim selectors
+*************
+
+.. automodule:: powerline.selectors.vim
+ :members:
diff --git a/docs/source/develop.rst b/docs/source/develop.rst
new file mode 100644
index 0000000..bf45498
--- /dev/null
+++ b/docs/source/develop.rst
@@ -0,0 +1,13 @@
+***************
+Developer guide
+***************
+
+.. toctree::
+ :maxdepth: 2
+ :glob:
+
+ develop/segments
+ develop/listers
+ develop/local-themes
+ develop/extensions
+ develop/tips-and-tricks
diff --git a/docs/source/develop/extensions.rst b/docs/source/develop/extensions.rst
new file mode 100644
index 0000000..2ddf223
--- /dev/null
+++ b/docs/source/develop/extensions.rst
@@ -0,0 +1,47 @@
+********************************
+Creating new powerline extension
+********************************
+
+Powerline extension is a code that tells powerline how to highlight and display
+segments in some set of applications. Specifically this means
+
+#. Creating a :py:class:`powerline.Powerline` subclass that knows how to obtain
+ :ref:`local configuration overrides <local-configuration-overrides>`. It also
+ knows how to load local themes, but not when to apply them.
+
+ Instance of this class is the only instance that interacts directly with
+ bindings code, so it has a proxy :py:meth:`powerline.Powerline.render` and
+ :py:meth:`powerline.Powerline.shutdown` methods and other methods which may
+ be useful for bindings.
+
+ This subclass must be placed directly in :file:`powerline` directory (e.g. in
+ :file:`powerline/vim.py`) and named like ``VimPowerline`` (version of the
+ file name without directory and extension and first capital letter
+ + ``Powerline``). There is no technical reason for naming classes like this.
+#. Creating a :py:class:`powerline.renderer.Renderer` subclass that knows how to
+ highlight a segment or reset highlighting to the default value (only makes
+ sense in prompts). It is also responsible for selecting local themes and
+ computing text width.
+
+ This subclass must be placed directly in :file:`powerline/renderers`
+ directory (for powerline extensions developed for a set of applications use
+ :file:`powerline/renderers/{ext}/*.py`) and named like ``ExtRenderer`` or
+ ``AppPromptRenderer``. For technical reasons the class itself must be
+ referenced in ``renderer`` module attribute thus allowing only one renderer
+ per one module.
+#. Creating an extension bindings. These are to be placed in
+ :file:`powerline/bindings/{ext}` and may contain virtually anything which may
+ be required for powerline to work inside given applications, assuming it does
+ not fit in other places.
+
+Powerline class
+===============
+
+.. autoclass:: powerline.Powerline
+ :members:
+
+Renderer class
+==============
+
+.. autoclass:: powerline.renderer.Renderer
+ :members:
diff --git a/docs/source/develop/listers.rst b/docs/source/develop/listers.rst
new file mode 100644
index 0000000..e779704
--- /dev/null
+++ b/docs/source/develop/listers.rst
@@ -0,0 +1,49 @@
+.. _dev-listers:
+
+***************
+Writing listers
+***************
+
+Listers provide a way to show some segments multiple times: once per each entity
+(buffer, tabpage, etc) lister knows. They are functions which receive the
+following arguments:
+
+``pl``
+ A :py:class:`powerline.PowerlineLogger` class instance. It must be used for
+ logging.
+
+``segment_info``
+ Base segment info dictionary. Lister function or class must have
+ ``powerline_requires_segment_info`` to receive this argument.
+
+ .. warning::
+ Listers are close to useless if they do not have access to this
+ argument.
+
+ Refer to :ref:`segment_info detailed description <dev-segments-info>` for
+ further details.
+
+``draw_inner_divider``
+ If False (default) soft dividers between segments in the listed group will
+ not be drawn regardless of actual segment settings. If True they will be
+ drawn, again regardless of actual segment settings. Set it to ``None`` in
+ order to respect segment settings.
+
+And also any other argument(s) specified by user in :ref:`args key
+<config-themes-seg-args>` (no additional arguments by default).
+
+Listers must return a sequence of pairs. First item in the pair must contain
+a ``segment_info`` dictionary specific to one of the listed entities.
+
+Second item must contain another dictionary: it will be used to modify the
+resulting segment. In addition to :ref:`usual keys that describe segment
+<dev-segments-segment>` the following keys may be present (it is advised that
+*only* the following keys will be used):
+
+``priority_multiplier``
+ Value (usually a ``float``) used to multiply segment priority. It is useful
+ for finer-grained controlling which segments disappear first: e.g. when
+ listing tab pages make first disappear directory names of the tabpages which
+ are most far away from current tabpage, then (when all directory names
+ disappeared) buffer names. Check out existing listers implementation in
+ :file:`powerline/listers/vim.py`.
diff --git a/docs/source/develop/local-themes.rst b/docs/source/develop/local-themes.rst
new file mode 100644
index 0000000..959e1c4
--- /dev/null
+++ b/docs/source/develop/local-themes.rst
@@ -0,0 +1,59 @@
+************
+Local themes
+************
+
+From the user point of view local themes are the regular themes with a specific
+scope where they are applied (i.e. specific vim window or specific kind of
+prompt). Used themes are defined in :ref:`local_themes key
+<config-ext-local_themes>`.
+
+Vim local themes
+================
+
+Vim is the only available extension that has a wide variaty of options for local
+themes. It is the only extension where local theme key refers to a function as
+described in :ref:`local_themes value documentation <config-ext-local_themes>`.
+
+This function always takes a single value named ``matcher_info`` which is the
+same dictionary as :ref:`segment_info dictionary <dev-segment_info-vim>`. Unlike
+segments it takes this single argument as a *positional* argument, not as
+a keyword one.
+
+Matcher function should return a boolean value: ``True`` if theme applies for
+the given ``matcher_info`` dictionary or ``False`` if it is not. When one of the
+matcher functions returns ``True`` powerline takes the corresponding theme at
+uses it for the given window. Matchers are not tested in any particular order.
+
+In addition to :ref:`local_themes configuration key <config-ext-local_themes>`
+developer of some plugin which wishes to support powerline without including his
+code in powerline tree may use
+:py:meth:`powerline.vim.VimPowerline.add_local_theme` method. It accepts two
+arguments: matcher name (same as in :ref:`local_themes
+<config-ext-local_themes>`) and dictionary with theme. This dictionary is merged
+with :ref:`top theme <config-ext-top_theme>` and
+:file:`powerline/themes/vim/__main__.json`. Note that if user already specified
+the matcher in his configuration file ``KeyError`` is raised.
+
+Other local themes
+==================
+
+Except for Vim only IPython and shells have local themes. Unlike Vim these
+themes are names with no special meaning (they do not refer to or cause loading
+of any Python functions):
+
++---------+------------+-------------------------------------------------------+
+|Extension|Theme name |Description |
++---------+------------+-------------------------------------------------------+
+|Shell |continuation|Shown for unfinished command (unclosed quote, |
+| | |unfinished cycle). |
+| +------------+-------------------------------------------------------+
+| |select |Shown for ``select`` command available in some shells. |
++---------+------------+-------------------------------------------------------+
+|IPython |in2 |Continuation prompt: shown for unfinished (multiline) |
+| | |expression, unfinished class or function definition. |
+| +------------+-------------------------------------------------------+
+| |out |Displayed before the result. |
+| +------------+-------------------------------------------------------+
+| |rewrite |Displayed before the actually executed code when |
+| | |``autorewrite`` IPython feature is enabled.  |
++---------+------------+-------------------------------------------------------+
diff --git a/docs/source/develop/segments.rst b/docs/source/develop/segments.rst
new file mode 100644
index 0000000..543ddd5
--- /dev/null
+++ b/docs/source/develop/segments.rst
@@ -0,0 +1,547 @@
+.. _dev-segments:
+
+****************
+Writing segments
+****************
+
+Each powerline segment is a callable object. It is supposed to be either
+a Python function or :py:class:`powerline.segments.Segment` class. As a callable
+object it should receive the following arguments:
+
+.. note:: All received arguments are keyword arguments.
+
+``pl``
+ A :py:class:`powerline.PowerlineLogger` instance. It must be used every time
+ something needs to be logged.
+
+``segment_info``
+ A dictionary. It is only received if callable has
+ ``powerline_requires_segment_info`` attribute.
+
+ Refer to :ref:`segment_info detailed description <dev-segments-info>` for
+ further details.
+
+``create_watcher``
+ Function that will create filesystem watcher once called. Which watcher will
+ be created exactly is controlled by :ref:`watcher configuration option
+ <config-common-watcher>`.
+
+And also any other argument(s) specified by user in :ref:`args key
+<config-themes-seg-args>` (no additional arguments by default).
+
+.. note::
+ For powerline-lint to work properly the following things may be needed:
+
+ #. If segment is a :py:class:`powerline.segments.Segment` instance and used
+ arguments are scattered over multiple methods
+ :py:meth:`powerline.segments.Segment.argspecobjs` should be overridden in
+ subclass to tell powerline-lint which objects should be inspected for
+ arguments.
+ #. If segment takes some arguments that are never listed, but accessed via
+ ``kwargs.get()`` or previous function cannot be used for whatever reason
+ :py:meth:`powerline.segments.Segment.additional_args` should be
+ overridden in subclass.
+ #. If user is expected to use one :ref:`name <config-themes-seg-name>` for
+ multiple segments which cannot be linked to the segment function
+ automatically by powerline-lint (e.g. because there are no instances of
+ the segments in question in the default configuration)
+ :py:func:`powerline.lint.checks.register_common_name` function should be
+ used.
+
+Object representing segment may have the following attributes used by
+powerline:
+
+``powerline_requires_segment_info``
+ This attribute controls whether segment will receive ``segment_info``
+ argument: if it is present argument will be received.
+
+``powerline_requires_filesystem_watcher``
+ This attribute controls whether segment will receive ``create_watcher``
+ argument: if it is present argument will be received.
+
+``powerline_segment_datas``
+ This attribute must be a dictionary containing ``top_theme: segment_data``
+ mapping where ``top_theme`` is any theme name (it is expected that all of
+ the names from :ref:`top-level themes list <config-top_themes-list>` are
+ present) and ``segment_data`` is a dictionary like the one that is contained
+ inside :ref:`segment_data dictionary in configuration
+ <config-themes-segment_data>`. This attribute should be used to specify
+ default theme-specific values for *third-party* segments: powerline
+ theme-specific values go directly to :ref:`top-level themes
+ <config-themes>`.
+
+.. _dev-segments-startup:
+
+``startup``
+ This attribute must be a callable which accepts the following keyword
+ arguments:
+
+ * ``pl``: :py:class:`powerline.PowerlineLogger` instance which is to be used
+ for logging.
+ * ``shutdown_event``: :py:class:`Event` object which will be set when
+ powerline will be shut down.
+ * Any arguments found in user configuration for the given segment (i.e.
+ :ref:`args key <config-themes-seg-args>`).
+
+ This function is called at powerline startup when using long-running
+ processes (e.g. powerline in vim, in zsh with libzpython, in ipython or in
+ powerline daemon) and not called when ``powerline-render`` executable is
+ used (more specific: when :py:class:`powerline.Powerline` constructor
+ received true ``run_once`` argument).
+
+.. _dev-segments-shutdown:
+
+``shutdown``
+ This attribute must be a callable that accepts no arguments and shuts down
+ threads and frees any other resources allocated in ``startup`` method of the
+ segment in question.
+
+ This function is not called when ``startup`` method is not called.
+
+.. _dev-segments-expand:
+
+``expand``
+ This attribute must be a callable that accepts the following keyword
+ arguments:
+
+ * ``pl``: :py:class:`powerline.PowerlineLogger` instance which is to be used
+ for logging.
+ * ``amount``: integer number representing amount of display cells result
+ must occupy.
+
+ .. warning::
+ “Amount of display cells” is *not* number of Unicode codepoints, string
+ length, or byte count. It is suggested that this function should look
+ something like ``return (' ' * amount) + segment['contents']`` where
+ ``' '`` may be replaced with anything that is known to occupy exactly
+ one display cell.
+ * ``segment``: :ref:`segment dictionary <dev-segments-segment>`.
+ * Any arguments found in user configuration for the given segment (i.e.
+ :ref:`args key <config-themes-seg-args>`).
+
+ It must return new value of :ref:`contents <dev-segments-seg-contents>` key.
+
+.. _dev-segments-truncate:
+
+``truncate``
+ Like :ref:`expand function <dev-segments-expand>`, but for truncating
+ segments. Here ``amount`` means the number of display cells which must be
+ freed.
+
+ This function is called for all segments before powerline starts purging
+ them to free space.
+
+This callable object should may return either a string (``unicode`` in Python2
+or ``str`` in Python3, *not* ``str`` in Python2 or ``bytes`` in Python3) object
+or a list of dictionaries. String object is a short form of the following return
+value:
+
+.. code-block:: python
+
+ [{
+ 'contents': original_return,
+ 'highlight_groups': [segment_name],
+ }]
+
+.. _dev-segments-return:
+
+Returned list is a list of segments treated independently, except for
+:ref:`draw_inner_divider key <dev-segments-draw_inner_divider>`.
+
+All keys in segments returned by the function override those obtained from
+:ref:`configuration <config-themes-segments>` and have the same meaning.
+
+Detailed description of used dictionary keys:
+
+.. _dev-segments-contents:
+
+``contents``
+ Text displayed by segment. Should be a ``unicode`` (Python2) or ``str``
+ (Python3) instance.
+
+``literal_contents``
+ Text that needs to be output literally (i.e. without passing through
+ :py:meth:`powerline.renderer.strwidth` to determine length, through
+ :py:meth:`powerline.renderer.escape` to escape special characters and
+ through :py:meth:`powerline.renderer.hl` to highlight it). Should be a tuple
+ ``(contents_length, contents)`` where ``contents_length`` is an integer and
+ ``contents`` is a ``unicode`` (Python2) or ``str`` (Python3) instance.
+
+ If this key is present and its second value is true then other contents keys
+ (:ref:`contents <dev-segments-contents>`, :ref:`after
+ <config-themes-seg-after>`, :ref:`before <config-themes-seg-before>`) will
+ be ignored.
+
+ .. note::
+ If target is inclusion of the segment in powerline upstream all segment
+ functions that output *only* subsegments with ``literal_contents`` key
+ must contain the following string in documentation::
+
+ No highlight groups are used (literal segment).
+
+ String must be present on the separate line.
+
+.. _dev-segments-draw_inner_divider:
+
+``draw_hard_divider``, ``draw_soft_divider``, ``draw_inner_divider``
+ Determines whether given divider should be drawn. All have the same meaning
+ as :ref:`the similar keys in configuration <config-themes-seg-draw_divider>`
+ (:ref:`draw_inner_divider <config-themes-seg-draw_inner_divider>`).
+
+.. _dev-segments-highlight_groups:
+
+``highlight_groups``
+ Determines segment highlighting. Refer to :ref:`themes documentation
+ <config-themes-seg-highlight_groups>` for more details.
+
+ Defaults to the name of the segment.
+
+ .. note::
+ If target is inclusion of the segment in powerline upstream all used
+ highlighting groups must be specified in the segment documentation in the
+ form::
+
+ Highlight groups used: ``g1``[ or ``g2``]*[, ``g3`` (gradient)[ or ``g4``]*]*.
+
+ I.e. use::
+
+ Highlight groups used: ``foo_gradient`` (gradient) or ``foo``, ``bar``.
+
+ to specify that the segment uses *either* ``foo_gradient`` group or
+ ``foo`` group *and* ``bar`` group meaning that ``powerline-lint`` will
+ check that at least one of the first two groups is defined (and if
+ ``foo_gradient`` is defined it must use at least one gradient color) and
+ third group is defined as well.
+
+ All groups must be specified on one line.
+
+``divider_highlight_group``
+ Determines segment divider highlight group. Only applicable for soft
+ dividers: colors for hard dividers are determined by colors of adjacent
+ segments.
+
+ .. note::
+ If target is inclusion of the segment in powerline upstream used divider
+ highlight group must be specified in the segment documentation in the
+ form::
+
+ Divider highlight group used: ``group``.
+
+ This text must not wrap and all divider highlight group names are
+ supposed to end with ``:divider``: e.g. ``cwd:divider``.
+
+``gradient_level``
+ First and the only key that may not be specified in user configuration. It
+ determines which color should be used for this segment when one of the
+ highlighting groups specified by :ref:`highlight_groups
+ <dev-segments-highlight_groups>` was defined to use the color gradient.
+
+ This key may have any value from 0 to 100 inclusive, value is supposed to be
+ an ``int`` or ``float`` instance.
+
+ No error occurs if segment has this key, but no used highlight groups use
+ gradient color.
+
+``_*``
+ Keys starting with underscore are reserved for powerline and must not be
+ returned.
+
+``__*``
+ Keys starting with two underscores are reserved for the segment functions,
+ specifically for :ref:`expand function <dev-segments-expand>`.
+
+.. _dev-segments-segment:
+
+Segment dictionary
+==================
+
+Segment dictionary contains the following keys:
+
+* All keys returned by segment function (if it was used).
+
+* All of the following keys:
+
+ ``name``
+ Segment name: value of the :ref:`name key <config-themes-seg-name>` or
+ function name (last component of the :ref:`function key
+ <config-themes-seg-function>`). May be ``None``.
+
+ ``type``
+ :ref:`Segment type <config-themes-seg-type>`. Always represents actual type
+ and is never ``None``.
+
+ ``highlight_groups``, ``divider_highlight_group``
+ Used highlight groups. May be ``None``.
+
+ ``highlight_group_prefix``
+ If this key is present then given prefix will be prepended to each highlight
+ group (both regular and divider) used by this segment in a form
+ ``{prefix}:{group}`` (note the colon). This key is mostly useful for
+ :ref:`segment listers <dev-listers>`.
+
+ .. _dev-segments-seg-around:
+
+ ``before``, ``after``
+ Value of :ref:`before <config-themes-seg-before>` or :ref:`after
+ <config-themes-seg-after>` configuration options. May be ``None`` as well as
+ an empty string.
+
+ ``contents_func``
+ Function used to get segment contents. May be ``None``.
+
+ .. _dev-segments-seg-contents:
+
+ ``contents``
+ Actual segment contents, excluding dividers and :ref:`before/after
+ <dev-segments-seg-around>`. May be ``None``.
+
+ ``priority``
+ :ref:`Segment priority <config-themes-seg-priority>`. May be ``None`` for no
+ priority (such segments are always shown).
+
+ ``draw_soft_divider``, ``draw_hard_divider``, ``draw_inner_divider``
+ :ref:`Divider control flags <dev-segments-draw_inner_divider>`.
+
+ ``side``
+ Segment side: ``right`` or ``left``.
+
+ ``display_condition``
+ Contains function that takes three position parameters:
+ :py:class:`powerline.PowerlineLogger` instance, :ref:`segment_info
+ <dev-segments-info>` dictionary and current mode and returns either ``True``
+ or ``False`` to indicate whether particular segment should be processed.
+
+ This key is constructed based on :ref:`exclude_/include_modes keys
+ <config-themes-seg-exclude_modes>` and :ref:`exclude_/include_function keys
+ <config-themes-seg-exclude_function>`.
+
+ ``width``, ``align``
+ :ref:`Width and align options <config-themes-seg-align>`. May be ``None``.
+
+ ``expand``, ``truncate``
+ Partially applied :ref:`expand <dev-segments-expand>` or :ref:`truncate
+ <dev-segments-truncate>` function. Accepts ``pl``, ``amount`` and
+ ``segment`` positional parameters, keyword parameters from :ref:`args
+ <config-themes-seg-args>` key were applied.
+
+ ``startup``
+ Partially applied :ref:`startup function <dev-segments-startup>`. Accepts
+ ``pl`` and ``shutdown_event`` positional parameters, keyword parameters from
+ :ref:`args <config-themes-seg-args>` key were applied.
+
+ ``shutdown``
+ :ref:`Shutdown function <dev-segments-shutdown>`. Accepts no argument.
+
+Segments layout
+===============
+
+Powerline segments are all located in one of the ``powerline.segments``
+submodules. For extension-specific segments ``powerline.segments.{ext}`` module
+should be used (e.g. ``powerline.segments.shell``), for extension-agnostic there
+is ``powerline.segments.common``.
+
+Plugin-specific segments (currently only those that are specific to vim plugins)
+should live in ``powerline.segments.{ext}.plugin.{plugin_name}``: e.g.
+``powerline.segments.vim.plugin.gundo``.
+
+.. _dev-segments-info:
+
+Segment information used in various extensions
+==============================================
+
+Each ``segment_info`` value should be a dictionary with at least the following
+keys:
+
+``environ``
+ Current environment, may be an alias to ``os.environ``. Is guaranteed to
+ have ``__getitem__`` and ``get`` methods and nothing more.
+
+ .. warning::
+ ``os.environ`` must not ever be used:
+
+ * If segment is run in the daemon this way it will get daemon’s
+ environment which is not correct.
+ * If segment is run in Vim or in zsh with libzpython ``os.environ`` will
+ contain Vim or zsh environ *at the moment Python interpreter was
+ loaded*.
+
+``getcwd``
+ Function that returns current working directory being called with no
+ arguments. ``os.getcwd`` must not be used for the same reasons the use of
+ ``os.environ`` is forbidden, except that current working directory is valid
+ in Vim and zsh (but not in daemon).
+
+``home``
+ Current home directory. May be false.
+
+.. _dev-segment_info-vim:
+
+Vim
+---
+
+Vim ``segment_info`` argument is a dictionary with the following keys:
+
+``window``
+ ``vim.Window`` object. ``vim.current.window`` or ``vim.windows[number - 1]``
+ may be used to obtain such object. May be a false object, in which case any
+ of this object’s properties must not be used.
+
+``winnr``
+ Window number. Same as ``segment_info['window'].number`` *assuming* Vim is
+ new enough for ``vim.Window`` object to have ``number`` attribute.
+
+``window_id``
+ Internal powerline window id, unique for each newly created window. It is
+ safe to assume that this ID is hashable and supports equality comparison,
+ but no other assumptions about it should be used. Currently uses integer
+ numbers incremented each time window is created.
+
+``buffer``
+ ``vim.Buffer`` object. One may be obtained using ``vim.current.buffer``,
+ ``segment_info['window'].buffer`` or ``vim.buffers[some_number]``. Note that
+ in the latter case depending on vim version ``some_number`` may be ``bufnr``
+ or the internal Vim buffer index which is *not* buffer number. For this
+ reason to get ``vim.Buffer`` object other then stored in ``segment_info``
+ dictionary iteration over ``vim.buffers`` and checking their ``number``
+ attributes should be performed.
+
+``bufnr``
+ Buffer number.
+
+``tabpage``
+ ``vim.Tabpage`` object. One may be obtained using ``vim.current.tabpage`` or
+ ``vim.tabpages[number - 1]``. May be a false object, in which case no
+ object’s properties can be used.
+
+``tabnr``
+ Tabpage number.
+
+``mode``
+ Current mode.
+
+``encoding``
+ Value of ``&encoding`` from the time when powerline was initialized. It
+ should be used to convert return values.
+
+.. note::
+ Segment generally should not assume that it is run for the current window,
+ current buffer or current tabpage. “Current window” and “current buffer”
+ restrictions may be ignored if ``window_cached`` decorator is used, “current
+ tabpage” restriction may be safely ignored if segment is not supposed to be
+ used in tabline.
+
+.. warning::
+ Powerline is being tested with vim-7.0.112 (some minor sanity check) and
+ latest Vim. This means that most of the functionality like
+ ``vim.Window.number``, ``vim.*.vars``, ``vim.*.options`` or even ``dir(vim
+ object)`` should be avoided in segments that want to be included in the
+ upstream.
+
+Shell
+-----
+
+``args``
+ Parsed shell arguments: a ``argparse.Namespace`` object. Check out
+ ``powerline-render --help`` for the list of all available arguments.
+ Currently it is expected to contain at least the following attributes:
+
+ ``last_exit_code``
+ Exit code returned by last shell command. Is either one integer,
+ ``sig{name}`` or ``sig{name}+core`` (latter two are only seen in ``rc``
+ shell).
+
+ ``last_pipe_status``
+ List of exit codes returned by last programs in the pipe or some false
+ object. Only available in ``zsh`` and ``rc``. Is a list of either
+ integers, ``sig{name}`` or ``sig{name}+core`` (latter two are only seen
+ in ``rc`` shell).
+
+ ``jobnum``
+ Number of background jobs.
+
+ ``renderer_arg``
+ Dictionary containing some keys that are additional arguments used by
+ shell bindings. *This attribute must not be used directly*: all
+ arguments from this dictionary are merged with ``segment_info``
+ dictionary. Known to have at least the following keys:
+
+ ``client_id``
+ Identifier unique to one shell instance. Is used to record instance
+ state by powerline daemon. In tmux this is the same as :ref:`pane_id
+ <dev-seginfo-shell-renarg-pane_id>`.
+
+ It is not guaranteed that existing client ID will not be retaken
+ when old shell with this ID quit: usually process PID is used as
+ a client ID.
+
+ It is also not guaranteed that client ID will be process PID, number
+ or something else at all. It is guaranteed though that client ID
+ will be some hashable object which supports equality comparison.
+
+ ``local_theme``
+ Local theme that will be used by shell. One should not rely on the
+ existence of this key.
+
+ .. _dev-seginfo-shell-renarg-pane_id:
+
+ ``pane_id``
+ Identifier unique to each tmux pane. Is always an integer, optional.
+ Obtained by using ``tmux display -p '#D'``, then all leading spaces
+ and per cent signs are stripped and the result is converted into an
+ integer.
+
+ Other keys, if any, are specific to segments.
+
+Ipython
+-------
+
+``ipython``
+ Some object which has ``prompt_count`` attribute. Currently it is guaranteed
+ to have only this attribute.
+
+ Attribute ``prompt_count`` contains the so-called “history count”
+ (equivalent to ``\N`` in ``in_template``).
+
+Pdb
+---
+
+``pdb``
+ Currently active :py:class:`pdb.Pdb` instance.
+
+``curframe``
+ Frame which will be run next. Note: due to the existence of
+ :py:func:`powerline.listers.pdb.frame_lister` one must not use
+ ``segment_info['pdb'].curframe``.
+
+``initial_stack_length``
+ Equal to the length of :py:attr:`pdb.Pdb.stack` at the first invocation of
+ the prompt decremented by one.
+
+i3wm
+----
+
+``mode``
+ Currently active i3 mode (as a string).
+
+``output``
+ ``xrandr`` output name currently drawing to. Currently only available
+ in lemonbar bindings.
+
+``workspace``
+ dictionary containing the workspace name under the key ``"name"`` and
+ boolean values for the ``"visible"``, ``"urgent"`` and ``"focused"``
+ keys, indicating the state of the workspace. Currently only provided by
+ the :py:func:`powerline.listers.i3wm.workspace_lister` lister.
+
+Segment class
+=============
+
+.. autoclass:: powerline.segments.Segment
+ :members:
+
+PowerlineLogger class
+=====================
+
+.. autoclass:: powerline.PowerlineLogger
+ :members:
+ :undoc-members:
diff --git a/docs/source/develop/tips-and-tricks.rst b/docs/source/develop/tips-and-tricks.rst
new file mode 100644
index 0000000..c850659
--- /dev/null
+++ b/docs/source/develop/tips-and-tricks.rst
@@ -0,0 +1,21 @@
+****************************************
+Tips and tricks for powerline developers
+****************************************
+
+Profiling powerline in Vim
+==========================
+
+Given that current directory is the root of the powerline repository the
+following command may be used:
+
+.. code-block:: sh
+
+ vim --cmd 'let g:powerline_pyeval="powerline#debug#profile_pyeval"' \
+ --cmd 'set rtp=powerline/bindings/vim' \
+ -c 'runtime! plugin/powerline.vim' \
+ {other arguments if needed}
+
+After some time run ``:WriteProfiling {filename}`` Vim command. Currently this
+only works with recent Vim and python-2*. It should be easy to modify
+:file:`powerline/bindings/vim/autoload/powerline/debug.vim` to suit other
+needs.
diff --git a/docs/source/index.rst b/docs/source/index.rst
new file mode 100644
index 0000000..9a4d84b
--- /dev/null
+++ b/docs/source/index.rst
@@ -0,0 +1,28 @@
+*********
+Powerline
+*********
+
+.. toctree::
+ :maxdepth: 3
+ :glob:
+
+ overview
+ installation
+ usage
+ configuration
+ develop
+ troubleshooting
+ tips-and-tricks
+ license-and-credits
+
+.. toctree::
+ :maxdepth: 2
+
+ commands
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
diff --git a/docs/source/installation.rst b/docs/source/installation.rst
new file mode 100644
index 0000000..eb40ed0
--- /dev/null
+++ b/docs/source/installation.rst
@@ -0,0 +1,132 @@
+************
+Installation
+************
+
+Generic requirements
+====================
+
+* Python 2.6 or later, 3.2 or later, PyPy 2.0 or later, PyPy3 2.3 or later. It
+ is the only non-optional requirement.
+
+ .. warning:
+ It is highly advised to use UCS-4 version of Python because UCS-2 version
+ uses significantly slower text processing (length determination and
+ non-printable character replacement) functions due to the need of
+ supporting unicode characters above U+FFFF which are represented as
+ surrogate pairs. This price will be paid even if configuration has no such
+ characters.
+
+* C compiler. Required to build powerline client on linux. If it is not present
+ then powerline will fall back to shell script or python client.
+* ``socat`` program. Required for shell variant of client which runs a bit
+ faster than python version of the client, but still slower than C version.
+* ``psutil`` python package. Required for some segments like cpu_percent. Some
+ segments have linux-only fallbacks for ``psutil`` functionality.
+* ``hglib`` python package *and* mercurial executable. Required to work with
+ mercurial repositories.
+* ``pygit2`` python package or ``git`` executable. Required to work with ``git``
+ repositories.
+* ``bzr`` python package (note: *not* standalone executable). Required to work
+ with bazaar repositories.
+* ``pyuv`` python package. Required for :ref:`libuv-based watcher
+ <config-common-watcher>` to work.
+* ``i3ipc`` python package. Required for i3wm bindings and segments.
+* ``xrandr`` program. Required for the multi-monitor lemonbar binding and the
+ :py:func:`powerline.listers.i3wm.output_lister`.
+
+.. note::
+ Until bazaar supports Python-3 or PyPy powerline will not support
+ repository information when running in these interpreters.
+
+.. _repository-root:
+
+.. note::
+ When using ``pip``, the ``{repository_root}`` directory referenced in
+ documentation may be found using ``pip show powerline-status``. In the output
+ of ``pip show`` there is a line like ``Location: {path}``, that ``{path}`` is
+ ``{repository_root}``. Unless it is ``--editable`` installation this is only
+ applicable for ``{repository_root}/powerline/…`` paths: something like
+ ``{repository_root}/scripts/powerline-render`` is not present.
+
+ When using other packages referenced paths may not exist, in this case refer
+ to package documentation.
+
+Pip installation
+================
+
+Due to a naming conflict with an unrelated project powerline is available on
+PyPI under the ``powerline-status`` name:
+
+.. code-block:: sh
+
+ pip install powerline-status
+
+is the preferred method because this will get the latest release. To get current
+development version
+
+.. code-block:: sh
+
+ pip install --user git+git://github.com/powerline/powerline
+
+may be used. If powerline was already checked out into some directory
+
+.. code-block:: sh
+
+ pip install --user --editable={path_to_powerline}
+
+is useful, but note that in this case ``pip`` will not install ``powerline``
+executable and something like
+
+.. code-block:: sh
+
+ ln -s {path_to_powerline}/scripts/powerline ~/.local/bin
+
+will have to be done (:file:`~/.local/bin` should be replaced with some path
+present in ``$PATH``).
+
+.. note::
+ If ISP blocks git protocol for some reason github also provides ``ssh``
+ (``git+ssh://git@github.com/powerline/powerline``) and ``https``
+ (``git+https://github.com/powerline/powerline``) protocols. ``git`` protocol
+ should be the fastest, but least secure one though.
+
+Fonts installation
+==================
+
+Powerline uses several special glyphs to get the arrow effect and some custom
+symbols for developers. This requires having either a symbol font or a patched
+font installed in the system. The used application (e.g. terminal emulator) must
+also either be configured to use patched fonts (in some cases even support it
+because custom glyphs live in private use area which some applications reserve
+for themselves) or support fontconfig for powerline to work properly with
+powerline-specific glyphs.
+
+:ref:`24-bit color support <config-common-term_truecolor>` may be enabled if
+used terminal emulator supports it (see :ref:`the terminal emulator support
+matrix <usage-terminal-emulators>`).
+
+There are basically two ways to get powerline glyphs displayed: use
+:file:`PowerlineSymbols.otf` font as a fallback for one of the existing fonts or
+install a patched font.
+
+.. _installation-patched-fonts:
+
+Patched fonts
+-------------
+
+This method is the fallback method and works for every terminal.
+
+Download the font from `powerline-fonts`_. If preferred font can’t be found in
+the `powerline-fonts`_ repo, then patching the preferred font is needed instead.
+
+.. _powerline-fonts: https://github.com/powerline/fonts
+
+After downloading this font refer to platform-specific instructions.
+
+Installation on various platforms
+=================================
+
+.. toctree::
+
+ Linux <installation/linux>
+ OS X <installation/osx>
diff --git a/docs/source/installation/linux.rst b/docs/source/installation/linux.rst
new file mode 100644
index 0000000..15ec606
--- /dev/null
+++ b/docs/source/installation/linux.rst
@@ -0,0 +1,110 @@
+*********************
+Installation on Linux
+*********************
+
+The following distribution-specific packages are officially supported, and they
+provide an easy way of installing and upgrading Powerline. The packages will
+automatically do most of the configuration.
+
+* `Arch Linux (AUR), Python 2 version <https://aur.archlinux.org/packages/python2-powerline-git/>`_
+* `Arch Linux (AUR), Python 3 version <https://aur.archlinux.org/packages/python-powerline-git/>`_
+* Gentoo Live ebuild in `raiagent <https://github.com/leycec/raiagent>`_ overlay
+* Powerline package is available for Debian starting from Wheezy (via `backports
+ <https://packages.debian.org/wheezy-backports/powerline>`_). Use `search
+ <https://packages.debian.org/search?keywords=powerline&searchon=names&suite=all&section=all>`_
+ to get more information.
+
+If used distribution does not have an official package installation guide below
+should be followed:
+
+1. Install Python 3.2+, Python 2.6+ or PyPy and ``pip`` with ``setuptools``.
+ This step is distribution-specific, so no commands provided.
+2. Install Powerline using one of the following commands:
+
+ .. code-block:: sh
+
+ pip install --user powerline-status
+
+ will get the latest release version and
+
+ .. code-block:: sh
+
+ pip install --user git+git://github.com/powerline/powerline
+
+ will get the latest development version.
+
+ .. note:: Due to the naming conflict with an unrelated project powerline is
+ named ``powerline-status`` in PyPI.
+
+ .. note::
+ Powerline developers should be aware that``pip install --editable`` does
+ not currently fully work. Installation performed this way are missing
+ ``powerline`` executable that needs to be symlinked. It will be located in
+ ``scripts/powerline``.
+
+Fonts installation
+==================
+
+Fontconfig
+----------
+
+This method only works on Linux. It’s the second recommended method if terminal
+emulator supports it as patching fonts is not needed, and it generally works
+with any coding font.
+
+#. Download the latest version of the symbol font and fontconfig file::
+
+ wget https://github.com/powerline/powerline/raw/develop/font/PowerlineSymbols.otf
+ wget https://github.com/powerline/powerline/raw/develop/font/10-powerline-symbols.conf
+
+#. Move the symbol font to a valid X font path. Valid font paths can be
+ listed with ``xset q``::
+
+ mv PowerlineSymbols.otf ~/.local/share/fonts/
+
+#. Update font cache for the path the font was moved to (root priveleges may be
+ needed to update cache for the system-wide paths)::
+
+ fc-cache -vf ~/.local/share/fonts/
+
+#. Install the fontconfig file. For newer versions of fontconfig the config
+ path is ``~/.config/fontconfig/conf.d/``, for older versions it’s
+ ``~/.fonts.conf.d/``::
+
+ mv 10-powerline-symbols.conf ~/.config/fontconfig/conf.d/
+
+If custom symbols still cannot be seen then try closing all instances of the
+terminal emulator. Restarting X may be needed for the changes to take effect.
+
+If custom symbols *still* can’t be seen, double-check that the font have been
+installed to a valid X font path, and that the fontconfig file was installed to
+a valid fontconfig path. Alternatively try to install a :ref:`patched font
+<installation-patched-fonts>`.
+
+Patched font installation
+-------------------------
+
+This is the preferred method, but it is not always available because not all
+fonts were patched and not all fonts *can* be patched due to licensing issues.
+
+After downloading font the following should be done:
+
+#. Move the patched font to a valid X font path. Valid font paths can be
+ listed with ``xset q``::
+
+ mv 'SomeFont for Powerline.otf' ~/.local/share/fonts/
+
+#. Update font cache for the path the font was moved to (root privileges may be
+ needed for updating font cache for some paths)::
+
+ fc-cache -vf ~/.local/share/fonts/
+
+After installing patched font terminal emulator, GVim or whatever application
+powerline should work with must be configured to use the patched font. The
+correct font usually ends with *for Powerline*.
+
+If custom symbols cannot be seen then try closing all instances of the terminal
+emulator. X server may need to be restarted for the changes to take effect.
+
+If custom symbols *still* can’t be seen then double-check that the font have
+been installed to a valid X font path.
diff --git a/docs/source/installation/osx.rst b/docs/source/installation/osx.rst
new file mode 100644
index 0000000..e520348
--- /dev/null
+++ b/docs/source/installation/osx.rst
@@ -0,0 +1,67 @@
+********************
+Installation on OS X
+********************
+
+Python package
+==============
+
+1. Install a proper Python version (see `issue #39
+ <https://github.com/powerline/powerline/issues/39>`_ for a discussion
+ regarding the required Python version on OS X)::
+
+ sudo port select python python27-apple
+
+ Homebrew may be used here::
+
+ brew install python
+
+ .. note::
+ In case :file:`powerline.sh` as a client ``socat`` and ``coreutils`` need
+ to be installed. ``coreutils`` may be installed using ``brew install
+ coreutils``.
+
+2. Install Powerline using one of the following commands:
+
+ .. code-block:: sh
+
+ pip install --user powerline-status
+
+ will get current release version and
+
+ .. code-block:: sh
+
+ pip install --user git+git://github.com/powerline/powerline
+
+ will get latest development version.
+
+ .. warning::
+ When using ``brew install`` to install Python one must not supply
+ ``--user`` flag to ``pip``.
+
+ .. note::
+ Due to the naming conflict with an unrelated project powerline is named
+ ``powerline-status`` in PyPI.
+
+ .. note::
+ Powerline developers should be aware that ``pip install --editable`` does
+ not currently fully work. Installation performed this way are missing
+ ``powerline`` executable that needs to be symlinked. It will be located in
+ ``scripts/powerline``.
+
+Vim installation
+================
+
+Any terminal vim version with Python 3.2+ or Python 2.6+ support should work,
+but MacVim users need to install it using the following command::
+
+ brew install macvim --env-std --with-override-system-vim
+
+Fonts installation
+==================
+
+To install patched font double-click the font file in Finder, then click
+:guilabel:`Install this font` in the preview window.
+
+After installing the patched font MacVim or terminal emulator (whatever
+application powerline should work with) need to be configured to use the patched
+font. The correct font usually ends with *for Powerline*.
diff --git a/docs/source/license-and-credits.rst b/docs/source/license-and-credits.rst
new file mode 100644
index 0000000..5226669
--- /dev/null
+++ b/docs/source/license-and-credits.rst
@@ -0,0 +1,31 @@
+*******************
+License and credits
+*******************
+
+Powerline is licensed under the `MIT license
+<https://raw.github.com/powerline/powerline/develop/LICENSE>`_.
+
+..
+ This document is parsed by powerline_automan.py module. Do not forget to
+ check that file before altering this one. Specifically it expects
+ ``Authors`` and ``Contributors`` sections underlined by ``---``, a list of
+ authors in format ``* `{name} <`` in the “Authors” section and fonts
+ contributor name in format ``The glyphs in the font patcher are created by
+ {name},`` in the “Contributors” section.
+
+Authors
+-------
+
+* `Kim Silkebækken <https://github.com/Lokaltog>`_
+* `Nikolay Pavlov <https://github.com/ZyX-I>`_
+* `Kovid Goyal <https://github.com/kovidgoyal>`_
+
+Contributors
+------------
+
+* `List of contributors
+ <https://github.com/powerline/powerline/contributors>`_
+* The glyphs in the font patcher are created by Fabrizio Schiavi, creator of
+ the excellent coding font `Pragmata Pro`_.
+
+.. _`Pragmata Pro`: http://www.fsd.it/fonts/pragmatapro.htm
diff --git a/docs/source/overview.rst b/docs/source/overview.rst
new file mode 100644
index 0000000..e943b04
--- /dev/null
+++ b/docs/source/overview.rst
@@ -0,0 +1,67 @@
+********
+Overview
+********
+
+**Powerline is a statusline plugin for vim, and provides statuslines and
+prompts for several other applications, including zsh, bash, tmux, IPython,
+Awesome, i3 and Qtile.**
+
+Features
+--------
+
+* **Extensible and feature rich, written in Python.** Powerline was
+ completely rewritten in Python to get rid of as much vimscript as
+ possible. This has allowed much better extensibility, leaner and better
+ config files, and a structured, object-oriented codebase with no mandatory
+ third-party dependencies other than a Python interpreter.
+* **Stable and testable code base.** Using Python has allowed unit testing
+ of all the project code. The code is tested to work in Python 2.6+ and
+ Python 3.
+* **Support for prompts and statuslines in many applications.** Originally
+ created exclusively for vim statuslines, the project has evolved to
+ provide statuslines in tmux and several WMs, and prompts for shells like
+ bash/zsh and other applications. It’s simple to write renderers for any
+ other applications that Powerline doesn’t yet support.
+* **Configuration and colorschemes written in JSON.** JSON is
+ a standardized, simple and easy to use file format that allows for easy
+ user configuration across all of Powerline’s supported applications.
+* **Fast and lightweight, with daemon support for even better performance.**
+ Although the code base spans a couple of thousand lines of code with no
+ goal of “less than X lines of code”, the main focus is on good performance
+ and as little code as possible while still providing a rich set of
+ features. The new daemon also ensures that only one Python instance is
+ launched for prompts and statuslines, which provides excellent
+ performance.
+
+*But I hate Python / I don’t need shell prompts / this is just too much
+hassle for me / what happened to the original vim-powerline project / …*
+
+You should check out some of the Powerline derivatives. The most lightweight
+and feature-rich alternative is currently Bailey Ling’s `vim-airline
+<https://github.com/bling/vim-airline>`_ project.
+
+Screenshots
+-----------
+
+Vim statusline
+^^^^^^^^^^^^^^
+
+**Mode-dependent highlighting**
+
+* .. image:: _static/img/pl-mode-normal.png
+ :alt: Normal mode
+* .. image:: _static/img/pl-mode-insert.png
+ :alt: Insert mode
+* .. image:: _static/img/pl-mode-visual.png
+ :alt: Visual mode
+* .. image:: _static/img/pl-mode-replace.png
+ :alt: Replace mode
+
+**Automatic truncation of segments in small windows**
+
+* .. image:: _static/img/pl-truncate1.png
+ :alt: Truncation illustration
+* .. image:: _static/img/pl-truncate2.png
+ :alt: Truncation illustration
+* .. image:: _static/img/pl-truncate3.png
+ :alt: Truncation illustration
diff --git a/docs/source/powerline_autodoc.py b/docs/source/powerline_autodoc.py
new file mode 100644
index 0000000..eba42ed
--- /dev/null
+++ b/docs/source/powerline_autodoc.py
@@ -0,0 +1,64 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import os
+
+from inspect import formatargspec
+
+from sphinx.ext import autodoc
+
+from powerline.lint.inspect import getconfigargspec
+from powerline.segments import Segment
+from powerline.lib.unicode import unicode
+
+
+def formatvalue(val):
+ if type(val) is str:
+ return '="' + unicode(val, 'utf-8').replace('"', '\\"').replace('\\', '\\\\') + '"'
+ else:
+ return '=' + repr(val)
+
+
+class ThreadedDocumenter(autodoc.FunctionDocumenter):
+ '''Specialized documenter subclass for ThreadedSegment subclasses.'''
+ @classmethod
+ def can_document_member(cls, member, membername, isattr, parent):
+ return (isinstance(member, Segment) or
+ super(ThreadedDocumenter, cls).can_document_member(member, membername, isattr, parent))
+
+ def format_args(self):
+ argspec = getconfigargspec(self.object)
+ return formatargspec(*argspec, formatvalue=formatvalue).replace('\\', '\\\\')
+
+
+class Repr(object):
+ def __init__(self, repr_contents):
+ self.repr_contents = repr_contents
+
+ def __repr__(self):
+ return '<{0}>'.format(self.repr_contents)
+
+
+class EnvironDocumenter(autodoc.AttributeDocumenter):
+ @classmethod
+ def can_document_member(cls, member, membername, isattr, parent):
+ if type(member) is dict and member.get('environ') is os.environ:
+ return True
+ else:
+ return False
+
+ def import_object(self, *args, **kwargs):
+ ret = super(EnvironDocumenter, self).import_object(*args, **kwargs)
+ if not ret:
+ return ret
+ self.object = self.object.copy()
+ if 'home' in self.object:
+ self.object.update(home=Repr('home directory'))
+ self.object.update(environ=Repr('environ dictionary'))
+ return True
+
+
+def setup(app):
+ autodoc.setup(app)
+ app.add_autodocumenter(ThreadedDocumenter)
+ app.add_autodocumenter(EnvironDocumenter)
diff --git a/docs/source/powerline_automan.py b/docs/source/powerline_automan.py
new file mode 100644
index 0000000..85d241c
--- /dev/null
+++ b/docs/source/powerline_automan.py
@@ -0,0 +1,408 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import os
+import re
+import codecs
+
+from collections import namedtuple
+from argparse import REMAINDER
+
+from functools import reduce
+
+from docutils.parsers.rst import Directive
+from docutils.parsers.rst.directives import unchanged_required
+from docutils import nodes
+
+from powerline.lib.unicode import u
+
+
+AUTHOR_LINE_START = '* `'
+GLYPHS_AUTHOR_LINE_START = '* The glyphs in the font patcher are created by '
+
+
+def get_authors():
+ credits_file = os.path.join(os.path.dirname(__file__), 'license-and-credits.rst')
+ authors = []
+ glyphs_author = None
+ with codecs.open(credits_file, encoding='utf-8') as CF:
+ section = None
+ prev_line = None
+ for line in CF:
+ line = line[:-1]
+ if line and not line.replace('-', ''):
+ section = prev_line
+ elif section == 'Authors':
+ if line.startswith(AUTHOR_LINE_START):
+ authors.append(line[len(AUTHOR_LINE_START):line.index('<')].strip())
+ elif section == 'Contributors':
+ if line.startswith(GLYPHS_AUTHOR_LINE_START):
+ assert(not glyphs_author)
+ glyphs_author = line[len(GLYPHS_AUTHOR_LINE_START):line.index(',')].strip()
+ prev_line = line
+ return {
+ 'authors': ', '.join(authors),
+ 'glyphs_author': glyphs_author,
+ }
+
+
+class AutoManSubparsers(object):
+ def __init__(self):
+ self.parsers = []
+
+ def add_parser(self, command, *args, **kwargs):
+ self.parsers.append((command, AutoManParser(*args, **kwargs)))
+ return self.parsers[-1][1]
+
+
+Argument = namedtuple('Argument', ('names', 'help', 'choices', 'metavar', 'required', 'nargs', 'is_option', 'is_long_option', 'is_short_option', 'multi', 'can_be_joined'))
+
+
+def parse_argument(*args, **kwargs):
+ is_option = args[0].startswith('-')
+ is_long_option = args[0].startswith('--')
+ is_short_option = is_option and not is_long_option
+ action = kwargs.get('action', 'store')
+ multi = kwargs.get('action') in ('append',) or kwargs.get('nargs') is REMAINDER
+ nargs = kwargs.get('nargs', (1 if action in ('append', 'store') else 0))
+ return Argument(
+ names=args,
+ help=u(kwargs.get('help', '')),
+ choices=[str(choice) for choice in kwargs.get('choices', [])],
+ metavar=kwargs.get('metavar') or args[-1].lstrip('-').replace('-', '_').upper(),
+ required=kwargs.get('required', False) if is_option else (
+ kwargs.get('nargs') not in ('?',)),
+ nargs=nargs,
+ multi=multi,
+ is_option=is_option,
+ is_long_option=is_long_option,
+ is_short_option=is_short_option,
+ can_be_joined=(is_short_option and not multi and not nargs)
+ )
+
+
+class AutoManGroup(object):
+ is_short_option = False
+ is_option = False
+ is_long_option = False
+ can_be_joined = False
+
+ def __init__(self):
+ self.arguments = []
+ self.required = False
+
+ def add_argument(self, *args, **kwargs):
+ self.arguments.append(parse_argument(*args, **kwargs))
+
+ def add_argument_group(self, *args, **kwargs):
+ self.arguments.append(AutoManGroup())
+ return self.arguments[-1]
+
+
+class SurroundWith():
+ def __init__(self, ret, condition, start='[', end=']'):
+ self.ret = ret
+ self.condition = condition
+ self.start = start
+ self.end = end
+
+ def __enter__(self, *args):
+ if self.condition:
+ self.ret.append(nodes.Text(self.start))
+
+ def __exit__(self, *args):
+ if self.condition:
+ self.ret.append(nodes.Text(self.end))
+
+
+def insert_separators(ret, sep):
+ for i in range(len(ret) - 1, 0, -1):
+ ret.insert(i, nodes.Text(sep))
+ return ret
+
+
+def format_usage_arguments(arguments, base_length=None):
+ line = []
+ prev_argument = None
+ arg_indexes = [0]
+ arguments = arguments[:]
+ while arguments:
+ argument = arguments.pop(0)
+ if isinstance(argument, nodes.Text):
+ line += [argument]
+ continue
+ can_join_arguments = (
+ argument.is_short_option
+ and prev_argument
+ and prev_argument.can_be_joined
+ and prev_argument.required == argument.required
+ )
+ if (
+ prev_argument
+ and not prev_argument.required
+ and prev_argument.can_be_joined
+ and not can_join_arguments
+ ):
+ line.append(nodes.Text(']'))
+ arg_indexes.append(len(line))
+ if isinstance(argument, AutoManGroup):
+ arguments = (
+ [nodes.Text(' (')]
+ + insert_separators(argument.arguments[:], nodes.Text(' |'))
+ + [nodes.Text(' )')]
+ + arguments
+ )
+ else:
+ if not can_join_arguments:
+ line.append(nodes.Text(' '))
+ with SurroundWith(line, not argument.required and not argument.can_be_joined):
+ if argument.can_be_joined and not can_join_arguments and not argument.required:
+ line.append(nodes.Text('['))
+ if argument.is_option:
+ line.append(nodes.strong())
+ name = argument.names[0]
+ if can_join_arguments:
+ name = name[1:]
+ # `--` is automatically transformed into &#8211; (EN DASH)
+ # when parsing into HTML. We do not need this.
+ line[-1] += [nodes.Text(char) for char in name]
+ elif argument.nargs is REMAINDER:
+ line.append(nodes.Text('['))
+ line.append(nodes.strong())
+ line[-1] += [nodes.Text(char) for char in '--']
+ line.append(nodes.Text('] '))
+ if argument.nargs:
+ assert(argument.nargs in (1, '?', REMAINDER))
+ with SurroundWith(
+ line, (
+ True
+ if argument.nargs is REMAINDER
+ else (argument.nargs == '?' and argument.is_option)
+ )
+ ):
+ if argument.is_long_option:
+ line.append(nodes.Text('='))
+ line.append(nodes.emphasis(text=argument.metavar))
+ elif not argument.is_option:
+ line.append(nodes.strong(text=argument.metavar))
+ if argument.multi:
+ line.append(nodes.Text('…'))
+ prev_argument = argument
+ if (
+ prev_argument
+ and prev_argument.can_be_joined
+ and not prev_argument.required
+ ):
+ line.append(nodes.Text(']'))
+ arg_indexes.append(len(line))
+ ret = []
+ if base_length is None:
+ ret = line
+ else:
+ length = base_length
+ prev_arg_idx = arg_indexes.pop(0)
+ while arg_indexes:
+ next_arg_idx = arg_indexes.pop(0)
+ arg_length = sum((len(element.astext()) for element in line[prev_arg_idx:next_arg_idx]))
+ if length + arg_length > 68:
+ ret.append(nodes.Text('\n' + (' ' * base_length)))
+ length = base_length
+ ret += line[prev_arg_idx:next_arg_idx]
+ length += arg_length
+ prev_arg_idx = next_arg_idx
+ return ret
+
+
+LITERAL_RE = re.compile(r"`(.*?)'")
+
+
+def parse_argparse_text(text):
+ rst_text = LITERAL_RE.subn(r'``\1``', text)[0]
+ ret = []
+ for i, text in enumerate(rst_text.split('``')):
+ if i % 2 == 0:
+ ret.append(nodes.Text(text))
+ else:
+ ret.append(nodes.literal(text=text))
+ return ret
+
+
+def flatten_groups(arguments):
+ for argument in arguments:
+ if isinstance(argument, AutoManGroup):
+ for group_argument in flatten_groups(argument.arguments):
+ yield group_argument
+ else:
+ yield argument
+
+
+def format_arguments(arguments):
+ return [nodes.definition_list(
+ '', *[
+ nodes.definition_list_item(
+ '',
+ nodes.term(
+ # node.Text('') is required because otherwise for some
+ # reason first name node is seen in HTML output as
+ # `<strong>abc</strong>`.
+ '', *([nodes.Text('')] + (
+ insert_separators([
+ nodes.strong('', '', *[nodes.Text(ch) for ch in name])
+ for name in argument.names
+ ], ', ')
+ if argument.is_option else
+ # Unless node.Text('') is here metavar is written in
+ # bold in the man page.
+ [nodes.Text(''), nodes.emphasis(text=argument.metavar)]
+ ) + (
+ [] if not argument.is_option or not argument.nargs else
+ [nodes.Text(' '), nodes.emphasis('', argument.metavar)]
+ ))
+ ),
+ nodes.definition('', nodes.paragraph('', *parse_argparse_text(argument.help or ''))),
+ )
+ for argument in flatten_groups(arguments)
+ ] + [
+ nodes.definition_list_item(
+ '',
+ nodes.term(
+ '', nodes.Text(''),
+ nodes.strong(text='-h'),
+ nodes.Text(', '),
+ nodes.strong('', '', nodes.Text('-'), nodes.Text('-help')),
+ ),
+ nodes.definition('', nodes.paragraph('', nodes.Text('Display help and exit.')))
+ )
+ ]
+ )]
+
+
+def format_subcommand_usage(arguments, subcommands, progname, base_length):
+ return reduce((lambda a, b: a + reduce((lambda c, d: c + d), b, [])), [
+ [
+ [progname]
+ + format_usage_arguments(arguments)
+ + [nodes.Text(' '), nodes.strong(text=subcmd)]
+ + format_usage_arguments(subparser.arguments)
+ + [nodes.Text('\n')]
+ for subcmd, subparser in subparsers.parsers
+ ]
+ for subparsers in subcommands
+ ], [])
+
+
+def format_subcommands(subcommands):
+ return reduce((lambda a, b: a + reduce((lambda c, d: c + d), b, [])), [
+ [
+ [
+ nodes.section(
+ '',
+ nodes.title(text='Arguments specific to ' + subcmd + ' subcommand'),
+ *format_arguments(subparser.arguments),
+ ids=['subcmd-' + subcmd]
+ )
+ ]
+ for subcmd, subparser in subparsers.parsers
+ ]
+ for subparsers in subcommands
+ ], [])
+
+
+class AutoManParser(object):
+ def __init__(self, description=None, help=None):
+ self.description = description
+ self.help = help
+ self.arguments = []
+ self.subcommands = []
+
+ def add_argument(self, *args, **kwargs):
+ self.arguments.append(parse_argument(*args, **kwargs))
+
+ def add_subparsers(self):
+ self.subcommands.append(AutoManSubparsers())
+ return self.subcommands[-1]
+
+ def add_mutually_exclusive_group(self):
+ self.arguments.append(AutoManGroup())
+ return self.arguments[-1]
+
+ def automan_usage(self, prog):
+ block = nodes.literal_block()
+ progname = nodes.strong()
+ progname += [nodes.Text(prog)]
+ base_length = len(prog)
+ if self.subcommands:
+ block += format_subcommand_usage(self.arguments, self.subcommands, progname, base_length)
+ else:
+ block += [progname]
+ block += format_usage_arguments(self.arguments, base_length)
+ return [block]
+
+ def automan_description(self):
+ ret = []
+ if self.help:
+ ret += parse_argparse_text(self.help)
+ ret += format_arguments(self.arguments) + format_subcommands(self.subcommands)
+ return ret
+
+
+class AutoMan(Directive):
+ required_arguments = 1
+ optional_arguments = 0
+ option_spec = dict(prog=unchanged_required, minimal=bool)
+ has_content = False
+
+ def run(self):
+ minimal = self.options.get('minimal')
+ module = self.arguments[0]
+ template_args = {}
+ template_args.update(get_authors())
+ get_argparser = __import__(str(module), fromlist=[str('get_argparser')]).get_argparser
+ parser = get_argparser(AutoManParser)
+ if minimal:
+ container = nodes.container()
+ container += parser.automan_usage(self.options['prog'])
+ container += parser.automan_description()
+ return [container]
+ synopsis_section = nodes.section(
+ '',
+ nodes.title(text='Synopsis'),
+ ids=['synopsis-section'],
+ )
+ synopsis_section += parser.automan_usage(self.options['prog'])
+ description_section = nodes.section(
+ '', nodes.title(text='Description'),
+ ids=['description-section'],
+ )
+ description_section += parser.automan_description()
+ author_section = nodes.section(
+ '', nodes.title(text='Author'),
+ nodes.paragraph(
+ '',
+ nodes.Text('Written by {authors} and contributors. The glyphs in the font patcher are created by {glyphs_author}.'.format(
+ **get_authors()
+ ))
+ ),
+ ids=['author-section']
+ )
+ issues_url = 'https://github.com/powerline/powerline/issues'
+ reporting_bugs_section = nodes.section(
+ '', nodes.title(text='Reporting bugs'),
+ nodes.paragraph(
+ '',
+ nodes.Text('Report {prog} bugs to '.format(
+ prog=self.options['prog'])),
+ nodes.reference(
+ issues_url, issues_url,
+ refuri=issues_url,
+ internal=False,
+ ),
+ nodes.Text('.'),
+ ),
+ ids=['reporting-bugs-section']
+ )
+ return [synopsis_section, description_section, author_section, reporting_bugs_section]
+
+
+def setup(app):
+ app.add_directive('automan', AutoMan)
diff --git a/docs/source/tips-and-tricks.rst b/docs/source/tips-and-tricks.rst
new file mode 100644
index 0000000..541b593
--- /dev/null
+++ b/docs/source/tips-and-tricks.rst
@@ -0,0 +1,94 @@
+***************
+Tips and tricks
+***************
+
+Vim
+===
+
+Useful settings
+---------------
+
+You may find the following vim settings useful when using the Powerline
+statusline:
+
+.. code-block:: vim
+
+ set laststatus=2 " Always display the statusline in all windows
+ set showtabline=2 " Always display the tabline, even if there is only one tab
+ set noshowmode " Hide the default mode text (e.g. -- INSERT -- below the statusline)
+
+.. _tips-and-tricks-urxvt:
+
+Rxvt-unicode
+============
+
+Terminus font and urxvt
+-----------------------
+
+The Terminus fonts does not have the powerline glyphs and unless someone submits
+a patch to the font author, it is unlikely to happen. However, Andre Klärner
+came up with this work around: In your ``~/.Xdefault`` file add the following::
+
+ urxvt*font: xft:Terminus:pixelsize=12,xft:Inconsolata\ for\ Powerline:pixelsize=12
+
+This will allow urxvt to fallback onto the Inconsolata fonts in case it does not
+find the right glyphs within the terminus font.
+
+Source Code Pro font and urxvt
+------------------------------
+
+Much like the terminus font that was mentioned above, a similar fix can be
+applied to the Source Code Pro fonts.
+
+In the ``~/.Xdefaults`` add the following::
+
+ URxvt*font: xft:Source\ Code\ Pro\ Medium:pixelsize=13:antialias=true:hinting=true,xft:Source\ Code\ Pro\ Medium:pixelsize=13:antialias=true:hinting=true
+
+I noticed that Source Code Pro has the glyphs there already, but the pixel size
+of the fonts play a role in whether or not the > or the < separators showing up
+or not. Using font size 12, glyphs on the right hand side of the powerline are
+present, but the ones on the left don’t. Pixel size 14, brings the reverse
+problem. Font size 13 seems to work just fine.
+
+Reloading powerline after update
+================================
+
+Once you have updated powerline you generally have the following options:
+
+#. Restart the application you are using it in. This is the safest one. Will not
+ work if the application uses ``powerline-daemon``.
+#. For shell and tmux bindings (except for zsh with libzpython): do not do
+ anything if you do not use ``powerline-daemon``, run ``powerline-daemon
+ --replace`` if you do.
+#. Use powerline reloading feature.
+
+ .. warning::
+ This feature is an unsafe one. It is not guaranteed to work always, it may
+ render your Python constantly error out in place of displaying powerline
+ and sometimes may render your application useless, forcing you to
+ restart.
+
+ *Do not report any bugs occurred when using this feature unless you know
+ both what caused it and how this can be fixed.*
+
+ * When using zsh with libzpython use
+
+ .. code-block:: bash
+
+ powerline-reload
+
+ .. note:: This shell function is only defined when using libzpython.
+
+ * When using IPython use
+
+ ::
+
+ %powerline reload
+
+ * When using Vim use
+
+ .. code-block:: Vim
+
+ py powerline.reload()
+ " or (depending on Python version you are using)
+ py3 powerline.reload()
diff --git a/docs/source/troubleshooting.rst b/docs/source/troubleshooting.rst
new file mode 100644
index 0000000..3599132
--- /dev/null
+++ b/docs/source/troubleshooting.rst
@@ -0,0 +1,329 @@
+***************
+Troubleshooting
+***************
+
+System-specific issues
+======================
+
+.. toctree::
+
+ Linux <troubleshooting/linux>
+ OS X <troubleshooting/osx>
+
+Common issues
+=============
+
+After an update something stopped working
+-----------------------------------------
+
+Assuming powerline was working before update and stopped only after there are
+two possible explanations:
+
+* You have more then one powerline installation (e.g. ``pip`` and ``Vundle``
+ installations) and you have updated only one.
+* Update brought some bug to powerline.
+
+In the second case you, of course, should report the bug to `powerline bug
+tracker <https://github.com/powerline/powerline>`_. In the first you should
+make sure you either have only one powerline installation or you update all of
+them simultaneously (beware that in the second case you are not supported). To
+diagnose this problem you may do the following:
+
+#) If this problem is observed within the shell make sure that
+
+ .. code-block:: sh
+
+ python -c 'import powerline; print (powerline.__file__)'
+
+ which should report something like
+ :file:`/usr/lib64/python2.7/site-packages/powerline/__init__.pyc` (if
+ powerline is installed system-wide) or
+ :file:`/home/USER/.../powerline/__init__.pyc` (if powerline was cloned
+ somewhere, e.g. in :file:`/home/USER/.vim/bundle/powerline`) reports the same
+ location you use to source in your shell configuration: in first case it
+ should be some location in :file:`/usr` (e.g.
+ :file:`/usr/share/zsh/site-contrib/powerline.zsh`), in the second it should
+ be something like
+ :file:`/home/USER/.../powerline/bindings/zsh/powerline.zsh`. If this is true
+ it may be a powerline bug, but if locations do not match you should not
+ report the bug until you observe it on configuration where locations do
+ match.
+#) If this problem is observed specifically within bash make sure that you clean
+ ``$POWERLINE_COMMAND`` and ``$PROMPT_COMMAND`` environment variables on
+ startup or, at least, that it was cleaned after update. While different
+ ``$POWERLINE_COMMAND`` variable should not cause any troubles most of time
+ (and when it will cause troubles are rather trivial) spoiled
+ ``$PROMPT_COMMAND`` may lead to strange error messages or absense of exit
+ code reporting.
+
+ These are the sources which may keep outdated environment variables:
+
+ * Any command launched from any application inherits its environment unless
+ callee explicitly requests to use specific environment. So if you did
+ ``exec bash`` after update it is rather unlikely to fix the problem.
+ * More interesting: `tmux` is a client-server application, it keeps one
+ server instance per one user. You probably already knew that, but there is
+ an interesting consequence: once `tmux` server was started it inherits its
+ environment from the callee and keeps it *forever* (i.e. until server is
+ killed). This environment is then inherited by applications you start with
+ ``tmux new-session``. Easiest solution is to kill tmux with ``tmux
+ kill-server``, but you may also use ``tmux set-environment -u`` to unset
+ offending variables.
+ * Also check `When using z powerline shows wrong number of jobs`_: though
+ this problem should not be seen after update only, it contains another
+ example of ``$PROMPT_COMMAND`` spoiling results.
+
+#) If this problem is observed within the vim instance you should check out the
+ output of the following Ex mode commands
+
+ .. code-block:: vim
+
+ python import powerline as pl ; print (pl.__file__)
+ python3 import powerline as pl ; print (pl.__file__)
+
+ One (but not both) of them will most likely error out, this is OK. The same
+ rules apply as in the 1), but in place of sourcing you should seek for the
+ place where you modify `runtimepath` vim option. If you install powerline
+ using `VAM <https://github.com/MarcWeber/vim-addon-manager>`_ then no
+ explicit modifications of runtimpath were performed in your vimrc
+ (runtimepath is modified by VAM in this case), but powerline will be placed
+ in :file:`{plugin_root_dir}/powerline` where `{plugin_root_dir}` is stored in
+ VAM settings dictionary: do `echo g:vim_addon_manager.plugin_root_dir`.
+
+There is a hint if you want to place powerline repository somewhere, but still
+make powerline package importable anywhere: use
+
+ .. code-block:: sh
+
+ pip install --user --editable path/to/powerline
+
+Tmux/screen-related issues
+==========================
+
+I’m using tmux and Powerline looks like crap, what’s wrong?
+-----------------------------------------------------------
+
+* You need to tell tmux that it has 256-color capabilities. Add this to your
+ :file:`.tmux.conf` to solve this issue::
+
+ set -g default-terminal "screen-256color"
+* If you’re using iTerm2, make sure that you have enabled the setting
+ :guilabel:`Set locale variables automatically` in :menuselection:`Profiles -->
+ Terminal --> Environment`.
+* Make sure tmux knows that terminal it is running in support 256 colors. You
+ may tell it tmux by using ``-2`` option when launching it.
+
+I’m using tmux/screen and Powerline is colorless
+------------------------------------------------
+
+* If the above advices do not help, then you need to disable
+ :ref:`term_truecolor <config-common-term_truecolor>`.
+* Alternative: set :ref:`additional_escapes <config-common-additional_escapes>`
+ to ``"tmux"`` or ``"screen"``. Note that it is known to work perfectly in
+ screen, but in tmux it may produce ugly spaces.
+
+ .. warning::
+ Both tmux and screen are not resending sequences escaped in such a way. Thus
+ even though additional escaping will work for the last shown prompt,
+ highlighting will eventually go away when tmux or screen will redraw screen
+ for some reason.
+
+ E.g. in screen it will go away when you used copy mode and prompt got out of
+ screen and in tmux it will go away immediately after you press ``<Enter>``.
+
+In tmux there is a green bar in place of powerline
+--------------------------------------------------
+
+In order for tmux bindings to work ``powerline-config`` script is required to be
+present in ``$PATH``. Alternatively one may define ``$POWERLINE_CONFIG_COMMAND``
+environment variable pointing to the location of the script. *This variable must
+be defined prior to launching tmux server and in the environment where server is
+started from.*
+
+Shell issues
+============
+
+Pipe status segment displays only last value in bash
+----------------------------------------------------
+
+Make sure that powerline command that sets prompt appears the very first in
+``$PROMPT_COMMAND``. To do this ``powerline.sh`` needs to be sourced the very
+last, after all other users of ``$PROMPT_COMMAND``.
+
+Bash prompt stopped updating
+----------------------------
+
+Make sure that powerline commands appear in ``$PROMPT_COMMAND``: some users of
+``$PROMPT_COMMAND`` have a habit of overwriting the value instead of
+prepending/appending to it. All powerline commands start with ``_powerline`` or
+``powerline``, e.g. ``_powerline_set_prompt``.
+
+Bash prompt does not show last exit code
+----------------------------------------
+
+There are two possibilities here:
+
+* You are using ``default`` theme in place of ``default_leftonly``. Unlike
+ ``default_leftonly`` ``default`` theme was designed for shells with right
+ prompt support (e.g. zsh, tcsh, fish) and status in question is supposed to be
+ shown on the right side which bash cannot display.
+
+* There is some other user of ``$PROMPT_COMMAND`` which prepended to this
+ variable, but did not bother keeping the exit code. For the best experience
+ powerline must appear first in ``$PROMPT_COMMAND`` which may be achieved by
+ sourcing powerline bindings the last.
+
+ .. note::
+ Resourcing bash bindings will not resolve the problem unless you clear
+ powerline commands from ``$PROMPT_COMMAND`` first.
+
+When sourcing shell bindings it complains about missing command or file
+-----------------------------------------------------------------------
+
+If you are using ``pip`` based installation do not forget to add pip-specific
+executable path to ``$PATH`` environment variable. This path usually looks
+something like ``$HOME/.local/bin`` (linux) or
+``$HOME/Library/Python/{python_version}/bin`` (OS X). One may check out where
+``powerline-config`` script was installed by using ``pip show -f
+powerline-status | grep powerline-config`` (does not always work).
+
+I am suffering bad lags before displaying shell prompt
+------------------------------------------------------
+
+To get rid of these lags there currently are two options:
+
+* Run ``powerline-daemon``. Powerline does not automatically start it for you.
+* Compile and install ``libzpython`` module that lives in
+ https://bitbucket.org/ZyX_I/zpython. This variant is zsh-specific.
+
+Prompt is spoiled after completing files in ksh
+-----------------------------------------------
+
+This is exactly why powerline has official mksh support, but not official ksh
+support. If you know the solution feel free to share it in `powerline bug
+tracker`_.
+
+When using z powerline shows wrong number of jobs
+-------------------------------------------------
+
+This happens because `z <https://github.com/rupa/z>`_ is launching some jobs in
+the background from ``$POWERLINE_COMMAND`` and these jobs fail to finish before
+powerline prompt is run.
+
+Solution to this problem is simple: be sure that :file:`z.sh` is sourced
+strictly after :file:`powerline/bindings/bash/powerline.sh`. This way background
+jobs are spawned by `z <https://github.com/rupa/z>`_ after powerline has done
+its job.
+
+When using shell I do not see powerline fancy characters
+--------------------------------------------------------
+
+If your locale encoding is not unicode (any encoding that starts with “utf” or
+“ucs” will work, case is ignored) powerline falls back to ascii-only theme. You
+should set up your system to use unicode locale or forget about powerline fancy
+characters.
+
+Urxvt unicode3 and frills
+-------------------------
+
+Make sure that, whatever urxvt package you're installing, both the `unicode3`
+and `frills` features are enabled at compile time. Run
+``urxvt --help 2>&1 | grep options:`` to get a list of enabled options.
+This should contain at least `frills`, `unicode3` and optionally `iso14755`
+if you want to input Unicode characters as well.
+
+Compiler flags example:
+
+ --enable-frills \
+ --enable-unicode3
+
+As long as your terminal emulator is compiled without unicode rendering,
+no amount of configuration will make it display unicode characters.
+They're being considered 'unnecessary features', but they add negligible
+overhead to the size of the installed package (~100KB).
+
+Vim issues
+==========
+
+My vim statusline has strange characters like ``^B`` in it!
+-----------------------------------------------------------
+
+* Please add ``set encoding=utf-8`` to your :file:`vimrc`.
+
+My vim statusline has a lot of ``^`` or underline characters in it!
+-------------------------------------------------------------------
+
+* You need to configure the ``fillchars`` setting to disable statusline
+ fillchars (see ``:h 'fillchars'`` for details). Add this to your :file:`vimrc`
+ to solve this issue:
+
+ .. code-block:: vim
+
+ set fillchars+=stl:\ ,stlnc:\
+
+My vim statusline is hidden/only appears in split windows!
+----------------------------------------------------------
+
+* Make sure that you have ``set laststatus=2`` in your :file:`vimrc`.
+
+My vim statusline is not displayed completely and has too much spaces
+---------------------------------------------------------------------
+
+* Be sure you have ``ambiwidth`` option set to ``single``.
+* Alternative: set :ref:`ambiwidth <config-common-ambiwidth>` to 2, remove fancy
+ dividers (they suck when ``ambiwidth`` is set to double).
+
+Powerline loses color after editing vimrc
+-----------------------------------------
+
+If your vimrc has something like
+
+.. code-block:: vim
+
+ autocmd! BufWritePost ~/.vimrc :source ~/.vimrc
+
+used to automatically source vimrc after saving it then you must add ``nested``
+after pattern (``vimrc`` in this case):
+
+.. code-block:: vim
+
+ autocmd! BufWritePost ~/.vimrc nested :source ~/.vimrc
+
+. Alternatively move ``:colorscheme`` command out of the vimrc to the file which
+will not be automatically resourced.
+
+Observed problem is that when you use ``:colorscheme`` command existing
+highlighting groups are usually cleared, including those defined by powerline.
+To workaround this issue powerline hooks ``Colorscheme`` event, but when you
+source vimrc with ``BufWritePost`` (or any other) event, but without ``nested``
+this event is not launched. See also `autocmd-nested
+<http://vimcommunity.bitbucket.org/doc/autocmd.txt.html#autocmd-nested>`_ Vim
+documentation.
+
+Powerline loses color after saving any file
+-------------------------------------------
+
+It may be one of the incarnations of the above issue: specifically minibufexpl
+is known to trigger it. If you are using minibufexplorer you should set
+
+.. code-block:: vim
+
+ let g:miniBufExplForceSyntaxEnable = 1
+
+variable so that this issue is not triggered. Complete explanation:
+
+#. When MBE autocommand is executed it launches ``:syntax enable`` Vim command…
+#. … which makes Vim source :file:`syntax/syntax.vim` file …
+#. … which in turn sources :file:`syntax/synload.vim` …
+#. … which executes ``:colorscheme`` command. Normally this command triggers
+ ``Colorscheme`` event, but in the first point minibufexplorer did set up
+ autocommands that miss ``nested`` attribute meaning that no events will be
+ triggered when processing MBE events.
+
+.. note::
+ This setting was introduced in version 6.3.1 of `minibufexpl
+ <http://www.vim.org/scripts/script.php?script_id=159>`_ and removed in
+ version 6.5.0 of its successor `minibufexplorer
+ <http://www.vim.org/scripts/script.php?script_id=3239>`_. It is highly
+ advised to use the latter because `minibufexpl`_ was last updated late in
+ 2004.
diff --git a/docs/source/troubleshooting/linux.rst b/docs/source/troubleshooting/linux.rst
new file mode 100644
index 0000000..e0493c6
--- /dev/null
+++ b/docs/source/troubleshooting/linux.rst
@@ -0,0 +1,78 @@
+************************
+Troubleshooting on Linux
+************************
+
+I can’t see any fancy symbols, what’s wrong?
+--------------------------------------------
+
+* Make sure that you’ve configured gvim or your terminal emulator to use
+ a patched font.
+* You need to set your ``LANG`` and ``LC_*`` environment variables to
+ a UTF-8 locale (e.g. ``LANG=en_US.utf8``). Consult your Linux distro’s
+ documentation for information about setting these variables correctly.
+* Make sure that vim is compiled with the ``--with-features=big`` flag.
+* If you’re using rxvt-unicode make sure that it’s compiled with the
+ ``--enable-unicode3`` flag.
+* If you’re using xterm make sure you have told it to work with unicode. You may
+ need ``-u8`` command-line argument, ``uxterm`` shell wrapper that is usually
+ shipped with xterm for this or ``xterm*utf8`` property set to ``1`` or ``2``
+ in ``~/.Xresources`` (applied with ``xrdb``). Note that in case ``uxterm`` is
+ used configuration is done via ``uxterm*…`` properties and not ``xterm*…``.
+
+ In any case the only absolute requirement is launching xterm with UTF-8
+ locale.
+* If you are using bitmap font make sure that
+ :file:`/etc/fonts/conf.d/70-no-bitmaps.conf` does not exist. If it does check
+ out your distribution documentation to find a proper way to remove it (so that
+ it won’t reappear after update). E.g. in Gentoo this is::
+
+ eselect fontconfig disable 70-no-bitmaps.conf
+
+ (currently this only removes the symlink from :file:`/etc/fonts/conf.d`). Also
+ check out that no other fontconfig file does not have ``rejectfont`` tag that
+ tells fontconfig to disable bitmap fonts (they are referenced as not
+ scalable).
+
+The fancy symbols look a bit blurry or “off”!
+---------------------------------------------
+
+* Make sure that you have patched all variants of your font (i.e. both the
+ regular and the bold font files).
+
+I am seeing strange blocks in place of playing/paused/stopped signs
+-------------------------------------------------------------------
+
+If you are using ``powerline_unicode7`` :ref:`top-level theme
+<config-common-default_top_theme>` then symbols for player segments are taken
+from U+23F4–U+23FA range which is missing from most fonts. You may fix the issue
+by using `Symbola <http://users.teilar.gr/~g1951d/>`_ font (or any other font
+which contains these glyphs).
+
+If your terminal emulator is using fontconfig library then you can create
+a fontconfig configuration file with the following contents:
+
+.. code-block:: xml
+
+ <?xml version="1.0"?>
+ <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+
+ <fontconfig>
+ <alias>
+ <family>Terminus</family>
+ <prefer><family>Symbola</family></prefer>
+ </alias>
+ </fontconfig>
+
+(replace ``Terminus`` with the name of the font you are using). Exact sequence
+of actions you need to perform is different across distributions, most likely it
+will work if you put the above xml into
+:file:`/etc/fonts/conf.d/99-prefer-symbola.conf`. On Gentoo you need to put it
+into :file:`/etc/fonts/conf.d/99-prefer-symbola.conf` and run::
+
+ eselect fontconfig enable 99-prefer-symbola
+
+.
+
+.. warning::
+ This answer is only applicable if you use ``powerline_unicode7`` theme or if
+ you configured powerline to use the same characters yourself.
diff --git a/docs/source/troubleshooting/osx.rst b/docs/source/troubleshooting/osx.rst
new file mode 100644
index 0000000..b61063e
--- /dev/null
+++ b/docs/source/troubleshooting/osx.rst
@@ -0,0 +1,71 @@
+***********************
+Troubleshooting on OS X
+***********************
+
+I can’t see any fancy symbols, what’s wrong?
+--------------------------------------------
+
+* If you’re using iTerm2, please update to `this revision
+ <https://github.com/gnachman/iTerm2/commit/8e3ad6dabf83c60b8cf4a3e3327c596401744af6>`_
+ or newer. Also make sure that Preferences>Profiles>Text>Non-ASCII Font is the same as
+ your main Font.
+* You need to set your ``LANG`` and ``LC_*`` environment variables to
+ a UTF-8 locale (e.g. ``LANG=en_US.utf8``). Consult your Linux distro’s
+ documentation for information about setting these variables correctly.
+
+The colors look weird in the default OS X Terminal app!
+-------------------------------------------------------
+
+* The arrows may have the wrong colors if you have changed the “minimum
+ contrast” slider in the color tab of your OS X settings.
+* The default OS X Terminal app is known to have some issues with the
+ Powerline colors. Please use another terminal emulator. iTerm2 should work
+ fine.
+
+The colors look weird in iTerm2!
+--------------------------------
+
+* The arrows may have the wrong colors if you have changed the “minimum
+ contrast” slider in the color tab of your OS X settings.
+* If you're using transparency, check “Keep background colors opaque”.
+
+Statusline is getting wrapped to the next line in iTerm2
+--------------------------------------------------------
+
+* Turn off “Treat ambigious-width characters as double width” in `Preferences
+ --> Text`.
+* Alternative: remove fancy dividers (they suck in this case), set
+ :ref:`ambiwidth <config-common-ambiwidth>` to 2.
+
+I receive a ``NameError`` when trying to use Powerline with MacVim!
+-------------------------------------------------------------------
+
+* Please install MacVim using this command::
+
+ brew install macvim --env-std --override-system-vim
+
+ Then install Powerline locally with ``pip install --user``, or by
+ running these commands in the ``powerline`` directory::
+
+ ./setup.py build
+ ./setup.py install --user
+
+I receive an ``ImportError`` when trying to use Powerline on OS X!
+------------------------------------------------------------------
+
+* This is caused by an invalid ``sys.path`` when using system vim and system
+ Python. Please try to select another Python distribution::
+
+ sudo port select python python27-apple
+
+* See `issue #39 <https://github.com/powerline/powerline/issues/39>`_ for
+ a discussion and other possible solutions for this issue.
+
+I receive “FSEventStreamStart: register_with_server: ERROR” with status_colors
+------------------------------------------------------------------------------
+
+This is `a known <https://github.com/joyent/node/issues/5463>`_ libuv issue that
+happens if one is trying to watch too many files. It should be fixed in
+libuv-0.12. Until then it is suggested to either disable ``status_colors`` (from
+:py:func:`powerline.segments.common.vcs.branch`) or choose stat-based watcher
+(will have effectively the same effect as disabling ``status_colors``).
diff --git a/docs/source/usage.rst b/docs/source/usage.rst
new file mode 100644
index 0000000..5bfd304
--- /dev/null
+++ b/docs/source/usage.rst
@@ -0,0 +1,88 @@
+*****
+Usage
+*****
+
+Application-specific requirements
+---------------------------------
+
+Vim plugin requirements
+^^^^^^^^^^^^^^^^^^^^^^^
+
+The vim plugin requires a vim version with Python support compiled in. Presence
+of Python support in Vim can be checked by running ``vim --version | grep
++python``.
+
+If Python support is absent then Vim needs to be compiled with it. To do this
+use ``--enable-pythoninterp`` :file:`./configure` flag (Python 3 uses
+``--enable-python3interp`` flag instead). Note that this also requires the
+related Python headers to be installed. Please consult distribution’s
+documentation for details on how to compile and install packages.
+
+Vim version 7.4 or newer is recommended for performance reasons, but Powerline
+supports Vim 7.0.112 and higher.
+
+Shell prompts requirements
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Due to fish having incorrect code for prompt width calculations up to version
+2.1 and no way to tell that certain sequence of characters has no width
+(``%{…%}`` in zsh and ``\[…\]`` in bash prompts serve exactly this purpose)
+users that have fish versions below 2.1 are not supported..
+
+
+WM widgets requirements
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Awesome is supported starting from version 3.5.1, inclusive. QTile is supported
+from version 0.6, inclusive.
+
+.. _usage-terminal-emulators:
+
+Terminal emulator requirements
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Powerline uses several special glyphs to get the arrow effect and some custom
+symbols for developers. This requires either a symbol font or a patched font
+installed. Used terminal emulator must also support either patched fonts or
+fontconfig for Powerline to work properly.
+
+:ref:`24-bit color support <config-common-term_truecolor>` can also be enabled
+if terminal emulator supports it.
+
+.. table:: Application/terminal emulator feature support matrix
+ :name: term-feature-support-matrix
+
+ ===================== ======= ===================== ===================== =====================
+ Name OS Patched font support Fontconfig support 24-bit color support
+ ===================== ======= ===================== ===================== =====================
+ Gvim Linux |i_yes| |i_no| |i_yes|
+ iTerm2 OS X |i_yes| |i_no| |i_no|
+ Konsole Linux |i_yes| |i_yes| |i_yes|
+ lxterminal Linux |i_yes| |i_yes| |i_no|
+ MacVim OS X |i_yes| |i_no| |i_yes|
+ rxvt-unicode Linux |i_partial| [#]_ |i_no| |i_no|
+ st Linux |i_yes| |i_yes| |i_yes| [#]_
+ Terminal.app OS X |i_yes| |i_no| |i_no|
+ libvte-based [#]_ Linux |i_yes| |i_yes| |i_yes| [#]_
+ xterm Linux |i_yes| |i_no| |i_partial| [#]_
+ fbterm Linux |i_yes| |i_yes| |i_no|
+ ===================== ======= ===================== ===================== =====================
+
+.. |i_yes| image:: _static/img/icons/tick.png
+.. |i_no| image:: _static/img/icons/cross.png
+.. |i_partial| image:: _static/img/icons/error.png
+
+.. [#] Must be compiled with ``--enable-unicode3`` for the patched font to work.
+.. [#] Since version 0.5.
+.. [#] Including XFCE terminal and GNOME terminal.
+.. [#] Since version 0.36.
+.. [#] Uses nearest color from 8-bit palette.
+
+Plugins
+-------
+
+.. toctree::
+
+ usage/shell-prompts
+ usage/wm-widgets
+ usage/other
diff --git a/docs/source/usage/other.rst b/docs/source/usage/other.rst
new file mode 100644
index 0000000..d773484
--- /dev/null
+++ b/docs/source/usage/other.rst
@@ -0,0 +1,209 @@
+*************
+Other plugins
+*************
+
+.. _vim-vimrc:
+
+Vim statusline
+==============
+
+If installed using pip just add
+
+.. code-block:: vim
+
+ python from powerline.vim import setup as powerline_setup
+ python powerline_setup()
+ python del powerline_setup
+
+(replace ``python`` with ``python3`` if appropriate) to the :file:`vimrc`.
+
+.. note::
+ Status line will not appear by default when there is only a single window
+ displayed. Run ``:h 'laststatus'`` in Vim for more information.
+
+If the repository was just cloned the following line needs to be added to the
+:file:`vimrc`:
+
+.. code-block:: vim
+
+ set rtp+={repository_root}/powerline/bindings/vim
+
+where ``{repository_root}`` is the absolute path to the Powerline installation
+directory (see :ref:`repository root <repository-root>`).
+
+If pathogen is used and Powerline functionality is not needed outside of Vim
+then it is possible to simply add Powerline as a bundle and point the path above
+to the Powerline bundle directory, e.g.
+:file:`~/.vim/bundle/powerline/powerline/bindings/vim`.
+
+Vundle and NeoBundle users may instead use
+
+.. code-block:: vim
+
+ Bundle 'powerline/powerline', {'rtp': 'powerline/bindings/vim/'}
+
+(NeoBundle users need ``NeoBundle`` in place of ``Bundle``, otherwise setup is
+the same).
+
+Vim-addon-manager setup is even easier because it is not needed to write this
+big path or install anything by hand: ``powerline`` can be installed and
+activated just like any other plugin using
+
+.. code-block:: vim
+
+ call vam#ActivateAddons(['powerline'])
+
+.. warning::
+ *Never* install powerline with pathogen/VAM/Vundle/NeoBundle *and* with pip.
+ If powerline functionality is needed in applications other then Vim then
+ system-wide installation (in case used OS distribution has powerline
+ package), pip-only or ``pip install --editable`` kind of installation
+ performed on the repository installed by Vim plugin manager should be used.
+
+ No issues are accepted in powerline issue tracker for double pip/non-pip
+ installations, especially if these issues occur after update.
+
+.. note::
+ If supplied :file:`powerline.vim` file is used to load powerline there are
+ additional configuration variables available: ``g:powerline_pycmd`` and
+ ``g:powerline_pyeval``. First sets command used to load powerline: expected
+ values are ``"py"`` and ``"py3"``. Second sets function used in statusline,
+ expected values are ``"pyeval"`` and ``"py3eval"``.
+
+ If ``g:powerline_pycmd`` is set to the one of the expected values then
+ ``g:powerline_pyeval`` will be set accordingly. If it is set to some other
+ value then ``g:powerline_pyeval`` must also be set. Powerline will not check
+ that Vim is compiled with Python support if ``g:powerline_pycmd`` is set to
+ an unexpected value.
+
+ These values are to be used to specify the only Python that is to be loaded
+ if both versions are present: Vim may disable loading one python version if
+ other was already loaded. They should also be used if two python versions
+ are able to load simultaneously, but powerline was installed only for
+ python-3 version.
+
+Tmux statusline
+===============
+
+Add the following lines to :file:`.tmux.conf`, where ``{repository_root}`` is
+the absolute path to the Powerline installation directory (see :ref:`repository
+root <repository-root>`)::
+
+ source "{repository_root}/powerline/bindings/tmux/powerline.conf"
+
+.. note::
+ The availability of the ``powerline-config`` command is required for
+ powerline support. The location of this script may be specified via
+ the ``$POWERLINE_CONFIG_COMMAND`` environment variable.
+
+.. note::
+ It is advised to run ``powerline-daemon`` before adding the above line to
+ tmux.conf. To do so add::
+
+ run-shell "powerline-daemon -q"
+
+ to :file:`.tmux.conf`.
+
+.. warning::
+ Segments which depend on current working directory (e.g.
+ :py:func:`powerline.segments.common.vcs.branch`) require also setting up
+ :ref:`shell bindings <usage-shell>`. It is not required to use powerline
+ shell prompt, :ref:`components setting <config-ext-components>` allows to
+ set up only powerline bindings for tmux without altering your prompt.
+ Without setting up shell bindings powerline will use current working
+ directory of *tmux server* which is probably not what you need.
+
+ Segments which depend on environment like
+ :py:func:`powerline.segments.common.env.virtualenv` will not work at all
+ (i.e. they will use environment of the tmux server), tracking environment
+ changes is going to slow down shell a lot.
+
+ In any case it is suggested to avoid both kinds of segments in tmux
+ :ref:`themes <config-themes>` because even support for tracking current
+ directory is very limited:
+
+ #. It works only in shell. Should you e.g. run Vim and run ``:cd`` there you
+ will get current working directory from shell.
+ #. It works only in local shell and requires configuring it.
+ #. Some shells are not supported at all.
+
+IPython prompt
+==============
+
+For IPython<0.11 add the following lines to :file:`.ipython/ipy_user_conf.py`:
+
+.. code-block:: Python
+
+ # top
+ from powerline.bindings.ipython.pre_0_11 import setup as powerline_setup
+
+ # main() function (assuming ipython was launched without configuration to
+ # create skeleton ipy_user_conf.py file):
+ powerline_setup()
+
+For IPython>=0.11 add the following line to
+:file:`~/.ipython/profile_default/ipython_config.py` file in the used profile:
+
+.. code-block:: Python
+
+ c = get_config()
+ c.InteractiveShellApp.extensions = [
+ 'powerline.bindings.ipython.post_0_11'
+ ]
+
+For IPython>=5.0 you may use the above set up, but it is deprecated. It is
+suggested to use
+
+.. code-block:: Python
+
+ from powerline.bindings.ipython.since_5 import PowerlinePrompts
+ c = get_config()
+ c.TerminalInteractiveShell.simple_prompt = False
+ c.TerminalInteractiveShell.prompts_class = PowerlinePrompts
+
+.. note::
+ Setting ``simple_prompt`` to False after IPython-5.0 is required regardless
+ of whether you use ``c.InteractiveShellApp.extensions`` setting or
+ ``c.TerminalInteractiveShell.prompts_class``. But you probably already have
+ this line because IPython is not very useful without it.
+
+IPython=0.11* is not supported and does not work. IPython<0.10 was not
+tested (not installable by pip).
+
+.. _pdb-prompt:
+
+PDB prompt
+==========
+
+To use Powerline with PDB prompt you need to use custom class. Inherit your
+class from :py:class:`pdb.Pdb` and decorate it with
+:py:func:`powerline.bindings.pdb.use_powerline_prompt`:
+
+.. code-block:: Python
+
+ import pdb
+
+ from powerline.bindings.pdb import use_powerline_prompt
+
+ @use_powerline_prompt
+ class MyPdb(pdb.Pdb):
+ pass
+
+ MyPdb.run('some.code.to.debug()')
+
+. Alternatively you may use
+
+.. code-block:: bash
+
+ python -mpowerline.bindings.pdb path/to/script.py
+
+just like you used ``python -m pdb``.
+
+.. note:
+ If you are using Python-2.6 you need to use ``python
+ -mpowerline.bindings.pdb.__main__``, not what is shown above.
+
+.. warning:
+ Using PyPy (not PyPy3) forces ASCII-only prompts. In other cases unicode
+ characters are allowed, even if you use `pdbpp
+ <https://pypi.python.org/pypi/pdbpp>`_.
diff --git a/docs/source/usage/shell-prompts.rst b/docs/source/usage/shell-prompts.rst
new file mode 100644
index 0000000..1ddb0a1
--- /dev/null
+++ b/docs/source/usage/shell-prompts.rst
@@ -0,0 +1,144 @@
+.. _usage-shell:
+
+*************
+Shell prompts
+*************
+
+.. note::
+ Powerline daemon is not run automatically by any of my bindings. It is
+ advised to add
+
+ .. code-block:: bash
+
+ powerline-daemon -q
+
+ before any other powerline-related code in the shell configuration file.
+
+Bash prompt
+===========
+
+Add the following line to the :file:`bashrc`, where ``{repository_root}`` is the
+absolute path to the Powerline installation directory (see :ref:`repository root
+<repository-root>`):
+
+.. code-block:: bash
+
+ . {repository_root}/powerline/bindings/bash/powerline.sh
+
+.. note::
+ Since without powerline daemon bash bindings are very slow PS2
+ (continuation) and PS3 (select) prompts are not set up. Thus it is advised
+ to use
+
+ .. code-block:: bash
+
+ powerline-daemon -q
+ POWERLINE_BASH_CONTINUATION=1
+ POWERLINE_BASH_SELECT=1
+ . {repository_root}/powerline/bindings/bash/powerline.sh
+
+ in the bash configuration file. Without ``POWERLINE_BASH_*`` variables PS2
+ and PS3 prompts are computed exactly once at bash startup.
+
+.. warning::
+ At maximum bash continuation PS2 and select PS3 prompts are computed each
+ time main PS1 prompt is computed. Thus putting e.g. current time into PS2 or
+ PS3 prompt will not work as expected.
+
+ At minimum they are computed once on startup.
+
+Zsh prompt
+==========
+
+Add the following line to the :file:`zshrc`, where ``{repository_root}`` is the
+absolute path to the Powerline installation directory (see :ref:`repository root
+<repository-root>`):
+
+.. code-block:: bash
+
+ . {repository_root}/powerline/bindings/zsh/powerline.zsh
+
+Fish prompt
+===========
+
+Add the following line to :file:`config.fish`, where ``{repository_root}`` is
+the absolute path to the Powerline installation directory (see :ref:`repository
+root <repository-root>`):
+
+.. code-block:: bash
+
+ set fish_function_path $fish_function_path "{repository_root}/powerline/bindings/fish"
+ powerline-setup
+
+.. warning:: Fish is supported only starting from version 2.1.
+
+Rcsh prompt
+===========
+
+Powerline supports Plan9 rc reimplementation *by Byron Rakitzis* packaged by
+many \*nix distributions. To use it add
+
+.. code-block:: bash
+
+ . {repository_root}/powerline/bindings/rc/powerline.rc
+
+(``{repository_root}`` is the absolute path to the Powerline installation
+directory, see :ref:`repository root <repository-root>`) to :file:`rcrc` file
+(usually :file:`~/.rcrc`) and make sure ``rc`` is started as a login shell (with
+``-l`` argument): otherwise this configuration file is not read.
+
+.. warning::
+ Original Plan9 shell and its \*nix port are not supported because they are
+ missing ``prompt`` special function (it is being called once before each
+ non-continuation prompt). Since powerline could not support shell without
+ this or equivalent feature some other not-so-critical features of that port
+ were used.
+
+Busybox (ash), mksh and dash prompt
+=====================================
+
+After launching busybox run the following command:
+
+.. code-block:: bash
+
+ . {repository_root}/powerline/bindings/shell/powerline.sh
+
+where ``{repository_root}`` is the absolute path to the Powerline installation
+directory (see :ref:`repository root <repository-root>`).
+
+Mksh users may put this line into ``~/.mkshrc`` file. Dash users may use the
+following in ``~/.profile``:
+
+.. code-block:: bash
+
+ if test "$0" != "${0#dash}" ; then
+ export ENV={repository_root}/powerline/bindings/shell/powerline.sh
+ fi
+
+.. note::
+ Dash users that already have ``$ENV`` defined should either put the ``.
+ …/shell/powerline.sh`` line in the ``$ENV`` file or create a new file which
+ will source (using ``.`` command) both former ``$ENV`` file and
+ :file:`powerline.sh` files and set ``$ENV`` to the path of this new file.
+
+.. warning::
+ Mksh users have to set ``$POWERLINE_SHELL_CONTINUATION`` and
+ ``$POWERLINE_SHELL_SELECT`` to 1 to get PS2 and PS3 (continuation and
+ select) prompts support respectively: as command substitution is not
+ performed in these shells for these prompts they are updated once each time
+ PS1 prompt is displayed which may be slow.
+
+ It is also known that while PS2 and PS3 update is triggered at PS1 update it
+ is *actually performed* only *next* time PS1 is displayed which means that
+ PS2 and PS3 prompts will be outdated and may be incorrect for this reason.
+
+ Without these variables PS2 and PS3 prompts will be set once at startup.
+ This only touches mksh users: busybox and dash both have no such problem.
+
+.. warning::
+ Job count is using some weird hack that uses signals and temporary files for
+ interprocess communication. It may be wrong sometimes. Not the case in mksh.
+
+.. warning::
+ Busybox has two shells: ``ash`` and ``hush``. Second is known to segfault in
+ busybox 1.22.1 when using :file:`powerline.sh` script.
diff --git a/docs/source/usage/wm-widgets.rst b/docs/source/usage/wm-widgets.rst
new file mode 100644
index 0000000..204c008
--- /dev/null
+++ b/docs/source/usage/wm-widgets.rst
@@ -0,0 +1,102 @@
+**********************
+Window manager widgets
+**********************
+
+Awesome widget
+==============
+
+.. note:: Powerline currently only supports awesome 3.5 and 4+.
+
+.. note:: The Powerline widget will spawn a shell script that runs in the
+ background and updates the statusline with ``awesome-client``.
+
+Add the following to :file:`rc.lua`, where ``{repository_root}`` is the absolute
+path to Powerline installation directory (see :ref:`repository root
+<repository-root>`):
+
+.. code-block:: lua
+
+ package.path = package.path .. ';{repository_root}/powerline/bindings/awesome/?.lua'
+ require('powerline')
+
+Then add the ``powerline_widget`` to ``wibox``:
+
+.. code-block:: lua
+
+ -- awesome3.5
+ right_layout:add(powerline_widget)
+
+ -- awesome4+
+ s.mywibox:setup {
+ ...
+ { -- Right widgets
+ ...
+ powerline_widget,
+ },
+ }
+
+Qtile widget
+============
+
+Add the following to :file:`~/.config/qtile/config.py`:
+
+.. code-block:: python
+
+ from libqtile.bar import Bar
+ from libqtile.config import Screen
+ from libqtile.widget import Spacer
+
+ from powerline.bindings.qtile.widget import PowerlineTextBox
+
+ screens = [
+ Screen(
+ top=Bar([
+ PowerlineTextBox(update_interval=2, side='left'),
+ Spacer(),
+ PowerlineTextBox(update_interval=2, side='right'),
+ ],
+ 35 # width
+ ),
+ ),
+ ]
+
+.. _lemonbar-usage:
+
+lemonbar (formerly bar-aint-recursive)
+======================================
+
+To run the bar simply start the binding script:
+
+ python /path/to/powerline/bindings/lemonbar/powerline-lemonbar.py
+
+You can specify options to be passed to ``lemonbar`` after ``--``, like so:
+
+ python /path/to/powerline/bindings/lemonbar/powerline-lemonbar.py --height 16 -- -f "Source Code Pro for Powerline-9"
+
+to run with i3, simply ``exec`` this in the i3 config file and set the ``--i3`` switch:
+
+ exec python /path/to/powerline/bindings/lemonbar/powerline-lemonbar.py --i3
+
+Running the binding in i3-mode will require `i3ipc <https://github.com/acrisci/i3ipc-python>`_
+(or the outdated `i3-py <https://github.com/ziberna/i3-py>`_).
+
+See the `lemonbar documentation <https://github.com/LemonBoy/bar>`_ for more
+information and options.
+
+All ``powerline-lemonbar.py`` arguments:
+
+.. automan:: powerline.commands.lemonbar
+ :prog: powerline-lemonbar.py
+ :minimal: true
+
+I3 bar
+======
+
+Add the following to :file:`~/.config/i3/config`::
+
+ bar {
+ status_command python /path/to/powerline/bindings/i3/powerline-i3.py
+ font pango:PowerlineFont 12
+ }
+
+where ``PowerlineFont`` is any system font with powerline support.
diff --git a/font/10-powerline-symbols.conf b/font/10-powerline-symbols.conf
new file mode 100644
index 0000000..7e34a12
--- /dev/null
+++ b/font/10-powerline-symbols.conf
@@ -0,0 +1,105 @@
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+
+<fontconfig>
+ <alias>
+ <family>monospace</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Droid Sans Mono</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Droid Sans Mono Slashed</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Droid Sans Mono Dotted</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>DejaVu Sans Mono</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>DejaVu Sans Mono</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Envy Code R</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Inconsolata</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Lucida Console</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Monaco</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Pragmata</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>PragmataPro</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Menlo</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Source Code Pro</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Consolas</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Anonymous pro</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Bitstream Vera Sans Mono</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Liberation Mono</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Ubuntu Mono</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Meslo LG L</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Meslo LG L DZ</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Meslo LG M</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Meslo LG M DZ</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Meslo LG S</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+ <alias>
+ <family>Meslo LG S DZ</family>
+ <prefer><family>PowerlineSymbols</family></prefer>
+ </alias>
+</fontconfig>
diff --git a/font/PowerlineSymbols.otf b/font/PowerlineSymbols.otf
new file mode 100644
index 0000000..b1582af
--- /dev/null
+++ b/font/PowerlineSymbols.otf
Binary files differ
diff --git a/powerline/__init__.py b/powerline/__init__.py
new file mode 100644
index 0000000..7c781d9
--- /dev/null
+++ b/powerline/__init__.py
@@ -0,0 +1,991 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import os
+import sys
+import logging
+
+from threading import Lock, Event
+
+from powerline.colorscheme import Colorscheme
+from powerline.lib.config import ConfigLoader
+from powerline.lib.unicode import unicode, safe_unicode, FailedUnicode
+from powerline.config import DEFAULT_SYSTEM_CONFIG_DIR
+from powerline.lib.dict import mergedicts
+from powerline.lib.encoding import get_preferred_output_encoding
+from powerline.lib.path import join
+
+
+class NotInterceptedError(BaseException):
+ pass
+
+
+def _config_loader_condition(path):
+ if path and os.path.isfile(path):
+ return path
+ return None
+
+
+def _find_config_files(search_paths, config_file, config_loader=None, loader_callback=None):
+ config_file += '.json'
+ found = False
+ for path in search_paths:
+ config_file_path = join(path, config_file)
+ if os.path.isfile(config_file_path):
+ yield config_file_path
+ found = True
+ elif config_loader:
+ config_loader.register_missing(_config_loader_condition, loader_callback, config_file_path)
+ if not found:
+ raise IOError('Config file not found in search paths ({0}): {1}'.format(
+ ', '.join(search_paths),
+ config_file
+ ))
+
+
+class PowerlineLogger(object):
+ '''Proxy class for logging.Logger instance
+
+ It emits messages in format ``{ext}:{prefix}:{message}`` where
+
+ ``{ext}``
+ is a used powerline extension (e.g. “vim”, “shell”, “ipython”).
+ ``{prefix}``
+ is a local prefix, usually a segment name.
+ ``{message}``
+ is the original message passed to one of the logging methods.
+
+ Each of the methods (``critical``, ``exception``, ``info``, ``error``,
+ ``warn``, ``debug``) expects to receive message in an ``str.format`` format,
+ not in printf-like format.
+
+ Log is saved to the location :ref:`specified by user <config-common-log>`.
+ '''
+
+ 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 '')
+ msg = safe_unicode(msg)
+ if args or kwargs:
+ args = [safe_unicode(s) if isinstance(s, bytes) else s for s in args]
+ kwargs = dict((
+ (k, safe_unicode(v) if isinstance(v, bytes) else v)
+ for k, v in kwargs.items()
+ ))
+ 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)
+
+
+_fallback_logger = None
+
+
+def get_fallback_logger(stream=None):
+ global _fallback_logger
+ if _fallback_logger:
+ return _fallback_logger
+
+ log_format = '%(asctime)s:%(levelname)s:%(message)s'
+ formatter = logging.Formatter(log_format)
+
+ level = logging.WARNING
+ handler = logging.StreamHandler(stream)
+ handler.setLevel(level)
+ handler.setFormatter(formatter)
+
+ logger = logging.Logger('powerline')
+ logger.setLevel(level)
+ logger.addHandler(handler)
+ _fallback_logger = PowerlineLogger(None, logger, '_fallback_')
+ return _fallback_logger
+
+
+def _generate_change_callback(lock, key, dictionary):
+ def on_file_change(path):
+ with lock:
+ dictionary[key] = True
+ return on_file_change
+
+
+def get_config_paths():
+ '''Get configuration paths from environment variables.
+
+ Uses $XDG_CONFIG_HOME and $XDG_CONFIG_DIRS according to the XDG specification.
+
+ :return: list of paths
+ '''
+ config_home = os.environ.get('XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config'))
+ config_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[:0] = reversed([join(d, 'powerline') for d in config_dirs.split(':')])
+ plugin_path = join(os.path.realpath(os.path.dirname(__file__)), 'config_files')
+ config_paths.insert(0, plugin_path)
+ return config_paths
+
+
+def generate_config_finder(get_config_paths=get_config_paths):
+ '''Generate find_config_files function
+
+ This function will find .json file given its path.
+
+ :param function get_config_paths:
+ Function that being called with no arguments will return a list of paths
+ that should be searched for configuration files.
+
+ :return:
+ Function that being given configuration file name will return full path
+ to it or raise IOError if it failed to find the file.
+ '''
+ config_paths = get_config_paths()
+ return lambda *args: _find_config_files(config_paths, *args)
+
+
+def load_config(cfg_path, find_config_files, config_loader, loader_callback=None):
+ '''Load configuration file and setup watches
+
+ Watches are only set up if loader_callback is not None.
+
+ :param str cfg_path:
+ Path for configuration file that should be loaded.
+ :param function find_config_files:
+ Function that finds configuration file. Check out the description of
+ the return value of ``generate_config_finder`` function.
+ :param ConfigLoader config_loader:
+ Configuration file loader class instance.
+ :param function loader_callback:
+ Function that will be called by config_loader when change to
+ configuration file is detected.
+
+ :return: Configuration file contents.
+ '''
+ found_files = find_config_files(cfg_path, config_loader, loader_callback)
+ ret = None
+ for path in found_files:
+ if loader_callback:
+ config_loader.register(loader_callback, path)
+ if ret is None:
+ ret = config_loader.load(path)
+ else:
+ mergedicts(ret, config_loader.load(path))
+ return ret
+
+
+def _set_log_handlers(common_config, logger, get_module_attr, stream=None):
+ '''Set log handlers
+
+ :param dict common_config:
+ Configuration dictionary used to create handler.
+ :param logging.Logger logger:
+ Logger to which handlers will be attached.
+ :param func get_module_attr:
+ :py:func:`gen_module_attr_getter` output.
+ :param file stream:
+ Stream to use by default for :py:class:`logging.StreamHandler` in place
+ of :py:attr:`sys.stderr`. May be ``None``.
+ '''
+ log_targets = common_config['log_file']
+ num_handlers = 0
+ for log_target in log_targets:
+ if log_target is None:
+ log_target = ['logging.StreamHandler', []]
+ elif isinstance(log_target, unicode):
+ log_target = os.path.expanduser(log_target)
+ log_dir = os.path.dirname(log_target)
+ if log_dir and not os.path.isdir(log_dir):
+ os.mkdir(log_dir)
+ log_target = ['logging.FileHandler', [[log_target]]]
+ module, handler_class_name = log_target[0].rpartition('.')[::2]
+ module = module or 'logging.handlers'
+ try:
+ handler_class_args = log_target[1][0]
+ except IndexError:
+ if module == 'logging' and handler_class_name == 'StreamHandler':
+ handler_class_args = [stream]
+ else:
+ handler_class_args = ()
+ try:
+ handler_class_kwargs = log_target[1][1]
+ except IndexError:
+ handler_class_kwargs = {}
+ module = str(module)
+ handler_class_name = str(handler_class_name)
+ handler_class = get_module_attr(module, handler_class_name)
+ if not handler_class:
+ continue
+ handler = handler_class(*handler_class_args, **handler_class_kwargs)
+ try:
+ handler_level_name = log_target[2]
+ except IndexError:
+ handler_level_name = common_config['log_level']
+ try:
+ handler_format = log_target[3]
+ except IndexError:
+ handler_format = common_config['log_format']
+ handler.setLevel(getattr(logging, handler_level_name))
+ handler.setFormatter(logging.Formatter(handler_format))
+ logger.addHandler(handler)
+ num_handlers += 1
+ if num_handlers == 0 and log_targets:
+ raise ValueError('Failed to set up any handlers')
+
+
+def create_logger(common_config, use_daemon_threads=True, ext='__unknown__',
+ import_paths=None, imported_modules=None, stream=None):
+ '''Create logger according to provided configuration
+
+ :param dict common_config:
+ Common configuration, from :py:func:`finish_common_config`.
+ :param bool use_daemon_threads:
+ Whether daemon threads should be used. Argument to
+ :py:class:`PowerlineLogger` constructor.
+ :param str ext:
+ Used extension. Argument to :py:class:`PowerlineLogger` constructor.
+ :param set imported_modules:
+ Set where imported modules are saved. Argument to
+ :py:func:`gen_module_attr_getter`. May be ``None``, in this case new
+ empty set is used.
+ :param file stream:
+ Stream to use by default for :py:class:`logging.StreamHandler` in place
+ of :py:attr:`sys.stderr`. May be ``None``.
+
+ :return: Three objects:
+
+ #. :py:class:`logging.Logger` instance.
+ #. :py:class:`PowerlineLogger` instance.
+ #. Function, output of :py:func:`gen_module_attr_getter`.
+ '''
+ logger = logging.Logger('powerline')
+ level = getattr(logging, common_config['log_level'])
+ logger.setLevel(level)
+
+ pl = PowerlineLogger(use_daemon_threads, logger, ext)
+ get_module_attr = gen_module_attr_getter(
+ pl, common_config['paths'],
+ set() if imported_modules is None else imported_modules)
+
+ _set_log_handlers(common_config, logger, get_module_attr, stream)
+
+ return logger, pl, get_module_attr
+
+
+def get_default_theme(is_unicode=True):
+ '''Get default theme used by powerline
+
+ :param bool is_unicode:
+ If true, return theme for unicode environments, otherwise return theme
+ that is supposed to be ASCII-only.
+
+ :return: theme name.
+ '''
+ return 'powerline_terminus' if is_unicode else 'ascii'
+
+
+def finish_common_config(encoding, common_config):
+ '''Add default values to common config and expand ~ in paths
+
+ :param dict common_config:
+ Common configuration, as it was just loaded.
+
+ :return:
+ Copy of common configuration with all configuration keys and expanded
+ paths.
+ '''
+ encoding = encoding.lower()
+ default_top_theme = get_default_theme(
+ encoding.startswith('utf') or encoding.startswith('ucs'))
+
+ common_config = common_config.copy()
+ common_config.setdefault('default_top_theme', default_top_theme)
+ common_config.setdefault('paths', [])
+ common_config.setdefault('watcher', 'auto')
+ common_config.setdefault('log_level', 'WARNING')
+ common_config.setdefault('log_format', '%(asctime)s:%(levelname)s:%(message)s')
+ common_config.setdefault('term_truecolor', False)
+ common_config.setdefault('term_escape_style', 'auto')
+ common_config.setdefault('ambiwidth', 1)
+ common_config.setdefault('additional_escapes', None)
+ common_config.setdefault('reload_config', True)
+ common_config.setdefault('interval', None)
+ common_config.setdefault('log_file', [None])
+
+ if not isinstance(common_config['log_file'], list):
+ common_config['log_file'] = [common_config['log_file']]
+
+ common_config['paths'] = [
+ os.path.expanduser(path) for path in common_config['paths']
+ ]
+
+ return common_config
+
+
+if sys.version_info < (3,):
+ # `raise exception[0], None, exception[1]` is a SyntaxError in python-3*
+ # Not using ('''…''') because this syntax does not work in python-2.6
+ exec((
+ 'def reraise(exception):\n'
+ ' if type(exception) is tuple:\n'
+ ' raise exception[0], None, exception[1]\n'
+ ' else:\n'
+ ' raise exception\n'
+ ))
+else:
+ def reraise(exception):
+ if type(exception) is tuple:
+ raise exception[0].with_traceback(exception[1])
+ else:
+ raise exception
+
+
+def gen_module_attr_getter(pl, import_paths, imported_modules):
+ def get_module_attr(module, attr, prefix='powerline'):
+ '''Import module and get its attribute.
+
+ Replaces ``from {module} import {attr}``.
+
+ :param str module:
+ Module name, will be passed as first argument to ``__import__``.
+ :param str attr:
+ Module attribute, will be passed to ``__import__`` as the only value
+ in ``fromlist`` tuple.
+
+ :return:
+ Attribute value or ``None``. Note: there is no way to distinguish
+ between successfull import of attribute equal to ``None`` and
+ unsuccessfull import.
+ '''
+ oldpath = sys.path
+ sys.path = import_paths + sys.path
+ module = str(module)
+ attr = str(attr)
+ try:
+ imported_modules.add(module)
+ return getattr(__import__(module, fromlist=(attr,)), attr)
+ except Exception as e:
+ pl.exception('Failed to import attr {0} from module {1}: {2}', attr, module, str(e), prefix=prefix)
+ return None
+ finally:
+ sys.path = oldpath
+
+ return get_module_attr
+
+
+LOG_KEYS = set(('log_format', 'log_level', 'log_file', 'paths'))
+'''List of keys related to logging
+'''
+
+
+def _get_log_keys(common_config):
+ '''Return a common configuration copy with only log-related config left
+
+ :param dict common_config:
+ Common configuration.
+
+ :return:
+ :py:class:`dict` instance which has only keys from
+ :py:attr:`powerline.LOG_KEYS` left.
+ '''
+ return dict((
+ (k, v) for k, v in common_config.items() if k in LOG_KEYS
+ ))
+
+
+DEFAULT_UPDATE_INTERVAL = 2
+'''Default value for :ref:`update_interval <config-ext-update_interval>`
+'''
+
+
+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.renderers.{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``). When ``.foo`` (with leading
+ dot) variant is used ``renderer_module`` will be
+ ``powerline.renderers.{ext}{renderer_module}``.
+ :param bool run_once:
+ Determines whether :py:meth:`render` method will be run only once
+ during python session.
+ :param Logger logger:
+ If present no new logger will be created and the provided logger will be
+ used.
+ :param bool use_daemon_threads:
+ When creating threads make them daemon ones.
+ :param Event shutdown_event:
+ Use this Event as shutdown_event instead of creating new event.
+ :param ConfigLoader config_loader:
+ Instance of the class that manages (re)loading of the configuration.
+ '''
+
+ def __init__(self, *args, **kwargs):
+ self.init_args = (args, kwargs)
+ self.init(*args, **kwargs)
+
+ def init(self,
+ ext,
+ renderer_module=None,
+ run_once=False,
+ logger=None,
+ use_daemon_threads=True,
+ shutdown_event=None,
+ config_loader=None):
+ '''Do actual initialization.
+
+ __init__ function only stores the arguments and runs this function. This
+ function exists for powerline to be able to reload itself: it is easier
+ to make ``__init__`` store arguments and call overriddable ``init`` than
+ tell developers that each time they override Powerline.__init__ in
+ subclasses they must store actual arguments.
+ '''
+ self.ext = ext
+ self.run_once = run_once
+ self.logger = logger
+ self.had_logger = bool(self.logger)
+ self.use_daemon_threads = use_daemon_threads
+
+ if not renderer_module:
+ self.renderer_module = 'powerline.renderers.' + ext
+ elif '.' not in renderer_module:
+ self.renderer_module = 'powerline.renderers.' + renderer_module
+ elif renderer_module.startswith('.'):
+ self.renderer_module = 'powerline.renderers.' + ext + renderer_module
+ elif renderer_module.endswith('.'):
+ self.renderer_module = renderer_module[:-1]
+ else:
+ self.renderer_module = renderer_module
+
+ self.find_config_files = generate_config_finder(self.get_config_paths)
+
+ self.cr_kwargs_lock = Lock()
+ self.cr_kwargs = {}
+ self.cr_callbacks = {}
+ for key in ('main', 'colors', 'colorscheme', 'theme'):
+ self.cr_kwargs['load_' + key] = True
+ self.cr_callbacks[key] = _generate_change_callback(
+ self.cr_kwargs_lock,
+ 'load_' + key,
+ self.cr_kwargs
+ )
+
+ self.shutdown_event = shutdown_event or Event()
+ self.config_loader = config_loader or ConfigLoader(shutdown_event=self.shutdown_event, run_once=run_once)
+ self.run_loader_update = False
+
+ self.renderer_options = {}
+
+ self.prev_common_config = None
+ self.prev_ext_config = None
+ self.pl = None
+ self.setup_args = ()
+ self.setup_kwargs = {}
+ self.imported_modules = set()
+ self.update_interval = DEFAULT_UPDATE_INTERVAL
+
+ get_encoding = staticmethod(get_preferred_output_encoding)
+ '''Get encoding used by the current application
+
+ Usually returns encoding of the current locale.
+ '''
+
+ def create_logger(self):
+ '''Create logger
+
+ This function is used to create logger unless it was already specified
+ at initialization.
+
+ :return: Three objects:
+
+ #. :py:class:`logging.Logger` instance.
+ #. :py:class:`PowerlineLogger` instance.
+ #. Function, output of :py:func:`gen_module_attr_getter`.
+ '''
+ return create_logger(
+ common_config=self.common_config,
+ use_daemon_threads=self.use_daemon_threads,
+ ext=self.ext,
+ imported_modules=self.imported_modules,
+ stream=self.default_log_stream,
+ )
+
+ 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 = finish_common_config(self.get_encoding(), config['common'])
+ if self.common_config != self.prev_common_config:
+ common_config_differs = True
+
+ load_theme = (load_theme
+ or not self.prev_common_config
+ or self.prev_common_config['default_top_theme'] != self.common_config['default_top_theme'])
+
+ log_keys_differ = (not self.prev_common_config or (
+ _get_log_keys(self.prev_common_config) != _get_log_keys(self.common_config)
+ ))
+
+ self.prev_common_config = self.common_config
+
+ if log_keys_differ:
+ if self.had_logger:
+ self.pl = PowerlineLogger(self.use_daemon_threads, self.logger, self.ext)
+ self.get_module_attr = gen_module_attr_getter(
+ self.pl, self.common_config['paths'], self.imported_modules)
+ else:
+ self.logger, self.pl, self.get_module_attr = self.create_logger()
+ self.config_loader.pl = self.pl
+
+ if not self.run_once:
+ self.config_loader.set_watcher(self.common_config['watcher'])
+
+ mergedicts(self.renderer_options, dict(
+ pl=self.pl,
+ term_truecolor=self.common_config['term_truecolor'],
+ term_escape_style=self.common_config['term_escape_style'],
+ ambiwidth=self.common_config['ambiwidth'],
+ tmux_escape=self.common_config['additional_escapes'] == 'tmux',
+ screen_escape=self.common_config['additional_escapes'] == 'screen',
+ theme_kwargs={
+ 'ext': self.ext,
+ 'common_config': self.common_config,
+ 'run_once': self.run_once,
+ 'shutdown_event': self.shutdown_event,
+ 'get_module_attr': self.get_module_attr,
+ },
+ ))
+
+ if not self.run_once and self.common_config['reload_config']:
+ interval = self.common_config['interval']
+ 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]
+
+ top_theme = (
+ self.ext_config.get('top_theme')
+ or self.common_config['default_top_theme']
+ )
+ self.theme_levels = (
+ os.path.join('themes', top_theme),
+ os.path.join('themes', self.ext, '__main__'),
+ )
+ self.renderer_options['theme_kwargs']['top_theme'] = top_theme
+
+ if self.ext_config != self.prev_ext_config:
+ ext_config_differs = True
+ if (
+ not self.prev_ext_config
+ or self.ext_config.get('components') != self.prev_ext_config.get('components')
+ ):
+ self.setup_components(self.ext_config.get('components'))
+ 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'))
+ self.update_interval = self.ext_config.get('update_interval', 2)
+ 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['theme_kwargs']['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:
+ Renderer = self.get_module_attr(self.renderer_module, 'renderer')
+ if not Renderer:
+ if hasattr(self, 'renderer'):
+ return
+ else:
+ raise ImportError('Failed to obtain renderer')
+
+ # 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.exception('Failed to construct renderer object: {0}', str(e))
+ if not hasattr(self, 'renderer'):
+ raise
+ else:
+ self.renderer = renderer
+
+ default_log_stream = sys.stdout
+ '''Default stream for default log handler
+
+ Usually it is ``sys.stderr``, but there is sometimes a reason to prefer
+ ``sys.stdout`` or a custom file-like object. It is not supposed to be used
+ to write to some file.
+ '''
+
+ def setup_components(self, components):
+ '''Run component-specific setup
+
+ :param set components:
+ Set of the enabled componets or None.
+
+ Should be overridden by subclasses.
+ '''
+ pass
+
+ @staticmethod
+ def get_config_paths():
+ '''Get configuration paths.
+
+ Should be overridden in subclasses in order to provide a way to override
+ used paths.
+
+ :return: list of paths
+ '''
+ return get_config_paths()
+
+ def load_config(self, cfg_path, cfg_type):
+ '''Load configuration and setup watches
+
+ :param str cfg_path:
+ Path to the configuration file without any powerline configuration
+ directory or ``.json`` suffix.
+ :param str cfg_type:
+ Configuration type. May be one of ``main`` (for ``config.json``
+ file), ``colors``, ``colorscheme``, ``theme``.
+
+ :return: dictionary with loaded configuration.
+ '''
+ return load_config(
+ cfg_path,
+ self.find_config_files,
+ self.config_loader,
+ self.cr_callbacks[cfg_type]
+ )
+
+ def _purge_configs(self, cfg_type):
+ function = self.cr_callbacks[cfg_type]
+ self.config_loader.unregister_functions(set((function,)))
+ self.config_loader.unregister_missing(set(((self.find_config_files, function),)))
+
+ 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_hierarhical_config(self, cfg_type, levels, ignore_levels):
+ '''Load and merge multiple configuration files
+
+ :param str cfg_type:
+ Type of the loaded configuration files (e.g. ``colorscheme``,
+ ``theme``).
+ :param list levels:
+ Configuration names resembling levels in hierarchy, sorted by
+ priority. Configuration file names with higher priority should go
+ last.
+ :param set ignore_levels:
+ If only files listed in this variable are present then configuration
+ file is considered not loaded: at least one file on the level not
+ listed in this variable must be present.
+ '''
+ config = {}
+ loaded = 0
+ exceptions = []
+ for i, cfg_path in enumerate(levels):
+ try:
+ lvl_config = self.load_config(cfg_path, cfg_type)
+ except IOError as e:
+ if sys.version_info < (3,):
+ tb = sys.exc_info()[2]
+ exceptions.append((e, tb))
+ else:
+ exceptions.append(e)
+ else:
+ if i not in ignore_levels:
+ loaded += 1
+ mergedicts(config, lvl_config)
+ if not loaded:
+ for exception in exceptions:
+ if type(exception) is tuple:
+ e = exception[0]
+ else:
+ e = exception
+ self.exception('Failed to load %s: {0}' % cfg_type, e, exception=exception)
+ raise e
+ return config
+
+ 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>`.
+ '''
+ levels = (
+ os.path.join('colorschemes', name),
+ os.path.join('colorschemes', self.ext, '__main__'),
+ os.path.join('colorschemes', self.ext, name),
+ )
+ return self._load_hierarhical_config('colorscheme', levels, (1,))
+
+ 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>`
+ '''
+ levels = self.theme_levels + (
+ os.path.join('themes', self.ext, name),
+ )
+ return self._load_hierarhical_config('theme', levels, (0, 1,))
+
+ 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()
+ cr_kwargs = None
+ with self.cr_kwargs_lock:
+ if self.cr_kwargs:
+ cr_kwargs = self.cr_kwargs.copy()
+ if cr_kwargs:
+ try:
+ self.create_renderer(**cr_kwargs)
+ except Exception as e:
+ self.exception('Failed to create renderer: {0}', str(e))
+ if hasattr(self, 'renderer'):
+ with self.cr_kwargs_lock:
+ self.cr_kwargs.clear()
+ else:
+ raise
+ else:
+ with self.cr_kwargs_lock:
+ self.cr_kwargs.clear()
+
+ def render(self, *args, **kwargs):
+ '''Update/create renderer if needed and pass all arguments further to
+ ``self.renderer.render()``.
+ '''
+ try:
+ self.update_renderer()
+ return self.renderer.render(*args, **kwargs)
+ except Exception as e:
+ exc = e
+ try:
+ self.exception('Failed to render: {0}', str(e))
+ except Exception as e:
+ exc = e
+ ret = FailedUnicode(safe_unicode(exc))
+ if kwargs.get('output_width', False):
+ ret = ret, len(ret)
+ return ret
+
+ def render_above_lines(self, *args, **kwargs):
+ '''Like .render(), but for ``self.renderer.render_above_lines()``
+ '''
+ try:
+ self.update_renderer()
+ for line in self.renderer.render_above_lines(*args, **kwargs):
+ yield line
+ except Exception as e:
+ exc = e
+ try:
+ self.exception('Failed to render: {0}', str(e))
+ except Exception as e:
+ exc = e
+ yield FailedUnicode(safe_unicode(exc))
+
+ def setup(self, *args, **kwargs):
+ '''Setup the environment to use powerline.
+
+ Must not be overridden by subclasses. This one only saves setup
+ arguments for :py:meth:`reload` method and calls :py:meth:`do_setup`.
+ '''
+ self.shutdown_event.clear()
+ self.setup_args = args
+ self.setup_kwargs.update(kwargs)
+ self.do_setup(*args, **kwargs)
+
+ @staticmethod
+ def do_setup():
+ '''Function that does initialization
+
+ Should be overridden by subclasses. May accept any number of regular or
+ keyword arguments.
+ '''
+ pass
+
+ def reload(self):
+ '''Reload powerline after update.
+
+ Should handle most (but not all) powerline updates.
+
+ Purges out all powerline modules and modules imported by powerline for
+ segment and matcher functions. Requires defining ``setup`` function that
+ updates reference to main powerline object.
+
+ .. warning::
+ Not guaranteed to work properly, use it at your own risk. It
+ may break your python code.
+ '''
+ import sys
+ modules = self.imported_modules | set((module for module in sys.modules if module.startswith('powerline')))
+ modules_holder = []
+ for module in modules:
+ try:
+ # Needs to hold module to prevent garbage collecting until they
+ # are all reloaded.
+ modules_holder.append(sys.modules.pop(module))
+ except KeyError:
+ pass
+ PowerlineClass = getattr(__import__(self.__module__, fromlist=(self.__class__.__name__,)), self.__class__.__name__)
+ self.shutdown(set_event=True)
+ init_args, init_kwargs = self.init_args
+ powerline = PowerlineClass(*init_args, **init_kwargs)
+ powerline.setup(*self.setup_args, **self.setup_kwargs)
+
+ def shutdown(self, set_event=True):
+ '''Shut down all background threads.
+
+ :param bool set_event:
+ Set ``shutdown_event`` and call ``renderer.shutdown`` which should
+ shut down all threads. Set it to False unless you are exiting an
+ application.
+
+ If set to False this does nothing more then resolving reference
+ cycle ``powerline → config_loader → bound methods → powerline`` by
+ unsubscribing from config_loader events.
+ '''
+ if set_event:
+ self.shutdown_event.set()
+ try:
+ self.renderer.shutdown()
+ except AttributeError:
+ pass
+ functions = tuple(self.cr_callbacks.values())
+ self.config_loader.unregister_functions(set(functions))
+ self.config_loader.unregister_missing(set(((self.find_config_files, function) for function in functions)))
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args):
+ self.shutdown()
+
+ def exception(self, msg, *args, **kwargs):
+ if 'prefix' not in kwargs:
+ kwargs['prefix'] = 'powerline'
+ exception = kwargs.pop('exception', None)
+ pl = getattr(self, 'pl', None) or get_fallback_logger(self.default_log_stream)
+ if exception:
+ try:
+ reraise(exception)
+ except Exception:
+ return pl.exception(msg, *args, **kwargs)
+ return pl.exception(msg, *args, **kwargs)
diff --git a/powerline/bindings/__init__.py b/powerline/bindings/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/powerline/bindings/__init__.py
diff --git a/powerline/bindings/awesome/powerline-awesome.py b/powerline/bindings/awesome/powerline-awesome.py
new file mode 100755
index 0000000..500d47d
--- /dev/null
+++ b/powerline/bindings/awesome/powerline-awesome.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import sys
+
+from powerline.bindings.wm import DEFAULT_UPDATE_INTERVAL
+from powerline.bindings.wm.awesome import run
+
+
+def main():
+ try:
+ interval = float(sys.argv[1])
+ except IndexError:
+ interval = DEFAULT_UPDATE_INTERVAL
+ run(interval=interval)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/powerline/bindings/awesome/powerline.lua b/powerline/bindings/awesome/powerline.lua
new file mode 100644
index 0000000..470901f
--- /dev/null
+++ b/powerline/bindings/awesome/powerline.lua
@@ -0,0 +1,15 @@
+local wibox = require('wibox')
+local awful = require('awful')
+
+powerline_widget = wibox.widget.textbox()
+powerline_widget:set_align('right')
+
+function powerline(mode, widget) end
+
+if string.find(awesome.version, 'v4') then
+ awful.spawn.with_shell('powerline-daemon -q')
+ awful.spawn.with_shell('powerline wm.awesome')
+else
+ awful.util.spawn_with_shell('powerline-daemon -q')
+ awful.util.spawn_with_shell('powerline wm.awesome')
+end
diff --git a/powerline/bindings/bar/powerline-bar.py b/powerline/bindings/bar/powerline-bar.py
new file mode 100755
index 0000000..71e8ae3
--- /dev/null
+++ b/powerline/bindings/bar/powerline-bar.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import os
+import sys
+import time
+
+from threading import Lock, Timer
+from argparse import ArgumentParser
+
+from powerline.lemonbar import LemonbarPowerline
+from powerline.lib.encoding import get_unicode_writer
+from powerline.bindings.wm import DEFAULT_UPDATE_INTERVAL
+
+
+if __name__ == '__main__':
+ parser = ArgumentParser(description='Powerline lemonbar bindings.')
+ parser.add_argument(
+ '--i3', action='store_true',
+ help='Subscribe for i3 events.'
+ )
+ args = parser.parse_args()
+ powerline = LemonbarPowerline()
+ powerline.update_renderer()
+ powerline.pl.warn("The 'bar' bindings are deprecated, please switch to 'lemonbar'")
+ lock = Lock()
+ modes = ['default']
+ write = get_unicode_writer(encoding='utf-8')
+
+ def render(reschedule=False):
+ if reschedule:
+ Timer(DEFAULT_UPDATE_INTERVAL, render, kwargs={'reschedule': True}).start()
+
+ global lock
+ with lock:
+ write(powerline.render(mode=modes[0]))
+ write('\n')
+ sys.stdout.flush()
+
+ def update(evt):
+ modes[0] = evt.change
+ render()
+
+ render(reschedule=True)
+
+ if args.i3:
+ try:
+ import i3ipc
+ except ImportError:
+ import i3
+ i3.Subscription(lambda evt, data, sub: print(render()), 'workspace')
+ else:
+ conn = i3ipc.Connection()
+ conn.on('workspace::focus', lambda conn, evt: render())
+ conn.on('mode', lambda conn, evt: update(evt))
+ conn.main()
+
+ while True:
+ time.sleep(1e8)
diff --git a/powerline/bindings/bash/powerline.sh b/powerline/bindings/bash/powerline.sh
new file mode 100644
index 0000000..f4e933e
--- /dev/null
+++ b/powerline/bindings/bash/powerline.sh
@@ -0,0 +1,153 @@
+_powerline_columns_fallback() {
+ if which stty &>/dev/null ; then
+ local cols="$(stty size 2>/dev/null)"
+ if ! test -z "$cols" ; then
+ echo "${cols#* }"
+ return 0
+ fi
+ fi
+ echo 0
+ return 0
+}
+
+_powerline_tmux_pane() {
+ echo "${TMUX_PANE:-`TMUX="$_POWERLINE_TMUX" tmux display -p "#D"`}" | \
+ tr -d ' %'
+}
+
+_powerline_tmux_setenv() {
+ TMUX="$_POWERLINE_TMUX" tmux setenv -g TMUX_"$1"_`_powerline_tmux_pane` "$2"
+ TMUX="$_POWERLINE_TMUX" tmux refresh -S
+}
+
+_powerline_tmux_set_pwd() {
+ if test "$_POWERLINE_SAVED_PWD" != "$PWD" ; then
+ _POWERLINE_SAVED_PWD="$PWD"
+ _powerline_tmux_setenv PWD "$PWD"
+ fi
+}
+
+_powerline_return() {
+ return $1
+}
+
+_POWERLINE_HAS_PIPESTATUS="$(
+ _powerline_return 0 | _powerline_return 43
+ test "${PIPESTATUS[*]}" = "0 43"
+ echo "$?"
+)"
+
+_powerline_has_pipestatus() {
+ return $_POWERLINE_HAS_PIPESTATUS
+}
+
+_powerline_status_wrapper() {
+ local last_exit_code=$? last_pipe_status=( "${PIPESTATUS[@]}" )
+
+ if ! _powerline_has_pipestatus \
+ || test "${#last_pipe_status[@]}" -eq "0" \
+ || test "$last_exit_code" != "${last_pipe_status[$(( ${#last_pipe_status[@]} - 1 ))]}" ; then
+ last_pipe_status=()
+ fi
+ "$@" $last_exit_code "${last_pipe_status[*]}"
+ return $last_exit_code
+}
+
+_powerline_add_status_wrapped_command() {
+ local action="$1" ; shift
+ local cmd="$1" ; shift
+ full_cmd="_powerline_status_wrapper $cmd"
+ if test "$action" = "append" ; then
+ PROMPT_COMMAND="$PROMPT_COMMAND"$'\n'"$full_cmd"
+ else
+ PROMPT_COMMAND="$full_cmd"$'\n'"$PROMPT_COMMAND"
+ fi
+}
+
+_powerline_tmux_set_columns() {
+ _powerline_tmux_setenv COLUMNS "${COLUMNS:-`_powerline_columns_fallback`}"
+}
+
+_powerline_init_tmux_support() {
+ if test -n "$TMUX" && tmux refresh -S &>/dev/null ; then
+ # TMUX variable may be unset to create new tmux session inside this one
+ _POWERLINE_TMUX="$TMUX"
+
+ trap '_powerline_tmux_set_columns' WINCH
+ _powerline_tmux_set_columns
+
+ test "$PROMPT_COMMAND" != "${PROMPT_COMMAND/_powerline_tmux_set_pwd}" \
+ || _powerline_add_status_wrapped_command append _powerline_tmux_set_pwd
+ fi
+}
+
+_powerline_local_prompt() {
+ # Arguments:
+ # 1: side
+ # 2: renderer_module arg
+ # 3: last_exit_code
+ # 4: last_pipe_status
+ # 5: jobnum
+ # 6: local theme
+ "$POWERLINE_COMMAND" $POWERLINE_COMMAND_ARGS shell $1 \
+ $2 \
+ --last-exit-code=$3 \
+ --last-pipe-status="$4" \
+ --jobnum=$5 \
+ --renderer-arg="client_id=$$" \
+ --renderer-arg="local_theme=$6"
+}
+
+_powerline_prompt() {
+ # Arguments:
+ # 1: side
+ # 2: last_exit_code
+ # 3: last_pipe_status
+ # 4: jobnum
+ "$POWERLINE_COMMAND" $POWERLINE_COMMAND_ARGS shell $1 \
+ --width="${COLUMNS:-$(_powerline_columns_fallback)}" \
+ -r.bash \
+ --last-exit-code=$2 \
+ --last-pipe-status="$3" \
+ --jobnum=$4 \
+ --renderer-arg="client_id=$$"
+}
+
+_powerline_set_prompt() {
+ local last_exit_code=$1 ; shift
+ local last_pipe_status=$1 ; shift
+ local jobnum="$(jobs -p|wc -l)"
+ PS1="$(_powerline_prompt aboveleft $last_exit_code "$last_pipe_status" $jobnum)"
+ if test -n "$POWERLINE_SHELL_CONTINUATION$POWERLINE_BASH_CONTINUATION" ; then
+ PS2="$(_powerline_local_prompt left -r.bash $last_exit_code "$last_pipe_status" $jobnum continuation)"
+ fi
+ if test -n "$POWERLINE_SHELL_SELECT$POWERLINE_BASH_SELECT" ; then
+ PS3="$(_powerline_local_prompt left '' $last_exit_code "$last_pipe_status" $jobnum select)"
+ fi
+}
+
+_powerline_setup_prompt() {
+ VIRTUAL_ENV_DISABLE_PROMPT=1
+ if test -z "${POWERLINE_COMMAND}" ; then
+ POWERLINE_COMMAND="$("$POWERLINE_CONFIG_COMMAND" shell command)"
+ fi
+ test "$PROMPT_COMMAND" != "${PROMPT_COMMAND%_powerline_set_prompt*}" \
+ || _powerline_add_status_wrapped_command prepend _powerline_set_prompt
+ PS2="$(_powerline_local_prompt left -r.bash 0 0 0 continuation)"
+ PS3="$(_powerline_local_prompt left '' 0 0 0 select)"
+}
+
+if test -z "${POWERLINE_CONFIG_COMMAND}" ; then
+ if which powerline-config >/dev/null ; then
+ POWERLINE_CONFIG_COMMAND=powerline-config
+ else
+ POWERLINE_CONFIG_COMMAND="$(dirname "$BASH_SOURCE")/../../../scripts/powerline-config"
+ fi
+fi
+
+if "${POWERLINE_CONFIG_COMMAND}" shell --shell=bash uses prompt ; then
+ _powerline_setup_prompt
+fi
+if "${POWERLINE_CONFIG_COMMAND}" shell --shell=bash uses tmux ; then
+ _powerline_init_tmux_support
+fi
diff --git a/powerline/bindings/config.py b/powerline/bindings/config.py
new file mode 100644
index 0000000..3100633
--- /dev/null
+++ b/powerline/bindings/config.py
@@ -0,0 +1,286 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import os
+import re
+import sys
+import subprocess
+import shlex
+
+from powerline.config import POWERLINE_ROOT, TMUX_CONFIG_DIRECTORY
+from powerline.lib.config import ConfigLoader
+from powerline import generate_config_finder, load_config, create_logger, finish_common_config
+from powerline.shell import ShellPowerline
+from powerline.lib.shell import which
+from powerline.bindings.tmux import (TmuxVersionInfo, run_tmux_command, set_tmux_environment, get_tmux_version,
+ source_tmux_file)
+from powerline.lib.encoding import get_preferred_output_encoding
+from powerline.renderers.tmux import attrs_to_tmux_attrs
+from powerline.commands.main import finish_args
+
+
+CONFIG_FILE_NAME = re.compile(r'powerline_tmux_(?P<major>\d+)\.(?P<minor>\d+)(?P<suffix>[a-z]+)?(?:_(?P<mod>plus|minus))?\.conf')
+CONFIG_MATCHERS = {
+ None: (lambda a, b: a.major == b.major and a.minor == b.minor),
+ 'plus': (lambda a, b: a[:2] <= b[:2]),
+ 'minus': (lambda a, b: a[:2] >= b[:2]),
+}
+CONFIG_PRIORITY = {
+ None: 3,
+ 'plus': 2,
+ 'minus': 1,
+}
+
+
+def list_all_tmux_configs():
+ '''List all version-specific tmux configuration files'''
+ for root, dirs, files in os.walk(TMUX_CONFIG_DIRECTORY):
+ dirs[:] = ()
+ for fname in files:
+ match = CONFIG_FILE_NAME.match(fname)
+ if match:
+ assert match.group('suffix') is None
+ yield (
+ os.path.join(root, fname),
+ CONFIG_MATCHERS[match.group('mod')],
+ CONFIG_PRIORITY[match.group('mod')],
+ TmuxVersionInfo(
+ int(match.group('major')),
+ int(match.group('minor')),
+ match.group('suffix'),
+ ),
+ )
+
+
+def get_tmux_configs(version):
+ '''Get tmux configuration suffix given parsed tmux version
+
+ :param TmuxVersionInfo version: Parsed tmux version.
+ '''
+ for fname, matcher, priority, file_version in list_all_tmux_configs():
+ if matcher(file_version, version):
+ yield (fname, priority + file_version.minor * 10 + file_version.major * 10000)
+
+
+def source_tmux_files(pl, args, tmux_version=None, source_tmux_file=source_tmux_file):
+ '''Source relevant version-specific tmux configuration files
+
+ Files are sourced in the following order:
+ * First relevant files with older versions are sourced.
+ * If files for same versions are to be sourced then first _minus files are
+ sourced, then _plus files and then files without _minus or _plus suffixes.
+ '''
+ tmux_version = tmux_version or get_tmux_version(pl)
+ source_tmux_file(os.path.join(TMUX_CONFIG_DIRECTORY, 'powerline-base.conf'))
+ for fname, priority in sorted(get_tmux_configs(tmux_version), key=(lambda v: v[1])):
+ source_tmux_file(fname)
+ if not os.environ.get('POWERLINE_COMMAND'):
+ cmd = deduce_command()
+ if cmd:
+ set_tmux_environment('POWERLINE_COMMAND', deduce_command(), remove=False)
+ try:
+ run_tmux_command('refresh-client')
+ except subprocess.CalledProcessError:
+ # On tmux-2.0 this command may fail for whatever reason. Since it is
+ # critical just ignore the failure.
+ pass
+
+
+class EmptyArgs(object):
+ def __init__(self, ext, config_path):
+ self.ext = [ext]
+ self.side = 'left'
+ self.config_path = None
+
+ def __getattr__(self, attr):
+ return None
+
+
+def init_tmux_environment(pl, args, set_tmux_environment=set_tmux_environment):
+ '''Initialize tmux environment from tmux configuration
+ '''
+ powerline = ShellPowerline(finish_args(None, os.environ, EmptyArgs('tmux', args.config_path)))
+ # TODO Move configuration files loading out of Powerline object and use it
+ # directly
+ powerline.update_renderer()
+ # FIXME Use something more stable then `theme_kwargs`
+ colorscheme = powerline.renderer_options['theme_kwargs']['colorscheme']
+
+ def get_highlighting(group):
+ return colorscheme.get_highlighting([group], None)
+
+ for varname, highlight_group in (
+ ('_POWERLINE_BACKGROUND_COLOR', 'background'),
+ ('_POWERLINE_ACTIVE_WINDOW_STATUS_COLOR', 'active_window_status'),
+ ('_POWERLINE_WINDOW_STATUS_COLOR', 'window_status'),
+ ('_POWERLINE_ACTIVITY_STATUS_COLOR', 'activity_status'),
+ ('_POWERLINE_BELL_STATUS_COLOR', 'bell_status'),
+ ('_POWERLINE_WINDOW_COLOR', 'window'),
+ ('_POWERLINE_WINDOW_DIVIDER_COLOR', 'window:divider'),
+ ('_POWERLINE_WINDOW_CURRENT_COLOR', 'window:current'),
+ ('_POWERLINE_WINDOW_NAME_COLOR', 'window_name'),
+ ('_POWERLINE_SESSION_COLOR', 'session'),
+ ):
+ highlight = get_highlighting(highlight_group)
+ set_tmux_environment(varname, powerline.renderer.hlstyle(**highlight)[2:-1])
+ for varname, prev_group, next_group in (
+ ('_POWERLINE_WINDOW_CURRENT_HARD_DIVIDER_COLOR', 'window', 'window:current'),
+ ('_POWERLINE_WINDOW_CURRENT_HARD_DIVIDER_NEXT_COLOR', 'window:current', 'window'),
+ ('_POWERLINE_SESSION_HARD_DIVIDER_NEXT_COLOR', 'session', 'background'),
+ ):
+ prev_highlight = get_highlighting(prev_group)
+ next_highlight = get_highlighting(next_group)
+ set_tmux_environment(
+ varname,
+ powerline.renderer.hlstyle(
+ fg=prev_highlight['bg'],
+ bg=next_highlight['bg'],
+ attrs=0,
+ )[2:-1]
+ )
+ for varname, attr, group in (
+ ('_POWERLINE_ACTIVE_WINDOW_FG', 'fg', 'active_window_status'),
+ ('_POWERLINE_WINDOW_STATUS_FG', 'fg', 'window_status'),
+ ('_POWERLINE_ACTIVITY_STATUS_FG', 'fg', 'activity_status'),
+ ('_POWERLINE_ACTIVITY_STATUS_ATTR', 'attrs', 'activity_status'),
+ ('_POWERLINE_BELL_STATUS_FG', 'fg', 'bell_status'),
+ ('_POWERLINE_BELL_STATUS_ATTR', 'attrs', 'bell_status'),
+ ('_POWERLINE_BACKGROUND_FG', 'fg', 'background'),
+ ('_POWERLINE_BACKGROUND_BG', 'bg', 'background'),
+ ('_POWERLINE_SESSION_FG', 'fg', 'session'),
+ ('_POWERLINE_SESSION_BG', 'bg', 'session'),
+ ('_POWERLINE_SESSION_ATTR', 'attrs', 'session'),
+ ('_POWERLINE_SESSION_PREFIX_FG', 'fg', 'session:prefix'),
+ ('_POWERLINE_SESSION_PREFIX_BG', 'bg', 'session:prefix'),
+ ('_POWERLINE_SESSION_PREFIX_ATTR', 'attrs', 'session:prefix'),
+ ):
+ if attr == 'attrs':
+ attrs = attrs_to_tmux_attrs(get_highlighting(group)[attr])
+ set_tmux_environment(varname, ']#['.join(attrs))
+ set_tmux_environment(varname + '_LEGACY', (','.join(
+ # Tmux-1.6 does not accept no… attributes in
+ # window-status-…-attr options.
+ (attr for attr in attrs if not attr.startswith('no')))
+ # But it does not support empty attributes as well.
+ or 'none'))
+ else:
+ if powerline.common_config['term_truecolor']:
+ set_tmux_environment(varname, '#{0:06x}'.format(get_highlighting(group)[attr][1]))
+ else:
+ set_tmux_environment(varname, 'colour' + str(get_highlighting(group)[attr][0]))
+
+ left_dividers = powerline.renderer.theme.dividers['left']
+ set_tmux_environment('_POWERLINE_LEFT_HARD_DIVIDER', left_dividers['hard'])
+ set_tmux_environment('_POWERLINE_LEFT_SOFT_DIVIDER', left_dividers['soft'])
+ set_tmux_environment('_POWERLINE_LEFT_HARD_DIVIDER_SPACES', (
+ ' ' * powerline.renderer.strwidth(left_dividers['hard'])))
+
+
+TMUX_VAR_RE = re.compile('\$(_POWERLINE_\w+)')
+
+
+def tmux_setup(pl, args):
+ tmux_environ = {}
+ tmux_version = get_tmux_version(pl)
+
+ def set_tmux_environment_nosource(varname, value, remove=True):
+ tmux_environ[varname] = value
+
+ def replace_cb(match):
+ return tmux_environ[match.group(1)]
+
+ def replace_env(s):
+ return TMUX_VAR_RE.subn(replace_cb, s)[0]
+
+ def source_tmux_file_nosource(fname):
+ with open(fname) as fd:
+ for line in fd:
+ if line.startswith('#') or line == '\n':
+ continue
+ args = shlex.split(line)
+ args = [args[0]] + [replace_env(arg) for arg in args[1:]]
+ run_tmux_command(*args)
+
+ if args.source is None:
+ args.source = tmux_version < (1, 9)
+
+ if args.source:
+ ste = set_tmux_environment
+ stf = source_tmux_file
+ else:
+ ste = set_tmux_environment_nosource
+ stf = source_tmux_file_nosource
+
+ init_tmux_environment(pl, args, set_tmux_environment=ste)
+ source_tmux_files(pl, args, tmux_version=tmux_version, source_tmux_file=stf)
+
+
+def get_main_config(args):
+ find_config_files = generate_config_finder()
+ config_loader = ConfigLoader(run_once=True)
+ return load_config('config', find_config_files, config_loader)
+
+
+def create_powerline_logger(args):
+ config = get_main_config(args)
+ common_config = finish_common_config(get_preferred_output_encoding(), config['common'])
+ logger, pl, get_module_attr = create_logger(common_config)
+ return pl
+
+
+def check_command(cmd):
+ if which(cmd):
+ return cmd
+
+
+def deduce_command():
+ '''Deduce which command to use for ``powerline``
+
+ Candidates:
+
+ * ``powerline``. Present only when installed system-wide.
+ * ``{powerline_root}/scripts/powerline``. Present after ``pip install -e``
+ was run and C client was compiled (in this case ``pip`` does not install
+ binary file).
+ * ``{powerline_root}/client/powerline.sh``. Useful when ``sh``, ``sed`` and
+ ``socat`` are present, but ``pip`` or ``setup.py`` was not run.
+ * ``{powerline_root}/client/powerline.py``. Like above, but when one of
+ ``sh``, ``sed`` and ``socat`` was not present.
+ * ``powerline-render``. Should not really ever be used.
+ * ``{powerline_root}/scripts/powerline-render``. Same.
+ '''
+ return (
+ None
+ or check_command('powerline')
+ or check_command(os.path.join(POWERLINE_ROOT, 'scripts', 'powerline'))
+ or ((which('sh') and which('sed') and which('socat'))
+ and check_command(os.path.join(POWERLINE_ROOT, 'client', 'powerline.sh')))
+ or check_command(os.path.join(POWERLINE_ROOT, 'client', 'powerline.py'))
+ or check_command('powerline-render')
+ or check_command(os.path.join(POWERLINE_ROOT, 'scripts', 'powerline-render'))
+ )
+
+
+def shell_command(pl, args):
+ cmd = deduce_command()
+ if cmd:
+ print(cmd)
+ else:
+ sys.exit(1)
+
+
+def uses(pl, args):
+ component = args.component
+ if not component:
+ raise ValueError('Must specify component')
+ shell = args.shell
+ template = 'POWERLINE_NO_{shell}_{component}'
+ for sh in (shell, 'shell') if shell else ('shell'):
+ varname = template.format(shell=sh.upper(), component=component.upper())
+ if os.environ.get(varname):
+ sys.exit(1)
+ config = get_main_config(args)
+ if component in config.get('ext', {}).get('shell', {}).get('components', ('tmux', 'prompt')):
+ sys.exit(0)
+ else:
+ sys.exit(1)
diff --git a/powerline/bindings/fish/powerline-setup.fish b/powerline/bindings/fish/powerline-setup.fish
new file mode 100644
index 0000000..3887138
--- /dev/null
+++ b/powerline/bindings/fish/powerline-setup.fish
@@ -0,0 +1,109 @@
+function powerline-setup
+ function _powerline_columns_fallback
+ if which stty >/dev/null
+ if stty size >/dev/null
+ stty size | cut -d' ' -f2
+ return 0
+ end
+ end
+ echo 0
+ return 0
+ end
+
+ function _powerline_columns
+ # Hack: `test "" -eq 0` is true, as well as `test 0 -eq 0`
+ # Note: at fish startup `$COLUMNS` is equal to zero, meaning that it may
+ # not be used.
+ if test "$COLUMNS" -eq 0
+ _powerline_columns_fallback
+ else
+ echo "$COLUMNS"
+ end
+ end
+
+ if test -z "$POWERLINE_CONFIG_COMMAND"
+ if which powerline-config >/dev/null
+ set -g POWERLINE_CONFIG_COMMAND powerline-config
+ else
+ set -g POWERLINE_CONFIG_COMMAND (dirname (status -f))/../../../scripts/powerline-config
+ end
+ end
+
+ if env $POWERLINE_CONFIG_COMMAND shell --shell=fish uses prompt
+ if test -z "$POWERLINE_COMMAND"
+ set -g POWERLINE_COMMAND (env $POWERLINE_CONFIG_COMMAND shell command)
+ end
+ function _powerline_set_default_mode --on-variable fish_key_bindings
+ if test $fish_key_bindings != fish_vi_key_bindings
+ set -g _POWERLINE_DEFAULT_MODE default
+ else
+ set -g -e _POWERLINE_DEFAULT_MODE
+ end
+ end
+ function _powerline_update --on-variable POWERLINE_COMMAND
+ set -l addargs "--last-exit-code=\$status"
+ set -l addargs "$addargs --last-pipe-status=\$status"
+ set -l addargs "$addargs --jobnum=(jobs -p | wc -l)"
+ # One random value has an 1/32767 = 0.0031% probability of having
+ # the same value in two shells
+ set -l addargs "$addargs --renderer-arg=client_id="(random)
+ set -l addargs "$addargs --width=\$_POWERLINE_COLUMNS"
+ set -l addargs "$addargs --renderer-arg=mode=\$fish_bind_mode"
+ set -l addargs "$addargs --renderer-arg=default_mode=\$_POWERLINE_DEFAULT_MODE"
+ set -l promptside
+ set -l rpromptpast
+ set -l columnsexpr
+ if test -z "$POWERLINE_NO_FISH_ABOVE$POWERLINE_NO_SHELL_ABOVE"
+ set promptside aboveleft
+ set rpromptpast 'echo -n " "'
+ set columnsexpr '(math (_powerline_columns) - 1)'
+ else
+ set promptside left
+ set rpromptpast
+ set columnsexpr '(_powerline_columns)'
+ end
+ echo "
+ function fish_prompt
+ env \$POWERLINE_COMMAND $POWERLINE_COMMAND_ARGS shell $promptside $addargs
+ end
+ function fish_right_prompt
+ env \$POWERLINE_COMMAND $POWERLINE_COMMAND_ARGS shell right $addargs
+ $rpromptpast
+ end
+ function _powerline_set_columns --on-signal WINCH
+ set -g _POWERLINE_COLUMNS $columnsexpr
+ end
+ " | source
+ _powerline_set_columns
+ end
+ _powerline_set_default_mode
+ _powerline_update
+ end
+ if env $POWERLINE_CONFIG_COMMAND shell --shell=fish uses tmux
+ if test -n "$TMUX"
+ if tmux refresh -S ^/dev/null
+ set -g _POWERLINE_TMUX "$TMUX"
+ function _powerline_tmux_pane
+ if test -z "$TMUX_PANE"
+ env TMUX="$_POWERLINE_TMUX" tmux display -p "#D" | tr -d ' %'
+ else
+ echo "$TMUX_PANE" | tr -d ' %'
+ end
+ end
+ function _powerline_tmux_setenv
+ env TMUX="$_POWERLINE_TMUX" tmux setenv -g TMUX_$argv[1]_(_powerline_tmux_pane) "$argv[2]"
+ env TMUX="$_POWERLINE_TMUX" tmux refresh -S
+ end
+ function _powerline_tmux_set_pwd --on-variable PWD
+ _powerline_tmux_setenv PWD "$PWD"
+ end
+ function _powerline_tmux_set_columns --on-signal WINCH
+ _powerline_tmux_setenv COLUMNS (_powerline_columns)
+ end
+ _powerline_tmux_set_columns
+ _powerline_tmux_set_pwd
+ end
+ end
+ end
+end
+# vim: ft=fish
diff --git a/powerline/bindings/i3/powerline-i3.py b/powerline/bindings/i3/powerline-i3.py
new file mode 100755
index 0000000..f44e928
--- /dev/null
+++ b/powerline/bindings/i3/powerline-i3.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import sys
+import time
+
+from threading import Lock
+
+from powerline.bindings.wm import get_i3_connection, i3_subscribe
+
+from powerline import Powerline
+from powerline.lib.monotonic import monotonic
+
+
+class I3Powerline(Powerline):
+ '''Powerline child for i3bar
+
+ Currently only changes the default log target.
+ '''
+ default_log_stream = sys.stderr
+
+
+if __name__ == '__main__':
+ name = 'wm'
+ if len(sys.argv) > 1:
+ name = sys.argv[1]
+
+ powerline = I3Powerline(name, renderer_module='i3bar')
+ powerline.update_renderer()
+
+ interval = 0.5
+
+ print ('{"version": 1}')
+ print ('[')
+ print ('[]')
+
+ lock = Lock()
+
+ def render(event=None, data=None, sub=None):
+ global lock
+ with lock:
+ print (',[' + powerline.render()[:-1] + ']')
+ sys.stdout.flush()
+
+ i3 = get_i3_connection()
+ i3_subscribe(i3, 'workspace', render)
+
+ while True:
+ start_time = monotonic()
+ render()
+ time.sleep(max(interval - (monotonic() - start_time), 0.1))
diff --git a/powerline/bindings/ipython/__init__.py b/powerline/bindings/ipython/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/powerline/bindings/ipython/__init__.py
diff --git a/powerline/bindings/ipython/post_0_11.py b/powerline/bindings/ipython/post_0_11.py
new file mode 100644
index 0000000..6c1efb1
--- /dev/null
+++ b/powerline/bindings/ipython/post_0_11.py
@@ -0,0 +1,123 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+from weakref import ref
+from warnings import warn
+
+try:
+ from IPython.core.prompts import PromptManager
+ has_prompt_manager = True
+except ImportError:
+ has_prompt_manager = False
+from IPython.core.magic import Magics, magics_class, line_magic
+
+from powerline.ipython import IPythonPowerline, IPythonInfo
+
+if has_prompt_manager:
+ from powerline.ipython import RewriteResult
+
+
+@magics_class
+class PowerlineMagics(Magics):
+ def __init__(self, ip, powerline):
+ super(PowerlineMagics, self).__init__(ip)
+ self._powerline = powerline
+
+ @line_magic
+ def powerline(self, line):
+ if line == 'reload':
+ self._powerline.reload()
+ else:
+ raise ValueError('Expected `reload`, but got {0}'.format(line))
+
+
+old_prompt_manager = None
+
+
+class ShutdownHook(object):
+ def __init__(self, ip):
+ self.powerline = lambda: None
+ ip.hooks.shutdown_hook.add(self)
+
+ def __call__(self):
+ from IPython.core.hooks import TryNext
+ powerline = self.powerline()
+ if powerline is not None:
+ powerline.shutdown()
+ raise TryNext()
+
+
+if has_prompt_manager:
+ class PowerlinePromptManager(PromptManager):
+ 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):
+ res = self.powerline.render(
+ is_prompt=name.startswith('in'),
+ side='left',
+ output_width=True,
+ output_raw=not color,
+ matcher_info=name,
+ segment_info=self.powerline_segment_info,
+ )
+ self.txtwidth = res[-1]
+ self.width = res[-1]
+ ret = res[0] if color else res[1]
+ if name == 'rewrite':
+ return RewriteResult(ret)
+ else:
+ return ret
+
+ 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.config_paths = config.get('config_paths')
+ if has_prompt_manager:
+ renderer_module = '.pre_5'
+ else:
+ renderer_module = '.since_5'
+ super(ConfigurableIPythonPowerline, self).init(
+ renderer_module=renderer_module)
+
+ def do_setup(self, ip, shutdown_hook):
+ global old_prompt_manager
+
+ if old_prompt_manager is None:
+ old_prompt_manager = ip.prompt_manager
+ prompt_manager = PowerlinePromptManager(
+ powerline=self,
+ shell=ip.prompt_manager.shell,
+ )
+ ip.prompt_manager = prompt_manager
+
+ magics = PowerlineMagics(ip, self)
+ shutdown_hook.powerline = ref(self)
+ ip.register_magics(magics)
+
+
+def load_ipython_extension(ip):
+ if has_prompt_manager:
+ shutdown_hook = ShutdownHook(ip)
+ powerline = ConfigurableIPythonPowerline(ip)
+ powerline.setup(ip, shutdown_hook)
+ else:
+ from powerline.bindings.ipython.since_5 import PowerlinePrompts
+ ip.prompts_class = PowerlinePrompts
+ ip.prompts = PowerlinePrompts(ip)
+ warn(DeprecationWarning(
+ 'post_0_11 extension is deprecated since IPython 5, use\n'
+ ' from powerline.bindings.ipython.since_5 import PowerlinePrompts\n'
+ ' c.TerminalInteractiveShell.prompts_class = PowerlinePrompts\n'
+ ))
+
+
+def unload_ipython_extension(ip):
+ global old_prompt_manager
+ if old_prompt_manager is not None:
+ ip.prompt_manager = old_prompt_manager
+ old_prompt_manager = None
diff --git a/powerline/bindings/ipython/pre_0_11.py b/powerline/bindings/ipython/pre_0_11.py
new file mode 100644
index 0000000..2bd8095
--- /dev/null
+++ b/powerline/bindings/ipython/pre_0_11.py
@@ -0,0 +1,146 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import re
+
+from weakref import ref
+
+from IPython.Prompts import BasePrompt
+from IPython.ipapi import get as get_ipython
+from IPython.ipapi import TryNext
+
+from powerline.ipython import IPythonPowerline, RewriteResult
+from powerline.lib.unicode import string
+
+
+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):
+ self.p_str, self.p_str_nocolor, self.powerline_prompt_width = (
+ self.powerline.render(
+ is_prompt=self.powerline_is_prompt,
+ side='left',
+ output_raw=True,
+ output_width=True,
+ segment_info=self.powerline_segment_info,
+ matcher_info=self.powerline_prompt_type,
+ )
+ )
+
+ @staticmethod
+ def set_colors():
+ pass
+
+
+class PowerlinePrompt1(PowerlinePrompt):
+ powerline_prompt_type = 'in'
+ powerline_is_prompt = True
+ 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.powerline_last_in['nrspaces'] = self.nrspaces
+
+ def auto_rewrite(self):
+ return RewriteResult(self.powerline.render(
+ is_prompt=False,
+ side='left',
+ matcher_info='rewrite',
+ segment_info=self.powerline_segment_info) + (' ' * self.nrspaces)
+ )
+
+
+class PowerlinePromptOut(PowerlinePrompt):
+ powerline_prompt_type = 'out'
+ powerline_is_prompt = False
+
+ def set_p_str(self):
+ super(PowerlinePromptOut, self).set_p_str()
+ spaces = ' ' * self.powerline_last_in['nrspaces']
+ self.p_str += spaces
+ self.p_str_nocolor += spaces
+
+
+class PowerlinePrompt2(PowerlinePromptOut):
+ powerline_prompt_type = 'in2'
+ powerline_is_prompt = True
+
+
+class ConfigurableIPythonPowerline(IPythonPowerline):
+ def init(self, config_overrides=None, theme_overrides={}, config_paths=None):
+ self.config_overrides = config_overrides
+ self.theme_overrides = theme_overrides
+ self.config_paths = config_paths
+ super(ConfigurableIPythonPowerline, self).init(renderer_module='.pre_5')
+
+ def ipython_magic(self, ip, parameter_s=''):
+ if parameter_s == 'reload':
+ self.reload()
+ else:
+ raise ValueError('Expected `reload`, but got {0}'.format(parameter_s))
+
+ def do_setup(self, ip, shutdown_hook):
+ last_in = {'nrspaces': 0}
+ for attr, prompt_class in (
+ ('prompt1', PowerlinePrompt1),
+ ('prompt2', PowerlinePrompt2),
+ ('prompt_out', PowerlinePromptOut)
+ ):
+ old_prompt = getattr(ip.IP.outputcache, attr)
+ prompt = prompt_class(self, last_in, old_prompt)
+ setattr(ip.IP.outputcache, attr, prompt)
+ ip.expose_magic('powerline', self.ipython_magic)
+ shutdown_hook.powerline = ref(self)
+
+
+class ShutdownHook(object):
+ powerline = lambda: None
+
+ def __call__(self):
+ from IPython.ipapi import TryNext
+ powerline = self.powerline()
+ if powerline is not None:
+ powerline.shutdown()
+ raise TryNext()
+
+
+def setup(**kwargs):
+ ip = get_ipython()
+
+ powerline = ConfigurableIPythonPowerline(**kwargs)
+ shutdown_hook = ShutdownHook()
+
+ def late_startup_hook():
+ powerline.setup(ip, shutdown_hook)
+ raise TryNext()
+
+ ip.IP.hooks.late_startup_hook.add(late_startup_hook)
+ ip.IP.hooks.shutdown_hook.add(shutdown_hook)
diff --git a/powerline/bindings/ipython/since_5.py b/powerline/bindings/ipython/since_5.py
new file mode 100644
index 0000000..5a899ae
--- /dev/null
+++ b/powerline/bindings/ipython/since_5.py
@@ -0,0 +1,81 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+from weakref import ref
+
+from IPython.terminal.prompts import Prompts
+from pygments.token import Token # NOQA
+
+from powerline.ipython import IPythonPowerline
+from powerline.renderers.ipython.since_5 import PowerlinePromptStyle
+from powerline.bindings.ipython.post_0_11 import PowerlineMagics, ShutdownHook
+
+
+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.config_paths = config.get('config_paths')
+ super(ConfigurableIPythonPowerline, self).init(
+ renderer_module='.since_5')
+
+ def do_setup(self, ip, prompts, shutdown_hook):
+ prompts.powerline = self
+
+ msfn_missing = ()
+ saved_msfn = getattr(ip, '_make_style_from_name', msfn_missing)
+
+ if hasattr(saved_msfn, 'powerline_original'):
+ saved_msfn = saved_msfn.powerline_original
+
+ def _make_style_from_name(ip, name):
+ prev_style = saved_msfn(name)
+ new_style = PowerlinePromptStyle(lambda: prev_style)
+ return new_style
+
+ _make_style_from_name.powerline_original = saved_msfn
+
+ if not isinstance(ip._style, PowerlinePromptStyle):
+ prev_style = ip._style
+ ip._style = PowerlinePromptStyle(lambda: prev_style)
+
+ if not isinstance(saved_msfn, type(self.init)):
+ _saved_msfn = saved_msfn
+ saved_msfn = lambda: _saved_msfn(ip)
+
+ if saved_msfn is not msfn_missing:
+ ip._make_style_from_name = _make_style_from_name
+
+ magics = PowerlineMagics(ip, self)
+ ip.register_magics(magics)
+
+ if shutdown_hook:
+ shutdown_hook.powerline = ref(self)
+
+
+class PowerlinePrompts(Prompts):
+ '''Class that returns powerline prompts
+ '''
+ def __init__(self, shell):
+ shutdown_hook = ShutdownHook(shell)
+ powerline = ConfigurableIPythonPowerline(shell)
+ self.shell = shell
+ powerline.do_setup(shell, self, shutdown_hook)
+ self.last_output_count = None
+ self.last_output = {}
+
+ for prompt in ('in', 'continuation', 'rewrite', 'out'):
+ exec((
+ 'def {0}_prompt_tokens(self, *args, **kwargs):\n'
+ ' if self.last_output_count != self.shell.execution_count:\n'
+ ' self.last_output.clear()\n'
+ ' self.last_output_count = self.shell.execution_count\n'
+ ' if "{0}" not in self.last_output:\n'
+ ' self.last_output["{0}"] = self.powerline.render('
+ ' side="left",'
+ ' matcher_info="{1}",'
+ ' segment_info=self.shell,'
+ ' ) + [(Token.Generic.Prompt, " ")]\n'
+ ' return self.last_output["{0}"]'
+ ).format(prompt, 'in2' if prompt == 'continuation' else prompt))
diff --git a/powerline/bindings/lemonbar/powerline-lemonbar.py b/powerline/bindings/lemonbar/powerline-lemonbar.py
new file mode 100755
index 0000000..7637254
--- /dev/null
+++ b/powerline/bindings/lemonbar/powerline-lemonbar.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import time
+import re
+import subprocess
+
+from threading import Lock, Timer
+
+from powerline.lemonbar import LemonbarPowerline
+from powerline.commands.lemonbar import get_argparser
+from powerline.bindings.wm import get_connected_xrandr_outputs
+
+
+if __name__ == '__main__':
+ parser = get_argparser()
+ args = parser.parse_args()
+
+ powerline = LemonbarPowerline()
+ powerline.update_renderer()
+ bars = []
+
+ for screen in get_connected_xrandr_outputs(powerline.pl):
+ command = [args.bar_command, '-g', '{0}x{1}+{2}'.format(screen['width'], args.height, screen['x'])] + args.args[1:]
+ process = subprocess.Popen(command, stdin=subprocess.PIPE)
+ bars.append((screen['name'], process, int(screen['width']) / 5))
+
+ lock = Lock()
+ modes = ['default']
+
+ def render(reschedule=False):
+ if reschedule:
+ Timer(args.interval, render, kwargs={'reschedule': True}).start()
+
+ global lock
+ with lock:
+ for output, process, width in bars:
+ process.stdin.write(powerline.render(mode=modes[0], width=width, matcher_info=output).encode('utf-8') + b'\n')
+ process.stdin.flush()
+
+ def update(evt):
+ modes[0] = evt.change
+ render()
+
+ render(reschedule=True)
+
+ if args.i3:
+ try:
+ import i3ipc
+ except ImportError:
+ import i3
+ i3.Subscription(lambda evt, data, sub: render(), 'workspace')
+ else:
+ conn = i3ipc.Connection()
+ conn.on('workspace::focus', lambda conn, evt: render())
+ conn.on('mode', lambda conn, evt: update(evt))
+ conn.main()
+
+ while True:
+ time.sleep(1e8)
diff --git a/powerline/bindings/pdb/__init__.py b/powerline/bindings/pdb/__init__.py
new file mode 100644
index 0000000..4033e61
--- /dev/null
+++ b/powerline/bindings/pdb/__init__.py
@@ -0,0 +1,183 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import sys
+import pdb
+
+from powerline.pdb import PDBPowerline
+from powerline.lib.encoding import get_preferred_output_encoding
+from powerline.lib.unicode import unicode
+
+
+if sys.version_info < (3,):
+ # XXX The below classes make code compatible with PDBpp which uses pyrepl
+ # which does not expect unicode or something above ASCII. They are
+ # completely not needed if pdbpp is not used, but that’s not always the
+ # case.
+ class PowerlineRenderBytesResult(bytes):
+ def __new__(cls, s, encoding=None):
+ encoding = encoding or s.encoding
+ if isinstance(s, PowerlineRenderResult):
+ return s.encode(encoding)
+ self = bytes.__new__(cls, s.encode(encoding) if isinstance(s, unicode) else s)
+ self.encoding = encoding
+ return self
+
+ for meth in (
+ '__contains__',
+ 'partition', 'rpartition',
+ 'split', 'rsplit',
+ 'count', 'join',
+ ):
+ exec((
+ 'def {0}(self, *args):\n'
+ ' if any((isinstance(arg, unicode) for arg in args)):\n'
+ ' return self.__unicode__().{0}(*args)\n'
+ ' else:\n'
+ ' return bytes.{0}(self, *args)'
+ ).format(meth))
+
+ for meth in (
+ 'find', 'rfind',
+ 'index', 'rindex',
+ ):
+ exec((
+ 'def {0}(self, *args):\n'
+ ' if any((isinstance(arg, unicode) for arg in args)):\n'
+ ' args = [arg.encode(self.encoding) if isinstance(arg, unicode) else arg for arg in args]\n'
+ ' return bytes.{0}(self, *args)'
+ ).format(meth))
+
+ def __len__(self):
+ return len(self.decode(self.encoding))
+
+ def __getitem__(self, *args):
+ return PowerlineRenderBytesResult(bytes.__getitem__(self, *args), encoding=self.encoding)
+
+ def __getslice__(self, *args):
+ return PowerlineRenderBytesResult(bytes.__getslice__(self, *args), encoding=self.encoding)
+
+ @staticmethod
+ def add(encoding, *args):
+ if any((isinstance(arg, unicode) for arg in args)):
+ return PowerlineRenderResult(''.join((
+ arg
+ if isinstance(arg, unicode)
+ else arg.decode(encoding)
+ for arg in args
+ )), encoding)
+ else:
+ return PowerlineRenderBytesResult(b''.join(args), encoding=encoding)
+
+ def __add__(self, other):
+ return self.add(self.encoding, self, other)
+
+ def __radd__(self, other):
+ return self.add(self.encoding, other, self)
+
+ def __unicode__(self):
+ return PowerlineRenderResult(self)
+
+ class PowerlineRenderResult(unicode):
+ def __new__(cls, s, encoding=None):
+ encoding = (
+ encoding
+ or getattr(s, 'encoding', None)
+ or get_preferred_output_encoding()
+ )
+ if isinstance(s, unicode):
+ self = unicode.__new__(cls, s)
+ else:
+ self = unicode.__new__(cls, s, encoding, 'replace')
+ self.encoding = encoding
+ return self
+
+ def __str__(self):
+ return PowerlineRenderBytesResult(self)
+
+ def __getitem__(self, *args):
+ return PowerlineRenderResult(unicode.__getitem__(self, *args))
+
+ def __getslice__(self, *args):
+ return PowerlineRenderResult(unicode.__getslice__(self, *args))
+
+ @staticmethod
+ def add(encoding, *args):
+ return PowerlineRenderResult(''.join((
+ arg
+ if isinstance(arg, unicode)
+ else arg.decode(encoding)
+ for arg in args
+ )), encoding)
+
+ def __add__(self, other):
+ return self.add(self.encoding, self, other)
+
+ def __radd__(self, other):
+ return self.add(self.encoding, other, self)
+
+ def encode(self, *args, **kwargs):
+ return PowerlineRenderBytesResult(unicode.encode(self, *args, **kwargs), args[0])
+else:
+ PowerlineRenderResult = str
+
+
+def use_powerline_prompt(cls):
+ '''Decorator that installs powerline prompt to the class
+
+ :param pdb.Pdb cls:
+ Class that should be decorated.
+
+ :return:
+ ``cls`` argument or a class derived from it. Latter is used to turn
+ old-style classes into new-style classes.
+ '''
+ @property
+ def prompt(self):
+ try:
+ powerline = self.powerline
+ except AttributeError:
+ powerline = PDBPowerline()
+ powerline.setup(self)
+ self.powerline = powerline
+ return PowerlineRenderResult(powerline.render(side='left'))
+
+ @prompt.setter
+ def prompt(self, _):
+ pass
+
+ @prompt.deleter
+ def prompt(self):
+ pass
+
+ if not hasattr(cls, '__class__'):
+ # Old-style class: make it new-style or @property will not work.
+ old_cls = cls
+
+ class cls(cls, object):
+ __module__ = cls.__module__
+ __doc__ = cls.__doc__
+
+ cls.__name__ = old_cls.__name__
+
+ cls.prompt = prompt
+
+ return cls
+
+
+def main():
+ '''Run module as a script
+
+ Uses :py:func:`pdb.main` function directly, but prior to that it mocks
+ :py:class:`pdb.Pdb` class with powerline-specific class instance.
+ '''
+ orig_pdb = pdb.Pdb
+
+ @use_powerline_prompt
+ class Pdb(pdb.Pdb, object):
+ def __init__(self):
+ orig_pdb.__init__(self)
+
+ pdb.Pdb = Pdb
+
+ return pdb.main()
diff --git a/powerline/bindings/pdb/__main__.py b/powerline/bindings/pdb/__main__.py
new file mode 100755
index 0000000..768b2f2
--- /dev/null
+++ b/powerline/bindings/pdb/__main__.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+from powerline.bindings.pdb import main
+
+
+if __name__ == '__main__':
+ main()
diff --git a/powerline/bindings/qtile/__init__.py b/powerline/bindings/qtile/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/powerline/bindings/qtile/__init__.py
diff --git a/powerline/bindings/qtile/widget.py b/powerline/bindings/qtile/widget.py
new file mode 100644
index 0000000..92e3a27
--- /dev/null
+++ b/powerline/bindings/qtile/widget.py
@@ -0,0 +1,61 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+from libqtile.bar import CALCULATED
+from libqtile.widget import TextBox
+
+from powerline import Powerline
+
+
+class QTilePowerline(Powerline):
+ def do_setup(self, obj):
+ obj.powerline = self
+
+
+class PowerlineTextBox(TextBox):
+ # TODO Replace timeout argument with update_interval argument in next major
+ # release.
+ def __init__(self, timeout=2, text=b' ', width=CALCULATED, side='right', update_interval=None, **config):
+ super(PowerlineTextBox, self).__init__(text, width, **config)
+ self.side = side
+ self.update_interval = update_interval or timeout
+ self.did_run_timer_setup = False
+ powerline = QTilePowerline(ext='wm', renderer_module='pango_markup')
+ powerline.setup(self)
+
+ def update(self):
+ if not self.configured:
+ return True
+ self.text = self.powerline.render(side=self.side).encode('utf-8')
+ self.bar.draw()
+ return True
+
+ def cmd_update(self, text):
+ self.update(text)
+
+ def cmd_get(self):
+ return self.text
+
+ def timer_setup(self):
+ if not self.did_run_timer_setup:
+ self.did_run_timer_setup = True
+ self.timeout_add(self.update_interval, self.update)
+
+ def _configure(self, qtile, bar):
+ super(PowerlineTextBox, self)._configure(qtile, bar)
+ if self.layout.markup:
+ # QTile-0.9.1: no need to recreate layout or run timer_setup
+ return
+ self.layout = self.drawer.textlayout(
+ self.text,
+ self.foreground,
+ self.font,
+ self.fontsize,
+ self.fontshadow,
+ markup=True,
+ )
+ self.timer_setup()
+
+
+# TODO: Remove this at next major release
+Powerline = PowerlineTextBox
diff --git a/powerline/bindings/rc/powerline.rc b/powerline/bindings/rc/powerline.rc
new file mode 100644
index 0000000..b2d6538
--- /dev/null
+++ b/powerline/bindings/rc/powerline.rc
@@ -0,0 +1,92 @@
+fn _powerline_sigwinch {
+ _POWERLINE_COLUMNS = `{
+ stty size | cut -d' ' -f2
+ }
+ _powerline_tmux_setenv COLUMNS $_POWERLINE_COLUMNS
+}
+fn _powerline_update_pwd {
+ _POWERLINE_NEW_PWD = `{pwd}
+ if (test $^_POWERLINE_NEW_PWD '=' $^_POWERLINE_SAVED_PWD) {
+ _POWERLINE_SAVED_PWD = $_POWERLINE_NEW_PWD
+ _powerline_tmux_setenv PWD $_POWERLINE_SAVED_PWD
+ }
+}
+fn _powerline_continuation_prompt {
+ _powerline_prompt --renderer-arg 'local_theme=continuation' $*
+}
+fn _powerline_prompt {
+ $POWERLINE_COMMAND $POWERLINE_COMMAND_ARGS shell aboveleft -r.readline --last-pipe-status $^_POWERLINE_STATUS --last-exit-code $_POWERLINE_STATUS($#_POWERLINE_STATUS) --jobnum $_POWERLINE_JOBNUM --renderer-arg 'client_id='$pid $*
+}
+fn _powerline_set_prompt {
+ _POWERLINE_STATUS = ( $status )
+ _POWERLINE_JOBNUM = $#apids
+ prompt = (``() {
+ _powerline_prompt
+ } ``() {
+ _powerline_continuation_prompt
+ })
+ _powerline_update_pwd
+}
+
+fn _powerline_common_setup {
+ fn sigwinch {
+ _powerline_sigwinch
+ }
+ _powerline_sigwinch
+ _POWERLINE_SAVED_PWD = ''
+}
+
+fn _powerline_tmux_pane {
+ if (test -n $TMUX_PANE) {
+ echo $TMUX_PANE | tr -d ' %'
+ } else {
+ TMUX=$_POWERLINE_TMUX tmux display -p '#D' | tr -d ' %'
+ }
+}
+
+fn _powerline_tmux_setenv {
+}
+
+if (test -z $POWERLINE_CONFIG_COMMAND) {
+ if (which powerline-config >/dev/null) {
+ POWERLINE_CONFIG_COMMAND = powerline-config
+ } else {
+ echo powerline-config executable not found, unable to proceed >[2=1]
+ }
+}
+if (test -n $POWERLINE_CONFIG_COMMAND) {
+ if ($POWERLINE_CONFIG_COMMAND shell --shell rcsh uses prompt) {
+ if (test -n $POWERLINE_COMMAND_ARGS) {
+ # Perform splitting
+ POWERLINE_COMMAND_ARGS=( `{echo $POWERLINE_COMMAND_ARGS} )
+ }
+ fn prompt {
+ _powerline_set_prompt
+ }
+ if (test -z $POWERLINE_SHELL_CONTINUATION$POWERLINE_RCSH_CONTINUATION) {
+ _POWERLINE_STATUS = 0
+ _POWERLINE_JOBNUM = 0
+ _POWERLINE_CONTINUATION = `{
+ _powerline_continuation_prompt
+ }
+ fn _powerline_continuation_prompt {
+ echo -n $_POWERLINE_CONTINUATION
+ }
+ }
+ _powerline_common_setup
+ }
+ if (test -n $TMUX) {
+ if ($POWERLINE_CONFIG_COMMAND shell --shell rcsh uses tmux) {
+ _POWERLINE_TMUX=$TMUX
+ fn _powerline_tmux_setenv {
+ if (test -n $2) {
+ TMUX=$_POWERLINE_TMUX tmux setenv -g TMUX_$1^_`{
+ _powerline_tmux_pane
+ } $2
+ }
+ }
+ _powerline_common_setup
+ }
+ }
+}
+# vim: ft=rcshell
diff --git a/powerline/bindings/shell/powerline.sh b/powerline/bindings/shell/powerline.sh
new file mode 100644
index 0000000..15e13f2
--- /dev/null
+++ b/powerline/bindings/shell/powerline.sh
@@ -0,0 +1,239 @@
+_POWERLINE_SOURCED="$_"
+_powerline_columns_fallback() {
+ if which stty >/dev/null ; then
+ # Ksh does not have “local” built-in
+ _powerline_cols="$(stty size 2>/dev/null)"
+ if ! test -z "$_powerline_cols" ; then
+ echo "${_powerline_cols#* }"
+ return 0
+ fi
+ fi
+ echo 0
+ return 0
+}
+
+_powerline_has_jobs_in_subshell() {
+ if test -n "$_POWERLINE_HAS_JOBS_IN_SUBSHELL" ; then
+ return $_POWERLINE_HAS_JOBS_IN_SUBSHELL
+ elif test -z "$1" ; then
+ sleep 1 &
+ # Check whether shell outputs anything in a subshell when using jobs
+ # built-in. Shells like dash will not output anything meaning that
+ # I have to bother with temporary files.
+ test "$(jobs -p|wc -l)" -gt 0
+ else
+ case "$1" in
+ dash|bb|ash) return 1 ;;
+ mksh|ksh|bash) return 0 ;;
+ *) _powerline_has_jobs_in_subshell ;;
+ esac
+ fi
+ _POWERLINE_HAS_JOBS_IN_SUBSHELL=$?
+ return $_POWERLINE_HAS_JOBS_IN_SUBSHELL
+}
+
+_powerline_set_append_trap() {
+ if _powerline_has_jobs_in_subshell "$@" ; then
+ _powerline_append_trap() {
+ # Arguments: command, signal
+ # Ksh does not have “local” built-in
+ _powerline_traps="$(trap)"
+ if echo "$_powerline_traps" | grep -cm1 $2'$' >/dev/null ; then
+ _powerline_traps="$(echo "$_powerline_traps" | sed "s/ $2/'\\n$1' $2/")"
+ eval "$_powerline_traps"
+ else
+ trap "$1" $2
+ fi
+ }
+ else
+ _powerline_append_trap() {
+ # Arguments: command, signal
+ _powerline_create_temp
+ trap > $_POWERLINE_TEMP
+ if grep -cm1 $2'$' $_POWERLINE_TEMP >/dev/null ; then
+ sed -i -e "s/ $2/'\\n$1' $2/"
+ . $_POWERLINE_TEMP
+ else
+ trap "$1" $2
+ fi
+ echo -n > $_POWERLINE_TEMP
+ }
+ fi
+ _powerline_set_append_trap() {
+ return 0
+ }
+}
+
+_powerline_create_temp() {
+ if test -z "$_POWERLINE_TEMP" || ! test -e "$_POWERLINE_TEMP" ; then
+ _POWERLINE_TEMP="$(mktemp "${TMPDIR:-/tmp}/powerline.XXXXXXXX")"
+ _powerline_append_trap 'rm $_POWERLINE_TEMP' EXIT
+ fi
+}
+
+_powerline_set_set_jobs() {
+ if _powerline_has_jobs_in_subshell "$@" ; then
+ _powerline_set_jobs() {
+ _POWERLINE_JOBS="$(jobs -p|wc -l|tr -d ' ')"
+ }
+ else
+ _powerline_set_append_trap "$@"
+ _POWERLINE_PID=$$
+ _powerline_append_trap '_powerline_do_set_jobs' USR1
+ _powerline_do_set_jobs() {
+ _powerline_create_temp
+ jobs -p > $_POWERLINE_TEMP
+ }
+ # This command will always be launched from a subshell, thus a hack is
+ # needed to run `jobs -p` outside of the subshell.
+ _powerline_set_jobs() {
+ kill -USR1 $_POWERLINE_PID
+ # Note: most likely this will read data from the previous run. Tests
+ # show that it is OK for some reasons.
+ _POWERLINE_JOBS="$(wc -l < $_POWERLINE_TEMP | tr -d ' ')"
+ }
+ fi
+ _powerline_set_set_jobs() {
+ return 0
+ }
+}
+
+_powerline_set_command() {
+ if test -z "${POWERLINE_COMMAND}" ; then
+ POWERLINE_COMMAND="$("$POWERLINE_CONFIG_COMMAND" shell command)"
+ fi
+}
+
+_powerline_tmux_pane() {
+ echo "${TMUX_PANE:-`TMUX="$_POWERLINE_TMUX" tmux display -p "#D"`}" | \
+ tr -d ' %'
+}
+
+_powerline_tmux_setenv() {
+ TMUX="$_POWERLINE_TMUX" tmux setenv -g TMUX_"$1"_`_powerline_tmux_pane` "$2"
+ TMUX="$_POWERLINE_TMUX" tmux refresh -S
+}
+
+_powerline_tmux_set_pwd() {
+ if test "$_POWERLINE_SAVED_PWD" != "$PWD" ; then
+ _POWERLINE_SAVED_PWD="$PWD"
+ _powerline_tmux_setenv PWD "$PWD"
+ fi
+}
+
+_powerline_tmux_set_columns() {
+ _powerline_tmux_setenv COLUMNS "${COLUMNS:-$(_powerline_columns_fallback)}"
+}
+
+_powerline_set_renderer_arg() {
+ case "$1" in
+ bb|ash) _POWERLINE_RENDERER_ARG="-r .bash" ;;
+ mksh|ksh) _POWERLINE_RENDERER_ARG="-r .ksh" ;;
+ bash|dash) _POWERLINE_RENDERER_ARG= ;;
+ esac
+}
+
+_powerline_set_jobs() {
+ _powerline_set_set_jobs
+ _powerline_set_jobs
+}
+
+_powerline_local_prompt() {
+ # Arguments: side, exit_code, local theme
+ _powerline_set_jobs
+ "$POWERLINE_COMMAND" $POWERLINE_COMMAND_ARGS shell $1 \
+ $_POWERLINE_RENDERER_ARG \
+ --renderer-arg="client_id=$$" \
+ --last-exit-code=$2 \
+ --jobnum=$_POWERLINE_JOBS \
+ --renderer-arg="local_theme=$3"
+}
+
+_powerline_prompt() {
+ # Arguments: side, exit_code
+ _powerline_set_jobs
+ "$POWERLINE_COMMAND" $POWERLINE_COMMAND_ARGS shell $1 \
+ --width="${COLUMNS:-$(_powerline_columns_fallback)}" \
+ $_POWERLINE_RENDERER_ARG \
+ --renderer-arg="client_id=$$" \
+ --last-exit-code=$2 \
+ --jobnum=$_POWERLINE_JOBS
+ _powerline_update_psN
+}
+
+_powerline_setup_psN() {
+ case "$1" in
+ mksh|ksh|bash)
+ _POWERLINE_PID=$$
+ _powerline_update_psN() {
+ kill -USR1 $_POWERLINE_PID
+ }
+ # No command substitution in PS2 and PS3
+ _powerline_set_psN() {
+ if test -n "$POWERLINE_SHELL_CONTINUATION" ; then
+ PS2="$(_powerline_local_prompt left $? continuation)"
+ fi
+ if test -n "$POWERLINE_SHELL_SELECT" ; then
+ PS3="$(_powerline_local_prompt left $? select)"
+ fi
+ }
+ _powerline_append_trap '_powerline_set_psN' USR1
+ _powerline_set_psN
+ ;;
+ bb|ash|dash)
+ _powerline_update_psN() {
+ # Do nothing
+ return
+ }
+ PS2='$(_powerline_local_prompt left $? continuation)'
+ # No select support
+ ;;
+ esac
+}
+
+_powerline_setup_prompt() {
+ VIRTUAL_ENV_DISABLE_PROMPT=1
+ _powerline_set_append_trap "$@"
+ _powerline_set_set_jobs "$@"
+ _powerline_set_command "$@"
+ _powerline_set_renderer_arg "$@"
+ PS1='$(_powerline_prompt aboveleft $?)'
+ PS2="$(_powerline_local_prompt left 0 continuation)"
+ PS3="$(_powerline_local_prompt left 0 select)"
+ _powerline_setup_psN "$@"
+}
+
+_powerline_init_tmux_support() {
+ # Dash does not have &>/dev/null
+ if test -n "$TMUX" && tmux refresh -S >/dev/null 2>/dev/null ; then
+ # TMUX variable may be unset to create new tmux session inside this one
+ _POWERLINE_TMUX="$TMUX"
+
+ _powerline_set_append_trap "$@"
+
+ # If _powerline_tmux_set_pwd is used before _powerline_prompt it sets $?
+ # to zero in ksh.
+ PS1="$PS1"'$(_powerline_tmux_set_pwd)'
+ _powerline_append_trap '_powerline_tmux_set_columns' WINCH
+ _powerline_tmux_set_columns
+ fi
+}
+
+if test -z "${POWERLINE_CONFIG_COMMAND}" ; then
+ if which powerline-config >/dev/null ; then
+ POWERLINE_CONFIG_COMMAND=powerline-config
+ else
+ POWERLINE_CONFIG_COMMAND="$(dirname "$_POWERLINE_SOURCED")/../../../scripts/powerline-config"
+ fi
+fi
+
+# Strips the leading `-`: it may be present when shell is a login shell
+_POWERLINE_USED_SHELL=${0#-}
+_POWERLINE_USED_SHELL=${_POWERLINE_USED_SHELL##*/}
+
+if "${POWERLINE_CONFIG_COMMAND}" shell uses tmux ; then
+ _powerline_init_tmux_support $_POWERLINE_USED_SHELL
+fi
+if "${POWERLINE_CONFIG_COMMAND}" shell --shell=bash uses prompt ; then
+ _powerline_setup_prompt $_POWERLINE_USED_SHELL
+fi
diff --git a/powerline/bindings/tcsh/powerline.tcsh b/powerline/bindings/tcsh/powerline.tcsh
new file mode 100644
index 0000000..4897b4c
--- /dev/null
+++ b/powerline/bindings/tcsh/powerline.tcsh
@@ -0,0 +1,60 @@
+# http://unix.stackexchange.com/questions/4650/determining-path-to-sourced-shell-script:
+# > In tcsh, $_ at the beginning of the script will contain the location if the
+# > file was sourced and $0 contains it if it was run.
+#
+# Guess this relies on `$_` being set as to last argument to previous command
+# which must be `.` or `source` in this case
+set POWERLINE_SOURCED=($_)
+if ! $?POWERLINE_CONFIG_COMMAND then
+ if ( { which powerline-config > /dev/null } ) then
+ set POWERLINE_CONFIG_COMMAND="powerline-config"
+ else
+ set POWERLINE_CONFIG_COMMAND="$POWERLINE_SOURCED[2]:h:h:h:h/scripts/powerline-config"
+ endif
+else
+ if "$POWERLINE_CONFIG_COMMAND" == "" then
+ if ( { which powerline-config > /dev/null } ) then
+ set POWERLINE_CONFIG_COMMAND="powerline-config"
+ else
+ set POWERLINE_CONFIG_COMMAND="$POWERLINE_SOURCED[2]:h:h:h:h/scripts/powerline-config"
+ endif
+ endif
+endif
+if ( { $POWERLINE_CONFIG_COMMAND shell --shell=tcsh uses tmux } ) then
+ if ( $?TMUX_PANE ) then
+ if ( "$TMUX_PANE" == "" ) then
+ set _POWERLINE_TMUX_PANE="`tmux display -p '#D'`"
+ else
+ set _POWERLINE_TMUX_PANE="$TMUX_PANE"
+ endif
+ else
+ set _POWERLINE_TMUX_PANE="`tmux display -p '#D'`"
+ endif
+ set _POWERLINE_TMUX_PANE="`echo $_POWERLINE_TMUX_PANE:q | tr -d '% '`"
+ alias _powerline_tmux_set_pwd 'if ( $?TMUX && { tmux refresh -S >&/dev/null } ) tmux setenv -g TMUX_PWD_$_POWERLINE_TMUX_PANE $PWD:q ; if ( $?TMUX ) tmux refresh -S >&/dev/null'
+ alias cwdcmd "`alias cwdcmd` ; _powerline_tmux_set_pwd"
+endif
+if ( { $POWERLINE_CONFIG_COMMAND shell --shell=tcsh uses prompt } ) then
+ if ! $?POWERLINE_COMMAND then
+ set POWERLINE_COMMAND="`$POWERLINE_CONFIG_COMMAND:q shell command`"
+ else
+ if "$POWERLINE_COMMAND" == "" then
+ set POWERLINE_COMMAND="`$POWERLINE_CONFIG_COMMAND:q shell command`"
+ endif
+ endif
+ if ! $?POWERLINE_COMMAND_ARGS then
+ set POWERLINE_COMMAND_ARGS=""
+ endif
+
+ if ( $?POWERLINE_NO_TCSH_ABOVE || $?POWERLINE_NO_SHELL_ABOVE ) then
+ alias _powerline_above true
+ else
+ alias _powerline_above '$POWERLINE_COMMAND:q $POWERLINE_COMMAND_ARGS shell above --renderer-arg=client_id=$$ --last-exit-code=$POWERLINE_STATUS --width=$POWERLINE_COLUMNS'
+ endif
+
+ alias _powerline_set_prompt 'set prompt="`$POWERLINE_COMMAND:q $POWERLINE_COMMAND_ARGS shell left -r .tcsh --renderer-arg=client_id=$$ --last-exit-code=$POWERLINE_STATUS --width=$POWERLINE_COLUMNS`"'
+ alias _powerline_set_rprompt 'set rprompt="`$POWERLINE_COMMAND:q $POWERLINE_COMMAND_ARGS shell right -r .tcsh --renderer-arg=client_id=$$ --last-exit-code=$POWERLINE_STATUS --width=$POWERLINE_COLUMNS`"'
+ alias _powerline_set_columns 'set POWERLINE_COLUMNS=`stty size|cut -d" " -f2` ; set POWERLINE_COLUMNS=`expr $POWERLINE_COLUMNS - 2`'
+
+ alias precmd 'set POWERLINE_STATUS=$? ; '"`alias precmd`"' ; _powerline_set_columns ; _powerline_above ; _powerline_set_prompt ; _powerline_set_rprompt'
+endif
diff --git a/powerline/bindings/tmux/__init__.py b/powerline/bindings/tmux/__init__.py
new file mode 100644
index 0000000..011cd68
--- /dev/null
+++ b/powerline/bindings/tmux/__init__.py
@@ -0,0 +1,84 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import re
+import os
+import subprocess
+
+from collections import namedtuple
+
+from powerline.lib.shell import run_cmd
+
+
+TmuxVersionInfo = namedtuple('TmuxVersionInfo', ('major', 'minor', 'suffix'))
+
+
+def get_tmux_executable_name():
+ '''Returns tmux executable name
+
+ It should be defined in POWERLINE_TMUX_EXE environment variable, otherwise
+ it is simply “tmux”.
+ '''
+
+ return os.environ.get('POWERLINE_TMUX_EXE', 'tmux')
+
+
+def _run_tmux(runner, args):
+ return runner([get_tmux_executable_name()] + list(args))
+
+
+def run_tmux_command(*args):
+ '''Run tmux command, ignoring the output'''
+ _run_tmux(subprocess.check_call, args)
+
+
+def get_tmux_output(pl, *args):
+ '''Run tmux command and return its output'''
+ return _run_tmux(lambda cmd: run_cmd(pl, cmd), args)
+
+
+def set_tmux_environment(varname, value, remove=True):
+ '''Set tmux global environment variable
+
+ :param str varname:
+ Name of the variable to set.
+ :param str value:
+ Variable value.
+ :param bool remove:
+ True if variable should be removed from the environment prior to
+ attaching any client (runs ``tmux set-environment -r {varname}``).
+ '''
+ run_tmux_command('set-environment', '-g', varname, value)
+ if remove:
+ try:
+ run_tmux_command('set-environment', '-r', varname)
+ except subprocess.CalledProcessError:
+ # On tmux-2.0 this command may fail for whatever reason. Since it is
+ # critical just ignore the failure.
+ pass
+
+
+def source_tmux_file(fname):
+ '''Source tmux configuration file
+
+ :param str fname:
+ Full path to the sourced file.
+ '''
+ run_tmux_command('source', fname)
+
+
+NON_DIGITS = re.compile('[^0-9]+')
+DIGITS = re.compile('[0-9]+')
+NON_LETTERS = re.compile('[^a-z]+')
+
+
+def get_tmux_version(pl):
+ version_string = get_tmux_output(pl, '-V')
+ _, version_string = version_string.split(' ')
+ version_string = version_string.strip()
+ if version_string == 'master':
+ return TmuxVersionInfo(float('inf'), 0, version_string)
+ major, minor = version_string.split('.')
+ suffix = DIGITS.subn('', minor)[0] or None
+ minor = NON_DIGITS.subn('', minor)[0]
+ return TmuxVersionInfo(int(major), int(minor), suffix)
diff --git a/powerline/bindings/tmux/powerline-base.conf b/powerline/bindings/tmux/powerline-base.conf
new file mode 100644
index 0000000..ca0bbf5
--- /dev/null
+++ b/powerline/bindings/tmux/powerline-base.conf
@@ -0,0 +1,11 @@
+set -g status on
+set -g status-interval 2
+set -g status-left-length 20
+set -g status-right '#(env "$POWERLINE_COMMAND" $POWERLINE_COMMAND_ARGS tmux right -R pane_id=\"`tmux display -p "#""D"`\")'
+set -g status-right-length 150
+set -g window-status-format "#[$_POWERLINE_WINDOW_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER_SPACES#I#F #[$_POWERLINE_WINDOW_DIVIDER_COLOR]$_POWERLINE_LEFT_SOFT_DIVIDER#[default]#W $_POWERLINE_LEFT_HARD_DIVIDER_SPACES"
+set -g window-status-current-format "#[$_POWERLINE_WINDOW_CURRENT_HARD_DIVIDER_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#[$_POWERLINE_WINDOW_CURRENT_COLOR]#I#F $_POWERLINE_LEFT_SOFT_DIVIDER#[$_POWERLINE_WINDOW_NAME_COLOR]#W #[$_POWERLINE_WINDOW_CURRENT_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER"
+
+# Legacy status-left definition to be overwritten for tmux Versions 1.8+
+set -g status-left "#[$_POWERLINE_SESSION_COLOR] #S #[$_POWERLINE_SESSION_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#(env \"\$POWERLINE_COMMAND\" tmux left -R pane_id=\"`tmux display -p '#''D'`\")"
+# vim: ft=tmux
diff --git a/powerline/bindings/tmux/powerline.conf b/powerline/bindings/tmux/powerline.conf
new file mode 100644
index 0000000..29ec6a4
--- /dev/null
+++ b/powerline/bindings/tmux/powerline.conf
@@ -0,0 +1,2 @@
+if-shell 'env "$POWERLINE_CONFIG_COMMAND" tmux setup' '' 'run-shell "powerline-config tmux setup"'
+# vim: ft=tmux
diff --git a/powerline/bindings/tmux/powerline_tmux_1.7_plus.conf b/powerline/bindings/tmux/powerline_tmux_1.7_plus.conf
new file mode 100644
index 0000000..ec225c0
--- /dev/null
+++ b/powerline/bindings/tmux/powerline_tmux_1.7_plus.conf
@@ -0,0 +1,3 @@
+set -g status-right '#(env "$POWERLINE_COMMAND" $POWERLINE_COMMAND_ARGS tmux right -R pane_id="`tmux display -p "#""D"`" --width=`tmux display -p "#""{client_width}"` -R width_adjust=`tmux show-options -g status-left-length | cut -d" " -f 2`)'
+set -g status-left "#[$_POWERLINE_SESSION_COLOR] #S #[$_POWERLINE_SESSION_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#(env \"\$POWERLINE_COMMAND\" tmux left --width=`tmux display -p '#''{client_width}'` -R width_adjust=`tmux show-options -g status-right-length | cut -d' ' -f2` -R pane_id=\"`tmux display -p '#''D'`\")"
+# vim: ft=tmux
diff --git a/powerline/bindings/tmux/powerline_tmux_1.8.conf b/powerline/bindings/tmux/powerline_tmux_1.8.conf
new file mode 100644
index 0000000..fbcd2a5
--- /dev/null
+++ b/powerline/bindings/tmux/powerline_tmux_1.8.conf
@@ -0,0 +1,5 @@
+# powerline_tmux_1.8.conf
+# tmux Version 1.8 introduces window-status-last-{attr,bg,fg}, which is
+# deprecated for versions 1.9+, thus only applicable to version 1.8.
+set -qg window-status-last-fg "$_POWERLINE_ACTIVE_WINDOW_FG"
+# vim: ft=tmux
diff --git a/powerline/bindings/tmux/powerline_tmux_1.8_minus.conf b/powerline/bindings/tmux/powerline_tmux_1.8_minus.conf
new file mode 100644
index 0000000..284eee0
--- /dev/null
+++ b/powerline/bindings/tmux/powerline_tmux_1.8_minus.conf
@@ -0,0 +1,11 @@
+# powerline_tmux_legacy_common.conf
+# tmux Version 1.8 and earlier (legacy) common options. The foo-{attr,bg,fg}
+# options are deprecated starting with tmux Version 1.9.
+set -g status-fg "$_POWERLINE_BACKGROUND_FG"
+set -g status-bg "$_POWERLINE_BACKGROUND_BG"
+set-window-option -g window-status-fg "$_POWERLINE_WINDOW_STATUS_FG"
+set-window-option -g window-status-activity-attr "$_POWERLINE_ACTIVITY_STATUS_ATTR_LEGACY"
+set-window-option -g window-status-bell-attr "$_POWERLINE_BELL_STATUS_ATTR_LEGACY"
+set-window-option -g window-status-activity-fg "$_POWERLINE_ACTIVITY_STATUS_FG"
+set-window-option -g window-status-bell-fg "$_POWERLINE_BELL_STATUS_FG"
+# vim: ft=tmux
diff --git a/powerline/bindings/tmux/powerline_tmux_1.8_plus.conf b/powerline/bindings/tmux/powerline_tmux_1.8_plus.conf
new file mode 100644
index 0000000..4edcf21
--- /dev/null
+++ b/powerline/bindings/tmux/powerline_tmux_1.8_plus.conf
@@ -0,0 +1,5 @@
+# powerline_tmux_1.8_plus.conf
+# tmux Version 1.8 introduces the 'client_prefix' format variable, applicable
+# for versions 1.8+
+set -qg status-left "#{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_FG]#[bg=$_POWERLINE_SESSION_PREFIX_BG]#[$_POWERLINE_SESSION_PREFIX_ATTR],#[fg=$_POWERLINE_SESSION_FG]#[bg=$_POWERLINE_SESSION_BG]#[$_POWERLINE_SESSION_ATTR]} #S #{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_BG],#[fg=$_POWERLINE_SESSION_BG]}#[bg=$_POWERLINE_BACKGROUND_BG]#[nobold]$_POWERLINE_LEFT_HARD_DIVIDER#(env \$POWERLINE_COMMAND \$POWERLINE_COMMAND_ARGS tmux left --width=`tmux display -p '#''{client_width}'` -R width_adjust=`tmux show-options -g status-right-length | cut -d' ' -f2` -R pane_id=\"`tmux display -p '#''D'`\")"
+# vim: ft=tmux
diff --git a/powerline/bindings/tmux/powerline_tmux_1.9_plus.conf b/powerline/bindings/tmux/powerline_tmux_1.9_plus.conf
new file mode 100644
index 0000000..7ab9a8b
--- /dev/null
+++ b/powerline/bindings/tmux/powerline_tmux_1.9_plus.conf
@@ -0,0 +1,8 @@
+# powerline_tmux_1.9_plus.conf
+# Version 1.9 introduces the foo-style options, applicable to version 1.9+
+set-option -qg status-style "$_POWERLINE_BACKGROUND_COLOR"
+set-option -qg window-status-last-style "$_POWERLINE_ACTIVE_WINDOW_STATUS_COLOR"
+set-window-option -qg window-status-style "$_POWERLINE_WINDOW_STATUS_COLOR"
+set-window-option -qg window-status-activity-style "$_POWERLINE_ACTIVITY_STATUS_COLOR"
+set-window-option -qg window-status-bell-style "$_POWERLINE_BELL_STATUS_COLOR"
+# vim: ft=tmux
diff --git a/powerline/bindings/tmux/powerline_tmux_2.1_plus.conf b/powerline/bindings/tmux/powerline_tmux_2.1_plus.conf
new file mode 100644
index 0000000..8bf8872
--- /dev/null
+++ b/powerline/bindings/tmux/powerline_tmux_2.1_plus.conf
@@ -0,0 +1,3 @@
+# Starting from tmux-2.1 escaping of dollar signs inside #() is harmful
+set -qg status-left "#{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_FG]#[bg=$_POWERLINE_SESSION_PREFIX_BG]#[$_POWERLINE_SESSION_PREFIX_ATTR],#[fg=$_POWERLINE_SESSION_FG]#[bg=$_POWERLINE_SESSION_BG]#[$_POWERLINE_SESSION_ATTR]} #S #{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_BG],#[fg=$_POWERLINE_SESSION_BG]}#[bg=$_POWERLINE_BACKGROUND_BG]#[nobold]$_POWERLINE_LEFT_HARD_DIVIDER#(env $POWERLINE_COMMAND $POWERLINE_COMMAND_ARGS tmux left --width=`tmux display -p '#''{client_width}'` -R width_adjust=`tmux show-options -g status-right-length | cut -d' ' -f2` -R pane_id=\"`tmux display -p '#''D'`\")"
+set -g window-status-format "#[$_POWERLINE_WINDOW_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER_SPACES#I#{?window_flags,#F, } #[$_POWERLINE_WINDOW_DIVIDER_COLOR]$_POWERLINE_LEFT_SOFT_DIVIDER#[default]#W $_POWERLINE_LEFT_HARD_DIVIDER_SPACES"
diff --git a/powerline/bindings/vim/__init__.py b/powerline/bindings/vim/__init__.py
new file mode 100644
index 0000000..b754c1f
--- /dev/null
+++ b/powerline/bindings/vim/__init__.py
@@ -0,0 +1,482 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import sys
+import codecs
+
+try:
+ import vim
+except ImportError:
+ vim = object()
+
+from powerline.lib.unicode import unicode
+
+
+if (
+ hasattr(vim, 'options')
+ and hasattr(vim, 'vvars')
+ and vim.vvars['version'] > 703
+):
+ if sys.version_info < (3,):
+ def get_vim_encoding():
+ return vim.options['encoding'] or 'ascii'
+ else:
+ def get_vim_encoding():
+ return vim.options['encoding'].decode('ascii') or 'ascii'
+elif hasattr(vim, 'eval'):
+ def get_vim_encoding():
+ return vim.eval('&encoding') or 'ascii'
+else:
+ def get_vim_encoding():
+ return 'utf-8'
+
+get_vim_encoding.__doc__ = (
+ '''Get encoding used for Vim strings
+
+ :return:
+ Value of ``&encoding``. If it is empty (i.e. Vim is compiled
+ without +multibyte) returns ``'ascii'``. When building documentation
+ outputs ``'utf-8'`` unconditionally.
+ '''
+)
+
+
+vim_encoding = get_vim_encoding()
+
+
+python_to_vim_types = {
+ unicode: (
+ lambda o: b'\'' + (o.translate({
+ ord('\''): '\'\'',
+ }).encode(vim_encoding)) + b'\''
+ ),
+ list: (
+ lambda o: b'[' + (
+ b','.join((python_to_vim(i) for i in o))
+ ) + b']'
+ ),
+ bytes: (lambda o: b'\'' + o.replace(b'\'', b'\'\'') + b'\''),
+ int: (str if str is bytes else (lambda o: unicode(o).encode('ascii'))),
+}
+python_to_vim_types[float] = python_to_vim_types[int]
+
+
+def python_to_vim(o):
+ return python_to_vim_types[type(o)](o)
+
+
+if sys.version_info < (3,):
+ def str_to_bytes(s):
+ return s
+
+ def unicode_eval(expr):
+ ret = vim.eval(expr)
+ return ret.decode(vim_encoding, 'powerline_vim_strtrans_error')
+else:
+ def str_to_bytes(s):
+ return s.encode(vim_encoding)
+
+ def unicode_eval(expr):
+ return vim.eval(expr)
+
+
+def safe_bytes_eval(expr):
+ return bytes(bytearray((
+ int(chunk) for chunk in (
+ vim.eval(
+ b'substitute(' + expr + b', ' +
+ b'\'^.*$\', \'\\=join(map(range(len(submatch(0))), ' +
+ b'"char2nr(submatch(0)[v:val])"))\', "")'
+ ).split()
+ )
+ )))
+
+
+def eval_bytes(expr):
+ try:
+ return str_to_bytes(vim.eval(expr))
+ except UnicodeDecodeError:
+ return safe_bytes_eval(expr)
+
+
+def eval_unicode(expr):
+ try:
+ return unicode_eval(expr)
+ except UnicodeDecodeError:
+ return safe_bytes_eval(expr).decode(vim_encoding, 'powerline_vim_strtrans_error')
+
+
+if hasattr(vim, 'bindeval'):
+ rettype_func = {
+ None: lambda f: f,
+ 'unicode': (
+ lambda f: (
+ lambda *args, **kwargs: (
+ f(*args, **kwargs).decode(
+ vim_encoding, 'powerline_vim_strtrans_error'
+ ))))
+ }
+ rettype_func['int'] = rettype_func['bytes'] = rettype_func[None]
+ rettype_func['str'] = rettype_func['bytes'] if str is bytes else rettype_func['unicode']
+
+ def vim_get_func(f, rettype=None):
+ '''Return a vim function binding.'''
+ try:
+ func = vim.bindeval('function("' + f + '")')
+ except vim.error:
+ return None
+ else:
+ return rettype_func[rettype](func)
+else:
+ rettype_eval = {
+ None: getattr(vim, 'eval', None),
+ 'int': lambda expr: int(vim.eval(expr)),
+ 'bytes': eval_bytes,
+ 'unicode': eval_unicode,
+ }
+ rettype_eval['str'] = rettype_eval[None]
+
+ class VimFunc(object):
+ '''Evaluate a vim function using vim.eval().
+
+ This is a fallback class for older vim versions.
+ '''
+ __slots__ = ('f', 'eval')
+
+ def __init__(self, f, rettype=None):
+ self.f = f.encode('utf-8')
+ self.eval = rettype_eval[rettype]
+
+ def __call__(self, *args):
+ return self.eval(self.f + b'(' + (b','.join((
+ python_to_vim(o) for o in args
+ ))) + b')')
+
+ vim_get_func = VimFunc
+
+
+def vim_get_autoload_func(f, rettype=None):
+ func = vim_get_func(f)
+ if not func:
+ vim.command('runtime! ' + f.replace('#', '/')[:f.rindex('#')] + '.vim')
+ func = vim_get_func(f)
+ return func
+
+
+if hasattr(vim, 'Function'):
+ def vim_func_exists(f):
+ try:
+ vim.Function(f)
+ except ValueError:
+ return False
+ else:
+ return True
+else:
+ def vim_func_exists(f):
+ try:
+ return bool(int(vim.eval('exists("*{0}")'.format(f))))
+ except vim.error:
+ return False
+
+
+if type(vim) is object:
+ vim_get_func = lambda *args, **kwargs: None
+
+
+_getbufvar = vim_get_func('getbufvar')
+_vim_exists = vim_get_func('exists', rettype='int')
+
+
+# It may crash on some old vim versions and I do not remember in which patch
+# I fixed this crash.
+if hasattr(vim, 'vvars') and vim.vvars[str('version')] > 703:
+ _vim_to_python_types = {
+ getattr(vim, 'Dictionary', None) or type(vim.bindeval('{}')):
+ lambda value: dict((
+ (_vim_to_python(k), _vim_to_python(v))
+ for k, v in value.items()
+ )),
+ getattr(vim, 'List', None) or type(vim.bindeval('[]')):
+ lambda value: [_vim_to_python(item) for item in value],
+ getattr(vim, 'Function', None) or type(vim.bindeval('function("mode")')):
+ lambda _: None,
+ }
+
+ def vim_getvar(varname):
+ return _vim_to_python(vim.vars[str(varname)])
+
+ def bufvar_exists(buffer, varname):
+ buffer = buffer or vim.current.buffer
+ return varname in buffer.vars
+
+ def vim_getwinvar(segment_info, varname):
+ return _vim_to_python(segment_info['window'].vars[str(varname)])
+
+ def vim_global_exists(name):
+ try:
+ vim.vars[name]
+ except KeyError:
+ return False
+ else:
+ return True
+else:
+ _vim_to_python_types = {
+ dict: (lambda value: dict(((k, _vim_to_python(v)) for k, v in value.items()))),
+ list: (lambda value: [_vim_to_python(i) for i in value]),
+ }
+
+ def vim_getvar(varname):
+ varname = 'g:' + varname
+ if _vim_exists(varname):
+ return vim.eval(varname)
+ else:
+ raise KeyError(varname)
+
+ def bufvar_exists(buffer, varname):
+ if not buffer or buffer.number == vim.current.buffer.number:
+ return int(vim.eval('exists("b:{0}")'.format(varname)))
+ else:
+ return int(vim.eval(
+ 'has_key(getbufvar({0}, ""), {1})'.format(buffer.number, varname)
+ ))
+
+ def vim_getwinvar(segment_info, varname):
+ result = vim.eval('getwinvar({0}, "{1}")'.format(segment_info['winnr'], varname))
+ if result == '':
+ if not int(vim.eval('has_key(getwinvar({0}, ""), "{1}")'.format(segment_info['winnr'], varname))):
+ raise KeyError(varname)
+ return result
+
+ def vim_global_exists(name):
+ return int(vim.eval('exists("g:' + name + '")'))
+
+
+def vim_command_exists(name):
+ return _vim_exists(':' + name)
+
+
+if sys.version_info < (3,):
+ getbufvar = _getbufvar
+else:
+ _vim_to_python_types[bytes] = lambda value: value.decode(vim_encoding)
+
+ def getbufvar(*args):
+ return _vim_to_python(_getbufvar(*args))
+
+
+_id = lambda value: value
+
+
+def _vim_to_python(value):
+ return _vim_to_python_types.get(type(value), _id)(value)
+
+
+if hasattr(vim, 'options'):
+ def vim_getbufoption(info, option):
+ return _vim_to_python(info['buffer'].options[str(option)])
+
+ def vim_getoption(option):
+ return vim.options[str(option)]
+
+ def vim_setoption(option, value):
+ vim.options[str(option)] = value
+else:
+ def vim_getbufoption(info, option):
+ return getbufvar(info['bufnr'], '&' + option)
+
+ def vim_getoption(option):
+ return vim.eval('&g:' + option)
+
+ def vim_setoption(option, value):
+ vim.command('let &g:{option} = {value}'.format(
+ option=option, value=python_to_vim(value)))
+
+
+if hasattr(vim, 'tabpages'):
+ current_tabpage = lambda: vim.current.tabpage
+ list_tabpages = lambda: vim.tabpages
+
+ def list_tabpage_buffers_segment_info(segment_info):
+ return (
+ {'buffer': window.buffer, 'bufnr': window.buffer.number}
+ for window in segment_info['tabpage'].windows
+ )
+else:
+ class FalseObject(object):
+ @staticmethod
+ def __nonzero__():
+ return False
+
+ __bool__ = __nonzero__
+
+ def get_buffer(number):
+ for buffer in vim.buffers:
+ if buffer.number == number:
+ return buffer
+ raise KeyError(number)
+
+ class WindowVars(object):
+ __slots__ = ('tabnr', 'winnr')
+
+ def __init__(self, window):
+ self.tabnr = window.tabnr
+ self.winnr = window.number
+
+ def __getitem__(self, key):
+ has_key = vim.eval('has_key(gettabwinvar({0}, {1}, ""), "{2}")'.format(self.tabnr, self.winnr, key))
+ if has_key == '0':
+ raise KeyError
+ return vim.eval('gettabwinvar({0}, {1}, "{2}")'.format(self.tabnr, self.winnr, key))
+
+ def get(self, key, default=None):
+ try:
+ return self[key]
+ except KeyError:
+ return default
+
+ class Window(FalseObject):
+ __slots__ = ('tabnr', 'number', '_vars')
+
+ def __init__(self, tabnr, number):
+ self.tabnr = tabnr
+ self.number = number
+ self.vars = WindowVars(self)
+
+ @property
+ def buffer(self):
+ return get_buffer(int(vim.eval('tabpagebuflist({0})[{1}]'.format(self.tabnr, self.number - 1))))
+
+ class Tabpage(FalseObject):
+ __slots__ = ('number',)
+
+ def __init__(self, number):
+ self.number = number
+
+ def __eq__(self, tabpage):
+ if not isinstance(tabpage, Tabpage):
+ raise NotImplementedError
+ return self.number == tabpage.number
+
+ @property
+ def window(self):
+ return Window(self.number, int(vim.eval('tabpagewinnr({0})'.format(self.number))))
+
+ def _last_tab_nr():
+ return int(vim.eval('tabpagenr("$")'))
+
+ def current_tabpage():
+ return Tabpage(int(vim.eval('tabpagenr()')))
+
+ def list_tabpages():
+ return [Tabpage(nr) for nr in range(1, _last_tab_nr() + 1)]
+
+ class TabBufSegmentInfo(dict):
+ def __getitem__(self, key):
+ try:
+ return super(TabBufSegmentInfo, self).__getitem__(key)
+ except KeyError:
+ if key != 'buffer':
+ raise
+ else:
+ buffer = get_buffer(super(TabBufSegmentInfo, self).__getitem__('bufnr'))
+ self['buffer'] = buffer
+ return buffer
+
+ def list_tabpage_buffers_segment_info(segment_info):
+ return (
+ TabBufSegmentInfo(bufnr=int(bufnrstr))
+ for bufnrstr in vim.eval('tabpagebuflist({0})'.format(segment_info['tabnr']))
+ )
+
+
+class VimEnviron(object):
+ @staticmethod
+ def __getitem__(key):
+ return vim.eval('$' + key)
+
+ @staticmethod
+ def get(key, default=None):
+ return vim.eval('$' + key) or default
+
+ @staticmethod
+ def __setitem__(key, value):
+ return vim.command(
+ 'let ${0}="{1}"'.format(
+ key,
+ value.replace('"', '\\"')
+ .replace('\\', '\\\\')
+ .replace('\n', '\\n')
+ .replace('\0', '')
+ )
+ )
+
+
+if sys.version_info < (3,):
+ def buffer_name(segment_info):
+ return segment_info['buffer'].name
+else:
+ vim_bufname = vim_get_func('bufname', rettype='bytes')
+
+ def buffer_name(segment_info):
+ try:
+ name = segment_info['buffer'].name
+ except UnicodeDecodeError:
+ return vim_bufname(segment_info['bufnr'])
+ else:
+ return name.encode(segment_info['encoding']) if name else None
+
+
+vim_strtrans = vim_get_func('strtrans', rettype='unicode')
+
+
+def powerline_vim_strtrans_error(e):
+ if not isinstance(e, UnicodeDecodeError):
+ raise NotImplementedError
+ text = vim_strtrans(e.object[e.start:e.end])
+ return (text, e.end)
+
+
+codecs.register_error('powerline_vim_strtrans_error', powerline_vim_strtrans_error)
+
+
+did_autocmd = False
+buffer_caches = []
+
+
+def register_buffer_cache(cachedict):
+ global did_autocmd
+ global buffer_caches
+ from powerline.vim import get_default_pycmd, pycmd
+ if not did_autocmd:
+ import __main__
+ __main__.powerline_on_bwipe = on_bwipe
+ vim.command('augroup Powerline')
+ vim.command(' autocmd! BufWipeout * :{pycmd} powerline_on_bwipe()'.format(
+ pycmd=(pycmd or get_default_pycmd())))
+ vim.command('augroup END')
+ did_autocmd = True
+ buffer_caches.append(cachedict)
+ return cachedict
+
+
+def on_bwipe():
+ global buffer_caches
+ bufnr = int(vim.eval('expand("<abuf>")'))
+ for cachedict in buffer_caches:
+ cachedict.pop(bufnr, None)
+
+
+environ = VimEnviron()
+
+
+def create_ruby_dpowerline():
+ vim.command((
+ '''
+ ruby
+ if $powerline == nil
+ class Powerline
+ end
+ $powerline = Powerline.new
+ end
+ '''
+ ))
diff --git a/powerline/bindings/vim/autoload/powerline/debug.vim b/powerline/bindings/vim/autoload/powerline/debug.vim
new file mode 100644
index 0000000..244319a
--- /dev/null
+++ b/powerline/bindings/vim/autoload/powerline/debug.vim
@@ -0,0 +1,20 @@
+python import cProfile
+python powerline_pr = cProfile.Profile()
+
+function powerline#debug#profile_pyeval(s)
+ python powerline_pr.enable()
+ try
+ let ret = pyeval(a:s)
+ finally
+ python powerline_pr.disable()
+ endtry
+ return ret
+endfunction
+
+function powerline#debug#write_profile(fname)
+ python import vim
+ python powerline_pr.dump_stats(vim.eval('a:fname'))
+ python powerline_pr = cProfile.Profile()
+endfunction
+
+command -nargs=1 -complete=file WriteProfiling :call powerline#debug#write_profile(<q-args>)
diff --git a/powerline/bindings/vim/plugin/powerline.vim b/powerline/bindings/vim/plugin/powerline.vim
new file mode 100644
index 0000000..11ec05e
--- /dev/null
+++ b/powerline/bindings/vim/plugin/powerline.vim
@@ -0,0 +1,169 @@
+if exists('g:powerline_loaded')
+ finish
+endif
+let g:powerline_loaded = 1
+
+if exists('g:powerline_pycmd')
+ let s:pycmd = substitute(g:powerline_pycmd, '\v\C^(py)%[thon](3?)$', '\1\2', '')
+ if s:pycmd is# 'py'
+ let s:has_python = has('python')
+ let s:pyeval = get(g:, 'powerline_pyeval', 'pyeval')
+ elseif s:pycmd is# 'py3'
+ let s:has_python = has('python3')
+ let s:pyeval = 'py3eval'
+ let s:pyeval = get(g:, 'powerline_pyeval', 'py3eval')
+ else
+ if !exists('g:powerline_pyeval')
+ echohl ErrorMsg
+ echomsg 'g:powerline_pycmd was set to an unknown values, but g:powerline_pyeval'
+ echomsg 'was not set. You should either set g:powerline_pycmd to "py3" or "py",'
+ echomsg 'specify g:powerline_pyeval explicitly or unset both and let powerline'
+ echomsg 'figure them out.'
+ echohl None
+ unlet s:pycmd
+ finish
+ endif
+ let s:pyeval = g:powerline_pyeval
+ let s:has_python = 1
+ endif
+elseif has('python')
+ let s:has_python = 1
+ let s:pycmd = 'py'
+ let s:pyeval = get(g:, 'powerline_pyeval', 'pyeval')
+elseif has('python3')
+ let s:has_python = 1
+ let s:pycmd = 'py3'
+ let s:pyeval = get(g:, 'powerline_pyeval', 'py3eval')
+else
+ let s:has_python = 0
+endif
+
+if !s:has_python
+ if !exists('g:powerline_no_python_error')
+ echohl ErrorMsg
+ echomsg 'You need vim compiled with Python 2.6, 2.7 or 3.2 and later support'
+ echomsg 'for Powerline to work. Please consult the documentation for more'
+ echomsg 'details.'
+ echohl None
+ endif
+ unlet s:has_python
+ finish
+endif
+unlet s:has_python
+
+let s:import_cmd = 'from powerline.vim import VimPowerline'
+function s:rcmd(s)
+ if !exists('s:pystr')
+ let s:pystr = a:s . "\n"
+ else
+ let s:pystr = s:pystr . a:s . "\n"
+ endif
+endfunction
+try
+ let s:can_replace_pyeval = !exists('g:powerline_pyeval')
+ call s:rcmd('try:')
+ call s:rcmd(' powerline_appended_path = None')
+ call s:rcmd(' try:')
+ call s:rcmd(' '.s:import_cmd.'')
+ call s:rcmd(' except ImportError:')
+ call s:rcmd(' import sys, vim')
+ call s:rcmd(' powerline_appended_path = vim.eval("expand(\"<sfile>:h:h:h:h:h\")")')
+ call s:rcmd(' sys.path.append(powerline_appended_path)')
+ call s:rcmd(' '.s:import_cmd.'')
+ call s:rcmd(' import vim')
+ call s:rcmd(' powerline_instance = VimPowerline()')
+ call s:rcmd(' powerline_instance.setup(pyeval=vim.eval("s:pyeval"), pycmd=vim.eval("s:pycmd"), can_replace_pyeval=int(vim.eval("s:can_replace_pyeval")))')
+ call s:rcmd(' del VimPowerline')
+ call s:rcmd(' del powerline_instance')
+ call s:rcmd('except Exception:')
+ call s:rcmd(' import traceback, sys')
+ call s:rcmd(' traceback.print_exc(file=sys.stdout)')
+ call s:rcmd(' raise')
+ execute s:pycmd s:pystr
+ unlet s:pystr
+ let s:launched = 1
+finally
+ unlet s:can_replace_pyeval
+ unlet s:import_cmd
+ if !exists('s:launched')
+ unlet s:pystr
+ echohl ErrorMsg
+ echomsg 'An error occurred while importing powerline module.'
+ echomsg 'This could be caused by invalid sys.path setting,'
+ echomsg 'or by an incompatible Python version (powerline requires'
+ echomsg 'Python 2.6, 2.7 or 3.2 and later to work). Please consult'
+ echomsg 'the troubleshooting section in the documentation for'
+ echomsg 'possible solutions.'
+ if s:pycmd is# 'py' && has('python3')
+ echomsg 'If powerline on your system is installed for python 3 only you'
+ echomsg 'should set g:powerline_pycmd to "py3" to make it load correctly.'
+ endif
+ echohl None
+ call s:rcmd('def powerline_troubleshoot():')
+ call s:rcmd(' import sys')
+ call s:rcmd(' import vim')
+ call s:rcmd(' if sys.version_info < (2, 6):')
+ call s:rcmd(' print("Too old python version: " + sys.version + " (first supported is 2.6)")')
+ call s:rcmd(' elif sys.version_info[0] == 3 and sys.version_info[1] < 2:')
+ call s:rcmd(' print("Too old python 3 version: " + sys.version + " (first supported is 3.2)")')
+ call s:rcmd(' try:')
+ call s:rcmd(' import powerline')
+ call s:rcmd(' except ImportError:')
+ call s:rcmd(' print("Unable to import powerline, is it installed?")')
+ call s:rcmd(' else:')
+ call s:rcmd(' if not vim.eval(''expand("<sfile>")'').startswith("/usr/"):')
+ call s:rcmd(' import os')
+ call s:rcmd(' powerline_dir = os.path.realpath(os.path.normpath(powerline.__file__))')
+ call s:rcmd(' powerline_dir = os.path.dirname(powerline.__file__)')
+ call s:rcmd(' this_dir = os.path.realpath(os.path.normpath(vim.eval(''expand("<sfile>:p")'')))')
+ call s:rcmd(' this_dir = os.path.dirname(this_dir)') " powerline/bindings/vim/plugin
+ call s:rcmd(' this_dir = os.path.dirname(this_dir)') " powerline/bindings/vim
+ call s:rcmd(' this_dir = os.path.dirname(this_dir)') " powerline/bindings
+ call s:rcmd(' this_dir = os.path.dirname(this_dir)') " powerline
+ call s:rcmd(' if os.path.basename(this_dir) != "powerline":')
+ call s:rcmd(' print("Check your installation:")')
+ call s:rcmd(' print("this script is not in powerline[/bindings/vim/plugin] directory,")')
+ call s:rcmd(' print("neither it is installed system-wide")')
+ call s:rcmd(' real_powerline_dir = os.path.realpath(powerline_dir)')
+ call s:rcmd(' real_this_dir = os.path.realpath(this_dir)')
+ call s:rcmd(' this_dir_par = os.path.dirname(real_this_dir)')
+ call s:rcmd(' powerline_appended_path = globals().get("powerline_appended_path")')
+ call s:rcmd(' if powerline_appended_path is not None and this_dir_par != powerline_appended_path:')
+ call s:rcmd(' print("Check your installation: this script is symlinked somewhere")')
+ call s:rcmd(' print("where powerline is not present: {0!r} != {1!r}.".format(')
+ call s:rcmd(' real_this_dir, powerline_appended_path))')
+ call s:rcmd(' elif real_powerline_dir != real_this_dir:')
+ call s:rcmd(' print("It appears that you have two powerline versions installed:")')
+ call s:rcmd(' print("one in " + real_powerline_dir + ", other in " + real_this_dir + ".")')
+ call s:rcmd(' print("You should remove one of this. Check out troubleshooting section,")')
+ call s:rcmd(' print("it contains some information about the alternatives.")')
+ call s:rcmd(' try:')
+ call s:rcmd(' from powerline.lint import check')
+ call s:rcmd(' except ImportError:')
+ call s:rcmd(' print("Failed to import powerline.lint.check, cannot run powerline-lint")')
+ call s:rcmd(' else:')
+ call s:rcmd(' try:')
+ call s:rcmd(' paths = powerline_instance.get_config_paths()')
+ call s:rcmd(' except NameError:')
+ call s:rcmd(' pass')
+ call s:rcmd(' else:')
+ call s:rcmd(' from powerline.lint.markedjson.error import echoerr')
+ call s:rcmd(' ee = lambda *args, **kwargs: echoerr(*args, stream=sys.stdout, **kwargs)')
+ call s:rcmd(' check(paths=paths, echoerr=ee, require_ext="vim")')
+ call s:rcmd('try:')
+ call s:rcmd(' powerline_troubleshoot()')
+ call s:rcmd('finally:')
+ call s:rcmd(' del powerline_troubleshoot')
+ execute s:pycmd s:pystr
+ unlet s:pystr
+ unlet s:pycmd
+ unlet s:pyeval
+ delfunction s:rcmd
+ finish
+ else
+ unlet s:launched
+ endif
+ unlet s:pycmd
+ unlet s:pyeval
+ delfunction s:rcmd
+endtry
diff --git a/powerline/bindings/wm/__init__.py b/powerline/bindings/wm/__init__.py
new file mode 100644
index 0000000..646b701
--- /dev/null
+++ b/powerline/bindings/wm/__init__.py
@@ -0,0 +1,85 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import re
+
+from powerline.theme import requires_segment_info
+from powerline.lib.shell import run_cmd
+from powerline.bindings.wm.awesome import AwesomeThread
+
+
+DEFAULT_UPDATE_INTERVAL = 0.5
+
+
+conn = None
+
+
+def i3_subscribe(conn, event, callback):
+ '''Subscribe to i3 workspace event
+
+ :param conn:
+ Connection returned by :py:func:`get_i3_connection`.
+ :param str event:
+ Event to subscribe to, e.g. ``'workspace'``.
+ :param func callback:
+ Function to run on event.
+ '''
+ try:
+ import i3ipc
+ except ImportError:
+ import i3
+ conn.Subscription(callback, event)
+ return
+ else:
+ pass
+
+ conn.on(event, callback)
+
+ from threading import Thread
+
+ class I3Thread(Thread):
+ daemon = True
+
+ def __init__(self, conn):
+ super(I3Thread, self).__init__()
+ self.__conn = conn
+
+ def run(self):
+ self.__conn.main()
+
+ thread = I3Thread(conn=conn)
+
+ thread.start()
+
+
+def get_i3_connection():
+ '''Return a valid, cached i3 Connection instance
+ '''
+ global conn
+ if not conn:
+ try:
+ import i3ipc
+ except ImportError:
+ import i3 as conn
+ else:
+ conn = i3ipc.Connection()
+ return conn
+
+
+XRANDR_OUTPUT_RE = re.compile(r'^(?P<name>[0-9A-Za-z-]+) connected(?P<primary> primary)? (?P<width>\d+)x(?P<height>\d+)\+(?P<x>\d+)\+(?P<y>\d+)', re.MULTILINE)
+
+
+def get_connected_xrandr_outputs(pl):
+ '''Iterate over xrandr outputs
+
+ Outputs are represented by a dictionary with ``name``, ``width``,
+ ``height``, ``primary``, ``x`` and ``y`` keys.
+ '''
+ return (match.groupdict() for match in XRANDR_OUTPUT_RE.finditer(
+ run_cmd(pl, ['xrandr', '-q'])
+ ))
+
+
+wm_threads = {
+ 'awesome': AwesomeThread,
+}
diff --git a/powerline/bindings/wm/awesome.py b/powerline/bindings/wm/awesome.py
new file mode 100644
index 0000000..b6e07f2
--- /dev/null
+++ b/powerline/bindings/wm/awesome.py
@@ -0,0 +1,59 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import sys
+
+from threading import Thread, Event
+from time import sleep
+from subprocess import Popen, PIPE
+
+from powerline import Powerline
+from powerline.lib.monotonic import monotonic
+
+
+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')
+
+
+def run(thread_shutdown_event=None, pl_shutdown_event=None, pl_config_loader=None,
+ interval=None):
+ powerline = Powerline(
+ 'wm',
+ renderer_module='pango_markup',
+ shutdown_event=pl_shutdown_event,
+ config_loader=pl_config_loader,
+ )
+ powerline.update_renderer()
+
+ if not thread_shutdown_event:
+ thread_shutdown_event = powerline.shutdown_event
+
+ while not thread_shutdown_event.is_set():
+ # powerline.update_interval may change over time
+ used_interval = interval or powerline.update_interval
+ start_time = monotonic()
+ s = powerline.render(side='right')
+ request = 'powerline_widget:set_markup(\'' + s.translate({'\'': '\\\'', '\\': '\\\\'}) + '\')\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)
+ thread_shutdown_event.wait(max(used_interval - (monotonic() - start_time), 0.1))
+
+
+class AwesomeThread(Thread):
+ __slots__ = ('powerline_shutdown_event',)
+
+ def __init__(self, **kwargs):
+ super(AwesomeThread, self).__init__()
+ self.powerline_run_kwargs = kwargs
+
+ def run(self):
+ run(**self.powerline_run_kwargs)
diff --git a/powerline/bindings/zsh/__init__.py b/powerline/bindings/zsh/__init__.py
new file mode 100644
index 0000000..1037bba
--- /dev/null
+++ b/powerline/bindings/zsh/__init__.py
@@ -0,0 +1,228 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import atexit
+
+from weakref import WeakValueDictionary, ref
+
+import zsh
+
+from powerline.shell import ShellPowerline
+from powerline.lib.overrides import parsedotval, parse_override_var
+from powerline.lib.unicode import unicode, u
+from powerline.lib.encoding import (get_preferred_output_encoding,
+ get_preferred_environment_encoding)
+from powerline.lib.dict import mergeargs
+
+
+used_powerlines = WeakValueDictionary()
+
+
+def shutdown():
+ for powerline in tuple(used_powerlines.values()):
+ powerline.shutdown()
+
+
+def get_var_config(var):
+ try:
+ val = zsh.getvalue(var)
+ if isinstance(val, dict):
+ return mergeargs([parsedotval((u(k), u(v))) for k, v in val.items()])
+ elif isinstance(val, (unicode, str, bytes)):
+ return mergeargs(parse_override_var(u(val)))
+ else:
+ return None
+ except:
+ return None
+
+
+class Args(object):
+ __slots__ = ('last_pipe_status', 'last_exit_code')
+ ext = ['shell']
+ renderer_module = '.zsh'
+
+ @property
+ def config_override(self):
+ return get_var_config('POWERLINE_CONFIG_OVERRIDES')
+
+ @property
+ def theme_override(self):
+ return get_var_config('POWERLINE_THEME_OVERRIDES')
+
+ @property
+ def config_path(self):
+ try:
+ ret = zsh.getvalue('POWERLINE_CONFIG_PATHS')
+ except IndexError:
+ return None
+ else:
+ if isinstance(ret, (unicode, str, bytes)):
+ return [
+ path
+ for path in ret.split((b':' if isinstance(ret, bytes) else ':'))
+ if path
+ ]
+ else:
+ return ret
+
+ @property
+ def jobnum(self):
+ return zsh.getvalue('_POWERLINE_JOBNUM')
+
+
+def string(s):
+ if type(s) is bytes:
+ return s.decode(get_preferred_environment_encoding(), '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
+
+ @staticmethod
+ def __contains__(key):
+ try:
+ zsh.getvalue(key)
+ return True
+ except IndexError:
+ return False
+
+
+if hasattr(getattr(zsh, 'environ', None), '__contains__'):
+ environ = zsh.environ
+else:
+ environ = Environment()
+
+
+if hasattr(zsh, 'expand') and zsh.expand('${:-}') == '':
+ zsh_expand = zsh.expand
+else:
+ def zsh_expand(s):
+ zsh.eval('local _POWERLINE_REPLY="' + s + '"')
+ ret = zsh.getvalue('_POWERLINE_REPLY')
+ zsh.setvalue('_POWERLINE_REPLY', None)
+ return ret
+
+
+class ZshPowerline(ShellPowerline):
+ def init(self, **kwargs):
+ super(ZshPowerline, self).init(Args(), **kwargs)
+
+ def precmd(self):
+ self.args.last_pipe_status = zsh.pipestatus()
+ self.args.last_exit_code = zsh.last_exit_code()
+
+ def do_setup(self, zsh_globals):
+ set_prompt(self, 'PS1', 'left', None, above=True)
+ set_prompt(self, 'RPS1', 'right', None)
+ set_prompt(self, 'PS2', 'left', 'continuation')
+ set_prompt(self, 'RPS2', 'right', 'continuation')
+ set_prompt(self, 'PS3', 'left', 'select')
+ used_powerlines[id(self)] = self
+ zsh_globals['_powerline'] = self
+
+
+class Prompt(object):
+ __slots__ = ('powerline', 'side', 'savedpsvar', 'savedps', 'args', 'theme', 'above', '__weakref__')
+
+ def __init__(self, powerline, side, theme, savedpsvar=None, savedps=None, above=False):
+ self.powerline = powerline
+ self.side = side
+ self.above = above
+ self.savedpsvar = savedpsvar
+ self.savedps = savedps
+ self.args = powerline.args
+ self.theme = theme
+
+ def __str__(self):
+ parser_state = u(zsh_expand('${(%):-%_}'))
+ shortened_path = u(zsh_expand('${(%):-%~}'))
+ try:
+ mode = u(zsh.getvalue('_POWERLINE_MODE'))
+ except IndexError:
+ mode = None
+ try:
+ default_mode = u(zsh.getvalue('_POWERLINE_DEFAULT_MODE'))
+ except IndexError:
+ default_mode = None
+ segment_info = {
+ 'args': self.args,
+ 'environ': environ,
+ 'client_id': 1,
+ 'local_theme': self.theme,
+ 'parser_state': parser_state,
+ 'shortened_path': shortened_path,
+ 'mode': mode,
+ 'default_mode': default_mode,
+ }
+ try:
+ zle_rprompt_indent = zsh.getvalue('ZLE_RPROMPT_INDENT')
+ except IndexError:
+ zle_rprompt_indent = 1
+ r = ''
+ if self.above:
+ for line in self.powerline.render_above_lines(
+ width=zsh.columns() - zle_rprompt_indent,
+ segment_info=segment_info,
+ ):
+ if line:
+ r += line + '\n'
+ r += self.powerline.render(
+ width=zsh.columns(),
+ side=self.side,
+ segment_info=segment_info,
+ mode=mode,
+ )
+ if type(r) is not str:
+ if type(r) is bytes:
+ return r.decode(get_preferred_output_encoding(), 'replace')
+ else:
+ return r.encode(get_preferred_output_encoding(), 'replace')
+ return r
+
+ def __del__(self):
+ if self.savedps:
+ zsh.setvalue(self.savedpsvar, self.savedps)
+ self.powerline.shutdown()
+
+
+def set_prompt(powerline, psvar, side, theme, above=False):
+ try:
+ savedps = zsh.getvalue(psvar)
+ except IndexError:
+ savedps = None
+ zpyvar = 'ZPYTHON_POWERLINE_' + psvar
+ prompt = Prompt(powerline, side, theme, psvar, savedps, above)
+ zsh.setvalue(zpyvar, None)
+ zsh.set_special_string(zpyvar, prompt)
+ zsh.setvalue(psvar, '${' + zpyvar + '}')
+ return ref(prompt)
+
+
+def reload():
+ for powerline in tuple(used_powerlines.values()):
+ powerline.reload()
+
+
+def reload_config():
+ for powerline in used_powerlines.values():
+ powerline.create_renderer(load_main=True, load_colors=True, load_colorscheme=True, load_theme=True)
+
+
+def setup(zsh_globals):
+ powerline = ZshPowerline()
+ powerline.setup(zsh_globals)
+ atexit.register(shutdown)
diff --git a/powerline/bindings/zsh/powerline.zsh b/powerline/bindings/zsh/powerline.zsh
new file mode 100644
index 0000000..5d7cb28
--- /dev/null
+++ b/powerline/bindings/zsh/powerline.zsh
@@ -0,0 +1,216 @@
+local _POWERLINE_SOURCED="$0:A"
+
+_powerline_columns_fallback() {
+ if which stty &>/dev/null ; then
+ local cols="$(stty size 2>/dev/null)"
+ if ! test -z "$cols" ; then
+ echo "${cols#* }"
+ return 0
+ fi
+ fi
+ echo 0
+ return 0
+}
+
+_powerline_append_precmd_function() {
+ if test -z "${precmd_functions[(re)$1]}" ; then
+ precmd_functions+=( $1 )
+ fi
+}
+
+integer -g _POWERLINE_JOBNUM=0
+
+_powerline_tmux_pane() {
+ local -x TMUX="$_POWERLINE_TMUX"
+ echo "${TMUX_PANE:-`tmux display -p "#D"`}" | tr -d ' %'
+}
+
+_powerline_tmux_pane() {
+ local -x TMUX="$_POWERLINE_TMUX"
+ echo "${TMUX_PANE:-`tmux display -p "#D"`}" | tr -d ' %'
+}
+
+_powerline_init_tmux_support() {
+ emulate -L zsh
+ if test -n "$TMUX" && tmux refresh -S &>/dev/null ; then
+ # TMUX variable may be unset to create new tmux session inside this one
+ typeset -g _POWERLINE_TMUX="$TMUX"
+
+ function -g _powerline_tmux_setenv() {
+ emulate -L zsh
+ local -x TMUX="$_POWERLINE_TMUX"
+ tmux setenv -g TMUX_"$1"_$(_powerline_tmux_pane) "$2"
+ tmux refresh -S
+ }
+
+ function -g _powerline_tmux_set_pwd() {
+ _powerline_tmux_setenv PWD "$PWD"
+ }
+
+ function -g _powerline_tmux_set_columns() {
+ _powerline_tmux_setenv COLUMNS "${COLUMNS:-$(_powerline_columns_fallback)}"
+ }
+
+ chpwd_functions+=( _powerline_tmux_set_pwd )
+ trap '_powerline_tmux_set_columns' SIGWINCH
+ _powerline_tmux_set_columns
+ _powerline_tmux_set_pwd
+ fi
+}
+
+_powerline_init_modes_support() {
+ emulate -L zsh
+
+ test -z "$ZSH_VERSION" && return 0
+
+ local -a vs
+ vs=( ${(s:.:)ZSH_VERSION} )
+
+ # Mode support requires >=zsh-4.3.11
+ if (( vs[1] < 4 || (vs[1] == 4 && (vs[2] < 3 || (vs[2] == 3 && vs[3] < 11))) )) ; then
+ return 0
+ fi
+
+ function -g _powerline_get_main_keymap_name() {
+ REPLY="${${(Q)${${(z)${"$(bindkey -lL main)"}}[3]}}:-.safe}"
+ }
+
+ function -g _powerline_set_true_keymap_name() {
+ typeset -g _POWERLINE_MODE="${1}"
+ local plm_bk="$(bindkey -lL ${_POWERLINE_MODE})"
+ if [[ $plm_bk = 'bindkey -A'* ]] ; then
+ _powerline_set_true_keymap_name ${(Q)${${(z)plm_bk}[3]}}
+ fi
+ }
+
+ function -g _powerline_zle_keymap_select() {
+ _powerline_set_true_keymap_name $KEYMAP
+ zle reset-prompt
+ test -z "$_POWERLINE_SAVE_WIDGET" || zle $_POWERLINE_SAVE_WIDGET
+ }
+
+ function -g _powerline_set_main_keymap_name() {
+ local REPLY
+ _powerline_get_main_keymap_name
+ _powerline_set_true_keymap_name "$REPLY"
+ }
+
+ _powerline_add_widget zle-keymap-select _powerline_zle_keymap_select
+ _powerline_set_main_keymap_name
+
+ if [[ "$_POWERLINE_MODE" != vi* ]] ; then
+ typeset -g _POWERLINE_DEFAULT_MODE="$_POWERLINE_MODE"
+ fi
+
+ _powerline_append_precmd_function _powerline_set_main_keymap_name
+}
+
+_powerline_set_jobnum() {
+ # If you are wondering why I am not using the same code as I use for bash
+ # ($(jobs|wc -l)): consider the following test:
+ # echo abc | less
+ # <C-z>
+ # . This way jobs will print
+ # [1] + done echo abc |
+ # suspended less -M
+ # ([ is in first column). You see: any line counting thingie will return
+ # wrong number of jobs. You need to filter the lines first. Or not use
+ # jobs built-in at all.
+ integer -g _POWERLINE_JOBNUM=${(%):-%j}
+}
+
+_powerline_update_counter() {
+ zpython '_powerline.precmd()'
+}
+
+_powerline_setup_prompt() {
+ emulate -L zsh
+
+ _powerline_append_precmd_function _powerline_set_jobnum
+
+ typeset -g VIRTUAL_ENV_DISABLE_PROMPT=1
+
+ if test -z "${POWERLINE_NO_ZSH_ZPYTHON}" && { zmodload libzpython || zmodload zsh/zpython } &>/dev/null ; then
+ _powerline_append_precmd_function _powerline_update_counter
+ zpython 'from powerline.bindings.zsh import setup as _powerline_setup'
+ zpython '_powerline_setup(globals())'
+ zpython 'del _powerline_setup'
+ powerline-reload() {
+ zpython 'from powerline.bindings.zsh import reload as _powerline_reload'
+ zpython '_powerline_reload()'
+ zpython 'del _powerline_reload'
+ }
+ powerline-reload-config() {
+ zpython 'from powerline.bindings.zsh import reload_config as _powerline_reload_config'
+ zpython '_powerline_reload_config()'
+ zpython 'del _powerline_reload_config'
+ }
+ else
+ if test -z "${POWERLINE_COMMAND}" ; then
+ typeset -g POWERLINE_COMMAND="$($POWERLINE_CONFIG_COMMAND shell command)"
+ fi
+
+ local add_args='-r .zsh'
+ add_args+=' --last-exit-code=$?'
+ add_args+=' --last-pipe-status="$pipestatus"'
+ add_args+=' --renderer-arg="client_id=$$"'
+ add_args+=' --renderer-arg="shortened_path=${(%):-%~}"'
+ add_args+=' --jobnum=$_POWERLINE_JOBNUM'
+ add_args+=' --renderer-arg="mode=$_POWERLINE_MODE"'
+ add_args+=' --renderer-arg="default_mode=$_POWERLINE_DEFAULT_MODE"'
+ local new_args_2=' --renderer-arg="parser_state=${(%%):-%_}"'
+ new_args_2+=' --renderer-arg="local_theme=continuation"'
+ local add_args_3=$add_args' --renderer-arg="local_theme=select"'
+ local add_args_2=$add_args$new_args_2
+ add_args+=' --width=$(( ${COLUMNS:-$(_powerline_columns_fallback)} - ${ZLE_RPROMPT_INDENT:-1} ))'
+ local add_args_r2=$add_args$new_args_2
+ typeset -g PS1='$("$POWERLINE_COMMAND" $=POWERLINE_COMMAND_ARGS shell aboveleft '$add_args')'
+ typeset -g RPS1='$("$POWERLINE_COMMAND" $=POWERLINE_COMMAND_ARGS shell right '$add_args')'
+ typeset -g PS2='$("$POWERLINE_COMMAND" $=POWERLINE_COMMAND_ARGS shell left '$add_args_2')'
+ typeset -g RPS2='$("$POWERLINE_COMMAND" $=POWERLINE_COMMAND_ARGS shell right '$add_args_r2')'
+ typeset -g PS3='$("$POWERLINE_COMMAND" $=POWERLINE_COMMAND_ARGS shell left '$add_args_3')'
+ fi
+}
+
+_powerline_add_widget() {
+ local widget="$1"
+ local function="$2"
+ local old_widget_command="$(zle -l -L $widget)"
+ if [[ "$old_widget_command" = "zle -N $widget $function" ]] ; then
+ return 0
+ elif [[ -z "$old_widget_command" ]] ; then
+ zle -N $widget $function
+ else
+ local save_widget="_powerline_save_$widget"
+ local -i i=0
+ while ! test -z "$(zle -l -L $save_widget)" ; do
+ save_widget="${save_widget}_$i"
+ (( i++ ))
+ done
+ # If widget was defined with `zle -N widget` (without `function`
+ # argument) then this function will be handy.
+ eval "function $save_widget() { emulate -L zsh; $widget \$@ }"
+ eval "${old_widget_command/$widget/$save_widget}"
+ zle -N $widget $function
+ typeset -g _POWERLINE_SAVE_WIDGET="$save_widget"
+ fi
+}
+
+if test -z "${POWERLINE_CONFIG_COMMAND}" ; then
+ if which powerline-config >/dev/null ; then
+ typeset -g POWERLINE_CONFIG_COMMAND=powerline-config
+ else
+ typeset -g POWERLINE_CONFIG_COMMAND="${_POWERLINE_SOURCED:h:h:h:h}/scripts/powerline-config"
+ fi
+fi
+
+setopt promptpercent
+setopt promptsubst
+
+if "${POWERLINE_CONFIG_COMMAND}" shell --shell=zsh uses prompt ; then
+ _powerline_setup_prompt
+ _powerline_init_modes_support
+fi
+if "${POWERLINE_CONFIG_COMMAND}" shell --shell=zsh uses tmux ; then
+ _powerline_init_tmux_support
+fi
diff --git a/powerline/colorscheme.py b/powerline/colorscheme.py
new file mode 100644
index 0000000..66416b5
--- /dev/null
+++ b/powerline/colorscheme.py
@@ -0,0 +1,147 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+from copy import copy
+
+from powerline.lib.unicode import unicode
+
+
+DEFAULT_MODE_KEY = None
+ATTR_BOLD = 1
+ATTR_ITALIC = 2
+ATTR_UNDERLINE = 4
+
+
+def get_attrs_flag(attrs):
+ '''Convert an attribute array to a renderer flag.'''
+ attrs_flag = 0
+ if 'bold' in attrs:
+ attrs_flag |= ATTR_BOLD
+ if 'italic' in attrs:
+ attrs_flag |= ATTR_ITALIC
+ if 'underline' in attrs:
+ attrs_flag |= ATTR_UNDERLINE
+ return attrs_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))]
+
+
+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_group_props(self, mode, trans, group, translate_colors=True):
+ if isinstance(group, (str, unicode)):
+ try:
+ group_props = trans['groups'][group]
+ except KeyError:
+ try:
+ group_props = self.groups[group]
+ except KeyError:
+ return None
+ else:
+ return self.get_group_props(mode, trans, group_props, True)
+ else:
+ return self.get_group_props(mode, trans, group_props, False)
+ else:
+ if translate_colors:
+ group_props = copy(group)
+ try:
+ ctrans = trans['colors']
+ except KeyError:
+ pass
+ else:
+ for key in ('fg', 'bg'):
+ try:
+ group_props[key] = ctrans[group_props[key]]
+ except KeyError:
+ pass
+ return group_props
+ else:
+ return group
+
+ def get_highlighting(self, groups, mode, gradient_level=None):
+ trans = self.translations.get(mode, {})
+ for group in groups:
+ group_props = self.get_group_props(mode, trans, group)
+ if group_props:
+ break
+ else:
+ raise KeyError('Highlighting groups not found in colorscheme: ' + ', '.join(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']),
+ 'attrs': get_attrs_flag(group_props.get('attrs', [])),
+ }
+
+
+# 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
+)
diff --git a/powerline/commands/__init__.py b/powerline/commands/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/powerline/commands/__init__.py
diff --git a/powerline/commands/config.py b/powerline/commands/config.py
new file mode 100644
index 0000000..06c6436
--- /dev/null
+++ b/powerline/commands/config.py
@@ -0,0 +1,109 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (division, absolute_import, print_function)
+
+import argparse
+
+import powerline.bindings.config as config
+
+
+class StrFunction(object):
+ def __init__(self, function, name=None):
+ self.name = name or function.__name__
+ self.function = function
+
+ def __call__(self, *args, **kwargs):
+ self.function(*args, **kwargs)
+
+ def __str__(self):
+ return self.name
+
+
+TMUX_ACTIONS = {
+ 'source': StrFunction(config.source_tmux_files, 'source'),
+ 'setenv': StrFunction(config.init_tmux_environment, 'setenv'),
+ 'setup': StrFunction(config.tmux_setup, 'setup'),
+}
+
+
+SHELL_ACTIONS = {
+ 'command': StrFunction(config.shell_command, 'command'),
+ 'uses': StrFunction(config.uses),
+}
+
+
+class ConfigArgParser(argparse.ArgumentParser):
+ def parse_args(self, *args, **kwargs):
+ ret = super(ConfigArgParser, self).parse_args(*args, **kwargs)
+ if not hasattr(ret, 'function'):
+ # In Python-3* `powerline-config` (without arguments) raises
+ # AttributeError. I have not found any standard way to display same
+ # error message as in Python-2*.
+ self.error('too few arguments')
+ return ret
+
+
+def get_argparser(ArgumentParser=ConfigArgParser):
+ parser = ArgumentParser(description='Script used to obtain powerline configuration.')
+ parser.add_argument(
+ '-p', '--config-path', action='append', metavar='PATH',
+ help='Path to configuration directory. If it is present '
+ 'then configuration files will only be seeked in the provided path. '
+ 'May be provided multiple times to search in a list of directories.'
+ )
+ subparsers = parser.add_subparsers()
+ tmux_parser = subparsers.add_parser('tmux', help='Tmux-specific commands')
+ tmux_parser.add_argument(
+ 'function',
+ choices=tuple(TMUX_ACTIONS.values()),
+ metavar='ACTION',
+ type=(lambda v: TMUX_ACTIONS.get(v)),
+ help='If action is `source\' then version-specific tmux configuration '
+ 'files are sourced, if it is `setenv\' then special '
+ '(prefixed with `_POWERLINE\') tmux global environment variables '
+ 'are filled with data from powerline configuration. '
+ 'Action `setup\' is just doing `setenv\' then `source\'.'
+ )
+ tpg = tmux_parser.add_mutually_exclusive_group()
+ tpg.add_argument(
+ '-s', '--source', action='store_true', default=None,
+ help='When using `setup\': always use configuration file sourcing. '
+ 'By default this is determined automatically based on tmux '
+ 'version: this is the default for tmux 1.8 and below.',
+ )
+ tpg.add_argument(
+ '-n', '--no-source', action='store_false', dest='source', default=None,
+ help='When using `setup\': in place of sourcing directly execute '
+ 'configuration files. That is, read each needed '
+ 'powerline-specific configuration file, substitute '
+ '`$_POWERLINE_…\' variables with appropriate values and run '
+ '`tmux config line\'. This is the default behaviour for '
+ 'tmux 1.9 and above.'
+ )
+
+ shell_parser = subparsers.add_parser('shell', help='Shell-specific commands')
+ shell_parser.add_argument(
+ 'function',
+ choices=tuple(SHELL_ACTIONS.values()),
+ type=(lambda v: SHELL_ACTIONS.get(v)),
+ metavar='ACTION',
+ help='If action is `command\' then preferred powerline command is '
+ 'output, if it is `uses\' then powerline-config script will exit '
+ 'with 1 if specified component is disabled and 0 otherwise.',
+ )
+ shell_parser.add_argument(
+ 'component',
+ nargs='?',
+ choices=('tmux', 'prompt'),
+ metavar='COMPONENT',
+ help='Only applicable for `uses\' subcommand: makes `powerline-config\' '
+ 'exit with 0 if specific component is enabled and with 1 otherwise. '
+ '`tmux\' component stands for tmux bindings '
+ '(e.g. those that notify tmux about current directory changes), '
+ '`prompt\' component stands for shell prompt.'
+ )
+ shell_parser.add_argument(
+ '-s', '--shell',
+ metavar='SHELL',
+ help='Shell for which query is run',
+ )
+ return parser
diff --git a/powerline/commands/daemon.py b/powerline/commands/daemon.py
new file mode 100644
index 0000000..7e8c8ab
--- /dev/null
+++ b/powerline/commands/daemon.py
@@ -0,0 +1,24 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (division, absolute_import, print_function)
+
+import argparse
+
+
+def get_argparser(ArgumentParser=argparse.ArgumentParser):
+ parser = ArgumentParser(description='Daemon that improves powerline performance.')
+ parser.add_argument(
+ '--quiet', '-q', action='store_true',
+ help='Without other options: do not complain about already running '
+ 'powerline-daemon instance. '
+ 'Will still exit with 1. '
+ 'With `--kill\' and `--replace\': do not show any messages. '
+ 'With `--foreground\': ignored. '
+ 'Does not silence exceptions in any case.'
+ )
+ parser.add_argument('--socket', '-s', help='Specify socket which will be used for connecting to daemon.')
+ exclusive_group = parser.add_mutually_exclusive_group()
+ exclusive_group.add_argument('--kill', '-k', action='store_true', help='Kill an already running instance.')
+ replace_group = exclusive_group.add_argument_group()
+ replace_group.add_argument('--foreground', '-f', action='store_true', help='Run in the foreground (don’t daemonize).')
+ replace_group.add_argument('--replace', '-r', action='store_true', help='Replace an already running instance.')
+ return parser
diff --git a/powerline/commands/lemonbar.py b/powerline/commands/lemonbar.py
new file mode 100644
index 0000000..547c52c
--- /dev/null
+++ b/powerline/commands/lemonbar.py
@@ -0,0 +1,35 @@
+# vim:fileencoding=utf-8:noet
+# WARNING: using unicode_literals causes errors in argparse
+from __future__ import (division, absolute_import, print_function)
+
+import argparse
+
+
+def get_argparser(ArgumentParser=argparse.ArgumentParser):
+ parser = ArgumentParser(
+ description='Powerline BAR bindings.'
+ )
+ parser.add_argument(
+ '--i3', action='store_true',
+ help='Subscribe for i3 events.'
+ )
+ parser.add_argument(
+ '--height', default='',
+ metavar='PIXELS', help='Bar height.'
+ )
+ parser.add_argument(
+ '--interval', '-i',
+ type=float, default=0.5,
+ metavar='SECONDS', help='Refresh interval.'
+ )
+ parser.add_argument(
+ '--bar-command', '-C',
+ default='lemonbar',
+ metavar='CMD', help='Name of the lemonbar executable to use.'
+ )
+ parser.add_argument(
+ 'args', nargs=argparse.REMAINDER,
+ help='Extra arguments for lemonbar. Should be preceded with ``--`` '
+ 'argument in order not to be confused with script own arguments.'
+ )
+ return parser
diff --git a/powerline/commands/lint.py b/powerline/commands/lint.py
new file mode 100755
index 0000000..8961a65
--- /dev/null
+++ b/powerline/commands/lint.py
@@ -0,0 +1,21 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (division, absolute_import, print_function)
+
+import argparse
+
+
+def get_argparser(ArgumentParser=argparse.ArgumentParser):
+ parser = ArgumentParser(description='Powerline configuration checker.')
+ parser.add_argument(
+ '-p', '--config-path', action='append', metavar='PATH',
+ help='Paths where configuration should be checked, in order. You must '
+ 'supply all paths necessary for powerline to work, '
+ 'checking partial (e.g. only user overrides) configuration '
+ 'is not supported.'
+ )
+ parser.add_argument(
+ '-d', '--debug', action='store_const', const=True,
+ help='Display additional information. Used for debugging '
+ '`powerline-lint\' itself, not for debugging configuration.'
+ )
+ return parser
diff --git a/powerline/commands/main.py b/powerline/commands/main.py
new file mode 100644
index 0000000..366eba2
--- /dev/null
+++ b/powerline/commands/main.py
@@ -0,0 +1,190 @@
+# vim:fileencoding=utf-8:noet
+# WARNING: using unicode_literals causes errors in argparse
+from __future__ import (division, absolute_import, print_function)
+
+import argparse
+import sys
+
+from itertools import chain
+
+from powerline.lib.overrides import parsedotval, parse_override_var
+from powerline.lib.dict import mergeargs
+from powerline.lib.encoding import get_preferred_arguments_encoding
+from powerline.lib.unicode import u, unicode
+from powerline.bindings.wm import wm_threads
+
+
+if sys.version_info < (3,):
+ encoding = get_preferred_arguments_encoding()
+
+ def arg_to_unicode(s):
+ return unicode(s, encoding, 'replace') if not isinstance(s, unicode) else s # NOQA
+else:
+ def arg_to_unicode(s):
+ return s
+
+
+def finish_args(parser, environ, args, is_daemon=False):
+ '''Do some final transformations
+
+ Transforms ``*_override`` arguments into dictionaries, adding overrides from
+ environment variables. Transforms ``renderer_arg`` argument into dictionary
+ as well, but only if it is true.
+
+ :param dict environ:
+ Environment from which additional overrides should be taken from.
+ :param args:
+ Arguments object returned by
+ :py:meth:`argparse.ArgumentParser.parse_args`. Will be modified
+ in-place.
+
+ :return: Object received as second (``args``) argument.
+ '''
+ args.config_override = mergeargs(chain(
+ parse_override_var(environ.get('POWERLINE_CONFIG_OVERRIDES', '')),
+ (parsedotval(v) for v in args.config_override or ()),
+ ))
+ args.theme_override = mergeargs(chain(
+ parse_override_var(environ.get('POWERLINE_THEME_OVERRIDES', '')),
+ (parsedotval(v) for v in args.theme_override or ()),
+ ))
+ if args.renderer_arg:
+ args.renderer_arg = mergeargs((parsedotval(v) for v in args.renderer_arg), remove=True)
+ if 'pane_id' in args.renderer_arg:
+ if isinstance(args.renderer_arg['pane_id'], (bytes, unicode)):
+ try:
+ args.renderer_arg['pane_id'] = int(args.renderer_arg['pane_id'].lstrip(' %'))
+ except ValueError:
+ pass
+ if 'client_id' not in args.renderer_arg:
+ args.renderer_arg['client_id'] = args.renderer_arg['pane_id']
+ args.config_path = (
+ [path for path in environ.get('POWERLINE_CONFIG_PATHS', '').split(':') if path]
+ + (args.config_path or [])
+ )
+ if args.ext[0].startswith('wm.'):
+ if not is_daemon:
+ parser.error('WM bindings must be used with daemon only')
+ elif args.ext[0][3:] not in wm_threads:
+ parser.error('WM binding not found')
+ elif not args.side:
+ parser.error('expected one argument')
+ return args
+
+
+def int_or_sig(s):
+ if s.startswith('sig'):
+ return u(s)
+ else:
+ return int(s)
+
+
+def get_argparser(ArgumentParser=argparse.ArgumentParser):
+ parser = ArgumentParser(description='Powerline prompt and statusline script.')
+ parser.add_argument(
+ 'ext', nargs=1,
+ help='Extension: application for which powerline command is launched '
+ '(usually `shell\' or `tmux\'). Also supports `wm.\' extensions: '
+ + ', '.join(('`wm.' + key + '\'' for key in wm_threads.keys())) + '.'
+ )
+ parser.add_argument(
+ 'side', nargs='?', choices=('left', 'right', 'above', 'aboveleft'),
+ help='Side: `left\' and `right\' represent left and right side '
+ 'respectively, `above\' emits lines that are supposed to be printed '
+ 'just above the prompt and `aboveleft\' is like concatenating '
+ '`above\' with `left\' with the exception that only one Python '
+ 'instance is used in this case. May be omitted for `wm.*\' extensions.'
+ )
+ parser.add_argument(
+ '-r', '--renderer-module', metavar='MODULE', type=str,
+ help='Renderer module. Usually something like `.bash\' or `.zsh\' '
+ '(with leading dot) which is `powerline.renderers.{ext}{MODULE}\', '
+ 'may also be full module name (must contain at least one dot or '
+ 'end with a dot in case it is top-level module) or '
+ '`powerline.renderers\' submodule (in case there are no dots).'
+ )
+ parser.add_argument(
+ '-w', '--width', type=int,
+ help='Maximum prompt with. Triggers truncation of some segments.'
+ )
+ parser.add_argument(
+ '--last-exit-code', metavar='INT', type=int_or_sig,
+ help='Last exit code.'
+ )
+ parser.add_argument(
+ '--last-pipe-status', metavar='LIST', default='',
+ type=lambda s: [int_or_sig(status) for status in s.split()],
+ help='Like above, but is supposed to contain space-separated array '
+ 'of statuses, representing exit statuses of commands in one pipe.'
+ )
+ parser.add_argument(
+ '--jobnum', metavar='INT', type=int,
+ help='Number of jobs.'
+ )
+ parser.add_argument(
+ '-c', '--config-override', metavar='KEY.KEY=VALUE', type=arg_to_unicode,
+ action='append',
+ help='Configuration overrides for `config.json\'. Is translated to a '
+ 'dictionary and merged with the dictionary obtained from actual '
+ 'JSON configuration: KEY.KEY=VALUE is translated to '
+ '`{"KEY": {"KEY": VALUE}}\' and then merged recursively. '
+ 'VALUE may be any JSON value, values that are not '
+ '`null\', `true\', `false\', start with digit, `{\', `[\' '
+ 'are treated like strings. If VALUE is omitted '
+ 'then corresponding key is removed.'
+ )
+ parser.add_argument(
+ '-t', '--theme-override', metavar='THEME.KEY.KEY=VALUE', type=arg_to_unicode,
+ action='append',
+ help='Like above, but theme-specific. THEME should point to '
+ 'an existing and used theme to have any effect, but it is fine '
+ 'to use any theme here.'
+ )
+ parser.add_argument(
+ '-R', '--renderer-arg',
+ metavar='KEY=VAL', type=arg_to_unicode, action='append',
+ help='Like above, but provides argument for renderer. Is supposed '
+ 'to be used only by shell bindings to provide various data like '
+ 'last-exit-code or last-pipe-status (they are not using '
+ '`--renderer-arg\' for historical resons: `--renderer-arg\' '
+ 'was added later).'
+ )
+ parser.add_argument(
+ '-p', '--config-path', action='append', metavar='PATH',
+ help='Path to configuration directory. If it is present then '
+ 'configuration files will only be seeked in the provided path. '
+ 'May be provided multiple times to search in a list of directories.'
+ )
+ parser.add_argument(
+ '--socket', metavar='ADDRESS', type=str,
+ help='Socket address to use in daemon clients. Is always UNIX domain '
+ 'socket on linux and file socket on Mac OS X. Not used here, '
+ 'present only for compatibility with other powerline clients. '
+ 'This argument must always be the first one and be in a form '
+ '`--socket ADDRESS\': no `=\' or short form allowed '
+ '(in other powerline clients, not here).'
+ )
+ return parser
+
+
+def write_output(args, powerline, segment_info, write):
+ if args.renderer_arg:
+ segment_info.update(args.renderer_arg)
+ if args.side.startswith('above'):
+ for line in powerline.render_above_lines(
+ width=args.width,
+ segment_info=segment_info,
+ mode=segment_info.get('mode', None),
+ ):
+ if line:
+ write(line + '\n')
+ args.side = args.side[len('above'):]
+
+ if args.side:
+ rendered = powerline.render(
+ width=args.width,
+ side=args.side,
+ segment_info=segment_info,
+ mode=segment_info.get('mode', None),
+ )
+ write(rendered)
diff --git a/powerline/config.py b/powerline/config.py
new file mode 100644
index 0000000..edcf921
--- /dev/null
+++ b/powerline/config.py
@@ -0,0 +1,10 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import os
+
+
+POWERLINE_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+BINDINGS_DIRECTORY = os.path.join(POWERLINE_ROOT, 'powerline', 'bindings')
+TMUX_CONFIG_DIRECTORY = os.path.join(BINDINGS_DIRECTORY, 'tmux')
+DEFAULT_SYSTEM_CONFIG_DIR = None
diff --git a/powerline/config_files/colors.json b/powerline/config_files/colors.json
new file mode 100644
index 0000000..1564f18
--- /dev/null
+++ b/powerline/config_files/colors.json
@@ -0,0 +1,124 @@
+{
+ "colors": {
+ "black": 16,
+ "white": 231,
+
+ "green": 2,
+ "darkestgreen": 22,
+ "darkgreen": 28,
+ "mediumgreen": 70,
+ "brightgreen": 148,
+
+ "darkestcyan": 23,
+ "darkcyan": 74,
+ "mediumcyan": 117,
+ "brightcyan": 159,
+
+ "darkestblue": 24,
+ "darkblue": 31,
+
+ "red": 1,
+ "darkestred": 52,
+ "darkred": 88,
+ "mediumred": 124,
+ "brightred": 160,
+ "brightestred": 196,
+
+ "darkestpurple": 55,
+ "mediumpurple": 98,
+ "brightpurple": 189,
+
+ "darkorange": 94,
+ "mediumorange": 166,
+ "brightorange": 208,
+ "brightestorange": 214,
+
+ "yellow": 11,
+ "brightyellow": 220,
+
+ "gray0": 233,
+ "gray1": 235,
+ "gray2": 236,
+ "gray3": 239,
+ "gray4": 240,
+ "gray5": 241,
+ "gray6": 244,
+ "gray7": 245,
+ "gray8": 247,
+ "gray9": 250,
+ "gray10": 252,
+
+ "gray11": 234,
+ "gray90": 254,
+
+ "gray70": [249, "b3b3b3"],
+
+ "lightyellowgreen": 106,
+ "gold3": 178,
+ "orangered": 202,
+
+ "steelblue": 67,
+ "darkorange3": 166,
+ "skyblue1": 117,
+ "khaki1": 228,
+
+ "solarized:base03": [8, "002b36"],
+ "solarized:base02": [0, "073642"],
+ "solarized:base01": [10, "586e75"],
+ "solarized:base00": [11, "657b83"],
+ "solarized:base0": [12, "839496"],
+ "solarized:base1": [14, "93a1a1"],
+ "solarized:base2": [7, "eee8d5"],
+ "solarized:base3": [15, "fdf6e3"],
+ "solarized:yellow": [3, "b58900"],
+ "solarized:orange": [9, "cb4b16"],
+ "solarized:red": [1, "dc322f"],
+ "solarized:magenta": [5, "d33682"],
+ "solarized:violet": [13, "6c71c4"],
+ "solarized:blue": [4, "268bd2"],
+ "solarized:cyan": [6, "2aa198"],
+ "solarized:green": [2, "859900"]
+ },
+ "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, 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, 94, 94, 94, 94, 94, 94, 94, 88, 52],
+ ["006000", "006000", "006000", "006000", "006000", "006000", "006000", "006000", "006000", "036000", "076000", "0a6000", "0d6000", "106000", "126000", "146000", "166000", "186000", "1a6000", "1b6000", "1d6000", "1e6000", "206000", "216000", "236000", "246000", "256000", "266000", "286000", "296000", "2a6000", "2b6000", "2c6100", "2d6100", "2f6100", "306100", "316100", "326100", "336100", "346100", "356100", "366100", "376100", "386100", "386100", "396100", "3a6100", "3b6100", "3c6100", "3d6100", "3e6100", "3f6100", "406100", "406100", "416100", "426000", "436000", "446000", "456000", "456000", "466000", "476000", "486000", "496000", "496000", "4a6000", "4b6000", "4c6000", "4d6000", "4d6000", "4e6000", "4f6000", "506000", "506000", "516000", "526000", "536000", "536000", "546000", "556000", "566000", "566000", "576000", "586000", "596000", "596000", "5a6000", "5d6000", "616000", "646000", "686000", "6b6000", "6f6000", "726000", "766000", "796000", "7d6000", "806000", "7e5500", "6f3105", "5d0001"]
+ ],
+ "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"]
+ ],
+ "white_red": [
+ [231, 255, 223, 216, 209, 202, 196],
+ ["ffffff", "fefefe", "fdfdfd", "fdfdfd", "fcfcfc", "fbfbfb", "fafafa", "fafafa", "f9f9f9", "f8f8f8", "f7f7f7", "f7f7f7", "f6f6f6", "f5f5f5", "f4f4f4", "f4f3f4", "f3f3f3", "f2f2f2", "f1f1f1", "f0f0f0", "f0f0f0", "efefef", "eeeeee", "efecea", "f1eae4", "f2e8de", "f3e6d8", "f5e4d3", "f6e2cd", "f7e0c7", "f8dec2", "f9dcbc", "fadab6", "fad8b1", "fbd5ac", "fbd2a9", "fbcea5", "fbcaa1", "fbc79e", "fbc39a", "fbc097", "fbbc93", "fbb88f", "fbb58c", "fab188", "faad85", "faaa81", "fba67e", "fba37a", "fb9f76", "fb9c73", "fb986f", "fb946c", "fb9168", "fa8d65", "fa8961", "fa865c", "fa8256", "fb7f4f", "fb7b48", "fb7841", "fb743a", "fb7133", "fb6d2c", "fa6a23", "fa661a", "fa620e", "fa5f03", "fa5d03", "fa5b03", "fa5a03", "fa5803", "fa5703", "fa5503", "fa5303", "fa5103", "fa4f03", "fa4e03", "fa4c03", "fa4a04", "fa4804", "fa4604", "fa4404", "fa4204", "fa3f04", "fa3d04", "fa3b04", "fa3805", "fa3605", "fa3305", "fb3105", "fb2e05", "fb2a05", "fb2705", "fb2306", "fb1f06", "fb1b06", "fb1506", "fb0e06", "fa0506", "fa0007"]
+ ],
+ "dark_green_gray": [
+ [70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247],
+ ["51b000", "52b000", "54b000", "55b002", "56b007", "57b00d", "58b011", "59af15", "5aaf18", "5caf1b", "5daf1e", "5eaf21", "5faf23", "60ae25", "61ae27", "62ae2a", "63ae2c", "64ae2e", "65ae30", "66ae31", "67ad33", "68ad35", "69ad37", "69ad38", "6aad3a", "6bad3c", "6cac3d", "6dac3f", "6eac40", "6fac42", "70ac44", "70ac45", "71ab47", "72ab48", "73ab49", "74ab4b", "75ab4c", "75ab4e", "76aa4f", "77aa51", "78aa52", "79aa53", "79aa55", "7aaa56", "7ba957", "7ca959", "7ca95a", "7da95b", "7ea95d", "7fa95e", "7fa85f", "80a861", "81a862", "81a863", "82a865", "83a766", "83a767", "84a768", "85a76a", "85a76b", "86a66c", "87a66d", "87a66f", "88a670", "89a671", "89a672", "8aa574", "8ba575", "8ba576", "8ca577", "8da579", "8da47a", "8ea47b", "8ea47c", "8fa47d", "90a47f", "90a380", "91a381", "91a382", "92a384", "93a385", "93a286", "94a287", "94a288", "95a28a", "95a18b", "96a18c", "97a18d", "97a18e", "98a190", "98a091", "99a092", "99a093", "9aa094", "9aa096", "9b9f97", "9b9f98", "9c9f99", "9c9f9a", "9d9e9c", "9d9e9d"]
+ ],
+ "light_green_gray": [
+ [148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 187, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250],
+ ["a3d900", "a4d800", "a4d800", "a5d805", "a5d80d", "a6d714", "a6d719", "a6d71d", "a7d621", "a7d625", "a8d628", "a8d62b", "a8d52e", "a9d531", "a9d533", "aad536", "aad438", "aad43a", "abd43d", "abd33f", "abd341", "acd343", "acd345", "acd247", "add249", "add24b", "add14d", "aed14f", "aed151", "aed152", "afd054", "afd056", "afd058", "b0d059", "b0cf5b", "b0cf5d", "b1cf5e", "b1ce60", "b1ce62", "b1ce63", "b2ce65", "b2cd67", "b2cd68", "b3cd6a", "b3cc6b", "b3cc6d", "b3cc6e", "b4cc70", "b4cb71", "b4cb73", "b4cb75", "b5ca76", "b5ca78", "b5ca79", "b5ca7a", "b6c97c", "b6c97d", "b6c97f", "b6c880", "b6c882", "b7c883", "b7c885", "b7c786", "b7c788", "b7c789", "b8c68a", "b8c68c", "b8c68d", "b8c68f", "b8c590", "b9c591", "b9c593", "b9c494", "b9c496", "b9c497", "b9c498", "bac39a", "bac39b", "bac39d", "bac29e", "bac29f", "bac2a1", "bac2a2", "bac1a4", "bbc1a5", "bbc1a6", "bbc0a8", "bbc0a9", "bbc0aa", "bbc0ac", "bbbfad", "bbbfae", "bbbfb0", "bbbeb1", "bcbeb3", "bcbeb4", "bcbdb5", "bcbdb7", "bcbdb8", "bcbdb9", "bcbcbb"]
+ ]
+ }
+}
diff --git a/powerline/config_files/colorschemes/default.json b/powerline/config_files/colorschemes/default.json
new file mode 100644
index 0000000..7e271ef
--- /dev/null
+++ b/powerline/config_files/colorschemes/default.json
@@ -0,0 +1,56 @@
+{
+ "name": "Default",
+ "groups": {
+ "information:additional": { "fg": "gray9", "bg": "gray4", "attrs": [] },
+ "information:regular": { "fg": "gray10", "bg": "gray4", "attrs": ["bold"] },
+ "information:highlighted": { "fg": "white", "bg": "gray4", "attrs": [] },
+ "information:priority": { "fg": "brightyellow", "bg": "mediumorange", "attrs": [] },
+ "warning:regular": { "fg": "white", "bg": "brightred", "attrs": ["bold"] },
+ "critical:failure": { "fg": "white", "bg": "darkestred", "attrs": [] },
+ "critical:success": { "fg": "white", "bg": "darkestgreen", "attrs": [] },
+ "background": { "fg": "white", "bg": "gray0", "attrs": [] },
+ "background:divider": { "fg": "gray5", "bg": "gray0", "attrs": [] },
+ "session": { "fg": "black", "bg": "gray10", "attrs": ["bold"] },
+ "date": { "fg": "gray8", "bg": "gray2", "attrs": [] },
+ "time": { "fg": "gray10", "bg": "gray2", "attrs": ["bold"] },
+ "time:divider": { "fg": "gray5", "bg": "gray2", "attrs": [] },
+ "email_alert": "warning:regular",
+ "email_alert_gradient": { "fg": "white", "bg": "yellow_orange_red", "attrs": ["bold"] },
+ "hostname": { "fg": "black", "bg": "gray10", "attrs": ["bold"] },
+ "weather": { "fg": "gray8", "bg": "gray0", "attrs": [] },
+ "weather_temp_gradient": { "fg": "blue_red", "bg": "gray0", "attrs": [] },
+ "weather_condition_hot": { "fg": "khaki1", "bg": "gray0", "attrs": [] },
+ "weather_condition_snowy": { "fg": "skyblue1", "bg": "gray0", "attrs": [] },
+ "weather_condition_rainy": { "fg": "skyblue1", "bg": "gray0", "attrs": [] },
+ "uptime": { "fg": "gray8", "bg": "gray0", "attrs": [] },
+ "external_ip": { "fg": "gray8", "bg": "gray0", "attrs": [] },
+ "internal_ip": { "fg": "gray8", "bg": "gray0", "attrs": [] },
+ "network_load": { "fg": "gray8", "bg": "gray0", "attrs": [] },
+ "network_load_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0", "attrs": [] },
+ "network_load_sent_gradient": "network_load_gradient",
+ "network_load_recv_gradient": "network_load_gradient",
+ "network_load:divider": "background:divider",
+ "system_load": { "fg": "gray8", "bg": "gray0", "attrs": [] },
+ "system_load_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0", "attrs": [] },
+ "environment": { "fg": "gray8", "bg": "gray0", "attrs": [] },
+ "cpu_load_percent": { "fg": "gray8", "bg": "gray0", "attrs": [] },
+ "cpu_load_percent_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0", "attrs": [] },
+ "battery": { "fg": "gray8", "bg": "gray0", "attrs": [] },
+ "battery_gradient": { "fg": "white_red", "bg": "gray0", "attrs": [] },
+ "battery_full": { "fg": "red", "bg": "gray0", "attrs": [] },
+ "battery_empty": { "fg": "white", "bg": "gray0", "attrs": [] },
+ "player": { "fg": "gray10", "bg": "black", "attrs": [] },
+ "user": { "fg": "white", "bg": "darkblue", "attrs": ["bold"] },
+ "branch": { "fg": "gray9", "bg": "gray2", "attrs": [] },
+ "branch_dirty": { "fg": "brightyellow", "bg": "gray2", "attrs": [] },
+ "branch_clean": { "fg": "gray9", "bg": "gray2", "attrs": [] },
+ "branch:divider": { "fg": "gray7", "bg": "gray2", "attrs": [] },
+ "stash": "branch_dirty",
+ "stash:divider": "branch:divider",
+ "cwd": "information:additional",
+ "cwd:current_folder": "information:regular",
+ "cwd:divider": { "fg": "gray7", "bg": "gray4", "attrs": [] },
+ "virtualenv": { "fg": "white", "bg": "darkcyan", "attrs": [] },
+ "attached_clients": { "fg": "gray8", "bg": "gray0", "attrs": [] }
+ }
+}
diff --git a/powerline/config_files/colorschemes/ipython/__main__.json b/powerline/config_files/colorschemes/ipython/__main__.json
new file mode 100644
index 0000000..982ea35
--- /dev/null
+++ b/powerline/config_files/colorschemes/ipython/__main__.json
@@ -0,0 +1,6 @@
+{
+ "groups": {
+ "prompt": "information:additional",
+ "prompt_count": "information:highlighted"
+ }
+}
diff --git a/powerline/config_files/colorschemes/pdb/__main__.json b/powerline/config_files/colorschemes/pdb/__main__.json
new file mode 100644
index 0000000..01a51fe
--- /dev/null
+++ b/powerline/config_files/colorschemes/pdb/__main__.json
@@ -0,0 +1,8 @@
+{
+ "groups": {
+ "current_code_name": "information:additional",
+ "current_context": "current_code_name",
+ "current_line": "information:regular",
+ "current_file": "information:regular"
+ }
+}
diff --git a/powerline/config_files/colorschemes/pdb/default.json b/powerline/config_files/colorschemes/pdb/default.json
new file mode 100644
index 0000000..b97acf7
--- /dev/null
+++ b/powerline/config_files/colorschemes/pdb/default.json
@@ -0,0 +1,5 @@
+{
+ "groups": {
+ "stack_depth": { "fg": "gray1", "bg": "gray10", "attrs": ["bold"] }
+ }
+}
diff --git a/powerline/config_files/colorschemes/pdb/solarized.json b/powerline/config_files/colorschemes/pdb/solarized.json
new file mode 100644
index 0000000..2e1c787
--- /dev/null
+++ b/powerline/config_files/colorschemes/pdb/solarized.json
@@ -0,0 +1,5 @@
+{
+ "groups": {
+ "stack_depth": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": ["bold"] }
+ }
+}
diff --git a/powerline/config_files/colorschemes/shell/__main__.json b/powerline/config_files/colorschemes/shell/__main__.json
new file mode 100644
index 0000000..6e3856f
--- /dev/null
+++ b/powerline/config_files/colorschemes/shell/__main__.json
@@ -0,0 +1,10 @@
+{
+ "groups": {
+ "continuation": "cwd",
+ "continuation:current": "cwd:current_folder",
+ "exit_fail": "critical:failure",
+ "exit_success": "critical:success",
+ "jobnum": "information:priority",
+ "superuser": "warning:regular"
+ }
+}
diff --git a/powerline/config_files/colorschemes/shell/default.json b/powerline/config_files/colorschemes/shell/default.json
new file mode 100644
index 0000000..1126feb
--- /dev/null
+++ b/powerline/config_files/colorschemes/shell/default.json
@@ -0,0 +1,16 @@
+{
+ "name": "Default color scheme for shell prompts",
+ "groups": {
+ "hostname": { "fg": "brightyellow", "bg": "mediumorange", "attrs": [] },
+ "environment": { "fg": "white", "bg": "darkestgreen", "attrs": [] },
+ "mode": { "fg": "darkestgreen", "bg": "brightgreen", "attrs": ["bold"] },
+ "attached_clients": { "fg": "white", "bg": "darkestgreen", "attrs": [] }
+ },
+ "mode_translations": {
+ "vicmd": {
+ "groups": {
+ "mode": {"fg": "darkestcyan", "bg": "white", "attrs": ["bold"]}
+ }
+ }
+ }
+}
diff --git a/powerline/config_files/colorschemes/shell/solarized.json b/powerline/config_files/colorschemes/shell/solarized.json
new file mode 100644
index 0000000..69dcab1
--- /dev/null
+++ b/powerline/config_files/colorschemes/shell/solarized.json
@@ -0,0 +1,13 @@
+{
+ "name": "Solarized dark for shell",
+ "groups": {
+ "mode": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": ["bold"] }
+ },
+ "mode_translations": {
+ "vicmd": {
+ "groups": {
+ "mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] }
+ }
+ }
+ }
+}
diff --git a/powerline/config_files/colorschemes/solarized.json b/powerline/config_files/colorschemes/solarized.json
new file mode 100644
index 0000000..c0eba5a
--- /dev/null
+++ b/powerline/config_files/colorschemes/solarized.json
@@ -0,0 +1,40 @@
+{
+ "name": "Solarized dark",
+ "groups": {
+ "information:additional": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
+ "information:regular": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": ["bold"] },
+ "information:highlighted": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": ["bold"]},
+ "information:priority": { "fg": "solarized:base3", "bg": "solarized:yellow", "attrs": [] },
+ "warning:regular": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": [] },
+ "critical:failure": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": [] },
+ "critical:success": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] },
+ "background": { "fg": "solarized:base3", "bg": "solarized:base02", "attrs": [] },
+ "background:divider": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
+ "user": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] },
+ "virtualenv": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] },
+ "branch": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
+ "branch_dirty": { "fg": "solarized:yellow", "bg": "solarized:base02", "attrs": [] },
+ "branch_clean": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
+ "stash": "branch_dirty",
+ "email_alert_gradient": { "fg": "solarized:base3", "bg": "yellow_orange_red", "attrs": [] },
+ "email_alert": "warning:regular",
+ "cwd": "information:additional",
+ "cwd:current_folder": "information:regular",
+ "cwd:divider": { "fg": "solarized:base1", "bg": "solarized:base01", "attrs": [] },
+ "network_load": { "fg": "solarized:base1", "bg": "solarized:base03", "attrs": [] },
+ "network_load:divider": "network_load",
+ "network_load_gradient": { "fg": "green_yellow_orange_red", "bg": "solarized:base03", "attrs": [] },
+ "network_load_sent_gradient": "network_load_gradient",
+ "network_load_recv_gradient": "network_load_gradient",
+ "hostname": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
+ "environment": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] },
+ "attached_clients": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] },
+ "date": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
+ "time": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": ["bold"] },
+ "time:divider": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
+ "system_load": { "fg": "solarized:base1", "bg": "solarized:base03", "attrs": [] },
+ "weather_temp_gradient": { "fg": "blue_red", "bg": "solarized:base03", "attrs": [] },
+ "weather": { "fg": "solarized:base1", "bg": "solarized:base03", "attrs": [] },
+ "uptime": { "fg": "solarized:base1", "bg": "solarized:base03", "attrs": [] }
+ }
+}
diff --git a/powerline/config_files/colorschemes/tmux/default.json b/powerline/config_files/colorschemes/tmux/default.json
new file mode 100644
index 0000000..8525fb0
--- /dev/null
+++ b/powerline/config_files/colorschemes/tmux/default.json
@@ -0,0 +1,14 @@
+{
+ "groups": {
+ "active_window_status": {"fg": "darkblue", "bg": "gray0", "attrs": []},
+ "window_status": {"fg": "gray70", "bg": "gray0", "attrs": []},
+ "activity_status": {"fg": "yellow", "bg": "gray0", "attrs": []},
+ "bell_status": {"fg": "red", "bg": "gray0", "attrs": []},
+ "window": {"fg": "gray6", "bg": "gray0", "attrs": []},
+ "window:divider": {"fg": "gray4", "bg": "gray0", "attrs": []},
+ "window:current": {"fg": "mediumcyan", "bg": "darkblue", "attrs": []},
+ "window_name": {"fg": "white", "bg": "darkblue", "attrs": ["bold"]},
+ "session": {"fg": "black", "bg": "gray90", "attrs": ["bold"]},
+ "session:prefix": {"fg": "gray90", "bg": "darkblue", "attrs": ["bold"]}
+ }
+}
diff --git a/powerline/config_files/colorschemes/tmux/solarized.json b/powerline/config_files/colorschemes/tmux/solarized.json
new file mode 100644
index 0000000..20c42d3
--- /dev/null
+++ b/powerline/config_files/colorschemes/tmux/solarized.json
@@ -0,0 +1,14 @@
+{
+ "groups": {
+ "active_window_status": { "fg": "solarized:blue", "bg": "solarized:base02", "attrs": [] },
+ "window_status": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
+ "activity_status": { "fg": "solarized:yellow", "bg": "solarized:base02", "attrs": [] },
+ "bell_status": { "fg": "solarized:red", "bg": "solarized:base02", "attrs": [] },
+ "window": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
+ "window:divider": { "fg": "solarized:base01", "bg": "solarized:base02", "attrs": [] },
+ "window:current": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
+ "window_name": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": ["bold"] },
+ "session": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
+ "session:prefix": { "fg": "solarized:base01", "bg": "solarized:base3", "attrs": [] }
+ }
+}
diff --git a/powerline/config_files/colorschemes/vim/__main__.json b/powerline/config_files/colorschemes/vim/__main__.json
new file mode 100644
index 0000000..1ce2e7b
--- /dev/null
+++ b/powerline/config_files/colorschemes/vim/__main__.json
@@ -0,0 +1,50 @@
+{
+ "groups": {
+ "branch_clean": "branch",
+ "environment": "information:unimportant",
+ "file_size": "information:unimportant",
+ "file_format": "information:unimportant",
+ "file_encoding": "file_format",
+ "file_type": "file_format",
+ "branch": "information:additional",
+ "file_scheme": "file_name",
+ "file_directory": "information:additional",
+ "file_name_empty": "file_directory",
+ "line_percent": "information:additional",
+ "line_count": "line_current",
+ "position": "information:additional",
+ "single_tab": "line_current",
+ "many_tabs": "line_current",
+ "bufnr": "file_directory",
+ "winnr": "information:unimportant",
+ "tabnr": "file_directory",
+ "capslock_indicator": "paste_indicator",
+
+ "csv:column_number": "line_current",
+ "csv:column_name": "line_current_symbol",
+
+ "tab:background": "background",
+ "tab:divider": "background:divider",
+
+ "tab_nc:modified_indicator": "modified_indicator",
+ "tab_nc:file_directory": "information:unimportant",
+ "tab_nc:file_name": "tab_nc:file_directory",
+ "tab_nc:tabnr": "tab_nc:file_directory",
+
+ "buf_nc:file_directory": "tab_nc:file_directory",
+ "buf_nc:file_name": "buf_nc:file_directory",
+ "buf_nc:bufnr": "buf_nc:file_directory",
+ "buf_nc:modified_indicator": "tab_nc:modified_indicator",
+
+ "buf_nc_mod:file_directory": "tab_nc:file_directory",
+ "buf_nc_mod:file_name": "buf_nc_mod:file_directory",
+ "buf_nc_mod:bufnr": "buf_nc_mod:file_directory",
+ "buf_nc_mod:modified_indicator": "tab_nc:modified_indicator",
+
+
+ "commandt:label": "file_name",
+ "commandt:background": "background",
+ "commandt:finder": "file_name",
+ "commandt:path": "file_directory"
+ }
+}
diff --git a/powerline/config_files/colorschemes/vim/default.json b/powerline/config_files/colorschemes/vim/default.json
new file mode 100644
index 0000000..e02a160
--- /dev/null
+++ b/powerline/config_files/colorschemes/vim/default.json
@@ -0,0 +1,154 @@
+{
+ "name": "Default color scheme",
+ "groups": {
+ "information:unimportant": { "fg": "gray8", "bg": "gray2", "attrs": [] },
+ "information:additional": { "fg": "gray9", "bg": "gray4", "attrs": [] },
+ "background": { "fg": "white", "bg": "gray2", "attrs": [] },
+ "background:divider": { "fg": "gray6", "bg": "gray2", "attrs": [] },
+ "mode": { "fg": "darkestgreen", "bg": "brightgreen", "attrs": ["bold"] },
+ "visual_range": { "fg": "brightestorange", "bg": "darkorange", "attrs": ["bold"] },
+ "modified_indicator": { "fg": "brightyellow", "bg": "gray4", "attrs": ["bold"] },
+ "paste_indicator": { "fg": "white", "bg": "mediumorange", "attrs": ["bold"] },
+ "readonly_indicator": { "fg": "brightestred", "bg": "gray4", "attrs": [] },
+ "branch_dirty": { "fg": "brightyellow", "bg": "gray4", "attrs": [] },
+ "branch:divider": { "fg": "gray7", "bg": "gray4", "attrs": [] },
+ "file_name": { "fg": "white", "bg": "gray4", "attrs": ["bold"] },
+ "window_title": { "fg": "white", "bg": "gray4", "attrs": [] },
+ "file_name_no_file": { "fg": "gray9", "bg": "gray4", "attrs": ["bold"] },
+ "file_vcs_status": { "fg": "brightestred", "bg": "gray4", "attrs": [] },
+ "file_vcs_status_M": { "fg": "brightyellow", "bg": "gray4", "attrs": [] },
+ "file_vcs_status_A": { "fg": "brightgreen", "bg": "gray4", "attrs": [] },
+ "line_percent": { "fg": "gray9", "bg": "gray4", "attrs": [] },
+ "line_percent_gradient": { "fg": "dark_green_gray", "bg": "gray4", "attrs": [] },
+ "position": { "fg": "gray9", "bg": "gray4", "attrs": [] },
+ "position_gradient": { "fg": "green_yellow_red", "bg": "gray4", "attrs": [] },
+ "line_current": { "fg": "gray1", "bg": "gray10", "attrs": ["bold"] },
+ "line_current_symbol": { "fg": "gray1", "bg": "gray10", "attrs": [] },
+ "virtcol_current_gradient": { "fg": "dark_GREEN_Orange_red", "bg": "gray10", "attrs": [] },
+ "col_current": { "fg": "gray6", "bg": "gray10", "attrs": [] },
+ "modified_buffers": { "fg": "brightyellow", "bg": "gray2", "attrs": [] },
+ "attached_clients": { "fg": "gray8", "bg": "gray2", "attrs": [] },
+ "error": { "fg": "brightestred", "bg": "darkred", "attrs": ["bold"] },
+ "warning": { "fg": "brightyellow", "bg": "darkorange", "attrs": ["bold"] },
+ "current_tag": { "fg": "gray9", "bg": "gray2", "attrs": [] },
+
+ "tab_nc:modified_indicator": { "fg": "brightyellow", "bg": "gray2", "attrs": ["bold"] }
+ },
+ "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",
+ "dark_green_gray": "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",
+ "dark_green_gray": "light_green_gray"
+ },
+ "groups": {
+ "mode": { "fg": "darkestcyan", "bg": "white", "attrs": ["bold"] },
+ "background:divider": { "fg": "darkcyan", "bg": "darkestblue", "attrs": [] },
+ "branch:divider": { "fg": "darkcyan", "bg": "darkblue", "attrs": [] }
+ }
+ },
+ "ic": {
+ "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",
+ "dark_green_gray": "light_green_gray"
+ },
+ "groups": {
+ "mode": { "fg": "darkestcyan", "bg": "white", "attrs": ["bold"] },
+ "background:divider": { "fg": "darkcyan", "bg": "darkestblue", "attrs": [] },
+ "branch:divider": { "fg": "darkcyan", "bg": "darkblue", "attrs": [] }
+ }
+ },
+ "ix": {
+ "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",
+ "dark_green_gray": "light_green_gray"
+ },
+ "groups": {
+ "mode": { "fg": "darkestcyan", "bg": "white", "attrs": ["bold"] },
+ "background:divider": { "fg": "darkcyan", "bg": "darkestblue", "attrs": [] },
+ "branch:divider": { "fg": "darkcyan", "bg": "darkblue", "attrs": [] }
+ }
+ },
+ "v": {
+ "groups": {
+ "mode": { "fg": "darkorange", "bg": "brightestorange", "attrs": ["bold"] }
+ }
+ },
+ "V": {
+ "groups": {
+ "mode": { "fg": "darkorange", "bg": "brightestorange", "attrs": ["bold"] }
+ }
+ },
+ "^V": {
+ "groups": {
+ "mode": { "fg": "darkorange", "bg": "brightestorange", "attrs": ["bold"] }
+ }
+ },
+ "R": {
+ "groups": {
+ "mode": { "fg": "white", "bg": "brightred", "attrs": ["bold"] }
+ }
+ },
+ "Rc": {
+ "groups": {
+ "mode": { "fg": "white", "bg": "brightred", "attrs": ["bold"] }
+ }
+ },
+ "Rx": {
+ "groups": {
+ "mode": { "fg": "white", "bg": "brightred", "attrs": ["bold"] }
+ }
+ }
+ }
+}
diff --git a/powerline/config_files/colorschemes/vim/solarized.json b/powerline/config_files/colorschemes/vim/solarized.json
new file mode 100644
index 0000000..55cfaa7
--- /dev/null
+++ b/powerline/config_files/colorschemes/vim/solarized.json
@@ -0,0 +1,121 @@
+{
+ "name": "Solarized dark for vim",
+ "groups": {
+ "information:additional": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
+ "information:unimportant": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
+ "background": { "fg": "solarized:base3", "bg": "solarized:base02", "attrs": [] },
+ "background:divider": { "fg": "solarized:base00", "bg": "solarized:base02", "attrs": [] },
+ "mode": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": ["bold"] },
+ "visual_range": { "fg": "solarized:green", "bg": "solarized:base3", "attrs": ["bold"] },
+ "modified_indicator": { "fg": "solarized:yellow", "bg": "solarized:base01", "attrs": ["bold"] },
+ "paste_indicator": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] },
+ "readonly_indicator": { "fg": "solarized:red", "bg": "solarized:base01", "attrs": [] },
+ "branch_dirty": { "fg": "solarized:yellow", "bg": "solarized:base01", "attrs": [] },
+ "branch:divider": { "fg": "solarized:base1", "bg": "solarized:base01", "attrs": [] },
+ "stash:divider": "branch:divider",
+ "file_name": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": ["bold"] },
+ "window_title": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
+ "file_name_no_file": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": ["bold"] },
+ "file_format": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
+ "file_vcs_status": { "fg": "solarized:red", "bg": "solarized:base01", "attrs": [] },
+ "file_vcs_status_M": { "fg": "solarized:yellow", "bg": "solarized:base01", "attrs": [] },
+ "file_vcs_status_A": { "fg": "solarized:green", "bg": "solarized:base01", "attrs": [] },
+ "line_percent": { "fg": "solarized:base3", "bg": "solarized:base00", "attrs": [] },
+ "line_percent_gradient": { "fg": "green_yellow_orange_red", "bg": "solarized:base00", "attrs": [] },
+ "position": { "fg": "solarized:base3", "bg": "solarized:base00", "attrs": [] },
+ "position_gradient": { "fg": "green_yellow_orange_red", "bg": "solarized:base00", "attrs": [] },
+ "line_current": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": ["bold"] },
+ "line_current_symbol": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
+ "virtcol_current_gradient": { "fg": "GREEN_Orange_red", "bg": "solarized:base2", "attrs": [] },
+ "col_current": { "fg": "solarized:base0", "bg": "solarized:base2", "attrs": [] },
+ "environment": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
+ "attached_clients": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
+ "error": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] },
+ "warning": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] },
+ "current_tag": { "fg": "solarized:base3", "bg": "solarized:base02", "attrs": ["bold"] }
+ },
+ "mode_translations": {
+ "nc": {
+ "colors": {
+ "solarized:base01": "solarized:base02",
+ "solarized:base00": "solarized:base02",
+ "solarized:base0": "solarized:base01",
+ "solarized:base1": "solarized:base00",
+ "solarized:base2": "solarized:base0",
+ "solarized:base3": "solarized:base1"
+ }
+ },
+ "i": {
+ "groups": {
+ "background": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
+ "background:divider": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
+ "mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] },
+ "modified_indicator": { "fg": "solarized:yellow", "bg": "solarized:base2", "attrs": ["bold"] },
+ "paste_indicator": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] },
+ "readonly_indicator": { "fg": "solarized:red", "bg": "solarized:base2", "attrs": [] },
+ "branch": { "fg": "solarized:base01", "bg": "solarized:base2", "attrs": [] },
+ "branch:divider": { "fg": "solarized:base00", "bg": "solarized:base2", "attrs": [] },
+ "file_directory": { "fg": "solarized:base01", "bg": "solarized:base2", "attrs": [] },
+ "file_name": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": ["bold"] },
+ "file_size": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
+ "file_name_no_file": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": ["bold"] },
+ "file_name_empty": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
+ "file_format": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
+ "file_vcs_status": { "fg": "solarized:red", "bg": "solarized:base2", "attrs": [] },
+ "file_vcs_status_M": { "fg": "solarized:yellow", "bg": "solarized:base2", "attrs": [] },
+ "file_vcs_status_A": { "fg": "solarized:green", "bg": "solarized:base2", "attrs": [] },
+ "line_percent": { "fg": "solarized:base3", "bg": "solarized:base1", "attrs": [] },
+ "line_percent_gradient": { "fg": "solarized:base3", "bg": "solarized:base1", "attrs": [] },
+ "position": { "fg": "solarized:base3", "bg": "solarized:base1", "attrs": [] },
+ "position_gradient": { "fg": "solarized:base3", "bg": "solarized:base1", "attrs": [] },
+ "line_current": { "fg": "solarized:base03", "bg": "solarized:base3", "attrs": ["bold"] },
+ "line_current_symbol": { "fg": "solarized:base03", "bg": "solarized:base3", "attrs": [] },
+ "col_current": { "fg": "solarized:base0", "bg": "solarized:base3", "attrs": [] }
+ }
+ },
+ "ic": {
+ "groups": {
+ "background": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
+ "background:divider": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
+ "mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] }
+ }
+ },
+ "ix": {
+ "groups": {
+ "background": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
+ "background:divider": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
+ "mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] }
+ }
+ },
+ "v": {
+ "groups": {
+ "mode": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] }
+ }
+ },
+ "V": {
+ "groups": {
+ "mode": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] }
+ }
+ },
+ "^V": {
+ "groups": {
+ "mode": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] }
+ }
+ },
+ "R": {
+ "groups": {
+ "mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
+ }
+ },
+ "Rc": {
+ "groups": {
+ "mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
+ }
+ },
+ "Rx": {
+ "groups": {
+ "mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
+ }
+ }
+ }
+}
diff --git a/powerline/config_files/colorschemes/vim/solarizedlight.json b/powerline/config_files/colorschemes/vim/solarizedlight.json
new file mode 100644
index 0000000..f862d39
--- /dev/null
+++ b/powerline/config_files/colorschemes/vim/solarizedlight.json
@@ -0,0 +1,122 @@
+{
+ "name": "Solarized light for vim",
+ "groups": {
+ "information:additional": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
+ "information:unimportant": { "fg": "solarized:base1", "bg": "solarized:base01", "attrs": [] },
+ "background": { "fg": "solarized:base03", "bg": "solarized:base01", "attrs": [] },
+ "background:divider": { "fg": "solarized:base0", "bg": "solarized:base01", "attrs": [] },
+ "mode": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": ["bold"] },
+ "visual_range": { "fg": "solarized:green", "bg": "solarized:base3", "attrs": ["bold"] },
+ "modified_indicator": { "fg": "solarized:yellow", "bg": "solarized:base2", "attrs": ["bold"] },
+ "paste_indicator": { "fg": "solarized:red", "bg": "solarized:base2", "attrs": ["bold"] },
+ "readonly_indicator": { "fg": "solarized:red", "bg": "solarized:base2", "attrs": [] },
+ "branch_dirty": { "fg": "solarized:yellow", "bg": "solarized:base2", "attrs": [] },
+ "branch:divider": { "fg": "solarized:base1", "bg": "solarized:base2", "attrs": [] },
+ "stash": "branch_dirty",
+ "stash:divider": "branch:divider",
+ "file_name": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": ["bold"] },
+ "window_title": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
+ "file_size": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
+ "file_name_no_file": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": ["bold"] },
+ "file_name_empty": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
+ "file_vcs_status": { "fg": "solarized:red", "bg": "solarized:base2", "attrs": [] },
+ "file_vcs_status_M": { "fg": "solarized:yellow", "bg": "solarized:base2", "attrs": [] },
+ "file_vcs_status_A": { "fg": "solarized:green", "bg": "solarized:base2", "attrs": [] },
+ "line_percent": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
+ "line_percent_gradient": { "fg": "green_yellow_orange_red", "bg": "solarized:base2", "attrs": [] },
+ "position": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
+ "position_gradient": { "fg": "green_yellow_orange_red", "bg": "solarized:base2", "attrs": [] },
+ "line_current": { "fg": "solarized:base3", "bg": "solarized:base02", "attrs": ["bold"] },
+ "line_current_symbol": { "fg": "solarized:base3", "bg": "solarized:base02", "attrs": [] },
+ "virtcol_current_gradient": { "fg": "yellow_orange_red", "bg": "solarized:base02", "attrs": [] },
+ "col_current": { "fg": "solarized:base00", "bg": "solarized:base02", "attrs": [] },
+ "error": { "fg": "solarized:base03", "bg": "solarized:red", "attrs": ["bold"] },
+ "warning": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": ["bold"] },
+ "current_tag": { "fg": "solarized:base03", "bg": "solarized:base01", "attrs": ["bold"] }
+ },
+ "mode_translations": {
+ "nc": {
+ "colors": {
+ "solarized:base2": "solarized:base01",
+ "solarized:base0": "solarized:base01",
+ "solarized:base00": "solarized:base2",
+ "solarized:base1": "solarized:base0",
+ "solarized:base02": "solarized:base00",
+ "solarized:base03": "solarized:base1"
+ }
+ },
+ "i": {
+ "groups": {
+ "background": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
+ "background:divider": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
+ "mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] },
+ "modified_indicator": { "fg": "solarized:yellow", "bg": "solarized:base02", "attrs": ["bold"] },
+ "paste_indicator": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] },
+ "readonly_indicator": { "fg": "solarized:red", "bg": "solarized:base02", "attrs": [] },
+ "branch": { "fg": "solarized:base2", "bg": "solarized:base02", "attrs": [] },
+ "branch:divider": { "fg": "solarized:base0", "bg": "solarized:base02", "attrs": [] },
+ "file_directory": { "fg": "solarized:base2", "bg": "solarized:base02", "attrs": [] },
+ "file_name": { "fg": "solarized:base01", "bg": "solarized:base02", "attrs": ["bold"] },
+ "file_size": { "fg": "solarized:base01", "bg": "solarized:base02", "attrs": [] },
+ "file_name_no_file": { "fg": "solarized:base01", "bg": "solarized:base02", "attrs": ["bold"] },
+ "file_name_empty": { "fg": "solarized:base01", "bg": "solarized:base02", "attrs": [] },
+ "file_format": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
+ "file_vcs_status": { "fg": "solarized:red", "bg": "solarized:base02", "attrs": [] },
+ "file_vcs_status_M": { "fg": "solarized:yellow", "bg": "solarized:base02", "attrs": [] },
+ "file_vcs_status_A": { "fg": "solarized:green", "bg": "solarized:base02", "attrs": [] },
+ "line_percent": { "fg": "solarized:base03", "bg": "solarized:base1", "attrs": [] },
+ "line_percent_gradient": { "fg": "solarized:base03", "bg": "solarized:base1", "attrs": [] },
+ "position": { "fg": "solarized:base03", "bg": "solarized:base1", "attrs": [] },
+ "position_gradient": { "fg": "solarized:base03", "bg": "solarized:base1", "attrs": [] },
+ "line_current": { "fg": "solarized:base3", "bg": "solarized:base03", "attrs": ["bold"] },
+ "line_current_symbol": { "fg": "solarized:base3", "bg": "solarized:base03", "attrs": [] },
+ "virtcol_current_gradient": { "fg": "yellow_orange_red", "bg": "solarized:base03", "attrs": [] },
+ "col_current": { "fg": "solarized:base00", "bg": "solarized:base03", "attrs": [] }
+ }
+ },
+ "ic": {
+ "groups": {
+ "background": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
+ "background:divider": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
+ "mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] }
+ }
+ },
+ "ix": {
+ "groups": {
+ "background": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
+ "background:divider": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
+ "mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] }
+ }
+ },
+ "v": {
+ "groups": {
+ "mode": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] }
+ }
+ },
+ "V": {
+ "groups": {
+ "mode": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] }
+ }
+ },
+ "^V": {
+ "groups": {
+ "mode": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] }
+ }
+ },
+ "R": {
+ "groups": {
+ "mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
+ }
+ },
+ "Rc": {
+ "groups": {
+ "mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
+ }
+ },
+ "Rx": {
+ "groups": {
+ "mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
+ }
+ }
+ }
+}
diff --git a/powerline/config_files/config.json b/powerline/config_files/config.json
new file mode 100644
index 0000000..4491885
--- /dev/null
+++ b/powerline/config_files/config.json
@@ -0,0 +1,53 @@
+{
+ "common": {
+ "term_truecolor": false
+ },
+ "ext": {
+ "ipython": {
+ "colorscheme": "default",
+ "theme": "in",
+ "local_themes": {
+ "rewrite": "rewrite",
+ "out": "out",
+ "in2": "in2"
+ }
+ },
+ "pdb": {
+ "colorscheme": "default",
+ "theme": "default"
+ },
+ "shell": {
+ "colorscheme": "default",
+ "theme": "default",
+ "local_themes": {
+ "continuation": "continuation",
+ "select": "select"
+ }
+ },
+ "tmux": {
+ "colorscheme": "default",
+ "theme": "default"
+ },
+ "vim": {
+ "colorscheme": "default",
+ "theme": "default",
+ "local_themes": {
+ "__tabline__": "tabline",
+
+ "cmdwin": "cmdwin",
+ "help": "help",
+ "quickfix": "quickfix",
+
+ "powerline.matchers.vim.plugin.nerdtree.nerdtree": "plugin_nerdtree",
+ "powerline.matchers.vim.plugin.commandt.commandt": "plugin_commandt",
+ "powerline.matchers.vim.plugin.gundo.gundo": "plugin_gundo",
+ "powerline.matchers.vim.plugin.gundo.gundo_preview": "plugin_gundo-preview"
+ }
+ },
+ "wm": {
+ "colorscheme": "default",
+ "theme": "default",
+ "update_interval": 2
+ }
+ }
+}
diff --git a/powerline/config_files/themes/ascii.json b/powerline/config_files/themes/ascii.json
new file mode 100644
index 0000000..0ea05e7
--- /dev/null
+++ b/powerline/config_files/themes/ascii.json
@@ -0,0 +1,153 @@
+{
+ "use_non_breaking_spaces": false,
+ "dividers": {
+ "left": {
+ "hard": " ",
+ "soft": "| "
+ },
+ "right": {
+ "hard": " ",
+ "soft": " |"
+ }
+ },
+ "spaces": 1,
+ "segment_data": {
+ "branch": {
+ "before": "BR "
+ },
+ "stash": {
+ "before": "ST "
+ },
+ "cwd": {
+ "args": {
+ "ellipsis": "..."
+ }
+ },
+ "player": {
+ "args": {
+ "state_symbols": {
+ "fallback": "",
+ "play": ">",
+ "pause": "~",
+ "stop": "X"
+ }
+ }
+ },
+
+ "line_current_symbol": {
+ "contents": "LN "
+ },
+
+ "time": {
+ "before": ""
+ },
+
+ "powerline.segments.common.net.network_load": {
+ "args": {
+ "recv_format": "DL {value:>8}",
+ "sent_format": "UL {value:>8}"
+ }
+ },
+ "powerline.segments.common.net.hostname": {
+ "before": "H "
+ },
+ "powerline.segments.common.bat.battery": {
+ "args": {
+ "full_heart": "O",
+ "empty_heart": "O",
+ "online": "C",
+ "offline": " "
+ }
+ },
+ "powerline.segments.common.sys.uptime": {
+ "before": "UP "
+ },
+ "powerline.segments.common.mail.email_imap_alert": {
+ "before": "MAIL "
+ },
+ "powerline.segments.common.env.virtualenv": {
+ "before": "(e) "
+ },
+ "powerline.segments.common.wthr.weather": {
+ "args": {
+ "icons": {
+ "day": "DAY",
+ "blustery": "WIND",
+ "rainy": "RAIN",
+ "cloudy": "CLOUDS",
+ "snowy": "SNOW",
+ "stormy": "STORM",
+ "foggy": "FOG",
+ "sunny": "SUN",
+ "night": "NIGHT",
+ "windy": "WINDY",
+ "not_available": "NA",
+ "unknown": "UKN"
+ },
+ "temp_format": "{temp:.0f} C"
+ }
+ },
+ "powerline.segments.common.time.fuzzy_time": {
+ "args": {
+ "unicode_text": false
+ }
+ },
+
+ "powerline.segments.vim.mode": {
+ "args": {
+ "override": {
+ "n": "NORMAL",
+ "no": "N-OPER",
+ "v": "VISUAL",
+ "V": "V-LINE",
+ "^V": "V-BLCK",
+ "s": "SELECT",
+ "S": "S-LINE",
+ "^S": "S-BLCK",
+ "i": "INSERT",
+ "ic": "I-COMP",
+ "ix": "I-C_X ",
+ "R": "RPLACE",
+ "Rv": "V-RPLC",
+ "Rc": "R-COMP",
+ "Rx": "R-C_X ",
+ "c": "COMMND",
+ "cv": "VIM-EX",
+ "ce": "NRM-EX",
+ "r": "PROMPT",
+ "rm": "-MORE-",
+ "r?": "CNFIRM",
+ "!": "!SHELL",
+ "t": "TERM "
+ }
+ }
+ },
+ "powerline.segments.vim.visual_range": {
+ "args": {
+ "CTRL_V_text": "{rows} x {vcols}",
+ "v_text_oneline": "C:{vcols}",
+ "v_text_multiline": "L:{rows}",
+ "V_text": "L:{rows}"
+ }
+ },
+ "powerline.segments.vim.readonly_indicator": {
+ "args": {
+ "text": "RO"
+ }
+ },
+ "powerline.segments.vim.modified_indicator": {
+ "args": {
+ "text": "+"
+ }
+ },
+
+ "powerline.segments.i3wm.scratchpad": {
+ "args": {
+ "icons": {
+ "fresh": "O",
+ "changed": "X"
+ }
+ }
+ }
+ }
+}
diff --git a/powerline/config_files/themes/ipython/in.json b/powerline/config_files/themes/ipython/in.json
new file mode 100644
index 0000000..edd4d29
--- /dev/null
+++ b/powerline/config_files/themes/ipython/in.json
@@ -0,0 +1,25 @@
+{
+ "segments": {
+ "left": [
+ {
+ "function": "powerline.segments.common.env.virtualenv",
+ "priority": 10
+ },
+ {
+ "type": "string",
+ "contents": "In [",
+ "draw_soft_divider": false,
+ "highlight_groups": ["prompt"]
+ },
+ {
+ "function": "powerline.segments.ipython.prompt_count",
+ "draw_soft_divider": false
+ },
+ {
+ "type": "string",
+ "contents": "]",
+ "highlight_groups": ["prompt"]
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/ipython/in2.json b/powerline/config_files/themes/ipython/in2.json
new file mode 100644
index 0000000..422c44b
--- /dev/null
+++ b/powerline/config_files/themes/ipython/in2.json
@@ -0,0 +1,12 @@
+{
+ "segments": {
+ "left": [
+ {
+ "type": "string",
+ "contents": "",
+ "width": "auto",
+ "highlight_groups": ["prompt"]
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/ipython/out.json b/powerline/config_files/themes/ipython/out.json
new file mode 100644
index 0000000..2425d0b
--- /dev/null
+++ b/powerline/config_files/themes/ipython/out.json
@@ -0,0 +1,24 @@
+{
+ "default_module": "powerline.segments.ipython",
+ "segments": {
+ "left": [
+ {
+ "type": "string",
+ "contents": "Out[",
+ "draw_soft_divider": false,
+ "width": "auto",
+ "align": "r",
+ "highlight_groups": ["prompt"]
+ },
+ {
+ "function": "prompt_count",
+ "draw_soft_divider": false
+ },
+ {
+ "type": "string",
+ "contents": "]",
+ "highlight_groups": ["prompt"]
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/ipython/rewrite.json b/powerline/config_files/themes/ipython/rewrite.json
new file mode 100644
index 0000000..8192fe4
--- /dev/null
+++ b/powerline/config_files/themes/ipython/rewrite.json
@@ -0,0 +1,23 @@
+{
+ "default_module": "powerline.segments.ipython",
+ "segments": {
+ "left": [
+ {
+ "type": "string",
+ "contents": "",
+ "draw_soft_divider": false,
+ "width": "auto",
+ "highlight_groups": ["prompt"]
+ },
+ {
+ "function": "prompt_count",
+ "draw_soft_divider": false
+ },
+ {
+ "type": "string",
+ "contents": ">",
+ "highlight_groups": ["prompt"]
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/pdb/default.json b/powerline/config_files/themes/pdb/default.json
new file mode 100644
index 0000000..dcae108
--- /dev/null
+++ b/powerline/config_files/themes/pdb/default.json
@@ -0,0 +1,27 @@
+{
+ "default_module": "powerline.segments.pdb",
+ "segments": {
+ "left": [
+ {
+ "function": "stack_depth"
+ },
+ {
+ "type": "segment_list",
+ "function": "powerline.listers.pdb.frame_lister",
+ "segments": [
+ {
+ "function": "current_file",
+ "after": ":"
+ },
+ {
+ "function": "current_line",
+ "after": " "
+ },
+ {
+ "function": "current_code_name"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/powerline.json b/powerline/config_files/themes/powerline.json
new file mode 100644
index 0000000..366a7ea
--- /dev/null
+++ b/powerline/config_files/themes/powerline.json
@@ -0,0 +1,151 @@
+{
+ "dividers": {
+ "left": {
+ "hard": " ",
+ "soft": " "
+ },
+ "right": {
+ "hard": " ",
+ "soft": " "
+ }
+ },
+ "spaces": 1,
+ "segment_data": {
+ "branch": {
+ "before": " "
+ },
+ "stash": {
+ "before": "⌆ "
+ },
+ "cwd": {
+ "args": {
+ "ellipsis": "⋯"
+ }
+ },
+
+ "line_current_symbol": {
+ "contents": " "
+ },
+ "player": {
+ "args": {
+ "state_symbols": {
+ "fallback": "♫",
+ "play": "▶",
+ "pause": "▮▮",
+ "stop": "■"
+ }
+ }
+ },
+
+ "time": {
+ "before": "⌚ "
+ },
+
+ "powerline.segments.common.net.network_load": {
+ "args": {
+ "recv_format": "⬇ {value:>8}",
+ "sent_format": "⬆ {value:>8}"
+ }
+ },
+ "powerline.segments.common.net.hostname": {
+ "before": " "
+ },
+ "powerline.segments.common.bat.battery": {
+ "args": {
+ "full_heart": "♥",
+ "empty_heart": "♥",
+ "online": "⚡︎",
+ "offline": " "
+ }
+ },
+ "powerline.segments.common.sys.uptime": {
+ "before": "⇑ "
+ },
+ "powerline.segments.common.mail.email_imap_alert": {
+ "before": "✉ "
+ },
+ "powerline.segments.common.env.virtualenv": {
+ "before": "ⓔ "
+ },
+ "powerline.segments.common.wthr.weather": {
+ "args": {
+ "icons": {
+ "day": "〇",
+ "blustery": "⚑",
+ "rainy": "☔",
+ "cloudy": "☁",
+ "snowy": "❅",
+ "stormy": "☈",
+ "foggy": "≡",
+ "sunny": "☼",
+ "night": "☾",
+ "windy": "☴",
+ "not_available": "�",
+ "unknown": "⚠"
+ }
+ }
+ },
+ "powerline.segments.common.time.fuzzy_time": {
+ "args": {
+ "unicode_text": true
+ }
+ },
+
+ "powerline.segments.vim.mode": {
+ "args": {
+ "override": {
+ "n": "NORMAL",
+ "no": "N·OPER",
+ "v": "VISUAL",
+ "V": "V·LINE",
+ "^V": "V·BLCK",
+ "s": "SELECT",
+ "S": "S·LINE",
+ "^S": "S·BLCK",
+ "i": "INSERT",
+ "ic": "I·COMP",
+ "ix": "I·C-X ",
+ "R": "RPLACE",
+ "Rv": "V·RPLC",
+ "Rc": "R·COMP",
+ "Rx": "R·C-X ",
+ "c": "COMMND",
+ "cv": "VIM·EX",
+ "ce": "NRM·EX",
+ "r": "PROMPT",
+ "rm": "-MORE-",
+ "r?": "CNFIRM",
+ "!": "!SHELL",
+ "t": "TERM "
+ }
+ }
+ },
+ "powerline.segments.vim.visual_range": {
+ "args": {
+ "CTRL_V_text": "↕{rows} ↔{vcols}",
+ "v_text_oneline": "↔{vcols}",
+ "v_text_multiline": "↕{rows}",
+ "V_text": "⇕{rows}"
+ }
+ },
+ "powerline.segments.vim.readonly_indicator": {
+ "args": {
+ "text": ""
+ }
+ },
+ "powerline.segments.vim.modified_indicator": {
+ "args": {
+ "text": "+"
+ }
+ },
+
+ "powerline.segments.i3wm.scratchpad": {
+ "args": {
+ "icons": {
+ "fresh": "●",
+ "changed": "○"
+ }
+ }
+ }
+ }
+}
diff --git a/powerline/config_files/themes/powerline_terminus.json b/powerline/config_files/themes/powerline_terminus.json
new file mode 100644
index 0000000..e5fb1c8
--- /dev/null
+++ b/powerline/config_files/themes/powerline_terminus.json
@@ -0,0 +1,151 @@
+{
+ "dividers": {
+ "left": {
+ "hard": " ",
+ "soft": " "
+ },
+ "right": {
+ "hard": " ",
+ "soft": " "
+ }
+ },
+ "spaces": 1,
+ "segment_data": {
+ "branch": {
+ "before": " "
+ },
+ "stash": {
+ "before": "ST "
+ },
+ "cwd": {
+ "args": {
+ "ellipsis": "…"
+ }
+ },
+
+ "line_current_symbol": {
+ "contents": " "
+ },
+ "player": {
+ "args": {
+ "state_symbols": {
+ "fallback": "♫",
+ "play": "▶",
+ "pause": "▮▮",
+ "stop": "■"
+ }
+ }
+ },
+
+ "time": {
+ "before": ""
+ },
+
+ "powerline.segments.common.net.network_load": {
+ "args": {
+ "recv_format": "⇓ {value:>8}",
+ "sent_format": "⇑ {value:>8}"
+ }
+ },
+ "powerline.segments.common.net.hostname": {
+ "before": " "
+ },
+ "powerline.segments.common.bat.battery": {
+ "args": {
+ "full_heart": "♥",
+ "empty_heart": "♥",
+ "online": "⚡︎",
+ "offline": " "
+ }
+ },
+ "powerline.segments.common.sys.uptime": {
+ "before": "↑ "
+ },
+ "powerline.segments.common.mail.email_imap_alert": {
+ "before": "MAIL "
+ },
+ "powerline.segments.common.env.virtualenv": {
+ "before": "(e) "
+ },
+ "powerline.segments.common.wthr.weather": {
+ "args": {
+ "icons": {
+ "day": "DAY",
+ "blustery": "WIND",
+ "rainy": "RAIN",
+ "cloudy": "CLOUDS",
+ "snowy": "SNOW",
+ "stormy": "STORM",
+ "foggy": "FOG",
+ "sunny": "SUN",
+ "night": "NIGHT",
+ "windy": "WINDY",
+ "not_available": "NA",
+ "unknown": "UKN"
+ }
+ }
+ },
+ "powerline.segments.common.time.fuzzy_time": {
+ "args": {
+ "unicode_text": true
+ }
+ },
+
+ "powerline.segments.vim.mode": {
+ "args": {
+ "override": {
+ "n": "NORMAL",
+ "no": "N·OPER",
+ "v": "VISUAL",
+ "V": "V·LINE",
+ "^V": "V·BLCK",
+ "s": "SELECT",
+ "S": "S·LINE",
+ "^S": "S·BLCK",
+ "i": "INSERT",
+ "ic": "I·COMP",
+ "ix": "I·C-X ",
+ "R": "RPLACE",
+ "Rv": "V·RPLC",
+ "Rc": "R·COMP",
+ "Rx": "R·C-X ",
+ "c": "COMMND",
+ "cv": "VIM·EX",
+ "ce": "NRM·EX",
+ "r": "PROMPT",
+ "rm": "-MORE-",
+ "r?": "CNFIRM",
+ "!": "!SHELL",
+ "t": "TERM "
+ }
+ }
+ },
+ "powerline.segments.vim.visual_range": {
+ "args": {
+ "CTRL_V_text": "↕{rows} ↔{vcols}",
+ "v_text_oneline": "↔{vcols}",
+ "v_text_multiline": "↕{rows}",
+ "V_text": "⇕{rows}"
+ }
+ },
+ "powerline.segments.vim.readonly_indicator": {
+ "args": {
+ "text": ""
+ }
+ },
+ "powerline.segments.vim.modified_indicator": {
+ "args": {
+ "text": "+"
+ }
+ },
+
+ "powerline.segments.i3wm.scratchpad": {
+ "args": {
+ "icons": {
+ "fresh": "●",
+ "changed": "○"
+ }
+ }
+ }
+ }
+}
diff --git a/powerline/config_files/themes/powerline_unicode7.json b/powerline/config_files/themes/powerline_unicode7.json
new file mode 100644
index 0000000..bd62826
--- /dev/null
+++ b/powerline/config_files/themes/powerline_unicode7.json
@@ -0,0 +1,165 @@
+{
+ "dividers": {
+ "left": {
+ "hard": " ",
+ "soft": " "
+ },
+ "right": {
+ "hard": " ",
+ "soft": " "
+ }
+ },
+ "spaces": 1,
+ "segment_data": {
+ "branch": {
+ "before": "🔀 "
+ },
+ "stash": {
+ "before": "📝"
+ },
+ "cwd": {
+ "args": {
+ "ellipsis": "⋯"
+ }
+ },
+
+ "line_current_symbol": {
+ "contents": " "
+ },
+ "player": {
+ "args": {
+ "state_symbols": {
+ "fallback": "♫",
+ "play": "⏵",
+ "pause": "⏸",
+ "stop": "⏹"
+ }
+ }
+ },
+
+ "time": {
+ "before": "🕐 "
+ },
+
+ "powerline.segments.common.net.network_load": {
+ "args": {
+ "recv_format": "⬇ {value:>8}",
+ "sent_format": "⬆ {value:>8}"
+ }
+ },
+ "powerline.segments.common.net.hostname": {
+ "before": "🏠 "
+ },
+ "powerline.segments.common.bat.battery": {
+ "args": {
+ "full_heart": "💙",
+ "empty_heart": "💛",
+ "online": "⚡️",
+ "offline": " "
+ }
+ },
+ "powerline.segments.common.sys.uptime": {
+ "before": "⇑ "
+ },
+ "powerline.segments.common.mail.email_imap_alert": {
+ "before": "✉ "
+ },
+ "powerline.segments.common.env.virtualenv": {
+ "before": "🐍 "
+ },
+ "powerline.segments.common.wthr.weather": {
+ "args": {
+ "icons": {
+ "tornado": "🌪",
+ "hurricane": "🌀",
+ "showers": "☔",
+ "scattered_showers": "☔",
+ "thunderstorms": "🌩",
+ "isolated_thunderstorms": "🌩",
+ "scattered_thunderstorms": "🌩",
+ "dust": "🌫",
+ "fog": "🌫",
+ "cold": "❄",
+ "partly_cloudy_day": "🌤",
+ "mostly_cloudy_day": "🌥",
+ "sun": "🌣",
+ "hot": "♨",
+ "day": "☀",
+ "blustery": "⚑",
+ "rainy": "☂",
+ "cloudy": "☁",
+ "snowy": "☃",
+ "stormy": "☈",
+ "foggy": "🌁",
+ "sunny": "🌣",
+ "night": "☾",
+ "windy": "☴",
+ "not_available": "�",
+ "unknown": "⚠"
+ }
+ }
+ },
+ "powerline.segments.common.time.fuzzy_time": {
+ "args": {
+ "unicode_text": true
+ }
+ },
+
+ "powerline.segments.vim.mode": {
+ "args": {
+ "override": {
+ "n": "NORMAL",
+ "no": "N·OPER",
+ "v": "VISUAL",
+ "V": "V·LINE",
+ "^V": "V·BLCK",
+ "s": "SELECT",
+ "S": "S·LINE",
+ "^S": "S·BLCK",
+ "i": "INSERT",
+ "ic": "I·COMP",
+ "ix": "I·C-X ",
+ "R": "RPLACE",
+ "Rv": "V·RPLC",
+ "Rc": "R·COMP",
+ "Rx": "R·C-X ",
+ "c": "COMMND",
+ "cv": "VIM·EX",
+ "ce": "NRM·EX",
+ "r": "PROMPT",
+ "rm": "-MORE-",
+ "r?": "CNFIRM",
+ "!": "!SHELL",
+ "t": "TERM "
+ }
+ }
+ },
+ "powerline.segments.vim.visual_range": {
+ "args": {
+ "CTRL_V_text": "↕{rows} ↔{vcols}",
+ "v_text_oneline": "↔{vcols}",
+ "v_text_multiline": "↕{rows}",
+ "V_text": "⇕{rows}"
+ }
+ },
+ "powerline.segments.vim.readonly_indicator": {
+ "args": {
+ "text": "🔏"
+ }
+ },
+ "powerline.segments.vim.modified_indicator": {
+ "args": {
+ "text": "🖫⃥"
+ }
+ },
+
+ "powerline.segments.i3wm.scratchpad": {
+ "args": {
+ "icons": {
+ "fresh": "●",
+ "changed": "○"
+ }
+ }
+ }
+ }
+}
diff --git a/powerline/config_files/themes/shell/__main__.json b/powerline/config_files/themes/shell/__main__.json
new file mode 100644
index 0000000..13ae942
--- /dev/null
+++ b/powerline/config_files/themes/shell/__main__.json
@@ -0,0 +1,14 @@
+{
+ "segment_data": {
+ "hostname": {
+ "args": {
+ "only_if_ssh": true
+ }
+ },
+ "cwd": {
+ "args": {
+ "dir_limit_depth": 3
+ }
+ }
+ }
+}
diff --git a/powerline/config_files/themes/shell/continuation.json b/powerline/config_files/themes/shell/continuation.json
new file mode 100644
index 0000000..9307fc0
--- /dev/null
+++ b/powerline/config_files/themes/shell/continuation.json
@@ -0,0 +1,12 @@
+{
+ "default_module": "powerline.segments.shell",
+ "segments": {
+ "left": [
+ {
+ "function": "continuation"
+ }
+ ],
+ "right": [
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/shell/default.json b/powerline/config_files/themes/shell/default.json
new file mode 100644
index 0000000..38039d8
--- /dev/null
+++ b/powerline/config_files/themes/shell/default.json
@@ -0,0 +1,43 @@
+{
+ "segments": {
+ "left": [
+ {
+ "function": "powerline.segments.shell.mode"
+ },
+ {
+ "function": "powerline.segments.common.net.hostname",
+ "priority": 10
+ },
+ {
+ "function": "powerline.segments.common.env.user",
+ "priority": 30
+ },
+ {
+ "function": "powerline.segments.common.env.virtualenv",
+ "priority": 50
+ },
+ {
+ "function": "powerline.segments.shell.cwd",
+ "priority": 10
+ },
+ {
+ "function": "powerline.segments.shell.jobnum",
+ "priority": 20
+ }
+ ],
+ "right": [
+ {
+ "function": "powerline.segments.shell.last_pipe_status",
+ "priority": 10
+ },
+ {
+ "function": "powerline.segments.common.vcs.stash",
+ "priority": 50
+ },
+ {
+ "function": "powerline.segments.common.vcs.branch",
+ "priority": 40
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/shell/default_leftonly.json b/powerline/config_files/themes/shell/default_leftonly.json
new file mode 100644
index 0000000..b576273
--- /dev/null
+++ b/powerline/config_files/themes/shell/default_leftonly.json
@@ -0,0 +1,34 @@
+{
+ "segments": {
+ "left": [
+ {
+ "function": "powerline.segments.common.net.hostname",
+ "priority": 10
+ },
+ {
+ "function": "powerline.segments.common.env.user",
+ "priority": 30
+ },
+ {
+ "function": "powerline.segments.common.env.virtualenv",
+ "priority": 50
+ },
+ {
+ "function": "powerline.segments.common.vcs.branch",
+ "priority": 40
+ },
+ {
+ "function": "powerline.segments.shell.cwd",
+ "priority": 10
+ },
+ {
+ "function": "powerline.segments.shell.jobnum",
+ "priority": 20
+ },
+ {
+ "function": "powerline.segments.shell.last_pipe_status",
+ "priority": 10
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/shell/select.json b/powerline/config_files/themes/shell/select.json
new file mode 100644
index 0000000..3d81408
--- /dev/null
+++ b/powerline/config_files/themes/shell/select.json
@@ -0,0 +1,13 @@
+{
+ "segments": {
+ "left": [
+ {
+ "type": "string",
+ "contents": "Select variant",
+ "width": "auto",
+ "align": "r",
+ "highlight_groups": ["continuation:current"]
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/tmux/default.json b/powerline/config_files/themes/tmux/default.json
new file mode 100644
index 0000000..4532ced
--- /dev/null
+++ b/powerline/config_files/themes/tmux/default.json
@@ -0,0 +1,28 @@
+{
+ "segments": {
+ "right": [
+ {
+ "function": "powerline.segments.common.sys.uptime",
+ "priority": 50
+ },
+ {
+ "function": "powerline.segments.common.sys.system_load",
+ "priority": 50
+ },
+ {
+ "function": "powerline.segments.common.time.date"
+ },
+ {
+ "function": "powerline.segments.common.time.date",
+ "name": "time",
+ "args": {
+ "format": "%H:%M",
+ "istime": true
+ }
+ },
+ {
+ "function": "powerline.segments.common.net.hostname"
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/unicode.json b/powerline/config_files/themes/unicode.json
new file mode 100644
index 0000000..0802852
--- /dev/null
+++ b/powerline/config_files/themes/unicode.json
@@ -0,0 +1,151 @@
+{
+ "dividers": {
+ "left": {
+ "hard": "▌ ",
+ "soft": "│ "
+ },
+ "right": {
+ "hard": " ▐",
+ "soft": " │"
+ }
+ },
+ "spaces": 1,
+ "segment_data": {
+ "branch": {
+ "before": "⎇ "
+ },
+ "stash": {
+ "before": "⌆"
+ },
+ "cwd": {
+ "args": {
+ "ellipsis": "⋯"
+ }
+ },
+ "player": {
+ "args": {
+ "state_symbols": {
+ "fallback": "♫",
+ "play": "▶",
+ "pause": "▮▮",
+ "stop": "■"
+ }
+ }
+ },
+
+ "line_current_symbol": {
+ "contents": "␤ "
+ },
+
+ "time": {
+ "before": "⌚ "
+ },
+
+ "powerline.segments.common.net.network_load": {
+ "args": {
+ "recv_format": "⬇ {value:>8}",
+ "sent_format": "⬆ {value:>8}"
+ }
+ },
+ "powerline.segments.common.net.hostname": {
+ "before": "⌂ "
+ },
+ "powerline.segments.common.bat.battery": {
+ "args": {
+ "full_heart": "♥",
+ "empty_heart": "♥",
+ "online": "⚡︎",
+ "offline": " "
+ }
+ },
+ "powerline.segments.common.sys.uptime": {
+ "before": "⇑ "
+ },
+ "powerline.segments.common.mail.email_imap_alert": {
+ "before": "✉ "
+ },
+ "powerline.segments.common.env.virtualenv": {
+ "before": "ⓔ "
+ },
+ "powerline.segments.common.wthr.weather": {
+ "args": {
+ "icons": {
+ "day": "〇",
+ "blustery": "⚑",
+ "rainy": "☔",
+ "cloudy": "☁",
+ "snowy": "❅",
+ "stormy": "☈",
+ "foggy": "≡",
+ "sunny": "☼",
+ "night": "☾",
+ "windy": "☴",
+ "not_available": "�",
+ "unknown": "⚠"
+ }
+ }
+ },
+ "powerline.segments.common.time.fuzzy_time": {
+ "args": {
+ "unicode_text": true
+ }
+ },
+
+ "powerline.segments.vim.mode": {
+ "args": {
+ "override": {
+ "n": "NORMAL",
+ "no": "N·OPER",
+ "v": "VISUAL",
+ "V": "V·LINE",
+ "^V": "V·BLCK",
+ "s": "SELECT",
+ "S": "S·LINE",
+ "^S": "S·BLCK",
+ "i": "INSERT",
+ "ic": "I·COMP",
+ "ix": "I·C-X ",
+ "R": "RPLACE",
+ "Rv": "V·RPLC",
+ "Rc": "R·COMP",
+ "Rx": "R·C-X ",
+ "c": "COMMND",
+ "cv": "VIM·EX",
+ "ce": "NRM·EX",
+ "r": "PROMPT",
+ "rm": "-MORE-",
+ "r?": "CNFIRM",
+ "!": "!SHELL",
+ "t": "TERM "
+ }
+ }
+ },
+ "powerline.segments.vim.visual_range": {
+ "args": {
+ "CTRL_V_text": "↕{rows} ↔{vcols}",
+ "v_text_oneline": "↔{vcols}",
+ "v_text_multiline": "↕{rows}",
+ "V_text": "⇕{rows}"
+ }
+ },
+ "powerline.segments.vim.readonly_indicator": {
+ "args": {
+ "text": "⊗"
+ }
+ },
+ "powerline.segments.vim.modified_indicator": {
+ "args": {
+ "text": "+"
+ }
+ },
+
+ "powerline.segments.i3wm.scratchpad": {
+ "args": {
+ "icons": {
+ "fresh": "●",
+ "changed": "○"
+ }
+ }
+ }
+ }
+}
diff --git a/powerline/config_files/themes/unicode_terminus.json b/powerline/config_files/themes/unicode_terminus.json
new file mode 100644
index 0000000..9c76985
--- /dev/null
+++ b/powerline/config_files/themes/unicode_terminus.json
@@ -0,0 +1,151 @@
+{
+ "dividers": {
+ "left": {
+ "hard": "▌ ",
+ "soft": "│ "
+ },
+ "right": {
+ "hard": " ▐",
+ "soft": " │"
+ }
+ },
+ "spaces": 1,
+ "segment_data": {
+ "branch": {
+ "before": "BR "
+ },
+ "stash": {
+ "before": "ST "
+ },
+ "cwd": {
+ "args": {
+ "ellipsis": "…"
+ }
+ },
+
+ "line_current_symbol": {
+ "contents": "␤ "
+ },
+ "player": {
+ "args": {
+ "state_symbols": {
+ "fallback": "♫",
+ "play": "▶",
+ "pause": "▮▮",
+ "stop": "■"
+ }
+ }
+ },
+
+ "time": {
+ "before": ""
+ },
+
+ "powerline.segments.common.net.network_load": {
+ "args": {
+ "recv_format": "⇓ {value:>8}",
+ "sent_format": "⇑ {value:>8}"
+ }
+ },
+ "powerline.segments.common.net.hostname": {
+ "before": "⌂ "
+ },
+ "powerline.segments.common.bat.battery": {
+ "args": {
+ "full_heart": "♥",
+ "empty_heart": "♥",
+ "online": "⚡︎",
+ "offline": " "
+ }
+ },
+ "powerline.segments.common.sys.uptime": {
+ "before": "↑ "
+ },
+ "powerline.segments.common.mail.email_imap_alert": {
+ "before": "MAIL "
+ },
+ "powerline.segments.common.env.virtualenv": {
+ "before": "(e) "
+ },
+ "powerline.segments.common.wthr.weather": {
+ "args": {
+ "icons": {
+ "day": "DAY",
+ "blustery": "WIND",
+ "rainy": "RAIN",
+ "cloudy": "CLOUDS",
+ "snowy": "SNOW",
+ "stormy": "STORM",
+ "foggy": "FOG",
+ "sunny": "SUN",
+ "night": "NIGHT",
+ "windy": "WINDY",
+ "not_available": "NA",
+ "unknown": "UKN"
+ }
+ }
+ },
+ "powerline.segments.common.time.fuzzy_time": {
+ "args": {
+ "unicode_text": true
+ }
+ },
+
+ "powerline.segments.vim.mode": {
+ "args": {
+ "override": {
+ "n": "NORMAL",
+ "no": "N·OPER",
+ "v": "VISUAL",
+ "V": "V·LINE",
+ "^V": "V·BLCK",
+ "s": "SELECT",
+ "S": "S·LINE",
+ "^S": "S·BLCK",
+ "i": "INSERT",
+ "ic": "I·COMP",
+ "ix": "I·C-X ",
+ "R": "RPLACE",
+ "Rv": "V·RPLC",
+ "Rc": "R·COMP",
+ "Rx": "R·C-X ",
+ "c": "COMMND",
+ "cv": "VIM·EX",
+ "ce": "NRM·EX",
+ "r": "PROMPT",
+ "rm": "-MORE-",
+ "r?": "CNFIRM",
+ "!": "!SHELL",
+ "t": "TERM "
+ }
+ }
+ },
+ "powerline.segments.vim.visual_range": {
+ "args": {
+ "CTRL_V_text": "{rows} × {vcols}",
+ "v_text_oneline": "C:{vcols}",
+ "v_text_multiline": "L:{rows}",
+ "V_text": "L:{rows}"
+ }
+ },
+ "powerline.segments.vim.readonly_indicator": {
+ "args": {
+ "text": "RO"
+ }
+ },
+ "powerline.segments.vim.modified_indicator": {
+ "args": {
+ "text": "+"
+ }
+ },
+
+ "powerline.segments.i3wm.scratchpad": {
+ "args": {
+ "icons": {
+ "fresh": "●",
+ "changed": "○"
+ }
+ }
+ }
+ }
+}
diff --git a/powerline/config_files/themes/unicode_terminus_condensed.json b/powerline/config_files/themes/unicode_terminus_condensed.json
new file mode 100644
index 0000000..421f5c8
--- /dev/null
+++ b/powerline/config_files/themes/unicode_terminus_condensed.json
@@ -0,0 +1,151 @@
+{
+ "dividers": {
+ "left": {
+ "hard": "▌",
+ "soft": "│"
+ },
+ "right": {
+ "hard": "▐",
+ "soft": "│"
+ }
+ },
+ "spaces": 0,
+ "segment_data": {
+ "branch": {
+ "before": "B "
+ },
+ "stash": {
+ "before": "S "
+ },
+ "cwd": {
+ "args": {
+ "use_path_separator": true,
+ "ellipsis": "…"
+ }
+ },
+
+ "line_current_symbol": {
+ "contents": "␤"
+ },
+ "player": {
+ "args": {
+ "state_symbols": {
+ "fallback": "♫",
+ "play": "▶",
+ "pause": "▮▮",
+ "stop": "■"
+ }
+ }
+ },
+
+ "time": {
+ "before": ""
+ },
+
+ "powerline.segments.common.net.network_load": {
+ "args": {
+ "recv_format": "⇓{value:>8}",
+ "sent_format": "⇑{value:>8}"
+ }
+ },
+ "powerline.segments.common.net.hostname": {
+ "before": "⌂"
+ },
+ "powerline.segments.common.bat.battery": {
+ "args": {
+ "full_heart": "♥",
+ "empty_heart": "♥",
+ "online": "⚡︎",
+ "offline": " "
+ }
+ },
+ "powerline.segments.common.sys.uptime": {
+ "before": "↑"
+ },
+ "powerline.segments.common.mail.email_imap_alert": {
+ "before": "M "
+ },
+ "powerline.segments.common.env.virtualenv": {
+ "before": "E "
+ },
+ "powerline.segments.common.wthr.weather": {
+ "args": {
+ "icons": {
+ "day": "D",
+ "blustery": "W",
+ "rainy": "R",
+ "cloudy": "c",
+ "snowy": "*",
+ "stormy": "S",
+ "foggy": "f",
+ "sunny": "s",
+ "night": "N",
+ "windy": "w",
+ "not_available": "-",
+ "unknown": "!"
+ }
+ }
+ },
+ "powerline.segments.common.time.fuzzy_time": {
+ "args": {
+ "unicode_text": true
+ }
+ },
+
+ "powerline.segments.vim.mode": {
+ "args": {
+ "override": {
+ "n": "NML",
+ "no": "NOP",
+ "v": "VIS",
+ "V": "VLN",
+ "^V": "VBL",
+ "s": "SEL",
+ "S": "SLN",
+ "^S": "SBL",
+ "i": "INS",
+ "ic": "I-C",
+ "ix": "I^X",
+ "R": "REP",
+ "Rv": "VRP",
+ "Rc": "R-C",
+ "Rx": "R^X",
+ "c": "CMD",
+ "cv": "VEX",
+ "ce": " EX",
+ "r": "PRT",
+ "rm": "MOR",
+ "r?": "CON",
+ "!": " SH"
+ }
+ }
+ },
+ "powerline.segments.vim.visual_range": {
+ "args": {
+ "CTRL_V_text": "{rows}×{vcols}",
+ "v_text_oneline": "↔{vcols}",
+ "v_text_multiline": "↕{rows}",
+ "V_text": "⇕{rows}"
+ }
+ },
+ "powerline.segments.vim.readonly_indicator": {
+ "args": {
+ "text": "RO"
+ }
+ },
+ "powerline.segments.vim.modified_indicator": {
+ "args": {
+ "text": "+"
+ }
+ },
+
+ "powerline.segments.i3wm.scratchpad": {
+ "args": {
+ "icons": {
+ "fresh": "●",
+ "changed": "○"
+ }
+ }
+ }
+ }
+}
diff --git a/powerline/config_files/themes/vim/__main__.json b/powerline/config_files/themes/vim/__main__.json
new file mode 100644
index 0000000..7cd3305
--- /dev/null
+++ b/powerline/config_files/themes/vim/__main__.json
@@ -0,0 +1,10 @@
+{
+ "segment_data": {
+ "line_percent": {
+ "args": {
+ "gradient": true
+ },
+ "after": "%"
+ }
+ }
+}
diff --git a/powerline/config_files/themes/vim/cmdwin.json b/powerline/config_files/themes/vim/cmdwin.json
new file mode 100644
index 0000000..e6a05b0
--- /dev/null
+++ b/powerline/config_files/themes/vim/cmdwin.json
@@ -0,0 +1,18 @@
+{
+ "segments": {
+ "left": [
+ {
+ "type": "string",
+ "contents": "Command Line",
+ "highlight_groups": ["file_name"]
+ },
+ {
+ "type": "string",
+ "highlight_groups": ["background"],
+ "draw_soft_divider": false,
+ "draw_hard_divider": false,
+ "width": "auto"
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/vim/default.json b/powerline/config_files/themes/vim/default.json
new file mode 100644
index 0000000..9b0c744
--- /dev/null
+++ b/powerline/config_files/themes/vim/default.json
@@ -0,0 +1,128 @@
+{
+ "segments": {
+ "left": [
+ {
+ "function": "mode",
+ "exclude_modes": ["nc"]
+ },
+ {
+ "function": "visual_range",
+ "include_modes": ["v", "V", "^V", "s", "S", "^S"],
+ "priority": 10
+ },
+ {
+ "function": "paste_indicator",
+ "exclude_modes": ["nc"],
+ "priority": 10
+ },
+ {
+ "function": "powerline.segments.vim.plugin.capslock.capslock_indicator",
+ "include_modes": ["i", "R", "Rv"],
+ "priority": 10
+ },
+ {
+ "function": "branch",
+ "exclude_modes": ["nc"],
+ "priority": 30
+ },
+ {
+ "function": "readonly_indicator",
+ "draw_soft_divider": false,
+ "after": " "
+ },
+ {
+ "function": "file_scheme",
+ "priority": 20
+ },
+ {
+ "function": "file_directory",
+ "priority": 40,
+ "draw_soft_divider": false
+ },
+ {
+ "function": "file_name",
+ "draw_soft_divider": false
+ },
+ {
+ "function": "file_vcs_status",
+ "before": " ",
+ "draw_soft_divider": false
+ },
+ {
+ "function": "modified_indicator",
+ "before": " "
+ },
+ {
+ "exclude_modes": ["i", "R", "Rv"],
+ "function": "trailing_whitespace",
+ "display": false,
+ "priority": 60
+ },
+ {
+ "exclude_modes": ["nc"],
+ "function": "powerline.segments.vim.plugin.syntastic.syntastic",
+ "priority": 50
+ },
+ {
+ "exclude_modes": ["nc"],
+ "function": "powerline.segments.vim.plugin.tagbar.current_tag",
+ "draw_soft_divider": false,
+ "priority": 50
+ },
+ {
+ "type": "string",
+ "highlight_groups": ["background"],
+ "draw_soft_divider": false,
+ "draw_hard_divider": false,
+ "width": "auto"
+ }
+ ],
+ "right": [
+ {
+ "function": "file_format",
+ "draw_soft_divider": false,
+ "exclude_modes": ["nc"],
+ "priority": 60
+ },
+ {
+ "function": "file_encoding",
+ "exclude_modes": ["nc"],
+ "priority": 60
+ },
+ {
+ "function": "file_type",
+ "exclude_modes": ["nc"],
+ "priority": 60
+ },
+ {
+ "function": "line_percent",
+ "priority": 50,
+ "width": 4,
+ "align": "r"
+ },
+ {
+ "function": "csv_col_current",
+ "priority": 30
+ },
+ {
+ "type": "string",
+ "name": "line_current_symbol",
+ "highlight_groups": ["line_current_symbol", "line_current"]
+ },
+ {
+ "function": "line_current",
+ "draw_soft_divider": false,
+ "width": 3,
+ "align": "r"
+ },
+ {
+ "function": "virtcol_current",
+ "draw_soft_divider": false,
+ "priority": 20,
+ "before": ":",
+ "width": 3,
+ "align": "l"
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/vim/help.json b/powerline/config_files/themes/vim/help.json
new file mode 100644
index 0000000..45c9458
--- /dev/null
+++ b/powerline/config_files/themes/vim/help.json
@@ -0,0 +1,36 @@
+{
+ "segments": {
+ "left": [
+ {
+ "function": "file_name",
+ "draw_soft_divider": false
+ },
+ {
+ "type": "string",
+ "highlight_groups": ["background"],
+ "draw_soft_divider": false,
+ "draw_hard_divider": false,
+ "width": "auto"
+ }
+ ],
+ "right": [
+ {
+ "function": "line_percent",
+ "priority": 30,
+ "width": 4,
+ "align": "r"
+ },
+ {
+ "type": "string",
+ "name": "line_current_symbol",
+ "highlight_groups": ["line_current_symbol", "line_current"]
+ },
+ {
+ "function": "line_current",
+ "draw_soft_divider": false,
+ "width": 3,
+ "align": "r"
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/vim/plugin_commandt.json b/powerline/config_files/themes/vim/plugin_commandt.json
new file mode 100644
index 0000000..dd6748f
--- /dev/null
+++ b/powerline/config_files/themes/vim/plugin_commandt.json
@@ -0,0 +1,26 @@
+{
+ "segments": {
+ "left": [
+ {
+ "type": "string",
+ "contents": "Command-T",
+ "highlight_groups": ["commandt:label"]
+ },
+ {
+ "function": "powerline.segments.vim.plugin.commandt.finder"
+ },
+ {
+ "function": "powerline.segments.vim.plugin.commandt.path"
+ },
+ {
+ "type": "string",
+ "highlight_groups": ["commandt:background"],
+ "draw_soft_divider": false,
+ "draw_hard_divider": false,
+ "width": "auto"
+ }
+ ],
+ "right": [
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/vim/plugin_gundo-preview.json b/powerline/config_files/themes/vim/plugin_gundo-preview.json
new file mode 100644
index 0000000..ad8432c
--- /dev/null
+++ b/powerline/config_files/themes/vim/plugin_gundo-preview.json
@@ -0,0 +1,18 @@
+{
+ "segments": {
+ "left": [
+ {
+ "type": "string",
+ "highlight_groups": ["gundo:name", "file_name"],
+ "contents": "Undo diff"
+ },
+ {
+ "type": "string",
+ "highlight_groups": ["gundo:background", "background"],
+ "draw_soft_divider": false,
+ "draw_hard_divider": false,
+ "width": "auto"
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/vim/plugin_gundo.json b/powerline/config_files/themes/vim/plugin_gundo.json
new file mode 100644
index 0000000..a03b256
--- /dev/null
+++ b/powerline/config_files/themes/vim/plugin_gundo.json
@@ -0,0 +1,18 @@
+{
+ "segments": {
+ "left": [
+ {
+ "type": "string",
+ "highlight_groups": ["gundo:name", "file_name"],
+ "contents": "Undo tree"
+ },
+ {
+ "type": "string",
+ "highlight_groups": ["gundo:background", "background"],
+ "draw_soft_divider": false,
+ "draw_hard_divider": false,
+ "width": "auto"
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/vim/plugin_nerdtree.json b/powerline/config_files/themes/vim/plugin_nerdtree.json
new file mode 100644
index 0000000..896d393
--- /dev/null
+++ b/powerline/config_files/themes/vim/plugin_nerdtree.json
@@ -0,0 +1,17 @@
+{
+ "default_module": "powerline.segments.vim.plugin.nerdtree",
+ "segments": {
+ "left": [
+ {
+ "function": "nerdtree"
+ },
+ {
+ "type": "string",
+ "highlight_groups": ["background"],
+ "draw_soft_divider": false,
+ "draw_hard_divider": false,
+ "width": "auto"
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/vim/quickfix.json b/powerline/config_files/themes/vim/quickfix.json
new file mode 100644
index 0000000..ae4d5a5
--- /dev/null
+++ b/powerline/config_files/themes/vim/quickfix.json
@@ -0,0 +1,40 @@
+{
+ "segment_data": {
+ "buffer_name": {
+ "contents": "Location List"
+ }
+ },
+ "segments": {
+ "left": [
+ {
+ "type": "string",
+ "name": "buffer_name",
+ "highlight_groups": ["file_name"]
+ },
+ {
+ "function": "window_title",
+ "draw_soft_divider": false
+ },
+ {
+ "type": "string",
+ "highlight_groups": ["background"],
+ "draw_soft_divider": false,
+ "draw_hard_divider": false,
+ "width": "auto"
+ }
+ ],
+ "right": [
+ {
+ "type": "string",
+ "name": "line_current_symbol",
+ "highlight_groups": ["line_current_symbol", "line_current"]
+ },
+ {
+ "function": "line_current",
+ "draw_soft_divider": false,
+ "width": 3,
+ "align": "r"
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/vim/tabline.json b/powerline/config_files/themes/vim/tabline.json
new file mode 100644
index 0000000..1e3130e
--- /dev/null
+++ b/powerline/config_files/themes/vim/tabline.json
@@ -0,0 +1,93 @@
+{
+ "default_module": "powerline.segments.vim",
+ "segments": {
+ "left": [
+ {
+ "type": "segment_list",
+ "function": "powerline.listers.vim.tablister",
+ "exclude_function": "single_tab",
+ "segments": [
+ {
+ "function": "tab"
+ },
+ {
+ "function": "tabnr",
+ "after": " ",
+ "priority": 5
+ },
+ {
+ "function": "file_directory",
+ "priority": 40
+ },
+ {
+ "function": "file_name",
+ "args": {
+ "display_no_file": true
+ },
+ "priority": 10
+ },
+ {
+ "function": "tab_modified_indicator",
+ "priority": 5
+ }
+ ]
+ },
+ {
+ "function": "tab",
+ "args": {
+ "end": true
+ }
+ },
+ {
+ "type": "segment_list",
+ "function": "powerline.listers.vim.bufferlister",
+ "include_function": "single_tab",
+ "segments": [
+ {
+ "function": "bufnr",
+ "after": " ",
+ "priority": 5
+ },
+ {
+ "function": "file_directory",
+ "priority": 40
+ },
+ {
+ "function": "file_name",
+ "args": {
+ "display_no_file": true
+ },
+ "priority": 10
+ },
+ {
+ "function": "modified_indicator",
+ "priority": 5
+ }
+ ]
+ },
+ {
+ "type": "string",
+ "highlight_groups": ["tab:background"],
+ "draw_soft_divider": false,
+ "draw_hard_divider": false,
+ "width": "auto"
+ }
+ ],
+ "right": [
+ {
+ "type": "string",
+ "contents": "Bufs",
+ "name": "single_tab",
+ "highlight_groups": ["single_tab"],
+ "include_function": "single_tab"
+ },
+ {
+ "type": "string",
+ "contents": "Tabs",
+ "name": "many_tabs",
+ "highlight_groups": ["many_tabs"],
+ "exclude_function": "single_tab"
+ }
+ ]
+ }
+}
diff --git a/powerline/config_files/themes/wm/default.json b/powerline/config_files/themes/wm/default.json
new file mode 100644
index 0000000..579080d
--- /dev/null
+++ b/powerline/config_files/themes/wm/default.json
@@ -0,0 +1,29 @@
+{
+ "segments": {
+ "right": [
+ {
+ "function": "powerline.segments.common.wthr.weather",
+ "priority": 50
+ },
+ {
+ "function": "powerline.segments.common.time.date"
+ },
+ {
+ "function": "powerline.segments.common.time.date",
+ "name": "time",
+ "args": {
+ "format": "%H:%M",
+ "istime": true
+ }
+ },
+ {
+ "function": "powerline.segments.common.mail.email_imap_alert",
+ "priority": 10,
+ "args": {
+ "username": "",
+ "password": ""
+ }
+ }
+ ]
+ }
+}
diff --git a/powerline/dist/systemd/powerline-daemon.service b/powerline/dist/systemd/powerline-daemon.service
new file mode 100644
index 0000000..96b685d
--- /dev/null
+++ b/powerline/dist/systemd/powerline-daemon.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=powerline-daemon - Daemon that improves powerline performance
+Documentation=man:powerline-daemon(1)
+Documentation=https://powerline.readthedocs.org/en/latest/
+
+[Service]
+ExecStart=/usr/bin/powerline-daemon --foreground
+
+[Install]
+WantedBy=default.target
diff --git a/powerline/ipython.py b/powerline/ipython.py
new file mode 100644
index 0000000..cb84fc7
--- /dev/null
+++ b/powerline/ipython.py
@@ -0,0 +1,68 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+from powerline import Powerline
+from powerline.lib.dict import mergedicts
+from powerline.lib.unicode import string
+
+
+class IPythonInfo(object):
+ def __init__(self, shell):
+ self._shell = shell
+
+ @property
+ def prompt_count(self):
+ return self._shell.execution_count
+
+
+# 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 IPythonPowerline(Powerline):
+ def init(self, **kwargs):
+ super(IPythonPowerline, self).init(
+ 'ipython',
+ use_daemon_threads=True,
+ **kwargs
+ )
+
+ def get_config_paths(self):
+ if self.config_paths:
+ return self.config_paths
+ 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
+
+ def do_setup(self, wrefs):
+ for wref in wrefs:
+ obj = wref()
+ if obj is not None:
+ setattr(obj, 'powerline', self)
diff --git a/powerline/lemonbar.py b/powerline/lemonbar.py
new file mode 100644
index 0000000..b49f86b
--- /dev/null
+++ b/powerline/lemonbar.py
@@ -0,0 +1,21 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+from powerline import Powerline
+from powerline.lib.dict import mergedicts
+
+
+class LemonbarPowerline(Powerline):
+ def init(self):
+ super(LemonbarPowerline, self).init(ext='wm', renderer_module='lemonbar')
+
+ get_encoding = staticmethod(lambda: 'utf-8')
+
+ def get_local_themes(self, local_themes):
+ if not local_themes:
+ return {}
+
+ return dict((
+ (key, {'config': self.load_theme_config(val)})
+ for key, val in local_themes.items()
+ ))
diff --git a/powerline/lib/__init__.py b/powerline/lib/__init__.py
new file mode 100644
index 0000000..2a5fbd0
--- /dev/null
+++ b/powerline/lib/__init__.py
@@ -0,0 +1,28 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+from functools import wraps
+
+
+def wraps_saveargs(wrapped):
+ def dec(wrapper):
+ r = wraps(wrapped)(wrapper)
+ r.powerline_origin = getattr(wrapped, 'powerline_origin', wrapped)
+ return r
+ return dec
+
+
+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
diff --git a/powerline/lib/config.py b/powerline/lib/config.py
new file mode 100644
index 0000000..0c95e47
--- /dev/null
+++ b/powerline/lib/config.py
@@ -0,0 +1,218 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import json
+import codecs
+
+from copy import deepcopy
+from threading import Event, Lock
+from collections import defaultdict
+
+from powerline.lib.threaded import MultiRunnedThread
+from powerline.lib.watcher import create_file_watcher
+
+
+def open_file(path):
+ return codecs.open(path, encoding='utf-8')
+
+
+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 DummyWatcher(object):
+ def __call__(self, *args, **kwargs):
+ return False
+
+ def watch(self, *args, **kwargs):
+ pass
+
+
+class DeferredWatcher(object):
+ def __init__(self, *args, **kwargs):
+ self.args = args
+ self.kwargs = kwargs
+ self.calls = []
+
+ def __call__(self, *args, **kwargs):
+ self.calls.append(('__call__', args, kwargs))
+
+ def watch(self, *args, **kwargs):
+ self.calls.append(('watch', args, kwargs))
+
+ def unwatch(self, *args, **kwargs):
+ self.calls.append(('unwatch', args, kwargs))
+
+ def transfer_calls(self, watcher):
+ for attr, args, kwargs in self.calls:
+ getattr(watcher, attr)(*args, **kwargs)
+
+
+class ConfigLoader(MultiRunnedThread):
+ def __init__(self, shutdown_event=None, watcher=None, watcher_type=None, load=load_json_config, run_once=False):
+ super(ConfigLoader, self).__init__()
+ self.shutdown_event = shutdown_event or Event()
+ if run_once:
+ self.watcher = DummyWatcher()
+ self.watcher_type = 'dummy'
+ else:
+ self.watcher = watcher or DeferredWatcher()
+ if watcher:
+ if not watcher_type:
+ raise ValueError('When specifying watcher you must also specify watcher type')
+ self.watcher_type = watcher_type
+ else:
+ self.watcher_type = 'deferred'
+ self._load = load
+
+ self.pl = None
+ self.interval = None
+
+ self.lock = Lock()
+
+ self.watched = defaultdict(set)
+ self.missing = defaultdict(set)
+ self.loaded = {}
+
+ def set_watcher(self, watcher_type, force=False):
+ if watcher_type == self.watcher_type:
+ return
+ watcher = create_file_watcher(self.pl, watcher_type)
+ with self.lock:
+ if self.watcher_type == 'deferred':
+ self.watcher.transfer_calls(watcher)
+ self.watcher = watcher
+ self.watcher_type = watcher_type
+
+ 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 logged and ignored. IOError exception
+ will be ignored without logging.
+ :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 deepcopy(self.loaded[path])
+ except KeyError:
+ r = self._load(path)
+ self.loaded[path] = deepcopy(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 IOError:
+ pass
+ 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] = deepcopy(self._load(path))
+ except Exception as e:
+ self.exception('Error while loading {0}: {1}', path, str(e))
+ try:
+ self.loaded.pop(path)
+ except KeyError:
+ pass
+ try:
+ self.loaded.pop(path)
+ except KeyError:
+ pass
+
+ 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
diff --git a/powerline/lib/debug.py b/powerline/lib/debug.py
new file mode 100755
index 0000000..515e8c4
--- /dev/null
+++ b/powerline/lib/debug.py
@@ -0,0 +1,97 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import gc
+import sys
+
+from types import FrameType
+from itertools import chain
+
+
+# From http://code.activestate.com/recipes/523004-find-cyclical-references/
+def print_cycles(objects, outstream=sys.stdout, show_progress=False):
+ '''Find reference cycles
+
+ :param list objects:
+ A list of objects to find cycles in. It is often useful to pass in
+ gc.garbage to find the cycles that are preventing some objects from
+ being garbage collected.
+ :param file outstream:
+ The stream for output.
+ :param bool show_progress:
+ If True, print the number of objects reached as they are found.
+ '''
+ def print_path(path):
+ for i, step in enumerate(path):
+ # next “wraps around”
+ next = path[(i + 1) % len(path)]
+
+ outstream.write(' %s -- ' % str(type(step)))
+ written = False
+ if isinstance(step, dict):
+ for key, val in step.items():
+ if val is next:
+ outstream.write('[%s]' % repr(key))
+ written = True
+ break
+ if key is next:
+ outstream.write('[key] = %s' % repr(val))
+ written = True
+ break
+ elif isinstance(step, (list, tuple)):
+ for i, item in enumerate(step):
+ if item is next:
+ outstream.write('[%d]' % i)
+ written = True
+ elif getattr(type(step), '__getattribute__', None) in (object.__getattribute__, type.__getattribute__):
+ for attr in chain(dir(step), getattr(step, '__dict__', ())):
+ if getattr(step, attr, None) is next:
+ try:
+ outstream.write('%r.%s' % (step, attr))
+ except TypeError:
+ outstream.write('.%s' % (step, attr))
+ written = True
+ break
+ if not written:
+ outstream.write(repr(step))
+ outstream.write(' ->\n')
+ outstream.write('\n')
+
+ def recurse(obj, start, all, current_path):
+ if show_progress:
+ outstream.write('%d\r' % len(all))
+
+ all[id(obj)] = None
+
+ referents = gc.get_referents(obj)
+ for referent in referents:
+ # If we’ve found our way back to the start, this is
+ # a cycle, so print it out
+ if referent is start:
+ try:
+ outstream.write('Cyclic reference: %r\n' % referent)
+ except TypeError:
+ try:
+ outstream.write('Cyclic reference: %i (%r)\n' % (id(referent), type(referent)))
+ except TypeError:
+ outstream.write('Cyclic reference: %i\n' % id(referent))
+ print_path(current_path)
+
+ # Don’t go back through the original list of objects, or
+ # through temporary references to the object, since those
+ # are just an artifact of the cycle detector itself.
+ elif referent is objects or isinstance(referent, FrameType):
+ continue
+
+ # We haven’t seen this object before, so recurse
+ elif id(referent) not in all:
+ recurse(referent, start, all, current_path + (obj,))
+
+ for obj in objects:
+ # We are not interested in non-powerline cyclic references
+ try:
+ if not type(obj).__module__.startswith('powerline'):
+ continue
+ except AttributeError:
+ continue
+ recurse(obj, obj, {}, ())
diff --git a/powerline/lib/dict.py b/powerline/lib/dict.py
new file mode 100644
index 0000000..c06ab30
--- /dev/null
+++ b/powerline/lib/dict.py
@@ -0,0 +1,88 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+
+REMOVE_THIS_KEY = object()
+
+
+def mergeargs(argvalue, remove=False):
+ if not argvalue:
+ return None
+ r = {}
+ for subval in argvalue:
+ mergedicts(r, dict([subval]), remove=remove)
+ return r
+
+
+def _clear_special_values(d):
+ '''Remove REMOVE_THIS_KEY values from dictionary
+ '''
+ l = [d]
+ while l:
+ i = l.pop()
+ pops = []
+ for k, v in i.items():
+ if v is REMOVE_THIS_KEY:
+ pops.append(k)
+ elif isinstance(v, dict):
+ l.append(v)
+ for k in pops:
+ i.pop(k)
+
+
+def mergedicts(d1, d2, remove=True):
+ '''Recursively merge two dictionaries
+
+ First dictionary is modified in-place.
+ '''
+ _setmerged(d1, d2)
+ for k in d2:
+ if k in d1 and isinstance(d1[k], dict) and isinstance(d2[k], dict):
+ mergedicts(d1[k], d2[k], remove)
+ elif remove and d2[k] is REMOVE_THIS_KEY:
+ d1.pop(k, None)
+ else:
+ if remove and isinstance(d2[k], dict):
+ _clear_special_values(d2[k])
+ d1[k] = d2[k]
+
+
+def mergedefaults(d1, d2):
+ '''Recursively merge two dictionaries, keeping existing values
+
+ First dictionary is modified in-place.
+ '''
+ for k in d2:
+ if k in d1 and isinstance(d1[k], dict) and isinstance(d2[k], dict):
+ mergedefaults(d1[k], d2[k])
+ else:
+ d1.setdefault(k, d2[k])
+
+
+def _setmerged(d1, d2):
+ if hasattr(d1, 'setmerged'):
+ d1.setmerged(d2)
+
+
+def mergedicts_copy(d1, d2):
+ '''Recursively merge two dictionaries.
+
+ Dictionaries are not modified. Copying happens only if necessary. Assumes
+ that first dictionary supports .copy() method.
+ '''
+ ret = d1.copy()
+ _setmerged(ret, d2)
+ for k in d2:
+ if k in d1 and isinstance(d1[k], dict) and isinstance(d2[k], dict):
+ ret[k] = mergedicts_copy(d1[k], d2[k])
+ else:
+ ret[k] = d2[k]
+ return ret
+
+
+def updated(d, *args, **kwargs):
+ '''Copy dictionary and update it with provided arguments
+ '''
+ d = d.copy()
+ d.update(*args, **kwargs)
+ return d
diff --git a/powerline/lib/encoding.py b/powerline/lib/encoding.py
new file mode 100644
index 0000000..76a51d8
--- /dev/null
+++ b/powerline/lib/encoding.py
@@ -0,0 +1,125 @@
+# vim:fileencoding=utf-8:noet
+
+'''Encodings support
+
+This is the only module from which functions obtaining encoding should be
+exported. Note: you should always care about errors= argument since it is not
+guaranteed that encoding returned by some function can encode/decode given
+string.
+
+All functions in this module must always return a valid encoding. Most of them
+are not thread-safe.
+'''
+
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import sys
+import locale
+
+
+def get_preferred_file_name_encoding():
+ '''Get preferred file name encoding
+ '''
+ return (
+ sys.getfilesystemencoding()
+ or locale.getpreferredencoding()
+ or 'utf-8'
+ )
+
+
+def get_preferred_file_contents_encoding():
+ '''Get encoding preferred for file contents
+ '''
+ return (
+ locale.getpreferredencoding()
+ or 'utf-8'
+ )
+
+
+def get_preferred_output_encoding():
+ '''Get encoding that should be used for printing strings
+
+ .. warning::
+ Falls back to ASCII, so that output is most likely to be displayed
+ correctly.
+ '''
+ if hasattr(locale, 'LC_MESSAGES'):
+ return (
+ locale.getlocale(locale.LC_MESSAGES)[1]
+ or locale.getdefaultlocale()[1]
+ or 'ascii'
+ )
+
+ return (
+ locale.getdefaultlocale()[1]
+ or 'ascii'
+ )
+
+
+def get_preferred_input_encoding():
+ '''Get encoding that should be used for reading shell command output
+
+ .. warning::
+ Falls back to latin1 so that function is less likely to throw as decoded
+ output is primary searched for ASCII values.
+ '''
+ if hasattr(locale, 'LC_MESSAGES'):
+ return (
+ locale.getlocale(locale.LC_MESSAGES)[1]
+ or locale.getdefaultlocale()[1]
+ or 'latin1'
+ )
+
+ return (
+ locale.getdefaultlocale()[1]
+ or 'latin1'
+ )
+
+
+def get_preferred_arguments_encoding():
+ '''Get encoding that should be used for command-line arguments
+
+ .. warning::
+ Falls back to latin1 so that function is less likely to throw as
+ non-ASCII command-line arguments most likely contain non-ASCII
+ filenames and screwing them up due to unidentified locale is not much of
+ a problem.
+ '''
+ return (
+ locale.getdefaultlocale()[1]
+ or 'latin1'
+ )
+
+
+def get_preferred_environment_encoding():
+ '''Get encoding that should be used for decoding environment variables
+ '''
+ return (
+ locale.getpreferredencoding()
+ or 'utf-8'
+ )
+
+
+def get_unicode_writer(stream=sys.stdout, encoding=None, errors='replace'):
+ '''Get function which will write unicode string to the given stream
+
+ Writing is done using encoding returned by
+ :py:func:`get_preferred_output_encoding`.
+
+ :param file stream:
+ Stream to write to. Default value is :py:attr:`sys.stdout`.
+ :param str encoding:
+ Determines which encoding to use. If this argument is specified then
+ :py:func:`get_preferred_output_encoding` is not used.
+ :param str errors:
+ Determines what to do with characters which cannot be encoded. See
+ ``errors`` argument of :py:func:`codecs.encode`.
+
+ :return: Callable which writes unicode string to the given stream using
+ the preferred output encoding.
+ '''
+ encoding = encoding or get_preferred_output_encoding()
+ if sys.version_info < (3,) or not hasattr(stream, 'buffer'):
+ return lambda s: stream.write(s.encode(encoding, errors))
+ else:
+ return lambda s: stream.buffer.write(s.encode(encoding, errors))
diff --git a/powerline/lib/humanize_bytes.py b/powerline/lib/humanize_bytes.py
new file mode 100644
index 0000000..c98a117
--- /dev/null
+++ b/powerline/lib/humanize_bytes.py
@@ -0,0 +1,25 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+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))
diff --git a/powerline/lib/inotify.py b/powerline/lib/inotify.py
new file mode 100644
index 0000000..8b74a7f
--- /dev/null
+++ b/powerline/lib/inotify.py
@@ -0,0 +1,184 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import sys
+import os
+import errno
+import ctypes
+import struct
+
+from ctypes.util import find_library
+
+from powerline.lib.encoding import get_preferred_file_name_encoding
+
+
+__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
+__docformat__ = 'restructuredtext en'
+
+
+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')
+ if sys.platform == 'darwin':
+ raise INotifyError('INotify not available on OS X')
+ if not hasattr(ctypes, 'c_ssize_t'):
+ raise INotifyError('You need python >= 2.7 to use inotify')
+ 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')))
+
+ # 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')))
+
+ # 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')))
+ _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):
+ 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 = get_preferred_file_name_encoding()
+ self.hdr = struct.Struct(b'iIII')
+ # 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):
+ eno = ctypes.get_errno()
+ extra = ''
+ if eno == errno.ENOSPC:
+ extra = 'You may need to increase the inotify limits on your system, via /proc/sys/fs/inotify/max_user_*'
+ raise OSError(eno, self.os.strerror(eno) + str(extra))
+
+ 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):
+ 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')
+ pos += name_len
+ self.process_event(wd, mask, cookie, name)
+
+ def process_event(self, *args):
+ raise NotImplementedError()
diff --git a/powerline/lib/memoize.py b/powerline/lib/memoize.py
new file mode 100644
index 0000000..cedbe45
--- /dev/null
+++ b/powerline/lib/memoize.py
@@ -0,0 +1,42 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+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
diff --git a/powerline/lib/monotonic.py b/powerline/lib/monotonic.py
new file mode 100644
index 0000000..cd7c414
--- /dev/null
+++ b/powerline/lib/monotonic.py
@@ -0,0 +1,100 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+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
+
+ monotonic = lambda: clock_gettime(CLOCK_ID)
+ except ImportError:
+ # >=python-3.3
+ from time import monotonic
+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():
+ 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():
+ 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():
+ 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
diff --git a/powerline/lib/overrides.py b/powerline/lib/overrides.py
new file mode 100644
index 0000000..3257d98
--- /dev/null
+++ b/powerline/lib/overrides.py
@@ -0,0 +1,80 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import json
+
+from powerline.lib.dict import REMOVE_THIS_KEY
+
+
+def parse_value(s):
+ '''Convert string to Python object
+
+ Rules:
+
+ * Empty string means that corresponding key should be removed from the
+ dictionary.
+ * Strings that start with a minus, digit or with some character that starts
+ JSON collection or string object are parsed as JSON.
+ * JSON special values ``null``, ``true``, ``false`` (case matters) are
+ parsed as JSON.
+ * All other values are considered to be raw strings.
+
+ :param str s: Parsed string.
+
+ :return: Python object.
+ '''
+ if not s:
+ return REMOVE_THIS_KEY
+ elif s[0] in '"{[0123456789-' or s in ('null', 'true', 'false'):
+ return json.loads(s)
+ else:
+ return s
+
+
+def keyvaluesplit(s):
+ '''Split K1.K2=VAL into K1.K2 and parsed VAL
+ '''
+ 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 = parse_value(s[idx + 1:])
+ return (o, val)
+
+
+def parsedotval(s):
+ '''Parse K1.K2=VAL into {"K1":{"K2":VAL}}
+
+ ``VAL`` is processed according to rules defined in :py:func:`parse_value`.
+ '''
+ if type(s) is tuple:
+ o, val = s
+ val = parse_value(val)
+ 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)
+
+
+def parse_override_var(s):
+ '''Parse a semicolon-separated list of strings into a sequence of values
+
+ Emits the same items in sequence as :py:func:`parsedotval` does.
+ '''
+ return (
+ parsedotval(item)
+ for item in s.split(';')
+ if item
+ )
diff --git a/powerline/lib/path.py b/powerline/lib/path.py
new file mode 100644
index 0000000..49ff433
--- /dev/null
+++ b/powerline/lib/path.py
@@ -0,0 +1,18 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import os
+
+
+def realpath(path):
+ return os.path.abspath(os.path.realpath(path))
+
+
+def join(*components):
+ if any((isinstance(p, bytes) for p in components)):
+ return os.path.join(*[
+ p if isinstance(p, bytes) else p.encode('ascii')
+ for p in components
+ ])
+ else:
+ return os.path.join(*components)
diff --git a/powerline/lib/shell.py b/powerline/lib/shell.py
new file mode 100644
index 0000000..2082e82
--- /dev/null
+++ b/powerline/lib/shell.py
@@ -0,0 +1,133 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import sys
+import os
+
+from subprocess import Popen, PIPE
+from functools import partial
+
+from powerline.lib.encoding import get_preferred_input_encoding, get_preferred_output_encoding
+
+
+if sys.platform.startswith('win32'):
+ # Prevent windows from launching consoles when calling commands
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx
+ Popen = partial(Popen, creationflags=0x08000000)
+
+
+def run_cmd(pl, cmd, stdin=None, strip=True):
+ '''Run command and return its stdout, stripped
+
+ If running command fails returns None and logs failure to ``pl`` argument.
+
+ :param PowerlineLogger pl:
+ Logger used to log failures.
+ :param list cmd:
+ Command which will be run.
+ :param str stdin:
+ String passed to command. May be None.
+ :param bool strip:
+ True if the result should be stripped.
+ '''
+ try:
+ p = Popen(cmd, shell=False, stdout=PIPE, stdin=PIPE)
+ except OSError as e:
+ pl.exception('Could not execute command ({0}): {1}', e, cmd)
+ return None
+ else:
+ stdout, err = p.communicate(
+ stdin if stdin is None else stdin.encode(get_preferred_output_encoding()))
+ stdout = stdout.decode(get_preferred_input_encoding())
+ return stdout.strip() if strip else stdout
+
+
+def asrun(pl, ascript):
+ '''Run the given AppleScript and return the standard output and error.'''
+ return run_cmd(pl, ['osascript', '-'], ascript)
+
+
+def readlines(cmd, cwd):
+ '''Run command and read its output, line by line
+
+ :param list cmd:
+ Command which will be run.
+ :param str cwd:
+ Working directory of the command which will be run.
+ '''
+ p = Popen(cmd, shell=False, stdout=PIPE, stderr=PIPE, cwd=cwd)
+ encoding = get_preferred_input_encoding()
+ p.stderr.close()
+ with p.stdout:
+ for line in p.stdout:
+ yield line[:-1].decode(encoding)
+
+
+try:
+ from shutil import which
+except ImportError:
+ # shutil.which was added in python-3.3. Here is what was added:
+ # Lib/shutil.py, commit 5abe28a9c8fe701ba19b1db5190863384e96c798
+ def which(cmd, mode=os.F_OK | os.X_OK, path=None):
+ '''Given a command, mode, and a PATH string, return the path which
+ conforms to the given mode on the PATH, or None if there is no such
+ file.
+
+ ``mode`` defaults to os.F_OK | os.X_OK. ``path`` defaults to the result
+ of ``os.environ.get('PATH')``, or can be overridden with a custom search
+ path.
+ '''
+ # Check that a given file can be accessed with the correct mode.
+ # Additionally check that `file` is not a directory, as on Windows
+ # directories pass the os.access check.
+ def _access_check(fn, mode):
+ return (
+ os.path.exists(fn)
+ and os.access(fn, mode)
+ and not os.path.isdir(fn)
+ )
+
+ # If we’re given a path with a directory part, look it up directly rather
+ # than referring to PATH directories. This includes checking relative to the
+ # current directory, e.g. ./script
+ if os.path.dirname(cmd):
+ if _access_check(cmd, mode):
+ return cmd
+ return None
+
+ if path is None:
+ path = os.environ.get('PATH', os.defpath)
+ if not path:
+ return None
+ path = path.split(os.pathsep)
+
+ if sys.platform == 'win32':
+ # The current directory takes precedence on Windows.
+ if os.curdir not in path:
+ path.insert(0, os.curdir)
+
+ # PATHEXT is necessary to check on Windows.
+ pathext = os.environ.get('PATHEXT', '').split(os.pathsep)
+ # See if the given file matches any of the expected path extensions.
+ # This will allow us to short circuit when given 'python.exe'.
+ # If it does match, only test that one, otherwise we have to try
+ # others.
+ if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
+ files = [cmd]
+ else:
+ files = [cmd + ext for ext in pathext]
+ else:
+ # On other platforms you don’t have things like PATHEXT to tell you
+ # what file suffixes are executable, so just pass on cmd as-is.
+ files = [cmd]
+
+ seen = set()
+ for dir in path:
+ normdir = os.path.normcase(dir)
+ if normdir not in seen:
+ seen.add(normdir)
+ for thefile in files:
+ name = os.path.join(dir, thefile)
+ if _access_check(name, mode):
+ return name
+ return None
diff --git a/powerline/lib/threaded.py b/powerline/lib/threaded.py
new file mode 100644
index 0000000..e5a6b3e
--- /dev/null
+++ b/powerline/lib/threaded.py
@@ -0,0 +1,262 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+from threading import Thread, Lock, Event
+from types import MethodType
+
+from powerline.lib.monotonic import monotonic
+from powerline.segments import Segment
+
+
+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(Segment, MultiRunnedThread):
+ min_sleep_time = 0.1
+ update_first = True
+ interval = 1
+ daemon = False
+
+ argmethods = ('render', 'set_state')
+
+ def __init__(self):
+ super(ThreadedSegment, self).__init__()
+ self.run_once = True
+ self.crashed = 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__.
+ self.start()
+ update_value = self.get_update_value(self.do_update_first)
+ else:
+ update_value = self.get_update_value(not self.updated)
+
+ if self.crashed:
+ return self.crashed_value
+
+ return self.render(update_value, update_first=update_first, pl=pl, **kwargs)
+
+ def set_update_value(self):
+ try:
+ self.update_value = self.update(self.update_value)
+ except Exception as e:
+ self.exception('Exception while updating: {0}', str(e))
+ self.crashed = True
+ except KeyboardInterrupt:
+ self.warn('Caught keyboard interrupt while updating')
+ self.crashed = True
+ else:
+ self.crashed = False
+ self.updated = True
+
+ def get_update_value(self, update=False):
+ if update:
+ self.set_update_value()
+ return self.update_value
+
+ def run(self):
+ if self.do_update_first:
+ start_time = monotonic()
+ while True:
+ self.shutdown_event.wait(max(self.interval - (monotonic() - start_time), self.min_sleep_time))
+ if self.shutdown_event.is_set():
+ break
+ start_time = monotonic()
+ self.set_update_value()
+ else:
+ while not self.shutdown_event.is_set():
+ start_time = monotonic()
+ self.set_update_value()
+ 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.do_update_first = update_first and self.update_first
+ self.updated = self.updated or (not self.do_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)
+
+ def argspecobjs(self):
+ for name in self.argmethods:
+ try:
+ yield name, getattr(self, name)
+ except AttributeError:
+ pass
+
+ def additional_args(self):
+ return (('interval', self.interval),)
+
+ _omitted_args = {
+ 'render': (0,),
+ 'set_state': ('shutdown_event',),
+ }
+
+ def omitted_args(self, name, method):
+ ret = self._omitted_args.get(name, ())
+ if isinstance(getattr(self, name, None), MethodType):
+ ret = tuple((i + 1 if isinstance(i, int) else i for i in ret))
+ return ret
+
+
+class KwThreadedSegment(ThreadedSegment):
+ update_first = True
+
+ argmethods = ('render', 'set_state', 'key', 'render_one')
+
+ 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, key=None, after_update=False, **kwargs):
+ queries, crashed = update_value
+ if key is None:
+ key = self.key(**kwargs)
+ if key in crashed:
+ return self.crashed_value
+
+ try:
+ update_state = queries[key][1]
+ except KeyError:
+ with self.write_lock:
+ self.new_queries.append(key)
+ if self.do_update_first or self.run_once:
+ if after_update:
+ self.error('internal error: value was not computed even though update_first was set')
+ update_state = None
+ else:
+ return self.render(
+ update_value=self.get_update_value(True),
+ update_first=False,
+ key=key,
+ after_update=True,
+ **kwargs
+ )
+ else:
+ update_state = None
+
+ return self.render_one(update_state, **kwargs)
+
+ def update_one(self, crashed, updates, key):
+ try:
+ updates[key] = (monotonic(), 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)
+
+ def update(self, old_update_value):
+ updates = {}
+ crashed = set()
+ update_value = (updates, crashed)
+ queries = old_update_value[0]
+
+ new_queries = self.new_queries
+ with self.write_lock:
+ self.new_queries = []
+
+ for key, (last_query_time, state) in queries.items():
+ if last_query_time < monotonic() < last_query_time + self.interval:
+ updates[key] = (last_query_time, state)
+ else:
+ self.update_one(crashed, updates, key)
+
+ for key in new_queries:
+ self.update_one(crashed, updates, key)
+
+ return update_value
+
+ def set_state(self, interval=None, update_first=True, shutdown_event=None, **kwargs):
+ self.set_interval(interval)
+ self.do_update_first = update_first and self.update_first
+ self.shutdown_event = shutdown_event or Event()
+
+ @staticmethod
+ def render_one(update_state, **kwargs):
+ return update_state
+
+ _omitted_args = {
+ 'render': ('update_value', 'key', 'after_update'),
+ 'set_state': ('shutdown_event',),
+ 'render_one': (0,),
+ }
diff --git a/powerline/lib/unicode.py b/powerline/lib/unicode.py
new file mode 100644
index 0000000..152bacd
--- /dev/null
+++ b/powerline/lib/unicode.py
@@ -0,0 +1,283 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import sys
+import codecs
+
+from unicodedata import east_asian_width, combining
+
+from powerline.lib.encoding import get_preferred_output_encoding
+
+
+try:
+ from __builtin__ import unicode
+except ImportError:
+ unicode = str
+
+
+try:
+ from __builtin__ import unichr
+except ImportError:
+ unichr = chr
+
+
+if sys.maxunicode < 0x10FFFF:
+ _unichr = unichr
+
+ def unichr(ch):
+ if ch <= sys.maxunicode:
+ return _unichr(ch)
+ else:
+ ch -= 0x10000
+ return _unichr((ch >> 10) + 0xD800) + _unichr((ch & ((1 << 10) - 1)) + 0xDC00)
+
+
+def u(s):
+ '''Return unicode instance assuming UTF-8 encoded string.
+ '''
+ if type(s) is unicode:
+ return s
+ else:
+ return unicode(s, 'utf-8')
+
+
+if sys.version_info < (3,):
+ def tointiter(s):
+ '''Convert a byte string to the sequence of integers
+ '''
+ return (ord(c) for c in s)
+else:
+ def tointiter(s):
+ '''Convert a byte string to the sequence of integers
+ '''
+ return iter(s)
+
+
+def powerline_decode_error(e):
+ if not isinstance(e, UnicodeDecodeError):
+ raise NotImplementedError
+ return (''.join((
+ '<{0:02X}>'.format(c)
+ for c in tointiter(e.object[e.start:e.end])
+ )), e.end)
+
+
+codecs.register_error('powerline_decode_error', powerline_decode_error)
+
+
+last_swe_idx = 0
+
+
+def register_strwidth_error(strwidth):
+ '''Create new encode errors handling method similar to ``replace``
+
+ Like ``replace`` this method uses question marks in place of the characters
+ that cannot be represented in the requested encoding. Unlike ``replace`` the
+ amount of question marks is identical to the amount of display cells
+ offending character occupies. Thus encoding ``…`` (U+2026, HORIZONTAL
+ ELLIPSIS) to ``latin1`` will emit one question mark, but encoding ``A``
+ (U+FF21, FULLWIDTH LATIN CAPITAL LETTER A) will emit two question marks.
+
+ Since width of some characters depends on the terminal settings and
+ powerline knows how to respect them a single error handling method cannot be
+ used. Instead of it the generator function is used which takes ``strwidth``
+ function (function that knows how to compute string width respecting all
+ needed settings) and emits new error handling method name.
+
+ :param function strwidth:
+ Function that computs string width measured in display cells the string
+ occupies when displayed.
+
+ :return: New error handling method name.
+ '''
+ global last_swe_idx
+ last_swe_idx += 1
+
+ def powerline_encode_strwidth_error(e):
+ if not isinstance(e, UnicodeEncodeError):
+ raise NotImplementedError
+ return ('?' * strwidth(e.object[e.start:e.end]), e.end)
+
+ ename = 'powerline_encode_strwidth_error_{0}'.format(last_swe_idx)
+ codecs.register_error(ename, powerline_encode_strwidth_error)
+ return ename
+
+
+def out_u(s):
+ '''Return unicode string suitable for displaying
+
+ Unlike other functions assumes get_preferred_output_encoding() first. Unlike
+ u() does not throw exceptions for invalid unicode strings. Unlike
+ safe_unicode() does throw an exception if object is not a string.
+ '''
+ if isinstance(s, unicode):
+ return s
+ elif isinstance(s, bytes):
+ return unicode(s, get_preferred_output_encoding(), 'powerline_decode_error')
+ else:
+ raise TypeError('Expected unicode or bytes instance, got {0}'.format(repr(type(s))))
+
+
+def safe_unicode(s):
+ '''Return unicode instance without raising an exception.
+
+ Order of assumptions:
+ * ASCII string or unicode object
+ * UTF-8 string
+ * Object with __str__() or __repr__() method that returns UTF-8 string or
+ unicode object (depending on python version)
+ * String in powerline.lib.encoding.get_preferred_output_encoding() encoding
+ * If everything failed use safe_unicode on last exception with which
+ everything failed
+ '''
+ try:
+ try:
+ if type(s) is bytes:
+ return unicode(s, 'ascii')
+ else:
+ return unicode(s)
+ except UnicodeDecodeError:
+ try:
+ return unicode(s, 'utf-8')
+ except TypeError:
+ return unicode(str(s), 'utf-8')
+ except UnicodeDecodeError:
+ return unicode(s, get_preferred_output_encoding())
+ except Exception as e:
+ return safe_unicode(e)
+
+
+class FailedUnicode(unicode):
+ '''Builtin ``unicode`` subclass indicating fatal error
+
+ If your code for some reason wants to determine whether `.render()` method
+ failed it should check returned string for being a FailedUnicode instance.
+ Alternatively you could subclass Powerline and override `.render()` method
+ to do what you like in place of catching the exception and returning
+ FailedUnicode.
+ '''
+ pass
+
+
+if sys.version_info < (3,):
+ def string(s):
+ if type(s) is not str:
+ return s.encode('utf-8')
+ else:
+ return s
+else:
+ def string(s):
+ if type(s) is not str:
+ return s.decode('utf-8')
+ else:
+ return s
+
+
+string.__doc__ = (
+ '''Transform ``unicode`` or ``bytes`` object into ``str`` object
+
+ On Python-2 this encodes ``unicode`` to ``bytes`` (which is ``str``) using
+ UTF-8 encoding; on Python-3 this decodes ``bytes`` to ``unicode`` (which is
+ ``str``) using UTF-8 encoding.
+
+ Useful for functions that expect an ``str`` object in both unicode versions,
+ not caring about the semantic differences between them in Python-2 and
+ Python-3.
+ '''
+)
+
+
+def surrogate_pair_to_character(high, low):
+ '''Transform a pair of surrogate codepoints to one codepoint
+ '''
+ return 0x10000 + ((high - 0xD800) << 10) + (low - 0xDC00)
+
+
+_strwidth_documentation = (
+ '''Compute string width in display cells
+
+ {0}
+
+ :param dict width_data:
+ Dictionary which maps east_asian_width property values to strings
+ lengths. It is expected to contain the following keys and values (from
+ `East Asian Width annex <http://www.unicode.org/reports/tr11/>`_):
+
+ === ====== ===========================================================
+ Key Value Description
+ === ====== ===========================================================
+ F 2 Fullwidth: all characters that are defined as Fullwidth in
+ the Unicode Standard [Unicode] by having a compatibility
+ decomposition of type <wide> to characters elsewhere in the
+ Unicode Standard that are implicitly narrow but unmarked.
+ H 1 Halfwidth: all characters that are explicitly defined as
+ Halfwidth in the Unicode Standard by having a compatibility
+ decomposition of type <narrow> to characters elsewhere in
+ the Unicode Standard that are implicitly wide but unmarked,
+ plus U+20A9 ₩ WON SIGN.
+ W 2 Wide: all other characters that are always wide. These
+ characters occur only in the context of East Asian
+ typography where they are wide characters (such as the
+ Unified Han Ideographs or Squared Katakana Symbols). This
+ category includes characters that have explicit halfwidth
+ counterparts.
+ Na 1 Narrow: characters that are always narrow and have explicit
+ fullwidth or wide counterparts. These characters are
+ implicitly narrow in East Asian typography and legacy
+ character sets because they have explicit fullwidth or wide
+ counterparts. All of ASCII is an example of East Asian
+ Narrow characters.
+ A 1 or 2 Ambigious: characters that may sometimes be wide and
+ sometimes narrow. Ambiguous characters require additional
+ information not contained in the character code to further
+ resolve their width. This information is usually defined in
+ terminal setting that should in turn respect glyphs widths
+ in used fonts. Also see :ref:`ambiwidth configuration
+ option <config-common-ambiwidth>`.
+ N 1 Neutral characters: character that does not occur in legacy
+ East Asian character sets.
+ === ====== ===========================================================
+
+ :param unicode string:
+ String whose width will be calculated.
+
+ :return: unsigned integer.''')
+
+
+def strwidth_ucs_4(width_data, string):
+ return sum(((
+ (
+ 0
+ ) if combining(symbol) else (
+ width_data[east_asian_width(symbol)]
+ )
+ ) for symbol in string))
+
+
+strwidth_ucs_4.__doc__ = _strwidth_documentation.format(
+ '''This version of function expects that characters above 0xFFFF are
+ represented using one symbol. This is only the case in UCS-4 Python builds.
+
+ .. note:
+ Even in UCS-4 Python builds it is possible to represent characters above
+ 0xFFFF using surrogate pairs. Characters represented this way are not
+ supported.''')
+
+
+def strwidth_ucs_2(width_data, string):
+ return sum(((
+ (
+ width_data[east_asian_width(string[i - 1] + symbol)]
+ ) if 0xDC00 <= ord(symbol) <= 0xDFFF else (
+ 0
+ ) if combining(symbol) or 0xD800 <= ord(symbol) <= 0xDBFF else (
+ width_data[east_asian_width(symbol)]
+ )
+ ) for i, symbol in enumerate(string)))
+
+
+strwidth_ucs_2.__doc__ = _strwidth_documentation.format(
+ '''This version of function expects that characters above 0xFFFF are
+ represented using two symbols forming a surrogate pair, which is the only
+ option in UCS-2 Python builds. It still works correctly in UCS-4 Python
+ builds, but is slower then its UCS-4 counterpart.''')
diff --git a/powerline/lib/url.py b/powerline/lib/url.py
new file mode 100644
index 0000000..f25919c
--- /dev/null
+++ b/powerline/lib/url.py
@@ -0,0 +1,17 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+try:
+ from urllib.error import HTTPError # NOQA
+ from urllib.request import urlopen # NOQA
+ 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
diff --git a/powerline/lib/vcs/__init__.py b/powerline/lib/vcs/__init__.py
new file mode 100644
index 0000000..1b7f5e2
--- /dev/null
+++ b/powerline/lib/vcs/__init__.py
@@ -0,0 +1,276 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import os
+import errno
+
+from threading import Lock
+from collections import defaultdict
+
+from powerline.lib.watcher import create_tree_watcher
+from powerline.lib.unicode import out_u
+from powerline.lib.path import join
+
+
+def generate_directories(path):
+ if os.path.isdir(path):
+ yield path
+ while True:
+ if os.path.ismount(path):
+ break
+ old_path = path
+ path = os.path.dirname(path)
+ if path == old_path or not path:
+ break
+ yield path
+
+
+_file_watcher = None
+
+
+def file_watcher(create_watcher):
+ global _file_watcher
+ if _file_watcher is None:
+ _file_watcher = create_watcher()
+ return _file_watcher
+
+
+_branch_watcher = None
+
+
+def branch_watcher(create_watcher):
+ global _branch_watcher
+ if _branch_watcher is None:
+ _branch_watcher = create_watcher()
+ return _branch_watcher
+
+
+branch_name_cache = {}
+branch_lock = Lock()
+file_status_lock = Lock()
+
+
+def get_branch_name(directory, config_file, get_func, create_watcher):
+ global branch_name_cache
+ with branch_lock:
+ # Check if the repo directory was moved/deleted
+ fw = branch_watcher(create_watcher)
+ is_watched = fw.is_watching(directory)
+ try:
+ changed = fw(directory)
+ except OSError as e:
+ if getattr(e, 'errno', None) != errno.ENOENT:
+ raise
+ changed = True
+ if changed:
+ branch_name_cache.pop(config_file, None)
+ # Remove the watches for this repo
+ if is_watched:
+ fw.unwatch(directory)
+ fw.unwatch(config_file)
+ else:
+ # Check if the config file has changed
+ try:
+ changed = fw(config_file)
+ except OSError as e:
+ if getattr(e, 'errno', None) != errno.ENOENT:
+ raise
+ # Config file does not exist (happens for mercurial)
+ if config_file not in branch_name_cache:
+ branch_name_cache[config_file] = out_u(get_func(directory, config_file))
+ if changed:
+ # Config file has changed or was not tracked
+ branch_name_cache[config_file] = out_u(get_func(directory, config_file))
+ return branch_name_cache[config_file]
+
+
+class FileStatusCache(dict):
+ def __init__(self):
+ self.dirstate_map = defaultdict(set)
+ self.ignore_map = defaultdict(set)
+ self.keypath_ignore_map = {}
+
+ def update_maps(self, keypath, directory, dirstate_file, ignore_file_name, extra_ignore_files):
+ parent = keypath
+ ignore_files = set()
+ while parent != directory:
+ nparent = os.path.dirname(keypath)
+ if nparent == parent:
+ break
+ parent = nparent
+ ignore_files.add(join(parent, ignore_file_name))
+ for f in extra_ignore_files:
+ ignore_files.add(f)
+ self.keypath_ignore_map[keypath] = ignore_files
+ for ignf in ignore_files:
+ self.ignore_map[ignf].add(keypath)
+ self.dirstate_map[dirstate_file].add(keypath)
+
+ def invalidate(self, dirstate_file=None, ignore_file=None):
+ for keypath in self.dirstate_map[dirstate_file]:
+ self.pop(keypath, None)
+ for keypath in self.ignore_map[ignore_file]:
+ self.pop(keypath, None)
+
+ def ignore_files(self, keypath):
+ for ignf in self.keypath_ignore_map[keypath]:
+ yield ignf
+
+
+file_status_cache = FileStatusCache()
+
+
+def get_file_status(directory, dirstate_file, file_path, ignore_file_name, get_func, create_watcher, extra_ignore_files=()):
+ global file_status_cache
+ keypath = file_path if os.path.isabs(file_path) else join(directory, file_path)
+ file_status_cache.update_maps(keypath, directory, dirstate_file, ignore_file_name, extra_ignore_files)
+
+ with file_status_lock:
+ # Optimize case of keypath not being cached
+ if keypath not in file_status_cache:
+ file_status_cache[keypath] = ans = get_func(directory, file_path)
+ return ans
+
+ # Check if any relevant files have changed
+ file_changed = file_watcher(create_watcher)
+ changed = False
+ # Check if dirstate has changed
+ try:
+ changed = file_changed(dirstate_file)
+ except OSError as e:
+ if getattr(e, 'errno', None) != errno.ENOENT:
+ raise
+ # The .git index file does not exist for a new git repo
+ return get_func(directory, file_path)
+
+ if changed:
+ # Remove all cached values for files that depend on this
+ # dirstate_file
+ file_status_cache.invalidate(dirstate_file=dirstate_file)
+ else:
+ # Check if the file itself has changed
+ try:
+ changed ^= file_changed(keypath)
+ except OSError as e:
+ if getattr(e, 'errno', None) != errno.ENOENT:
+ raise
+ # Do not call get_func again for a non-existant file
+ if keypath not in file_status_cache:
+ file_status_cache[keypath] = get_func(directory, file_path)
+ return file_status_cache[keypath]
+
+ if changed:
+ file_status_cache.pop(keypath, None)
+ else:
+ # Check if one of the ignore files has changed
+ for ignf in file_status_cache.ignore_files(keypath):
+ try:
+ changed ^= file_changed(ignf)
+ except OSError as e:
+ if getattr(e, 'errno', None) != errno.ENOENT:
+ raise
+ if changed:
+ # Invalidate cache for all files that might be affected
+ # by this ignore file
+ file_status_cache.invalidate(ignore_file=ignf)
+ break
+
+ try:
+ return file_status_cache[keypath]
+ except KeyError:
+ file_status_cache[keypath] = ans = get_func(directory, file_path)
+ return ans
+
+
+class TreeStatusCache(dict):
+ def __init__(self, pl):
+ self.tw = create_tree_watcher(pl)
+ self.pl = pl
+
+ def cache_and_get(self, key, status):
+ ans = self.get(key, self)
+ if ans is self:
+ ans = self[key] = status()
+ return ans
+
+ def __call__(self, repo):
+ key = repo.directory
+ try:
+ if self.tw(key, ignore_event=getattr(repo, 'ignore_event', None)):
+ self.pop(key, None)
+ except OSError as e:
+ self.pl.warn('Failed to check {0} for changes, with error: {1}', key, str(e))
+ return self.cache_and_get(key, repo.status)
+
+
+_tree_status_cache = None
+
+
+def tree_status(repo, pl):
+ global _tree_status_cache
+ if _tree_status_cache is None:
+ _tree_status_cache = TreeStatusCache(pl)
+ return _tree_status_cache(repo)
+
+
+vcs_props = (
+ ('git', '.git', os.path.exists),
+ ('mercurial', '.hg', os.path.isdir),
+ ('bzr', '.bzr', os.path.isdir),
+)
+
+
+vcs_props_bytes = [
+ (vcs, vcs_dir.encode('ascii'), check)
+ for vcs, vcs_dir, check in vcs_props
+]
+
+
+def guess(path, create_watcher):
+ for directory in generate_directories(path):
+ for vcs, vcs_dir, check in (vcs_props_bytes if isinstance(path, bytes) else vcs_props):
+ repo_dir = os.path.join(directory, vcs_dir)
+ if check(repo_dir):
+ if os.path.isdir(repo_dir) and not os.access(repo_dir, os.X_OK):
+ continue
+ try:
+ if vcs not in globals():
+ globals()[vcs] = getattr(__import__(str('powerline.lib.vcs'), fromlist=[str(vcs)]), str(vcs))
+ return globals()[vcs].Repository(directory, create_watcher)
+ except:
+ pass
+ return None
+
+
+def get_fallback_create_watcher():
+ from powerline.lib.watcher import create_file_watcher
+ from powerline import get_fallback_logger
+ from functools import partial
+ return partial(create_file_watcher, get_fallback_logger(), 'auto')
+
+
+def debug():
+ '''Test run guess(), repo.branch() and repo.status()
+
+ To use::
+ python -c 'from powerline.lib.vcs import debug; debug()' some_file_to_watch.
+ '''
+ import sys
+ dest = sys.argv[-1]
+ repo = guess(os.path.abspath(dest), get_fallback_create_watcher)
+ if repo is None:
+ print ('%s is not a recognized vcs repo' % dest)
+ raise SystemExit(1)
+ print ('Watching %s' % dest)
+ print ('Press Ctrl-C to exit.')
+ try:
+ while True:
+ if os.path.isdir(dest):
+ print ('Branch name: %s Status: %s' % (repo.branch(), repo.status()))
+ else:
+ print ('File status: %s' % repo.status(dest))
+ raw_input('Press Enter to check again: ')
+ except KeyboardInterrupt:
+ pass
+ except EOFError:
+ pass
diff --git a/powerline/lib/vcs/bzr.py b/powerline/lib/vcs/bzr.py
new file mode 100644
index 0000000..e47d8b2
--- /dev/null
+++ b/powerline/lib/vcs/bzr.py
@@ -0,0 +1,108 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import os
+import re
+
+from io import StringIO
+
+from bzrlib import (workingtree, status, library_state, trace, ui)
+
+from powerline.lib.vcs import get_branch_name, get_file_status
+from powerline.lib.path import join
+from powerline.lib.encoding import get_preferred_file_contents_encoding
+
+
+class CoerceIO(StringIO):
+ def write(self, arg):
+ if isinstance(arg, bytes):
+ arg = arg.decode(get_preferred_file_contents_encoding(), 'replace')
+ return super(CoerceIO, self).write(arg)
+
+
+nick_pat = re.compile(br'nickname\s*=\s*(.+)')
+
+
+def branch_name_from_config_file(directory, config_file):
+ ans = None
+ try:
+ with open(config_file, 'rb') as f:
+ for line in f:
+ m = nick_pat.match(line)
+ if m is not None:
+ ans = m.group(1).strip().decode(get_preferred_file_contents_encoding(), 'replace')
+ break
+ except Exception:
+ pass
+ return ans or os.path.basename(directory)
+
+
+state = None