Convert many segments to new class-based code

This commit is contained in:
Buck Ryan 2017-08-26 17:46:46 -04:00
parent b4a279b0e7
commit fafd37babb
14 changed files with 163 additions and 114 deletions

View file

@ -7,20 +7,7 @@ import sys
import config
import importlib
from .themes.default import DefaultColor
py3 = sys.version_info.major == 3
if py3:
def unicode(x):
return x
def warn(msg):
print('[powerline-bash] ', msg)
def get_default_theme():
return DefaultColor
from .utils import warn, py3
class Powerline(object):
@ -54,7 +41,7 @@ class Powerline(object):
def __init__(self, args, cwd, theme=None):
self.args = args
self.cwd = cwd
self.theme = theme or get_default_theme()
self.theme = theme or DefaultColor
mode, shell = args.mode, args.shell
self.color_template = self.color_templates[shell]
self.reset = self.color_template % '[0m'
@ -157,8 +144,10 @@ def main():
args = arg_parser.parse_args()
powerline = Powerline(args, get_valid_cwd())
for segment in config.SEGMENTS:
mod = importlib.import_module("powerline_shell.segments." + segment)
fn = getattr(mod, "add_" + segment + "_segment")
fn(powerline)
segments = []
for seg_name in config.SEGMENTS:
mod = importlib.import_module("powerline_shell.segments." + seg_name)
segments.append(getattr(mod, "Segment")(powerline))
for segment in segments:
segment.add_to_powerline()
sys.stdout.write(powerline.draw())

View file

@ -1,4 +1,3 @@
#! /usr/bin/env python
from colorsys import hls_to_rgb, rgb_to_hls
# md5 deprecated since Python 2.5
try:
@ -6,19 +5,13 @@ try:
except ImportError:
from hashlib import md5
import sys
# Original, non-relative import errors on Python3
from .colortrans import *
py3 = sys.version_info.major == 3
from ..utils import py3
def getOppositeColor(r,g,b):
hls = rgb_to_hls(r,g,b)
#print "hls is"
#print hls
opp = list(hls[:])
#opp[0] = (opp[0]+0.5)%1 # reverse hue (a.k.a. color), reversing tends to be jarring
opp[0] = (opp[0]+0.2)%1 # shift hue (a.k.a. color)
if opp[1] > 255/2: # for level you want to make sure they
opp[1] -= 255/2 # are quite different so easily readable
@ -26,7 +19,6 @@ def getOppositeColor(r,g,b):
opp[1] += 255/2
if opp[2] > -0.5: # if saturation is low on first color increase second's
opp[2] -= 0.5
#print opp
opp = hls_to_rgb(*opp)
m = max(opp)
if m > 255: #colorsys module doesn't give caps to their conversions
@ -34,8 +26,6 @@ def getOppositeColor(r,g,b):
return tuple([ int(x) for x in opp])
def stringToHashToColorAndOpposite(string):
# Python3: Unicode string must be encoded before digest
# Python2.7: works either way, but check in case breaks earlier py2
if py3:
string = string.encode('utf-8')
string = md5(string).hexdigest()[:6] # get a random color

View file

View file

@ -1,8 +1,8 @@
import os
import sys
from ..utils import warn, py3, BasicSegment
ELLIPSIS = u'\u2026'
py3 = sys.version_info.major == 3
def replace_home_dir(cwd):
@ -94,3 +94,8 @@ def add_cwd_segment(powerline):
powerline.append(' %s ' % maybe_shorten_name(powerline, name), fg, bg,
separator, separator_fg)
class Segment(BasicSegment):
def add_to_powerline(self):
add_cwd_segment(self.powerline)

View file

@ -1,6 +1,10 @@
def add_exit_code_segment(powerline):
if powerline.args.prev_error == 0:
return
fg = powerline.theme.CMD_FAILED_FG
bg = powerline.theme.CMD_FAILED_BG
powerline.append(' %s ' % str(powerline.args.prev_error), fg, bg)
from ..utils import BasicSegment
class Segment(BasicSegment):
def add_to_powerline(self):
if self.powerline.args.prev_error == 0:
return
fg = self.powerline.theme.CMD_FAILED_FG
bg = self.powerline.theme.CMD_FAILED_BG
self.powerline.append(' %s ' % str(self.powerline.args.prev_error), fg, bg)

View file

