From ca28ca1680a7f5fd2101a18c9af110b325d91f50 Mon Sep 17 00:00:00 2001 From: Martinez Date: Sun, 26 Apr 2015 14:15:48 +0200 Subject: [PATCH] roughed out the new render program in Python, closing #2 as we're not going to support fish --- .gitignore | 1 + fish-init | 9 -- over-prompt-9999.ebuild | 2 +- render.py | 213 ++++++++++++++++++++++++++++++++++++++++ zsh-init | 15 +++ 5 files changed, 230 insertions(+), 10 deletions(-) delete mode 100644 fish-init create mode 100755 render.py diff --git a/.gitignore b/.gitignore index 6ab3a7b..fba2a00 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +__pycache__ render colors.sh diff --git a/fish-init b/fish-init deleted file mode 100644 index bf58ff7..0000000 --- a/fish-init +++ /dev/null @@ -1,9 +0,0 @@ -#! /bin/fish - -function fish_prompt - ~/git/over-prompt/render .1 .35 $COLUMNS $status - # ^ ^ ^ ^- last command's exit status - # | \- terminal width - # | \- yellow threshold - # \- red threshold -end diff --git a/over-prompt-9999.ebuild b/over-prompt-9999.ebuild index 84e98e3..7deb069 100644 --- a/over-prompt-9999.ebuild +++ b/over-prompt-9999.ebuild @@ -6,7 +6,7 @@ EAPI=5 inherit git-2 -DESCRIPTION="A nonintrusive shell prompt that provides: username, hostname, tty name, cwd, return value of the last command, current time, disk space, and system load. Fish or zsh is preferred, although bash is also somewhat supported." +DESCRIPTION="A nonintrusive zsh prompt that provides useful data like pwd, git info and system stats to the user." HOMEPAGE="https://git.covalent.cz/overwatch/over-prompt" SRC_URI="" diff --git a/render.py b/render.py new file mode 100755 index 0000000..bd395bc --- /dev/null +++ b/render.py @@ -0,0 +1,213 @@ +#! /usr/bin/env python3 +# encoding: utf-8 + +import os +import socket +import sys + +SYM_GIT = "\ue0a0" +SYM_LOCK = "\ue0a2" + +def style_color(fg, bg): + return '\033[38;5;%dm\033[48;5;%dm' %(fg, bg) + +def style_bold(): + return '\033[1m' + +def style_reset(): + return '\033[0m' + +class LoginPart: + user_fg = 34 + root_fg = 196 + remote_fg = 202 + local_fg = 7 + screen_fg = 27 + bg = 0 + + def __init__(self): + self.user = os.getlogin() + self.remote = bool(os.getenv('SSH_CLIENT')) + self.sign = ' ⇄ ' if self.remote else '@' + self.host = socket.gethostname() + self.screen = os.getenv('WINDOW') + + @property + def length(self): + return len(self.user) + len(self.host) + len(self.screen) + len(self.sign) + 1 + + def __str__(self): + output = '' + + if os.geteuid() == 0: + output += style_color(self.root_fg, self.bg) + else: + output += style_color(self.user_fg, self.bg) + + output += self.user + + if self.remote: + output += style_color(self.remote_fg, self.bg) + else: + output += style_color(self.local_fg, self.bg) + + output += self.sign + output += self.host + + if self.screen: + output += style_reset() + output += ':' + output += style_color(self.screen_fg, self.bg) + output += self.screen + + output += style_reset() + + return output + +def list_homes(): + with open('/etc/passwd') as f: + for line in f: + tokens = line.split(':') + + if tokens[5] != '/dev/null': + yield (tokens[5], tokens[0]) + +class Dir: + writable_fg = 34 + fg = 196 + bg = 0 + + def __init__(self, path, name=None, slash='/'): + self.path = path + self.slash = slash + self.lock = not os.access(path, os.W_OK) + self.truncated = False + + if name is None: + name = os.path.basename(path) + + self.raw_str = name + ('' if self.lock else '') + + @property + def length(self): + return len(self.raw_str) + len(self.slash) + + def truncate(self): + self.truncated = True + + if self.raw_str: + self.raw_str = self.raw_str[0] + + def __str__(self): + output = self.slash + + if self.truncated: + output += style_bold() + + if self.raw_str: + output += style_color(self.fg if self.lock else self.writable_fg, self.bg) + output += self.raw_str + + output += style_reset() + + return output + +class PathPart: + def __init__(self, term_width): + self.term_width = term_width + self.segments = [] + + homes = dict(list_homes()) + dirs = os.getcwd().split('/')[1:] + path = '' + + for dir in dirs: + path += '/' + dir + + if path in homes: + self.segments = [] + + if homes[path] == os.getlogin(): + self.segments.append(Dir(path, '', '~')) + else: + self.segments.append(Dir(path, homes[path], '~')) + + else: + self.segments.append(Dir(path)) + + @property + def length(self): + return sum(s.length for s in self.segments) + + def truncate(self, length): + for s in self.segments: + if self.length > length: + s.truncate() + else: + break + + def truncate_fit(self, line): + space = self.term_width - sum(part.length for part in line if part is not self) + self.truncate(space) + + def __str__(self): + return ''.join(str(s) for s in self.segments) + +class GitPart: + def __init__(self): + ... + + @property + def length(self): + return len(str(self)) + + def __str__(self): + return 'GIT' + +class Padding: + def __init__(self, term_width): + self.term_width = term_width + self.length = 0 + + def expand_fit(self, line): + self.length = self.term_width - sum(part.length for part in line if part is not self) - len(line) + 1 + + def __str__(self): + return ' ' * self.length + +class StatsPart: + clock = 27 + space_good = 34 + space_warn = 208 + space_bad = 196 + + def __init__(self, red_thresh, yellow_thresh, warning_only=True): + self.red = red_thresh + self.yellow = yellow_thresh + + @property + def length(self): + return len(str(self)) + + def __str__(self): + return '[ 13:34 | 0.53 | r4.20M' + +if __name__ == '__main__': + red_thresh = float(sys.argv[1]) + yellow_thresh = float(sys.argv[2]) + term_width = int(sys.argv[3]) + exit_status = int(sys.argv[4]) + + lp = LoginPart() + pp = PathPart(term_width) + gp = GitPart() + pad = Padding(term_width) + sp = StatsPart(red_thresh, yellow_thresh) + + line = [lp, pp, gp, pad, sp] + pp.truncate_fit(line) + pad.expand_fit(line) + + line_str = ' '.join(str(part) for part in line) + sys.stderr.write(line_str) + sys.stderr.flush() diff --git a/zsh-init b/zsh-init index 99813c0..c6094fe 100755 --- a/zsh-init +++ b/zsh-init @@ -15,6 +15,19 @@ function strlen { echo ${#PLAIN} } +function set_title { + if [[ ${TERM} == "screen-bce" || ${TERM} == "screen" ]]; then + print -Pn "\033k\033${@}\033\134" + fi +} + +function preexec { + local -a cmd + cmd=(${(z)1}) + + set_title "${PWD}: ${cmd}" +} + function precmd { local CUT OVER_OPTS RAW_DATA LOGIN_PART STATS_PART DATA TOP_LEFT TOP_RIGHT PADDING PADDING_SIZE GIT_BRANCH COLOR set -A OVER_OPTS ${(s. .)OVER_PROMPT_OPTS} @@ -63,6 +76,8 @@ function precmd { else print -P "\e[5;31m!!! unable to run /usr/share/over-prompt/data\e[0m" fi + + set_title "${PWD}" } unset OVER_PROMPT_CFG