Add: Powerline-Shell

This commit is contained in:
nold 2021-04-20 13:12:35 +02:00
parent b148d7a2b7
commit 9f5e86de4a
42 changed files with 1278 additions and 0 deletions

View File

@ -0,0 +1,16 @@
{
"theme": "~/.config/powerline-shell/themes/default.py",
"segments": [
"hostname",
"cwd",
"git",
"root"
],
"cwd": {
"max_depth": 8,
"max_dir_size": 20
},
"hostname": {
"ignore": "lbswvpa002"
}
}

View File

@ -0,0 +1,12 @@
from ..utils import BasicSegment
import os
class Segment(BasicSegment):
def add_to_powerline(self):
aws_profile = os.environ.get("AWS_PROFILE") or \
os.environ.get("AWS_DEFAULT_PROFILE")
if aws_profile:
self.powerline.append(" aws:%s " % os.path.basename(aws_profile),
self.powerline.theme.AWS_PROFILE_FG,
self.powerline.theme.AWS_PROFILE_BG)

View File

@ -0,0 +1,37 @@
from ..utils import BasicSegment, warn
import os
class Segment(BasicSegment):
def add_to_powerline(self):
# See discussion in https://github.com/banga/powerline-shell/pull/204
# regarding the directory where battery info is saved
if os.path.exists("/sys/class/power_supply/BAT0"):
dir_ = "/sys/class/power_supply/BAT0"
elif os.path.exists("/sys/class/power_supply/BAT1"):
dir_ = "/sys/class/power_supply/BAT1"
else:
warn("battery directory could not be found")
return
with open(os.path.join(dir_, "capacity")) as f:
cap = int(f.read().strip())
with open(os.path.join(dir_, "status")) as f:
status = f.read().strip()
if status == "Full":
if self.powerline.segment_conf("battery", "always_show_percentage", False):
pwr_fmt = u" {cap:d}% \U0001F50C "
else:
pwr_fmt = u" \U0001F50C "
elif status == "Charging":
pwr_fmt = u" {cap:d}% \u26A1 "
else:
pwr_fmt = " {cap:d}% "
if cap < self.powerline.segment_conf("battery", "low_threshold", 20):
bg = self.powerline.theme.BATTERY_LOW_BG
fg = self.powerline.theme.BATTERY_LOW_FG
else:
bg = self.powerline.theme.BATTERY_NORMAL_BG
fg = self.powerline.theme.BATTERY_NORMAL_FG
self.powerline.append(pwr_fmt.format(cap=cap), fg, bg)

View File