@ -1,7 +1,7 @@
import re
import subprocess
import os
from ..repos import RepoStats
from ..utils import RepoStats, ThreadedSegment
def get_PATH():
@ -59,18 +59,18 @@ def parse_git_stats(status):
return stats
def add_git_segment(powerline):
def build_stats():
try:
p = subprocess.Popen(['git', 'status', '--porcelain', '-b'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
env=git_subprocess_env())
except OSError:
# Popen will throw an OSError if git is not found
return
return None
pdata = p.communicate()
if p.returncode != 0:
return
return None
status = pdata[0].decode("utf-8").splitlines()
stats = parse_git_stats(status)
@ -82,12 +82,22 @@ def add_git_segment(powerline):
branch = branch_info['local']
else:
branch = _get_git_detached_branch()
return stats, branch
bg = powerline.theme.REPO_CLEAN_BG
fg = powerline.theme.REPO_CLEAN_FG
if stats.dirty:
bg = powerline.theme.REPO_DIRTY_BG
fg = powerline.theme.REPO_DIRTY_FG
powerline.append(' %s ' % branch, fg, bg)
stats.add_to_powerline(powerline, powerline.theme)
class Segment(ThreadedSegment):
def run(self):
self.stats, self.branch = build_stats()
def add_to_powerline(self):
self.join()
if not self.stats:
return
bg = self.powerline.theme.REPO_CLEAN_BG
fg = self.powerline.theme.REPO_CLEAN_FG
if self.stats.dirty:
bg = self.powerline.theme.REPO_DIRTY_BG
fg = self.powerline.theme.REPO_DIRTY_FG
self.powerline.append(" " + self.branch + " ", fg, bg)
self.stats.add_to_powerline(self.powerline)

View file

@ -1,21 +1,28 @@
def add_hostname_segment(powerline):
if powerline.args.colorize_hostname:
from lib.color_compliment import stringToHashToColorAndOpposite
from lib.colortrans import rgb2short
from socket import gethostname
hostname = gethostname()
FG, BG = stringToHashToColorAndOpposite(hostname)
FG, BG = (rgb2short(*color) for color in [FG, BG])
host_prompt = ' %s ' % hostname.split('.')[0]
from ..utils import BasicSegment
powerline.append(host_prompt, FG, BG)
else:
if powerline.args.shell == 'bash':
host_prompt = ' \\h '
elif powerline.args.shell == 'zsh':
host_prompt = ' %m '
class Segment(BasicSegment):
def add_to_powerline(self):
powerline = self.powerline
if powerline.args.colorize_hostname:
from lib.color_compliment import stringToHashToColorAndOpposite
from lib.colortrans import rgb2short
from socket import gethostname
hostname = gethostname()
FG, BG = stringToHashToColorAndOpposite(hostname)
FG, BG = (rgb2short(*color) for color in [FG, BG])
host_prompt = ' %s ' % hostname.split('.')[0]
powerline.append(host_prompt, FG, BG)
else:
import socket
host_prompt = ' %s ' % socket.gethostname().split('.')[0]
if powerline.args.shell == 'bash':
host_prompt = ' \\h '
elif powerline.args.shell == 'zsh':
host_prompt = ' %m '
else:
import socket
host_prompt = ' %s ' % socket.gethostname().split('.')[0]
powerline.append(host_prompt, powerline.theme.HOSTNAME_FG, powerline.theme.HOSTNAME_BG)
powerline.append(host_prompt,
powerline.theme.HOSTNAME_FG,
powerline.theme.HOSTNAME_BG)

View file

@ -2,29 +2,30 @@ import os
import re
import subprocess
import platform
from ..utils import ThreadedSegment
def add_jobs_segment(powerline):
num_jobs = 0
if platform.system().startswith('CYGWIN'):
# cygwin ps is a special snowflake...
output_proc = subprocess.Popen(['ps', '-af'], stdout=subprocess.PIPE)
output = map(lambda l: int(l.split()[2].strip()),
output_proc.communicate()[0].decode("utf-8").splitlines()[1:])
class Segment(ThreadedSegment):
def run(self):
self.num_jobs = 0
if platform.system().startswith('CYGWIN'):
# cygwin ps is a special snowflake...
output_proc = subprocess.Popen(['ps', '-af'], stdout=subprocess.PIPE)
output = map(lambda l: int(l.split()[2].strip()),
output_proc.communicate()[0].decode("utf-8").splitlines()[1:])
self.num_jobs = output.count(os.getppid()) - 1
else:
pppid_proc = subprocess.Popen(['ps', '-p', str(os.getppid()), '-oppid='],
stdout=subprocess.PIPE)
pppid = pppid_proc.communicate()[0].decode("utf-8").strip()
output_proc = subprocess.Popen(['ps', '-a', '-o', 'ppid'],
stdout=subprocess.PIPE)
output = output_proc.communicate()[0].decode("utf-8")
self.num_jobs = len(re.findall(str(pppid), output)) - 1
num_jobs = output.count(os.getppid()) - 1
else:
pppid_proc = subprocess.Popen(['ps', '-p', str(os.getppid()), '-oppid='],
stdout=subprocess.PIPE)
pppid = pppid_proc.communicate()[0].decode("utf-8").strip()
output_proc = subprocess.Popen(['ps', '-a', '-o', 'ppid'],
stdout=subprocess.PIPE)
output = output_proc.communicate()[0].decode("utf-8")
num_jobs = len(re.findall(str(pppid), output)) - 1
if num_jobs > 0:
powerline.append(' %d ' % num_jobs, powerline.theme.JOBS_FG, powerline.theme.JOBS_BG)
def add_to_powerline(self):
self.join()
if self.num_jobs > 0:
self.powerline.append(' %d ' % self.num_jobs,
self.powerline.theme.JOBS_FG,
self.powerline.theme.JOBS_BG)

View file

@ -1,2 +1,9 @@
def add_newline_segment(powerline):
powerline.append("\n", powerline.theme.RESET, powerline.theme.RESET, separator='')
from ..utils import BasicSegment
class Segment(BasicSegment):
def add_to_powerline(self):
self.powerline.append("\n",
self.powerline.theme.RESET,
self.powerline.theme.RESET,
separator="")

View file

@ -1,12 +1,17 @@
def add_root_segment(powerline):
root_indicators = {
'bash': ' \\$ ',
'zsh': ' %# ',
'bare': ' $ ',
}
bg = powerline.theme.CMD_PASSED_BG
fg = powerline.theme.CMD_PASSED_FG
if powerline.args.prev_error != 0:
fg = powerline.theme.CMD_FAILED_FG
bg = powerline.theme.CMD_FAILED_BG
powerline.append(root_indicators[powerline.args.shell], fg, bg)
from ..utils import BasicSegment
class Segment(BasicSegment):
def add_to_powerline(self):
powerline = self.powerline
root_indicators = {
'bash': ' \\$ ',
'zsh': ' %# ',
'bare': ' $ ',
}
bg = powerline.theme.CMD_PASSED_BG
fg = powerline.theme.CMD_PASSED_FG
if powerline.args.prev_error != 0:
fg = powerline.theme.CMD_FAILED_FG
bg = powerline.theme.CMD_FAILED_BG
powerline.append(root_indicators[powerline.args.shell], fg, bg)

View file

@ -1,4 +1,5 @@
import os
import socket
def add_set_term_title_segment(powerline):
@ -11,7 +12,6 @@ def add_set_term_title_segment(powerline):
elif powerline.args.shell == 'zsh':
set_title = '%{\033]0;%n@%m: %~\007%}'
else:
import socket
set_title = '\033]0;%s@%s: %s\007' % (os.getenv('USER'), socket.gethostname().split('.')[0], powerline.cwd or os.getenv('PWD'))
powerline.append(set_title, None, None, '')

View file

@ -1,11 +1,15 @@
import os
from ..utils import BasicSegment
def add_virtual_env_segment(powerline):
env = os.getenv('VIRTUAL_ENV') or os.getenv('CONDA_ENV_PATH') or os.getenv('CONDA_DEFAULT_ENV')
if env is None:
return
env_name = os.path.basename(env)
bg = powerline.theme.VIRTUAL_ENV_BG
fg = powerline.theme.VIRTUAL_ENV_FG
powerline.append(' %s ' % env_name, fg, bg)
class Segment(BasicSegment):
def add_to_powerline(self):
env = os.getenv('VIRTUAL_ENV') \
or os.getenv('CONDA_ENV_PATH') \
or os.getenv('CONDA_DEFAULT_ENV')
if not env:
return
env_name = os.path.basename(env)
bg = self.powerline.theme.VIRTUAL_ENV_BG
fg = self.powerline.theme.VIRTUAL_ENV_FG
self.powerline.append(" " + env_name + " ", fg, bg)

View file

@ -1,3 +1,13 @@
import sys
import threading
py3 = sys.version_info.major == 3
if py3:
def unicode(x):
return x
class RepoStats(object):
symbols = {
'detached': u'\u2693',
@ -43,14 +53,31 @@ class RepoStats(object):
"""
return unicode(self[_key]) if int(self[_key]) > 1 else u''
def add_to_powerline(self, powerline, color):
def add_to_powerline(self, powerline):
def add(_key, fg, bg):
if self[_key]:
s = u" {}{} ".format(self.n_or_empty(_key), self.symbols[_key])
powerline.append(s, fg, bg)
color = powerline.theme
add('ahead', color.GIT_AHEAD_FG, color.GIT_AHEAD_BG)
add('behind', color.GIT_BEHIND_FG, color.GIT_BEHIND_BG)
add('staged', color.GIT_STAGED_FG, color.GIT_STAGED_BG)
add('not_staged', color.GIT_NOTSTAGED_FG, color.GIT_NOTSTAGED_BG)
add('untracked', color.GIT_UNTRACKED_FG, color.GIT_UNTRACKED_BG)
add('conflicted', color.GIT_CONFLICTED_FG, color.GIT_CONFLICTED_BG)
def warn(msg):
print('[powerline-bash] ', msg)
class BasicSegment(object):
def __init__(self, powerline):
self.powerline = powerline
class ThreadedSegment(threading.Thread):
def __init__(self, powerline):
super(ThreadedSegment, self).__init__()
self.powerline = powerline
self.start()

View file

@ -1,6 +1,6 @@
import unittest
import powerline_shell_base as p
from powerline_shell.repos import RepoStats
from powerline_shell.utils import RepoStats
class RepoStatsTest(unittest.TestCase):