Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VCS symbols #298

Merged
merged 9 commits into from
Jan 15, 2018
32 changes: 22 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,21 @@ quick look into the state of your repo:
of commits is shown along with `⇡` or `⇣` indicating whether a git push
or pull is pending.

In addition, git has a few extra symbols:
If files are modified or in conflict, the situation is summarized with the
following symbols:

- `✎` -- a file has been modified, but not staged for commit
- `✔` -- a file is staged for commit
- `✎` -- a file has been modified (but not staged for commit, in git)
- `✔` -- a file is staged for commit (git) or added for tracking
- `✼` -- a file has conflicts

FIXME

- A `+` appears when untracked files are present (except for git, which uses
`?` instead)
- `❓` -- a file is untracked

Each of these will have a number next to it if more than one file matches.

The segment can start with a symbol representing the version control system in
use. To show that symbol, the configuration file must have a variable `vcs`
with an option `show_symbol` set to `true` (see
[Segment Configuration](#segment-configuration)).

## Setup

This script uses ANSI color codes to display colors in a terminal. These are
Expand Down Expand Up @@ -237,13 +239,17 @@ for the `cwd` segment are set in `~/.powerline-shell.json` like:
"cwd": {
options go here
}
"theme": "theme-name",
"vcs": {
options go here
}
}
```

The options for the `cwd` segment are:

- `mode`: If "plain" then simple text will be used to show the cwd. If
"dironly," only the current directory will be shown. Otherwise expands the
- `mode`: If `plain`, then simple text will be used to show the cwd. If
`dironly`, only the current directory will be shown. Otherwise expands the
cwd into individual directories.
- `max_depth`: Maximum number of directories to show in path.
- `max_dir_size`: Maximum number of characters displayed for each directory in
Expand All @@ -256,6 +262,12 @@ The `hostname` segment provides one option:
- `colorize`: If true, the hostname will be colorized based on a hash of
itself.

The `vcs` segment provides one option:

- `show_symbol`: If `true`, the version control system segment will start with
a symbol representing the specific version control system in use in the
current directory.

The options for the `battery` segment are:

- `always_show_percentage`: If true, show percentage when fully charged on AC.
Expand Down
7 changes: 5 additions & 2 deletions powerline_shell/segments/bzr.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ def add_to_powerline(self):
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)
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)
7 changes: 5 additions & 2 deletions powerline_shell/segments/fossil.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ def add_to_powerline(self):
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)
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)
7 changes: 5 additions & 2 deletions powerline_shell/segments/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ def add_to_powerline(self):
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)
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)
6 changes: 5 additions & 1 deletion powerline_shell/segments/hg.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,9 @@ def add_to_powerline(self):
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)
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)
98 changes: 64 additions & 34 deletions powerline_shell/segments/svn.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,68 @@
import subprocess
import subprocess, os
from ..utils import ThreadedSegment, RepoStats


class Segment(ThreadedSegment):
def __init__(self, powerline):
super(Segment, self).__init__(powerline)
self.stats = None
self.revision = ""
def get_PATH():
"""Normally gets the PATH from the OS. This function exists to enable
easily mocking the PATH in tests.
"""
return os.getenv("PATH")

def run(self):
try:
svn_status = subprocess.Popen(["svn", "status"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
svn_info = subprocess.Popen(["svn", "info"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
svn_stdout, svn_stderr = svn_status.communicate()
svn_info, _ = svn_info.communicate()
except OSError:
return

if len(svn_stderr.decode("utf-8").strip()) != 0:
return
def svn_subprocess_env():
return {"PATH": get_PATH()}


def _get_svn_revision():
p = subprocess.Popen(["svn", "info", "--xml"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=svn_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

self.stats = RepoStats()
for line in svn_stdout.splitlines():
line = line.decode("utf-8").strip()
if line[0] == "?":
self.stats.new += 1
elif line[0] == "C":
self.stats.conflicted += 1
elif line[0] in ["A", "D", "I", "M", "R", "!", "~"]:
self.stats.changed += 1

for line in svn_info.splitlines():
line = line.decode("utf-8").strip()
if "Revision: " in line:
self.revision = line.split(" ", 1)[1]

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=svn_subprocess_env())
except OSError:
# Popen will throw an OSError if svn is not found
return 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()
Expand All @@ -46,6 +73,9 @@ def add_to_powerline(self):
if self.stats.dirty:
bg = self.powerline.theme.REPO_DIRTY_BG
fg = self.powerline.theme.REPO_DIRTY_FG

self.powerline.append(" rev " + self.revision + " ", fg, bg)
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)
7 changes: 6 additions & 1 deletion powerline_shell/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ class RepoStats(object):
'staged': u'\u2714',
'changed': u'\u270E',
'new': u'?',
'conflicted': u'\u273C'
'conflicted': u'\u273C',
'git': u'\uE0A0',
'hg': u'\u263F',
'bzr': u'\u2B61\u20DF',
'fossil': u'\u2332',
'svn': u'\u2446'
}

def __init__(self, ahead=0, behind=0, new=0, changed=0, staged=0, conflicted=0):
Expand Down