@ -0,0 +1,69 @@
import subprocess
from ..utils import RepoStats, ThreadedSegment, get_subprocess_env
def _get_bzr_branch():
p = subprocess.Popen(['bzr', 'nick'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
env=get_subprocess_env())
branch = p.communicate()[0].decode("utf-8").rstrip('\n')
return branch
def parse_bzr_stats(status):
stats = RepoStats()
statustype = "changed"
for statusline in status:
if statusline[:2] == " ":
setattr(stats, statustype, getattr(stats, statustype) + 1)
elif statusline == "added:":
statustype = "staged"
elif statusline == "unknown:":
statustype = "new"
else: # removed, missing, renamed, modified or kind changed
statustype = "changed"
return stats
def _get_bzr_status(output):
"""This function exists to enable mocking the `bzr status` output in tests.
"""
return output[0].decode("utf-8").splitlines()
def build_stats():
try:
p = subprocess.Popen(['bzr', 'status'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
env=get_subprocess_env())
except OSError:
# Popen will throw an OSError if bzr is not found
return (None, None)
pdata = p.communicate()
if p.returncode != 0:
return (None, None)
status = _get_bzr_status(pdata)
stats = parse_bzr_stats(status)
branch = _get_bzr_branch()
return stats, branch
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
if self.powerline.segment_conf("vcs", "show_symbol"):
symbol = RepoStats().symbols["bzr"] + " "
else:
symbol = ""
self.powerline.append(" " + symbol + self.branch + " ", fg, bg)
self.stats.add_to_powerline(self.powerline)

View File

@ -0,0 +1,105 @@
import os
import sys
from ..utils import warn, py3, BasicSegment
ELLIPSIS = u'\u2026'
def replace_home_dir(cwd):
home = os.path.realpath(os.getenv('HOME'))
if cwd.startswith(home):
return '~' + cwd[len(home):]
return cwd
def split_path_into_names(cwd):
names = cwd.split(os.sep)
if names[0] == '':
names = names[1:]
if not names[0]:
return ['/']
return names
def requires_special_home_display(powerline, name):
"""Returns true if the given directory name matches the home indicator and
the chosen theme should use a special home indicator display."""
return (name == '~' and powerline.theme.HOME_SPECIAL_DISPLAY)
def maybe_shorten_name(powerline, name):
"""If the user has asked for each directory name to be shortened, will
return the name up to their specified length. Otherwise returns the full
name."""
max_size = powerline.segment_conf("cwd", "max_dir_size")
if max_size:
return name[:max_size]
return name
def get_fg_bg(powerline, name, is_last_dir):
"""Returns the foreground and background color to use for the given name.
"""
if requires_special_home_display(powerline, name):
return (powerline.theme.HOME_FG, powerline.theme.HOME_BG,)
if is_last_dir:
return (powerline.theme.CWD_FG, powerline.theme.PATH_BG,)
else:
return (powerline.theme.PATH_FG, powerline.theme.PATH_BG,)
def add_cwd_segment(powerline):
cwd = powerline.cwd
if not py3:
cwd = cwd.decode("utf-8")
cwd = replace_home_dir(cwd)
names = split_path_into_names(cwd)
full_cwd = powerline.segment_conf("cwd", "full_cwd", False)
max_depth = powerline.segment_conf("cwd", "max_depth", 5)
if max_depth <= 0:
warn("Ignoring cwd.max_depth option since it's not greater than 0")
elif len(names) > max_depth:
# https://github.com/milkbikis/powerline-shell/issues/148
# n_before is the number is the number of directories to put before the
# ellipsis. So if you are at ~/a/b/c/d/e and max depth is 4, it will
# show `~ a ... d e`.
#
# max_depth must be greater than n_before or else you end up repeating
# parts of the path with the way the splicing is written below.
n_before = 2 if max_depth > 2 else max_depth - 1
names = names[:n_before] + [ELLIPSIS] + names[n_before - max_depth:]
if powerline.segment_conf("cwd", "mode") == "dironly":
# The user has indicated they only want the current directory to be
# displayed, so chop everything else off
names = names[-1:]
elif powerline.segment_conf("cwd", "mode") == "plain":
joined = os.path.sep.join(names)
powerline.append(" %s " % (joined,), powerline.theme.CWD_FG,
powerline.theme.PATH_BG)
return
for i, name in enumerate(names):
is_last_dir = (i == len(names) - 1)
fg, bg = get_fg_bg(powerline, name, is_last_dir)
separator = powerline.separator_thin
separator_fg = powerline.theme.SEPARATOR_FG
if requires_special_home_display(powerline, name) or is_last_dir:
separator = None
separator_fg = None
if not (is_last_dir and full_cwd):
name = maybe_shorten_name(powerline, name)
powerline.append(' %s ' % name, fg, bg, separator, separator_fg)
class Segment(BasicSegment):
def add_to_powerline(self):
add_cwd_segment(self.powerline)

View File

@ -0,0 +1,10 @@
import os
from ..utils import BasicSegment
class Segment(BasicSegment):
def add_to_powerline(self):
self.powerline.append(
" %s " % os.getenv(self.segment_def["var"]),
self.segment_def.get("fg_color", self.powerline.theme.PATH_FG),
self.segment_def.get("bg_color", self.powerline.theme.PATH_BG))

View File

@ -0,0 +1,10 @@
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

@ -0,0 +1,71 @@
import os
import subprocess
from ..utils import RepoStats, ThreadedSegment, get_subprocess_env
def _get_fossil_branch():
branches = os.popen("fossil branch 2>/dev/null").read().strip().split("\n")
return ''.join([
i.replace('*','').strip()
for i in branches
if i.startswith('*')
])
def parse_fossil_stats(status):
stats = RepoStats()
for line in status:
if line.startswith("ADDED"):
stats.staged += 1
elif line.startswith("EXTRA"):
stats.new += 1
elif line.startswith("CONFLICT"):
stats.conflicted += 1
else:
stats.changed += 1
return stats
def _get_fossil_status():
changes = os.popen("fossil changes 2>/dev/null").read().strip().split("\n")
extra = os.popen("fossil extras 2>/dev/null").read().strip().split("\n")
extra = ["EXTRA " + filename for filename in extra if filename != ""]
status = [line for line in changes + extra if line != '']
return status
def build_stats():
try:
subprocess.Popen(['fossil'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=get_subprocess_env()).communicate()
except OSError:
# Popen will throw an OSError if fossil is not found
return (None, None)
branch = _get_fossil_branch()
if branch == "":
return (None, None)
status = _get_fossil_status()
if status == []:
return (RepoStats(), branch)
stats = parse_fossil_stats(status)
return stats, branch
class Segment(ThreadedSegment):
def add_to_powerline(self):
self.stats, self.branch = build_stats()
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
if self.powerline.segment_conf("vcs", "show_symbol"):
symbol = RepoStats().symbols["fossil"] + " "
else:
symbol = ""
self.powerline.append(" " + symbol + self.branch + " ", fg, bg)
self.stats.add_to_powerline(self.powerline)

View File

@ -0,0 +1,84 @@
import re
import subprocess
from ..utils import RepoStats, ThreadedSegment, get_git_subprocess_env
def parse_git_branch_info(status):
info = re.search('^## (?P<local>\S+?)''(\.{3}(?P<remote>\S+?)( \[(ahead (?P<ahead>\d+)(, )?)?(behind (?P<behind>\d+))?\])?)?$', status[0])
return info.groupdict() if info else None
def _get_git_detached_branch():
p = subprocess.Popen(['git', 'describe', '--tags', '--always'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
env=get_git_subprocess_env())
detached_ref = p.communicate()[0].decode("utf-8").rstrip('\n')
if p.returncode == 0:
branch = u'{} {}'.format(RepoStats.symbols['detached'], detached_ref)
else:
branch = 'Big Bang'
return branch
def parse_git_stats(status):
stats = RepoStats()
for statusline in status[1:]:
code = statusline[:2]
if code == '??':
stats.new += 1
elif code in ('DD', 'AU', 'UD', 'UA', 'DU', 'AA', 'UU'):
stats.conflicted += 1
else:
if code[1] != ' ':
stats.changed += 1
if code[0] != ' ':
stats.staged += 1
return stats
def build_stats():
try:
p = subprocess.Popen(['git', 'status', '--porcelain', '-b'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
env=get_git_subprocess_env())
except OSError:
# Popen will throw an OSError if git is not found
return (None, None)
pdata = p.communicate()
if p.returncode != 0:
return (None, None)
status = pdata[0].decode("utf-8").splitlines()
stats = parse_git_stats(status)
branch_info = parse_git_branch_info(status)
if branch_info:
stats.ahead = branch_info["ahead"]
stats.behind = branch_info["behind"]
branch = branch_info['local']
else:
branch = _get_git_detached_branch()
return stats, branch
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
if self.powerline.segment_conf("vcs", "show_symbol"):
symbol = RepoStats().symbols["git"] + " "
else:
symbol = ""
self.powerline.append(" " + symbol + self.branch + " ", fg, bg)
self.stats.add_to_powerline(self.powerline)

View File

@ -0,0 +1,34 @@
import subprocess
from ..utils import RepoStats, ThreadedSegment, get_git_subprocess_env
def get_stash_count():
try:
p = subprocess.Popen(['git', 'stash', 'list'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
env=get_git_subprocess_env())
except OSError:
return 0
pdata = p.communicate()
if p.returncode != 0:
return 0
return pdata[0].count(b'\n')
class Segment(ThreadedSegment):
def run(self):
self.stash_count = get_stash_count()
def add_to_powerline(self):
self.join()
if not self.stash_count:
return
bg = self.powerline.theme.GIT_STASH_BG
fg = self.powerline.theme.GIT_STASH_FG
sc = self.stash_count if self.stash_count > 1 else ''
stash_str = u' {}{} '.format(sc, RepoStats.symbols['stash'])
self.powerline.append(stash_str, fg, bg)

View File

@ -0,0 +1,68 @@
import subprocess
from ..utils import RepoStats, ThreadedSegment, get_subprocess_env
def _get_hg_branch():
p = subprocess.Popen(["hg", "branch"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=get_subprocess_env())
branch = p.communicate()[0].decode("utf-8").rstrip('\n')
return branch
def parse_hg_stats(status):
stats = RepoStats()
for statusline in status:
if statusline[0] == "A":
stats.staged += 1
elif statusline[0] == "?":
stats.new += 1
else: # [M]odified, [R]emoved, (!)missing
stats.changed += 1
return stats
def _get_hg_status(output):
"""This function exists to enable mocking the `hg status` output in tests.
"""
return output[0].decode("utf-8").splitlines()
def build_stats():
try:
p = subprocess.Popen(["hg", "status"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=get_subprocess_env())
except OSError:
# Will be thrown if hg cannot be found
return None, None
pdata = p.communicate()
if p.returncode != 0:
return None, None
status = _get_hg_status(pdata)
stats = parse_hg_stats(status)
branch = _get_hg_branch()
return stats, branch
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
if self.powerline.segment_conf("vcs", "show_symbol"):
symbol = RepoStats().symbols["hg"] + " "
else:
symbol = ""
self.powerline.append(" " + symbol + self.branch + " ", fg, bg)
self.stats.add_to_powerline(self.powerline)

View File

@ -0,0 +1,27 @@
from ..utils import BasicSegment
from ..color_compliment import stringToHashToColorAndOpposite
from ..colortrans import rgb2short
from socket import gethostname
class Segment(BasicSegment):
def add_to_powerline(self):
powerline = self.powerline
if powerline.segment_conf("hostname", "ignore") in gethostname():
return
if powerline.segment_conf("hostname", "colorize"):
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:
if powerline.args.shell == "bash":
host_prompt = r" \h "
elif powerline.args.shell == "zsh":
host_prompt = " %m "
else:
host_prompt = " %s " % gethostname().split(".")[0]
powerline.append(host_prompt,
powerline.theme.HOSTNAME_FG,
powerline.theme.HOSTNAME_BG)

View File

@ -0,0 +1,31 @@
import os
import re
import subprocess
import platform
from ..utils import ThreadedSegment
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
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

@ -0,0 +1,12 @@
from ..utils import BasicSegment, warn
class Segment(BasicSegment):
def add_to_powerline(self):
if self.powerline.args.shell == "tcsh":
warn("newline segment not supported for tcsh (yet?)")
return
self.powerline.append("\n",
self.powerline.theme.RESET,
self.powerline.theme.RESET,
separator="")

View File

@ -0,0 +1,18 @@
import subprocess
from ..utils import ThreadedSegment
class Segment(ThreadedSegment):
def run(self):
try:
p1 = subprocess.Popen(["node", "--version"], stdout=subprocess.PIPE)
self.version = p1.communicate()[0].decode("utf-8").rstrip()
except OSError:
self.version = None
def add_to_powerline(self):
self.join()
if not self.version:
return
# FIXME no hard-coded colors
self.powerline.append("node " + self.version, 15, 18)

View File

@ -0,0 +1,17 @@
import subprocess
from ..utils import ThreadedSegment
class Segment(ThreadedSegment):
def run(self):
try:
p1 = subprocess.Popen(["npm", "--version"], stdout=subprocess.PIPE)
self.version = p1.communicate()[0].decode("utf-8").rstrip()
except OSError:
self.version = None
def add_to_powerline(self):
self.join()
if self.version:
# FIXME no hard-coded colors
self.powerline.append("npm " + self.version, 15, 18)

View File

@ -0,0 +1,21 @@
import subprocess
from ..utils import ThreadedSegment, decode
class Segment(ThreadedSegment):
def run(self):
self.version = None
try:
output = decode(
subprocess.check_output(['php', '-r', 'echo PHP_VERSION;'],
stderr=subprocess.STDOUT))
self.version = output.split('-')[0] if '-' in output else output
except OSError:
self.version = None
def add_to_powerline(self):
self.join()
if not self.version:
return
# FIXME no hard-coded colors
self.powerline.append(" " + self.version + " ", 15, 4)

View File

@ -0,0 +1,17 @@
import subprocess
from ..utils import BasicSegment
class Segment(BasicSegment):
def add_to_powerline(self):
powerline = self.powerline
try:
p1 = subprocess.Popen(["rbenv", "local"], stdout=subprocess.PIPE)
version = p1.communicate()[0].decode("utf-8").rstrip()
if len(version) <= 0:
return
powerline.append(' %s ' % version,
powerline.theme.VIRTUAL_ENV_FG,
powerline.theme.VIRTUAL_ENV_BG)
except OSError:
return

View File

@ -0,0 +1,11 @@
import os
from ..utils import BasicSegment
class Segment(BasicSegment):
def add_to_powerline(self):
powerline = self.powerline
if not os.access(powerline.cwd, os.W_OK):
powerline.append(' %s ' % powerline.lock,
powerline.theme.READONLY_FG,
powerline.theme.READONLY_BG)

View File

@ -0,0 +1,18 @@
from ..utils import BasicSegment
class Segment(BasicSegment):
def add_to_powerline(self):
powerline = self.powerline
root_indicators = {
'bash': ' \\$ ',
'tcsh': ' %# ',
'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, sanitize=False)

View File

@ -0,0 +1,22 @@
import os
import subprocess
from ..utils import BasicSegment
class Segment(BasicSegment):
def add_to_powerline(self):
powerline = self.powerline
try:
p1 = subprocess.Popen(['ruby', '-v'], stdout=subprocess.PIPE)
p2 = subprocess.Popen(['sed', "s/ (.*//"], stdin=p1.stdout, stdout=subprocess.PIPE)
ruby_and_gemset = p2.communicate()[0].decode('utf-8').rstrip()
gem_set = os.environ.get('GEM_HOME', '@').split('@')
if len(gem_set) > 1:
ruby_and_gemset += "@{}".format(gem_set.pop())
powerline.append(ruby_and_gemset, 15, 1)
except OSError:
return

View File

@ -0,0 +1,22 @@
import os
import socket
from ..utils import BasicSegment
class Segment(BasicSegment):
def add_to_powerline(self):
powerline = self.powerline
term = os.getenv('TERM')
if not (('xterm' in term) or ('rxvt' in term)):
return
if powerline.args.shell == 'bash':
set_title = '\\[\\e]0;\\u@\\h: \\w\\a\\]'
elif powerline.args.shell == 'zsh':
set_title = '%{\033]0;%n@%m: %~\007%}'
else:
set_title = '\033]0;%s@%s: %s\007' % (
os.getenv('USER'),
socket.gethostname().split('.')[0],
powerline.cwd,
)
powerline.append(set_title, None, None, '')

View File

@ -0,0 +1,11 @@
import os
from ..utils import BasicSegment
class Segment(BasicSegment):
def add_to_powerline(self):
if os.getenv('SSH_CLIENT'):
powerline = self.powerline
powerline.append(' %s ' % powerline.network,
powerline.theme.SSH_FG,
powerline.theme.SSH_BG)

View File

@ -0,0 +1,17 @@
import subprocess
from ..utils import ThreadedSegment
class Segment(ThreadedSegment):
def run(self):
cmd = self.segment_def["command"]
self.output = subprocess.check_output(cmd).decode("utf-8").strip()
# TODO handle OSError
# TODO handle no command defined or malformed
def add_to_powerline(self):
self.join()
self.powerline.append(
" %s " % self.output,
self.segment_def.get("fg_color", self.powerline.theme.PATH_FG),
self.segment_def.get("bg_color", self.powerline.theme.PATH_BG))

View File

@ -0,0 +1,70 @@
import subprocess
from ..utils import ThreadedSegment, RepoStats, get_subprocess_env
def _get_svn_revision():
p = subprocess.Popen(["svn", "info", "--xml"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=get_subprocess_env())
for line in p.communicate()[0].decode("utf-8").splitlines():
if "revision" in line:
revision = line.split("=")[1].split('"')[1]
break
return revision
def parse_svn_stats(status):
stats = RepoStats()
for line in status:
if line[0] == "?":
stats.new += 1
elif line[0] == "C":
stats.conflicted += 1
elif line[0] in ["A", "D", "I", "M", "R", "!", "~"]:
stats.changed += 1
return stats
def _get_svn_status(output):
"""This function exists to enable mocking the `svn status` output in tests.
"""
return output[0].decode("utf-8").splitlines()
def build_stats():
try:
p = subprocess.Popen(['svn', 'status'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
env=get_subprocess_env())
except OSError:
# Popen will throw an OSError if svn is not found
return None, None
pdata = p.communicate()
if p.returncode != 0 or pdata[1][:22] == b'svn: warning: W155007:':
return None, None
status = _get_svn_status(pdata)
stats = parse_svn_stats(status)
revision = _get_svn_revision()
return stats, revision
class Segment(ThreadedSegment):
def run(self):
self.stats, self.revision = 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
if self.powerline.segment_conf("vcs", "show_symbol"):
symbol = " " + RepoStats().symbols["svn"]
else:
symbol = ""
self.powerline.append(symbol + " rev " + self.revision + " ", fg, bg)
self.stats.add_to_powerline(self.powerline)

View File

@ -0,0 +1,20 @@
from __future__ import absolute_import
from ..utils import BasicSegment
import time
class Segment(BasicSegment):
def add_to_powerline(self):
powerline = self.powerline
format = powerline.segment_conf('time', 'format')
if format:
time_ = ' %s ' % time.strftime(format)
elif powerline.args.shell == 'bash':
time_ = ' \\t '
elif powerline.args.shell == 'zsh':
time_ = ' %* '
else:
time_ = ' %s ' % time.strftime('%H:%M:%S')
powerline.append(time_,
powerline.theme.TIME_FG,
powerline.theme.TIME_BG)

View File

@ -0,0 +1,20 @@
import subprocess
import re
from ..utils import BasicSegment, decode
class Segment(BasicSegment):
def add_to_powerline(self):
powerline = self.powerline
try:
output = decode(subprocess.check_output(['uptime'], stderr=subprocess.STDOUT))
raw_uptime = re.search('(?<=up).+(?=,\s+\d+\s+user)', output).group(0)
day_search = re.search('\d+(?=\s+day)', output)
days = '' if not day_search else '%sd ' % day_search.group(0)
hour_search = re.search('\d{1,2}(?=\:)', raw_uptime)
hours = '' if not hour_search else '%sh ' % hour_search.group(0)
minutes = re.search('(?<=\:)\d{1,2}|\d{1,2}(?=\s+min)', raw_uptime).group(0)
uptime = u' %s%s%sm \u2191 ' % (days, hours, minutes)
powerline.append(uptime, powerline.theme.CWD_FG, powerline.theme.PATH_BG)
except OSError:
return

View File

@ -0,0 +1,21 @@
from ..utils import BasicSegment
import os
import getpass
class Segment(BasicSegment):
def add_to_powerline(self):
powerline = self.powerline
if powerline.args.shell == "bash":
user_prompt = r" \u "
elif powerline.args.shell == "zsh":
user_prompt = " %n "
else:
user_prompt = " %s " % os.getenv("USER")
if getpass.getuser() == "root":
bgcolor = powerline.theme.USERNAME_ROOT_BG
else:
bgcolor = powerline.theme.USERNAME_BG
powerline.append(user_prompt, powerline.theme.USERNAME_FG, bgcolor)

View File

@ -0,0 +1,18 @@
import os
from ..utils import BasicSegment
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 os.getenv('VIRTUAL_ENV') \
and os.path.basename(env) == '.venv':
env = os.path.basename(os.path.dirname(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

@ -0,0 +1,45 @@
from powerline_shell.themes.default import DefaultColor
class Color(DefaultColor):
"""Basic theme which only uses colors in 0-15 range"""
USERNAME_FG = 8
USERNAME_BG = 15
USERNAME_ROOT_BG = 1
HOSTNAME_FG = 8
HOSTNAME_BG = 7
HOME_SPECIAL_DISPLAY = False
PATH_BG = 8 # dark grey
PATH_FG = 7 # light grey
CWD_FG = 15 # white
SEPARATOR_FG = 7
READONLY_BG = 1
READONLY_FG = 15
REPO_CLEAN_BG = 2 # green
REPO_CLEAN_FG = 0 # black
REPO_DIRTY_BG = 1 # red
REPO_DIRTY_FG = 15 # white
JOBS_FG = 14
JOBS_BG = 8
CMD_PASSED_BG = 8
CMD_PASSED_FG = 15
CMD_FAILED_BG = 11
CMD_FAILED_FG = 0
SVN_CHANGES_BG = REPO_DIRTY_BG
SVN_CHANGES_FG = REPO_DIRTY_FG
VIRTUAL_ENV_BG = 2
VIRTUAL_ENV_FG = 0
AWS_PROFILE_FG = 14
AWS_PROFILE_BG = 8
TIME_FG = 8
TIME_BG = 7

View File

@ -0,0 +1,84 @@
class DefaultColor(object):
"""
This class should have the default colors for every segment.
Please test every new segment with this theme first.
"""
# RESET is not a real color code. It is used as in indicator
# within the code that any foreground / background color should
# be cleared
RESET = -1
USERNAME_FG = 250
USERNAME_BG = 240
USERNAME_ROOT_BG = 124
HOSTNAME_FG = 250
HOSTNAME_BG = 238
HOME_SPECIAL_DISPLAY = True
HOME_BG = 31 # blueish
HOME_FG = 15 # white
PATH_BG = 237 # dark grey
PATH_FG = 250 # light grey
CWD_FG = 254 # nearly-white grey
SEPARATOR_FG = 244
READONLY_BG = 124
READONLY_FG = 254
SSH_BG = 166 # medium orange
SSH_FG = 254
REPO_CLEAN_BG = 148 # a light green color
REPO_CLEAN_FG = 0 # black
REPO_DIRTY_BG = 161 # pink/red
REPO_DIRTY_FG = 15 # white
JOBS_FG = 39
JOBS_BG = 238
CMD_PASSED_BG = 236
CMD_PASSED_FG = 15
CMD_FAILED_BG = 161
CMD_FAILED_FG = 15
SVN_CHANGES_BG = 148
SVN_CHANGES_FG = 22 # dark green
GIT_AHEAD_BG = 240
GIT_AHEAD_FG = 250
GIT_BEHIND_BG = 240
GIT_BEHIND_FG = 250
GIT_STAGED_BG = 22
GIT_STAGED_FG = 15
GIT_NOTSTAGED_BG = 130
GIT_NOTSTAGED_FG = 15
GIT_UNTRACKED_BG = 52
GIT_UNTRACKED_FG = 15
GIT_CONFLICTED_BG = 9
GIT_CONFLICTED_FG = 15
GIT_STASH_BG = 221
GIT_STASH_FG = 0
VIRTUAL_ENV_BG = 35 # a mid-tone green
VIRTUAL_ENV_FG = 00
BATTERY_NORMAL_BG = 22
BATTERY_NORMAL_FG = 7
BATTERY_LOW_BG = 196
BATTERY_LOW_FG = 7
AWS_PROFILE_FG = 39
AWS_PROFILE_BG = 238
TIME_FG = 250
TIME_BG = 238
class Color(DefaultColor):
"""
This subclass is required when the user chooses to use 'default' theme.
Because the segments require a 'Color' class for every theme.
"""
pass

View File

@ -0,0 +1,111 @@
from powerline_shell.themes.default import DefaultColor
"""
absolute colors based on
https://github.com/morhetz/gruvbox/blob/master/colors/gruvbox.vim
"""
dark0 = 235
dark1 = 237
dark2 = 239
dark3 = 241
dark4 = 243
light0 = 229
light1 = 223
light2 = 250
light3 = 248
light4 = 246
dark_gray = 245
light_gray = 244
neutral_red = 124
neutral_green = 106
neutral_yellow = 172
neutral_blue = 66
neutral_purple = 132
neutral_aqua = 72
neutral_orange = 166
bright_red = 167
bright_green = 142
bright_yellow = 214
bright_blue = 109
bright_purple = 175
bright_aqua = 108
bright_orange = 208
faded_red = 88
faded_green = 100
faded_yellow = 136
faded_blue = 24
faded_purple = 96
faded_aqua = 66
faded_orange = 130
class Color(DefaultColor):
USERNAME_ROOT_BG = faded_red
USERNAME_BG = dark2
USERNAME_FG = bright_purple
HOSTNAME_BG = dark1
HOSTNAME_FG = bright_purple
HOME_SPECIAL_DISPLAY = True
HOME_BG = neutral_blue
HOME_FG = light2
PATH_BG = dark3
PATH_FG = light3
CWD_FG = light2
SEPARATOR_FG = dark_gray
READONLY_BG = bright_red
READONLY_FG = light0
SSH_BG = faded_purple
SSH_FG = light0
REPO_CLEAN_BG = faded_green
REPO_CLEAN_FG = dark1
REPO_DIRTY_BG = faded_orange
REPO_DIRTY_FG = light0
JOBS_FG = neutral_aqua
JOBS_BG = dark1
CMD_PASSED_FG = light4
CMD_PASSED_BG = dark1
CMD_FAILED_FG = light0
CMD_FAILED_BG = neutral_red
SVN_CHANGES_FG = REPO_DIRTY_FG
SVN_CHANGES_BG = REPO_DIRTY_BG
GIT_AHEAD_BG = dark2
GIT_AHEAD_FG = light3
GIT_BEHIND_BG = dark2
GIT_BEHIND_FG = light3
GIT_STAGED_BG = neutral_green
GIT_STAGED_FG = light0
GIT_NOTSTAGED_BG = neutral_orange
GIT_NOTSTAGED_FG = light0
GIT_UNTRACKED_BG = faded_red
GIT_UNTRACKED_FG = light0
GIT_CONFLICTED_BG = neutral_red
GIT_CONFLICTED_FG = light0
GIT_STASH_BG = neutral_yellow
GIT_STASH_FG = dark0
VIRTUAL_ENV_BG = faded_green
VIRTUAL_ENV_FG = light0
BATTERY_NORMAL_BG = neutral_green
BATTERY_NORMAL_FG = dark2
BATTERY_LOW_BG = neutral_red
BATTERY_LOW_FG = light1
AWS_PROFILE_FG = neutral_aqua
AWS_PROFILE_BG = dark1
TIME_FG = light2
TIME_BG = dark4

View File

@ -0,0 +1,44 @@
from powerline_shell.themes.default import DefaultColor
class Color(DefaultColor):
USERNAME_FG = 15
USERNAME_BG = 4
USERNAME_ROOT_BG = 1
HOSTNAME_FG = 15
HOSTNAME_BG = 10
HOME_SPECIAL_DISPLAY = False
PATH_FG = 7
PATH_BG = 10
CWD_FG = 15
SEPARATOR_FG = 14
READONLY_BG = 1
READONLY_FG = 7
REPO_CLEAN_FG = 14
REPO_CLEAN_BG = 0
REPO_DIRTY_FG = 3
REPO_DIRTY_BG = 0
JOBS_FG = 4
JOBS_BG = 8
CMD_PASSED_FG = 15
CMD_PASSED_BG = 2
CMD_FAILED_FG = 15
CMD_FAILED_BG = 1
SVN_CHANGES_FG = REPO_DIRTY_FG
SVN_CHANGES_BG = REPO_DIRTY_BG
VIRTUAL_ENV_BG = 15
VIRTUAL_ENV_FG = 2
AWS_PROFILE_FG = 7
AWS_PROFILE_BG = 2
TIME_FG = 15
TIME_BG = 10

View File

@ -0,0 +1,41 @@
from powerline_shell.themes.default import DefaultColor
class Color(DefaultColor):
USERNAME_FG = 15
USERNAME_BG = 4
USERNAME_ROOT_BG = 1
HOSTNAME_FG = 15
HOSTNAME_BG = 10
HOME_SPECIAL_DISPLAY = False
PATH_FG = 10
PATH_BG = 7
CWD_FG = 0
SEPARATOR_FG = 14
READONLY_BG = 1
READONLY_FG = 7
REPO_CLEAN_FG = 0
REPO_CLEAN_BG = 15
REPO_DIRTY_FG = 1
REPO_DIRTY_BG = 15
JOBS_FG = 4
JOBS_BG = 7
CMD_PASSED_FG = 15
CMD_PASSED_BG = 2
CMD_FAILED_FG = 15
CMD_FAILED_BG = 1
SVN_CHANGES_FG = REPO_DIRTY_FG
SVN_CHANGES_BG = REPO_DIRTY_BG
VIRTUAL_ENV_BG = 15
VIRTUAL_ENV_FG = 2
TIME_FG = 15
TIME_BG = 10

View File

@ -0,0 +1,44 @@
from powerline_shell.themes.default import DefaultColor
class Color(DefaultColor):
USERNAME_FG = 8
USERNAME_BG = 251
USERNAME_ROOT_BG = 209
HOSTNAME_FG = 8
HOSTNAME_BG = 7
HOME_SPECIAL_DISPLAY = False
PATH_BG = 15
PATH_FG = 8
CWD_FG = 8
SEPARATOR_FG = 251
READONLY_BG = 209
READONLY_FG = 15
REPO_CLEAN_BG = 150 # pale green
REPO_CLEAN_FG = 235
REPO_DIRTY_BG = 203 # pale red
REPO_DIRTY_FG = 15
JOBS_FG = 14
JOBS_BG = 8
CMD_PASSED_BG = 7
CMD_PASSED_FG = 8
CMD_FAILED_BG = 9
CMD_FAILED_FG = 15
SVN_CHANGES_BG = REPO_DIRTY_BG
SVN_CHANGES_FG = REPO_DIRTY_FG
VIRTUAL_ENV_BG = 150
VIRTUAL_ENV_FG = 0
AWS_PROFILE_FG = 0
AWS_PROFILE_BG = 7
TIME_FG = 8
TIME_BG = 7