213 lines
4.2 KiB
Python
Executable file
213 lines
4.2 KiB
Python
Executable file
#! /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()
|