kuroko port

This commit is contained in:
K. Lange 2022-03-22 22:41:22 +09:00
parent 8a2c71416e
commit 2a32fed223
14 changed files with 592 additions and 531 deletions

1
.gitignore vendored
View file

@ -39,7 +39,6 @@ _/
/*ponies/onlyheights
/*ponies/widths
/*ponies/metadata
/ponysay
/bin/
/obj/

View file

@ -39,56 +39,57 @@ Authors:
Jan Alexander "heftig" Steffens: Major contributor of the first implementation
Kyah "L-four" Rindlisbacher: Patched the first implementation
'''
from common import *
from argparser import *
from ponysay import *
from ponysay.common import printerr, printinfo, gettermsize, endswith
from ponysay.argparser import ArgParser
from ponysay.ponysay import Ponysay
import os
import kuroko
'''
Start the program
'''
if __name__ == '__main__':
istool = sys.argv[0]
let istool = kuroko.argv[0]
if os.sep in istool:
istool = istool[istool.rfind(os.sep) + 1:]
if os.extsep in istool:
istool = istool[:istool.find(os.extsep)]
istool = istool.endswith('-tool')
if istool:
from ponysaytool import * ## will start ponysay-tool
exit(0)
import ponysaytool
os.exit(0)
isthink = sys.argv[0]
let isthink = kuroko.argv[0]
if os.sep in isthink:
isthink = isthink[isthink.rfind(os.sep) + 1:]
if os.extsep in isthink:
isthink = isthink[:isthink.find(os.extsep)]
isthink = isthink.endswith('think')
usage_saythink = '\033[34;1m(ponysay | ponythink)\033[21;39m'
usage_common = '[-c] [-W\033[33mCOLUMN\033[39m] [-b\033[33mSTYLE\033[39m]'
usage_listhelp = '(-l | -L | -B | +l | +L | -A | + A | -v | -h)'
usage_file = '[-f\033[33mPONY\033[39m]* [[--] \033[33mmessage\033[39m]'
usage_xfile = '(+f\033[33mPONY\033[39m)* [[--] \033[33mmessage\033[39m]'
usage_afile = '(-F\033[33mPONY\033[39m)* [[--] \033[33mmessage\033[39m]'
usage_quote = '(-q\033[33mPONY\033[39m)*'
let usage_saythink = '\033[34;1m(ponysay | ponythink)\033[22;39m'
let usage_common = '[-c] [-W\033[33mCOLUMN\033[39m] [-b\033[33mSTYLE\033[39m]'
let usage_listhelp = '(-l | -L | -B | +l | +L | -A | + A | -v | -h)'
let usage_file = '[-f\033[33mPONY\033[39m]* [[--] \033[33mmessage\033[39m]'
let usage_xfile = '(+f\033[33mPONY\033[39m)* [[--] \033[33mmessage\033[39m]'
let usage_afile = '(-F\033[33mPONY\033[39m)* [[--] \033[33mmessage\033[39m]'
let usage_quote = '(-q\033[33mPONY\033[39m)*'
usage = ('%s %s' + 4 * '\n%s %s %s') % (usage_saythink, usage_listhelp,
let usage = ('{} {}' + 4 * '\n{} {} {}') .format (usage_saythink, usage_listhelp,
usage_saythink, usage_common, usage_file,
usage_saythink, usage_common, usage_xfile,
usage_saythink, usage_common, usage_afile,
usage_saythink, usage_common, usage_quote)
usage = usage.replace('\033[', '\0')
usage = usage.replace('\033[', '')
for sym in ('[', ']', '(', ')', '|', '...', '*'):
usage = usage.replace(sym, '\033[2m' + sym + '\033[22m')
usage = usage.replace('\0', '\033[')
usage = usage.replace('', '\033[')
'''
Argument parsing
'''
opts = ArgParser(program = 'ponythink' if isthink else 'ponysay',
let opts = ArgParser(program = 'ponythink' if isthink else 'ponysay',
description = 'cowsay reimplemention for ponies',
usage = usage,
longdescription =
@ -117,8 +118,8 @@ run `man ponysay`. Ponysay has so much more to offer than described here.''')
opts.add_argumented( ['--colour-pony'], arg = 'COLOUR')
opts.add_argumented( ['--colour-wrap', '--colour-hyphen'], arg = 'COLOUR')
_F = ['--any-file', '--anyfile', '--any-pony', '--anypony']
__F = [_.replace("pony", "ponie") + 's' for _ in _F]
let _F = ['--any-file', '--anyfile', '--any-pony', '--anypony']
let __F = [_.replace("pony", "ponie") + 's' for _ in _F]
opts.add_argumentless(['-h', '--help'], help = 'Print this help message.')
opts.add_argumentless(['+h', '++help', '--help-colour'], help = 'Print this help message with colours even if piped.')
opts.add_argumentless(['-v', '--version'], help = 'Print the version of the program.')
@ -145,10 +146,10 @@ run `man ponysay`. Ponysay has so much more to offer than described here.''')
'''
Whether at least one unrecognised option was used
'''
unrecognised = not opts.parse()
let unrecognised = not opts.parse()
## Start
ponysay = Ponysay()
let ponysay = Ponysay()
ponysay.unrecognised = unrecognised
ponysay.run(opts)

View file

@ -29,21 +29,23 @@ that line FREE: yes, is included inside the image between two $$$
lines and the FREE is and upper case and directly followed by
the colon.
'''
from common import *
from ponysay.common import printerr, printinfo, gettermsize, endswith
import os
import kuroko
import fileio
ARGUMENTLESS = 0
let ARGUMENTLESS = 0
'''
Option takes no arguments
'''
ARGUMENTED = 1
let ARGUMENTED = 1
'''
Option takes one argument per instance
'''
VARIADIC = 2
let VARIADIC = 2
'''
Option consumes all following arguments
'''
@ -83,7 +85,7 @@ class ArgParser():
@param help:str Short description, use `None` to hide the option
'''
self.__arguments.append((ARGUMENTLESS, alternatives, None, help))
stdalt = alternatives[0]
let stdalt = alternatives[0]
self.opts[stdalt] = None
for alt in alternatives:
self.optmap[alt] = (stdalt, ARGUMENTLESS)
@ -97,7 +99,7 @@ class ArgParser():
@param help:str Short description, use `None` to hide the option
'''
self.__arguments.append((ARGUMENTED, alternatives, arg, help))
stdalt = alternatives[0]
let stdalt = alternatives[0]
self.opts[stdalt] = None
for alt in alternatives:
self.optmap[alt] = (stdalt, ARGUMENTED)
@ -111,13 +113,13 @@ class ArgParser():
@param help:str Short description, use `None` to hide the option
'''
self.__arguments.append((VARIADIC, alternatives, arg, help))
stdalt = alternatives[0]
let stdalt = alternatives[0]
self.opts[stdalt] = None
for alt in alternatives:
self.optmap[alt] = (stdalt, VARIADIC)
def parse(self, argv = sys.argv):
def parse(self, argv = kuroko.argv):
'''
Parse arguments
@ -127,23 +129,24 @@ class ArgParser():
self.argcount = len(argv) - 1
self.files = []
argqueue = []
optqueue = []
deque = []
let arg, i, n, opt, varopt
let argqueue = []
let optqueue = []
let deque = []
for arg in argv[1:]:
deque.append(arg)
dashed = False
tmpdashed = False
get = 0
dontget = 0
let dashed = False
let tmpdashed = False
let get = 0
let dontget = 0
self.rc = True
self.unrecognisedCount = 0
def unrecognised(arg):
self.unrecognisedCount += 1
if self.unrecognisedCount <= 5:
sys.stderr.write('%s: warning: unrecognised option %s\n' % (self.__program, arg))
fileio.stderr.write('{}: warning: unrecognised option {}\n' .format (self.__program, arg))
self.rc = False
while len(deque) != 0:
@ -184,11 +187,11 @@ class ArgParser():
else:
unrecognised(arg)
else:
sign = arg[0]
i = 1
n = len(arg)
let sign = arg[0]
let i = 1
let n = len(arg)
while i < n:
narg = sign + arg[i]
let narg = sign + arg[i]
i += 1
if (narg in self.optmap):
if self.optmap[narg][1] == ARGUMENTLESS:
@ -196,7 +199,7 @@ class ArgParser():
argqueue.append(None)
elif self.optmap[narg][1] == ARGUMENTED:
optqueue.append(narg)
nargarg = arg[i:]
let nargarg = arg[i:]
if len(nargarg) == 0:
get += 1
else:
@ -204,7 +207,7 @@ class ArgParser():
break
elif self.optmap[narg][1] == VARIADIC:
optqueue.append(narg)
nargarg = arg[i:]
let nargarg = arg[i:]
argqueue.append(nargarg if len(nargarg) > 0 else None)
dashed = True
break
@ -240,7 +243,7 @@ class ArgParser():
self.message = ' '.join(self.files) if len(self.files) > 0 else None
if self.unrecognisedCount > 5:
sys.stderr.write('%s: warning: %i more unrecognised %s\n' % (self.unrecognisedCount - 5, 'options' if self.unrecognisedCount == 6 else 'options'))
fileio.stderr.write('{}: warning: {} more unrecognised {}\n' .format (self.unrecognisedCount - 5, 'options' if self.unrecognisedCount == 6 else 'options'))
return self.rc
@ -252,94 +255,102 @@ class ArgParser():
@param use_colours:bool? Whether to use colours, `None` if stdout is not piped
'''
if use_colours is None:
use_colours = sys.stdout.isatty()
use_colours = True # os.isatty(1)
print(('\033[1m%s\033[21m %s %s' if use_colours else '%s %s %s') % (self.__program, '-' if self.linuxvt else '—', self.__description))
print(('\[[1m{}\[[22m {} {}' if use_colours else '{} {} {}').format(self.__program, '-' if self.linuxvt else '—', self.__description))
print()
if self.__longdescription is not None:
desc = self.__longdescription
let desc = self.__longdescription
if not use_colours:
while '\033' in desc:
esc = desc.find('\033')
while '\[' in desc:
esc = desc.find('\[')
desc = desc[:esc] + desc[desc.find('m', esc) + 1:]
print(desc)
print()
print('\033[1mUSAGE:\033[21m' if use_colours else 'USAGE:', end='')
first = True
print('\[[1mUSAGE:\[[22m' if use_colours else 'USAGE:', end='')
let first = True
for line in self.__usage.split('\n'):
if first:
first = False
else:
print(' or', end='')
if not use_colours:
while '\033' in line:
esc = line.find('\033')
while '\[' in line:
esc = line.find('\[')
line = line[:esc] + line[line.find('m', esc) + 1:]
print('\t%s' % line)
print('\t{}'.format(line))
print()
maxfirstlen = []
let maxfirstlen = []
for opt in self.__arguments:
opt_alts = opt[1]
opt_help = opt[3]
let opt_alts = opt[1]
let opt_help = opt[3]
if opt_help is None:
continue
first = opt_alts[0]
last = opt_alts[-1]
let last = opt_alts[-1]
if first is not last:
maxfirstlen.append(first)
maxfirstlen = len(max(maxfirstlen, key = len))
print('\033[1mSYNOPSIS:\033[21m' if use_colours else 'SYNOPSIS')
(lines, lens) = ([], [])
print('\[[1mSYNOPSIS:\[[22m' if use_colours else 'SYNOPSIS')
let lines, lens = [], []
for opt in self.__arguments:
opt_type = opt[0]
opt_alts = opt[1]
opt_arg = opt[2]
opt_help = opt[3]
let opt_type = opt[0]
let opt_alts = opt[1]
let opt_arg = opt[2]
let opt_help = opt[3]
if opt_help is None:
continue
(line, l) = ('', 0)
let line, l = '', 0
first = opt_alts[0]
last = opt_alts[-1]
alts = ['', last] if first is last else [first, last]
let last = opt_alts[-1]
let alts = ['', last] if first is last else [first, last]
alts[0] += ' ' * (maxfirstlen - len(alts[0]))
for opt_alt in alts:
if opt_alt is alts[-1]:
line += '%colour%' + opt_alt
l += len(opt_alt)
if use_colours:
if opt_type == ARGUMENTED: line += ' \033[4m%s\033[24m' % (opt_arg); l += len(opt_arg) + 1
elif opt_type == VARIADIC: line += ' [\033[4m%s\033[24m...]' % (opt_arg); l += len(opt_arg) + 6
if opt_type == ARGUMENTED:
line += ' \[[4m{}\[[24m' .format (opt_arg)
l += len(opt_arg) + 1
elif opt_type == VARIADIC:
line += ' [\[[4m{}\[[24m...]' .format (opt_arg)
l += len(opt_arg) + 6
else:
if opt_type == ARGUMENTED: line += ' %s' % (opt_arg); l += len(opt_arg) + 1
elif opt_type == VARIADIC: line += ' [%s...]' % (opt_arg); l += len(opt_arg) + 6
if opt_type == ARGUMENTED:
line += ' {}' .format (opt_arg)
l += len(opt_arg) + 1
elif opt_type == VARIADIC:
line += ' [{}...]' .format (opt_arg)
l += len(opt_arg) + 6
else:
if use_colours:
line += ' \033[2m%s\033[22m ' % (opt_alt)
line += ' \[[2m{}\[[22m ' .format (opt_alt)
else:
line += ' %s ' % (opt_alt)
line += ' {} ' .format (opt_alt)
l += len(opt_alt) + 6
lines.append(line)
lens.append(l)
col = max(lens)
let col = max(lens)
col += 8 - ((col - 4) & 7)
index = 0
let index = 0
for opt in self.__arguments:
opt_help = opt[3]
let opt_help = opt[3]
if opt_help is None:
continue
first = True
colour = ('36' if (index & 1) == 0 else '34') if use_colours else ''
print(lines[index].replace('%colour%', ('\033[%s;1m' % colour) if use_colours else ''), end=' ' * (col - lens[index]))
let colour = ('36' if (index & 1) == 0 else '34') if use_colours else ''
print(lines[index].replace('%colour%', ('\[[{};1m' .format (colour)) if use_colours else ''), end=' ' * (col - lens[index]))
for line in opt_help.split('\n'):
if first:
first = False
print('%s' % (line), end='\033[21;39m\n' if use_colours else '\n')
print(line, end='\[[22;39m\n' if use_colours else '\n')
else:
print(('%s\033[%sm%s\033[39m' if use_colours else '%s%s%s') % (' ' * col, colour, line))
print(('{}\[[{}m{}\[[39m' if use_colours else '{}{}{}').format (' ' * col, colour, line))
index += 1
print()

View file

@ -29,14 +29,14 @@ that line FREE: yes, is included inside the image between two $$$
lines and the FREE is and upper case and directly followed by
the colon.
'''
from common import *
from balloon import *
from colourstack import *
from ucs import *
import unicodedata
from ponysay.common import printerr, printinfo, gettermsize, endswith
from ponysay.balloon import Balloon
from ponysay.colourstack import ColourStack
from ponysay.ucs import UCS
from wcwidth import wcwidth
import fileio
import os
class Backend():
'''
@ -89,6 +89,7 @@ class Backend():
if self.pony.startswith('$$$\n'):
self.pony = self.pony[4:]
let infoend, info
if self.pony.startswith('$$$\n'):
infoend = 4
info = ''
@ -104,21 +105,21 @@ class Backend():
else:
info = info.split('\n')
for line in info:
sep = line.find(':')
let sep = line.find(':')
if sep > 0:
key = line[:sep].strip()
let key = line[:sep].strip()
if key == 'BALLOON TOP':
value = line[sep + 1:].strip()
let value = line[sep + 1:].strip()
if len(value) > 0:
self.balloontop = int(value)
if key == 'BALLOON BOTTOM':
value = line[sep + 1:].strip()
let value = line[sep + 1:].strip()
if len(value) > 0:
self.balloonbottom = int(value)
printinfo(info)
self.pony = self.pony[infoend:]
elif self.infolevel == 2:
self.message = '\033[01;31mI am the mysterious mare...\033[21;39m'
self.message = '\033[01;31mI am the mysterious mare...\033[22;39m'
elif self.infolevel == 1:
self.pony = 'There is not metadata for this pony file'
self.pony = self.mode + self.pony
@ -149,7 +150,7 @@ class Backend():
test = test.replace(c, '')
if (len(test) == 0) and (len(key.replace(' ', '')) > 0):
value = line[sep + 1:].strip()
line = '\033[1m%s\033[21m: %s\n' % (key.strip(), value)
line = '\033[1m{}\033[22m: {}\n' .format (key.strip(), value)
tags += line
continue
comment += '\n' + line
@ -163,16 +164,16 @@ class Backend():
'''
Remove padding spaces fortune cookies are padded with whitespace (damn featherbrains)
'''
lines = self.message.split('\n')
let lines = self.message.split('\n')
for spaces in (128, 64, 32, 16, 8, 4, 2, 1):
padded = True
let padded = True
for line in lines:
if not line.startswith(' ' * spaces):
padded = False
break
if padded:
for i in range(0, len(lines)):
line = lines[i]
let line = lines[i]
line = line[spaces:]
lines[i] = line
lines = [line.rstrip(' ') for line in lines]
@ -183,19 +184,19 @@ class Backend():
'''
Converts all tabs in the message to spaces by expanding
'''
lines = self.message.split('\n')
buf = ''
let lines = self.message.split('\n')
let buf = ''
for line in lines:
(i, n, x) = (0, len(line), 0)
let i, n, x = (0, len(line), 0)
while i < n:
c = line[i]
let c = line[i]
i += 1
if c == '\033':
colour = Backend.getColour(line, i - 1)
let colour = Backend.getColour(line, i - 1)
i += len(colour) - 1
buf += colour
elif c == '\t':
nx = 8 - (x & 7)
let nx = 8 - (x & 7)
buf += ' ' * nx
x += nx
else:
@ -210,8 +211,8 @@ class Backend():
'''
Loads the pony file
'''
with open(self.ponyfile, 'rb') as ponystream:
self.pony = ponystream.read().decode('utf8', 'replace')
with fileio.open(self.ponyfile, 'rb') as ponystream:
self.pony = ponystream.read().decode()
def __truncate(self):
@ -220,15 +221,15 @@ class Backend():
'''
if self.width is None:
return
lines = self.output.split('\n')
let lines = self.output.split('\n')
self.output = ''
for line in lines:
(i, n, x) = (0, len(line), 0)
let i, n, x = (0, len(line), 0)
while i < n:
c = line[i]
let c = line[i]
i += 1
if c == '\033':
colour = Backend.getColour(line, i - 1)
let colour = Backend.getColour(line, i - 1)
i += len(colour) - 1
self.output += colour
else:
@ -246,35 +247,36 @@ class Backend():
'''
self.output = ''
AUTO_PUSH = '\033[01010~'
AUTO_POP = '\033[10101~'
let AUTO_PUSH = '\033[01010~'
let AUTO_POP = '\033[10101~'
variables = {'' : '$'}
let variables = {'' : '$'}
for key in self.link:
variables[key] = AUTO_PUSH + self.link[key] + AUTO_POP
indent = 0
dollar = None
balloonLines = None
colourstack = ColourStack(AUTO_PUSH, AUTO_POP)
let indent = 0
let dollar = None
let balloonLines = None
let balloonLine, balloonIndent
let colourstack = ColourStack(AUTO_PUSH, AUTO_POP)
(i, n, lineindex, skip, nonskip) = (0, len(self.pony), 0, 0, 0)
let i, n, lineindex, skip, nonskip = (0, len(self.pony), 0, 0, 0)
while i < n:
c = self.pony[i]
let c = self.pony[i]
if c == '\t':
n += 7 - (indent & 7)
ed = ' ' * (8 - (indent & 7))
let ed = ' ' * (8 - (indent & 7))
c = ' '
self.pony = self.pony[:i] + ed + self.pony[i + 1:]
i += 1
if c == '$':
if dollar is not None:
if '=' in dollar:
name = dollar[:dollar.find('=')]
value = dollar[dollar.find('=') + 1:]
let name = dollar[:dollar.find('=')]
let value = dollar[dollar.find('=') + 1:]
variables[name] = value
elif not dollar.startswith('balloon'):
data = variables[dollar].replace('$', '$$')
let data = variables[dollar].replace('$', '$$')
if data == '$$': # if not handled specially we will get an infinity loop
if (skip == 0) or (nonskip > 0):
if nonskip > 0:
@ -287,8 +289,8 @@ class Backend():
n += len(data)
self.pony = self.pony[:i] + data + self.pony[i:]
elif self.balloon is not None:
(w, h, x, justify) = ('0', 0, 0, None)
props = dollar[7:]
let w, h, x, justify = ('0', 0, 0, None)
let props = dollar[7:]
if len(props) > 0:
if ',' in props:
if props[0] != ',':
@ -299,28 +301,28 @@ class Backend():
if 'l' in w:
(x, w) = (int(w[:w.find('l')]), int(w[w.find('l') + 1:]))
justify = 'l'
w -= x;
w -= x
elif 'c' in w:
(x, w) = (int(w[:w.find('c')]), int(w[w.find('c') + 1:]))
justify = 'c'
w -= x;
w -= x
elif 'r' in w:
(x, w) = (int(w[:w.find('r')]), int(w[w.find('r') + 1:]))
justify = 'r'
w -= x;
w -= x
else:
w = int(w)
balloon = self.__getBalloon(w, h, x, justify, indent)
let balloon = self.__getBalloon(w, h, x, justify, indent)
balloon = balloon.split('\n')
balloon = [AUTO_PUSH + self.ballooncolour + item + AUTO_POP for item in balloon]
for b in balloon[0]:
self.output += b + colourstack.feed(b)
if lineindex == 0:
balloonpre = '\n' + (' ' * indent)
let balloonpre = '\n' + (' ' * indent)
for line in balloon[1:]:
self.output += balloonpre;
self.output += balloonpre
for b in line:
self.output += b + colourstack.feed(b);
self.output += b + colourstack.feed(b)
indent = 0
elif len(balloon) > 1:
balloonLines = balloon
@ -337,9 +339,9 @@ class Backend():
i += 1
dollar += c
elif c == '\033':
colour = Backend.getColour(self.pony, i - 1)
let colour = Backend.getColour(self.pony, i - 1)
for b in colour:
self.output += b + colourstack.feed(b);
self.output += b + colourstack.feed(b)
i += len(colour) - 1
elif c == '\n':
self.output += c
@ -364,7 +366,7 @@ class Backend():
if (skip == 0) or (nonskip > 0):
if nonskip > 0:
nonskip -= 1
self.output += c + colourstack.feed(c);
self.output += c + colourstack.feed(c)
if not UCS.isCombining(c):
indent += 1
else:
@ -374,7 +376,7 @@ class Backend():
for line in balloonLines[balloonLine:]:
data = ' ' * (balloonIndent - indent) + line + '\n'
for b in data:
self.output += b + colourstack.feed(b);
self.output += b + colourstack.feed(b)
indent = 0
self.output = self.output.replace(AUTO_PUSH, '').replace(AUTO_POP, '')
@ -395,11 +397,11 @@ class Backend():
@param offset:int The offset at where to start reading, a escape must begin here
@return :str The escape sequence
'''
(i, n) = (offset, len(input))
rc = input[i]
let i, n = (offset, len(input))
let rc = input[i]
i += 1
if i == n: return rc
c = input[i]
let c = input[i]
i += 1
rc += c
@ -450,16 +452,16 @@ class Backend():
@param input:str The input buffer
@return :int The number of visible characters
'''
(rc, i, n) = (0, 0, len(input))
let rc, i, n = 0, 0, len(input)
while i < n:
c = input[i]
let c = input[i]
if c == '\033':
i += len(Backend.getColour(input, i))
else:
i += 1
if not UCS.isCombining(c):
rc += 1
if unicodedata.east_asian_width(c) in ('F', 'W'):
if wcwidth(ord(c)) in ('F', 'W'):
rc += 1
return rc
@ -476,22 +478,22 @@ class Backend():
@param left:int The column where the balloon starts
@return :str The balloon the the message as a string
'''
wrap = None
let wrap = None
if self.wrapcolumn is not None:
wrap = self.wrapcolumn - left
if wrap < 8:
wrap = 8
msg = self.message
let msg = self.message
if wrap is not None:
msg = self.__wrapMessage(msg, wrap)
msg = msg.replace('\n', '\033[0m%s\n' % (self.ballooncolour)) + '\033[0m' + self.ballooncolour
msg = msg.replace('\n', '\033[0m{}\n' .format (self.ballooncolour)) + '\033[0m' + self.ballooncolour
msg = msg.split('\n')
extraleft = 0
let extraleft = 0
if justify is not None:
msgwidth = self.len(max(msg, key = self.len)) + self.balloon.minwidth
let msgwidth = self.len(max(msg, key = self.len)) + self.balloon.minwidth
extraleft = innerleft
if msgwidth > width:
if (justify == 'l') and (wrap is not None):
@ -507,7 +509,7 @@ class Backend():
if extraleft + msgwidth > wrap:
extraleft -= msgwidth - wrap
rc = self.balloon.get(width, height, msg, Backend.len);
let rc = self.balloon.get(width, height, msg, Backend.len)
if extraleft > 0:
rc = ' ' * extraleft + rc.replace('\n', '\n' + ' ' * extraleft)
return rc
@ -521,39 +523,39 @@ class Backend():
@param wrap:int The width at where to force wrapping
@return :str The message wrapped
'''
wraplimit = os.environ['PONYSAY_WRAP_LIMIT'] if 'PONYSAY_WRAP_LIMIT' in os.environ else ''
let wraplimit = os.environ['PONYSAY_WRAP_LIMIT'] if 'PONYSAY_WRAP_LIMIT' in os.environ else ''
wraplimit = 8 if len(wraplimit) == 0 else int(wraplimit)
wrapexceed = os.environ['PONYSAY_WRAP_EXCEED'] if 'PONYSAY_WRAP_EXCEED' in os.environ else ''
let wrapexceed = os.environ['PONYSAY_WRAP_EXCEED'] if 'PONYSAY_WRAP_EXCEED' in os.environ else ''
wrapexceed = 5 if len(wrapexceed) == 0 else int(wrapexceed)
buf = ''
let buf = ''
let AUTO_PUSH = '\033[01010~'
let AUTO_POP = '\033[10101~'
try:
AUTO_PUSH = '\033[01010~'
AUTO_POP = '\033[10101~'
msg = message.replace('\n', AUTO_PUSH + '\n' + AUTO_POP)
cstack = ColourStack(AUTO_PUSH, AUTO_POP)
let msg = message.replace('\n', AUTO_PUSH + '\n' + AUTO_POP)
let cstack = ColourStack(AUTO_PUSH, AUTO_POP)
for c in msg:
buf += c + cstack.feed(c)
lines = buf.replace(AUTO_PUSH, '').replace(AUTO_POP, '').split('\n')
let lines = buf.replace(AUTO_PUSH, '').replace(AUTO_POP, '').split('\n')
buf = ''
for line in lines:
b = [None] * len(line)
map = {0 : 0}
(bi, cols, w) = (0, 0, wrap)
(indent, indentc) = (-1, 0)
let b = [None] * len(line)
let map = {0 : 0}
let bi, cols, w = (0, 0, wrap)
let indent, indentc = (-1, 0)
(i, n) = (0, len(line))
let i, n = (0, len(line))
while i <= n:
d = None
let d = None
if i < n:
d = line[i]
i += 1
if d == '\033':
## Invisible stuff
i -= 1
colourseq = Backend.getColour(line, i)
let colourseq = Backend.getColour(line, i)
b[bi : bi + len(colourseq)] = colourseq
i += len(colourseq)
bi += len(colourseq)
@ -571,18 +573,18 @@ class Backend():
map[cols] = bi
else:
## Wrap?
mm = 0
bisub = 0
iwrap = wrap - (0 if indent == 1 else indentc)
let mm = 0
let bisub = 0
let iwrap = wrap - (0 if indent == 1 else indentc)
while ((w > wraplimit) and (cols > w + wrapexceed)) or (cols > iwrap):
## wrap
x = w;
let x = w
if mm + x not in map: # Too much whitespace?
cols = 0
break
nbsp = b[map[mm + x]] == ' ' # nbsp
m = map[mm + x]
let nbsp = b[map[mm + x]] == ' ' # nbsp
let m = map[mm + x]
if ('­' in b[bisub : m]) and not nbsp: # soft hyphen
hyphen = m - 1
@ -597,7 +599,7 @@ class Backend():
for bb in b[bisub : m]:
buf += bb
buf += '\n' if nbsp else '\0\n'
buf += '\n' if nbsp else '\n'
cols -= x - (0 if nbsp else 1)
bisub = m
@ -635,21 +637,15 @@ class Backend():
w -= indentc
buf += '\n'
rc = '\n'.join(line.rstrip(' ') for line in buf[:-1].split('\n'));
rc = rc.replace('­', ''); # remove soft hyphens
rc = rc.replace('\0', '%s%s%s' % (AUTO_PUSH, self.hyphen, AUTO_POP))
let rc = '\n'.join(line.rstrip(' ') for line in buf[:-1].split('\n'))
rc = rc.replace('­', '') # remove soft hyphens
rc = rc.replace('あ', '{}{}{}' .format (AUTO_PUSH, self.hyphen, AUTO_POP))
return rc
except Exception as err:
import traceback
errormessage = ''.join(traceback.format_exception(type(err), err, None))
rc = '\n'.join(line.rstrip(' ') for line in buf.split('\n'));
rc = rc.replace('\0', '%s%s%s' % (AUTO_PUSH, self.hyphen, AUTO_POP))
let errormessage = str(err)
let rc = '\n'.join(line.rstrip(' ') for line in buf.split('\n'))
rc = rc.replace('あ', '{}{}{}' .format (AUTO_PUSH, self.hyphen, AUTO_POP))
errormessage += '\n---- WRAPPING BUFFER ----\n\n' + rc
try:
if os.readlink('/proc/self/fd/2') != os.readlink('/proc/self/fd/1'):
printerr(errormessage, end='')
return message
except:
pass
return message + '\n\n\033[0;1;31m---- EXCEPTION IN PONYSAY WHILE WRAPPING ----\033[0m\n\n' + errormessage

View file

@ -29,10 +29,18 @@ that line FREE: yes, is included inside the image between two $$$
lines and the FREE is and upper case and directly followed by
the colon.
'''
from common import *
from ucs import *
from ponysay.common import printerr, printinfo, gettermsize, endswith
from ponysay.ucs import UCS
import fileio
def fmax(lst,key):
if not lst: return None
let best = lst[0]
for i in lst[1:]:
if key(best) < key(i):
best = i
return best
class Balloon():
'''
@ -73,15 +81,15 @@ class Balloon():
(self.sse, self.s, self.ssw) = (sse, s, ssw)
(self.sww, self.w, self.nww) = (sww, w, nww)
_ne = max(ne, key = UCS.dispLen)
_nw = max(nw, key = UCS.dispLen)
_se = max(se, key = UCS.dispLen)
_sw = max(sw, key = UCS.dispLen)
let _ne = fmax(ne, key = UCS.dispLen)
let _nw = fmax(nw, key = UCS.dispLen)
let _se = fmax(se, key = UCS.dispLen)
let _sw = fmax(sw, key = UCS.dispLen)
minE = UCS.dispLen(max([_ne, nee, e, see, _se, ee], key = UCS.dispLen))
minW = UCS.dispLen(max([_nw, nww, e, sww, _sw, ww], key = UCS.dispLen))
minN = len(max([ne, nne, n, nnw, nw], key = len))
minS = len(max([se, sse, s, ssw, sw], key = len))
let minE = UCS.dispLen(fmax([_ne, nee, e, see, _se, ee], key = UCS.dispLen))
let minW = UCS.dispLen(fmax([_nw, nww, e, sww, _sw, ww], key = UCS.dispLen))
let minN = len(fmax([ne, nne, n, nnw, nw], key = len))
let minS = len(fmax([se, sse, s, ssw, sw], key = len))
self.minwidth = minE + minE
self.minheight = minN + minS
@ -98,26 +106,27 @@ class Balloon():
@return :str The balloon as a formated string
'''
## Get dimension
h = self.minheight + len(lines)
w = self.minwidth + lencalc(max(lines, key = lencalc))
let h = self.minheight + len(lines)
let w = self.minwidth + lencalc(fmax(lines, key = lencalc))
if w < minw: w = minw
if h < minh: h = minh
## Create edges
let ws, es
if len(lines) > 1:
(ws, es) = ({0 : self.nww, len(lines) - 1 : self.sww}, {0 : self.nee, len(lines) - 1 : self.see})
ws, es = ({0 : self.nww, len(lines) - 1 : self.sww}, {0 : self.nee, len(lines) - 1 : self.see})
for j in range(1, len(lines) - 1):
ws[j] = self.w
es[j] = self.e
else:
(ws, es) = ({0 : self.ww}, {0 : self.ee})
ws, es = ({0 : self.ww}, {0 : self.ee})
rc = []
let rc = []
## Create the upper part of the balloon
for j in range(0, len(self.n)):
outer = UCS.dispLen(self.nw[j]) + UCS.dispLen(self.ne[j])
inner = UCS.dispLen(self.nnw[j]) + UCS.dispLen(self.nne[j])
let outer = UCS.dispLen(self.nw[j]) + UCS.dispLen(self.ne[j])
let inner = UCS.dispLen(self.nnw[j]) + UCS.dispLen(self.nne[j])
if outer + inner <= w:
rc.append(self.nw[j] + self.nnw[j] + self.n[j] * (w - outer - inner) + self.nne[j] + self.ne[j])
else:
@ -129,8 +138,8 @@ class Balloon():
## Create the lower part of the balloon
for j in range(0, len(self.s)):
outer = UCS.dispLen(self.sw[j]) + UCS.dispLen(self.se[j])
inner = UCS.dispLen(self.ssw[j]) + UCS.dispLen(self.sse[j])
let outer = UCS.dispLen(self.sw[j]) + UCS.dispLen(self.se[j])
let inner = UCS.dispLen(self.ssw[j]) + UCS.dispLen(self.sse[j])
if outer + inner <= w:
rc.append(self.sw[j] + self.ssw[j] + self.s[j] * (w - outer - inner) + self.sse[j] + self.se[j])
else:
@ -155,24 +164,25 @@ class Balloon():
return Balloon('\\', '/', 'X', '< ', ' >', [' _'], ['_'], ['_'], ['_'], ['_ '], ' \\', ' |', ' /', ['- '], ['-'], ['-'], ['-'], [' -'], '\\ ', '| ', '/ ')
## Initialise map for balloon parts
map = {}
let map = {}
for elem in ('\\', '/', 'X', 'ww', 'ee', 'nw', 'nnw', 'n', 'nne', 'ne', 'nee', 'e', 'see', 'se', 'sse', 's', 'ssw', 'sw', 'sww', 'w', 'nww'):
map[elem] = []
## Read all lines in the balloon file
with open(balloonfile, 'rb') as balloonstream:
data = balloonstream.read().decode('utf8', 'replace')
let data
with fileio.open(balloonfile, 'rb') as balloonstream:
data = balloonstream.read().decode()
data = [line.replace('\n', '') for line in data.split('\n')]
## Parse the balloon file, and fill the map
last = None
let last = None
for line in data:
if len(line) > 0:
if line[0] == ':':
map[last].append(line[1:])
else:
last = line[:line.index(':')]
value = line[len(last) + 1:]
let value = line[len(last) + 1:]
map[last].append(value)
## Return the balloon

View file

@ -29,7 +29,7 @@ that line FREE: yes, is included inside the image between two $$$
lines and the FREE is and upper case and directly followed by
the colon.
'''
from common import *
from ponysay.common import printerr, printinfo, gettermsize, endswith
@ -63,7 +63,10 @@ class ColourStack():
@return :str String that should be inserted into your buffer
'''
if self.stack:
self.stack.insert(0, [self.bufproto, None, None, [False] * 9])
else:
self.stack.append([self.bufproto, None, None, [False] * 9])
if len(self.stack) == 1:
return None
return '\033[0m'
@ -75,11 +78,11 @@ class ColourStack():
@return :str String that should be inserted into your buffer
'''
old = self.stack.pop(0)
rc = '\033[0;'
let old = self.stack.pop(0)
let rc = '\033[0;'
if len(self.stack) == 0: # last resort in case something made it pop too mush
push()
new = self.stack[0]
let new = self.stack[0]
if new[1] is not None: rc += new[1] + ';'
if new[2] is not None: rc += new[2] + ';'
for i in range(0, 9):
@ -101,10 +104,10 @@ class ColourStack():
if (char == '~') or (('a' <= char) and (char <= 'z')) or (('A' <= char) and (char <= 'Z')):
if (self.seq[0] == '[') and (self.seq[-1] == 'm'):
self.seq = self.seq[1:-1].split(';')
(i, n) = (0, len(self.seq))
let i, n = (0, len(self.seq))
while i < n:
part = self.seq[i]
p = 0 if part == '' else int(part)
let part = self.seq[i]
let p = 0 if part == '' else int(part)
i += 1
if p == 0: self.stack[0][1:] = [None, None, [False] * 9]
elif 1 <= p <= 9: self.stack[0][3][p - 1] = True
@ -116,17 +119,17 @@ class ColourStack():
elif 40 <= p <= 47: self.stack[0][2] = part
elif 100 <= p <= 107: self.stack[0][2] = part
elif p == 38:
self.stack[0][1] = '%s;%s;%s' % (part, self.seq[i], self.seq[i + 1])
self.stack[0][1] = '{};{};{}' .format (part, self.seq[i], self.seq[i + 1])
i += 2
elif p == 48:
self.stack[0][2] = '%s;%s;%s' % (part, self.seq[i], self.seq[i + 1])
self.stack[0][2] = '{};{};{}' .format (part, self.seq[i], self.seq[i + 1])
i += 2
self.seq = None
elif char == '\033':
self.seq = ''
buf = self.stack[0][0]
let buf = self.stack[0][0]
buf = buf[1:] + char
rc = ''
let rc = ''
if buf[-self.lenpush:] == self.autopush: rc = self.push()
elif buf[-self.lenpop:] == self.autopop: rc = self.pop()
self.stack[0][0] = buf

View file

@ -30,30 +30,8 @@ lines and the FREE is and upper case and directly followed by
the colon.
'''
import fileio
import os
import shutil
import sys
import random
from subprocess import Popen, PIPE
VERSION = 'dev' # this line should not be edited, it is fixed by the build system
'''
The version of ponysay
'''
def print(text = '', end = '\n'):
'''
Hack to enforce UTF-8 in output (in the future, if you see anypony not using utf-8 in
programs by default, report them to Princess Celestia so she can banish them to the moon)
@param text:str The text to print (empty string is default)
@param end:str The appendix to the text to print (line breaking is default)
'''
sys.stdout.buffer.write((str(text) + end).encode('utf-8'))
def printerr(text = '', end = '\n'):
'''
@ -62,9 +40,8 @@ def printerr(text = '', end = '\n'):
@param text:str The text to print (empty string is default)
@param end:str The appendix to the text to print (line breaking is default)
'''
sys.stderr.buffer.write((str(text) + end).encode('utf-8'))
fileio.stderr.write((str(text) + end))
fd3 = None
def printinfo(text = '', end = '\n'):
'''
/proc/self/fd/3 equivalent to print()
@ -72,12 +49,8 @@ def printinfo(text = '', end = '\n'):
@param text:str The text to print (empty string is default)
@param end:str The appendix to the text to print (line breaking is default)
'''
global fd3
if os.path.exists('/proc/self/fd/3') and not os.path.isdir(os.path.realpath('/proc/self/fd/3')):
if fd3 is None:
fd3 = os.fdopen(3, 'w')
if fd3 is not None:
fd3.write(str(text) + end)
pass
#os.write(2, (str(text) + end).encode())
def endswith(text, ending):
@ -97,12 +70,12 @@ def gettermsize():
@return (rows, columns):(int, int) The number or lines and the number of columns in the terminal's display area
'''
## Call `stty` to determine the size of the terminal, this way is better than using python's ncurses
for channel in (sys.stderr, sys.stdout, sys.stdin):
termsize = Popen(['stty', 'size'], stdout=PIPE, stdin=channel, stderr=PIPE).communicate()[0]
if len(termsize) > 0:
termsize = termsize.decode('utf8', 'replace')[:-1].split(' ') # [:-1] removes a \n
termsize = [int(item) for item in termsize]
return termsize
# TODO we don't have a thing for this??
try:
os.system("stty size > /tmp/.ponysaysize")
with fileio.open("/tmp/.ponysaysize") as f:
let tmp = f.read().strip()
return tuple(int(x) for x in tmp.split(' '))
except:
return (24, 80) # fall back to minimal sane size

View file

@ -29,7 +29,7 @@ that line FREE: yes, is included inside the image between two $$$
lines and the FREE is and upper case and directly followed by
the colon.
'''
from common import *
from ponysay.common import *

View file

@ -34,11 +34,17 @@ File listing functions.
'''
from ucs import *
import itertools
from ponysay.common import endswith, gettermsize
from ponysay.ucs import UCS
import os
def _range(min,max,step):
let i = min
while i < max:
yield i
i += step
def _columnise_list(items: list, available_width: int, length_fn: callable, separation : int = 2):
def _columnise_list(items: list, available_width: int, length_fn: function, separation : int = 2):
"""
From a list of items, produce a list of columns. Each columns is a list of tuples. Each tuple contains the element and a an int, specifying how much shorter the element is compared to the column width.
@ -48,18 +54,27 @@ def _columnise_list(items: list, available_width: int, length_fn: callable, sepa
:param separation: Amount of space to insert between columns.
"""
num_items = len(items)
items_with_length = [(i, length_fn(i)) for i in items]
max_item_length = max(i for _, i in items_with_length)
let num_items = len(items)
let items_with_length = [(i, length_fn(i)) for i in items]
let max_item_length = max(i for _, i in items_with_length)
# Make at least one column to handle very narrow terminals.
num_columns = max((available_width + separation) // (max_item_length + separation), 1)
column_length = (num_items - 1) // num_columns + 1
let num_columns = max((available_width + separation) // (max_item_length + separation), 1)
let column_length = (num_items - 1) // num_columns + 1
items_with_spacing = [(i, max_item_length - l + separation) for i, l in items_with_length]
let items_with_spacing = [(i, max_item_length - l + separation) for i, l in items_with_length]
return [items_with_spacing[i:i + column_length] for i in range(0, num_items, column_length)]
return [items_with_spacing[i:(i + column_length)] for i in _range(0, num_items, column_length)]
def _sorted(lst, key):
class Sortable():
def __init__(self, thing):
self.thing = thing
def __lt__(self, other):
return key(self.thing) < key(other.thing)
let out = [Sortable(l) for l in lst]
out.sort()
return [l.thing for l in out]
def _print_columnised(items):
'''
@ -68,26 +83,24 @@ def _print_columnised(items):
@param ponies:list<(str, str)> All items to list, each item should have to elements: unformatted name, formatted name.
'''
## Get terminal width
_, term_width = gettermsize()
let _, term_width = gettermsize()
columns = _columnise_list(
sorted(items, key = lambda x: x[0]),
let columns = _columnise_list(
_sorted(items, key = lambda x: x[0]),
term_width,
lambda x: UCS.dispLen(x[0]))
for row in itertools.zip_longest(*columns):
for row in zip(*columns):
def iter_parts():
spacing = 0
let spacing = 0
for cell in row:
if cell:
# Yield this here to prevent whitespace to be printed after the last column.
yield ' ' * spacing
(_, item), spacing = cell
let item, _, inner
inner, spacing = cell
_, item = inner
yield item
print(''.join(iter_parts()))
print()
@ -114,7 +127,7 @@ def simplelist(ponydirs, quoters = [], ucsiser = None):
'''
for ponydir in ponydirs: # Loop ponydirs
## Get all ponies in the directory
ponies = _get_file_list(ponydir, '.pony')
let ponies = _get_file_list(ponydir, '.pony')
print()
@ -125,8 +138,8 @@ def simplelist(ponydirs, quoters = [], ucsiser = None):
## If ther directory is not empty print its name and all ponies, columnised
if len(ponies) == 0:
continue
print('\033[1mponies located in ' + ponydir + '\033[21m')
_print_columnised([(pony, '\033[1m' + pony + '\033[21m' if pony in quoters else pony) for pony in ponies])
print('\033[1mponies located in ' + ponydir + '\033[22m')
_print_columnised([(pony, '\033[1m' + pony + '\033[22m' if pony in quoters else pony) for pony in ponies])
def linklist(ponydirs = None, quoters = [], ucsiser = None):
@ -145,7 +158,7 @@ def linklist(ponydirs = None, quoters = [], ucsiser = None):
## If there are no ponies in the directory skip to next directory, otherwise, print the directories name
if len(ponies) == 0:
continue
print('\033[1mponies located in ' + ponydir + '\033[21m')
print('\033[1mponies located in ' + ponydir + '\033[22m')
## UCS:ise pony names
pseudolinkmap = {}
@ -156,7 +169,7 @@ def linklist(ponydirs = None, quoters = [], ucsiser = None):
pairs = []
for pony in ponies:
if pony in pseudolinkmap:
pairs.append((pony, pseudolinkmap[pony] + '.pony'));
pairs.append((pony, pseudolinkmap[pony] + '.pony'))
else:
pairs.append((pony, os.path.realpath(ponydir + pony + '.pony') if os.path.islink(ponydir + pony + '.pony') else None))
@ -179,7 +192,7 @@ def linklist(ponydirs = None, quoters = [], ucsiser = None):
ponies = {}
for pony in ponymap:
w = UCS.dispLen(pony)
item = '\033[1m' + pony + '\033[21m' if (pony in quoters) else pony
item = '\033[1m' + pony + '\033[22m' if (pony in quoters) else pony
syms = ponymap[pony]
syms.sort()
if len(syms) > 0:
@ -190,9 +203,9 @@ def linklist(ponydirs = None, quoters = [], ucsiser = None):
w += UCS.dispLen(sym)
if first: first = False
else: item += ' '
item += '\033[1m' + sym + '\033[21m' if (sym in quoters) else sym
item += '\033[1m' + sym + '\033[22m' if (sym in quoters) else sym
item += ')'
ponies[(item.replace('\033[1m', '').replace('\033[21m', ''), item)] = w
ponies[(item.replace('\033[1m', '').replace('\033[22m', ''), item)] = w
## Print the ponies, columnised
_print_columnised(list(ponies))
@ -206,14 +219,14 @@ def onelist(pony_dirs, ucsiser):
@param ucsiser:(list<str>)→void Function used to UCS:ise names
'''
## Get all pony files
ponies = [name for dir in pony_dirs for name in _get_file_list(dir, '.pony')]
let ponies = [name for dir in pony_dirs for name in _get_file_list(dir, '.pony')]
## UCS:ise and sort
ucsiser(ponies)
ponies.sort()
## Print each one on a seperate line, but skip duplicates
last = ''
let last = ''
for pony in ponies:
if not pony == last:
last = pony

View file

@ -29,7 +29,7 @@ that line FREE: yes, is included inside the image between two $$$
lines and the FREE is and upper case and directly followed by
the colon.
'''
from common import *
from ponysay.common import printerr, printinfo, gettermsize, endswith

View file

@ -29,16 +29,72 @@ that line FREE: yes, is included inside the image between two $$$
lines and the FREE is and upper case and directly followed by
the colon.
'''
from common import *
from backend import *
from balloon import *
from spellocorrecter import *
from ucs import *
from kms import *
import lists
from metadata import *
from ponysay.common import printerr, printinfo, gettermsize, endswith
from ponysay.backend import Backend
from ponysay.balloon import Balloon
from ponysay.spellocorrecter import SpelloCorrecter
from ponysay.ucs import UCS
import ponysay.lists as lists
from ponysay.metadata import Metadata
import os
import kuroko
import fileio
import stat
import random
def randrange(low,high):
with fileio.open('/dev/urandom','rb') as f:
let b = f.read(4)
let val = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]
let flt = val / 0xFFFFFFFF
return int(flt*(high-low)+low)
def rfind(self, sub):
let last = self.find(sub)
while True:
let next = self.find(sub,last+1)
if next == -1: break
last = next
return last
str.rfind = rfind
random.randrange = randrange
class OSExtensions():
def exists(self, p):
try:
os.stat(p)
return True
except:
return False
def isdir(self, p):
try:
let res = os.stat(p)
return stat.S_ISDIR(res.st_mode)
except:
return False
def isfile(self, p):
try:
let res = os.stat(p)
return stat.S_ISREG(res.st_mode)
except:
return False
def islink(self, p):
try:
let res = os.stat(p)
return stat.S_ISLNK(res.st_mode)
except:
return False
os.path = OSExtensions()
let exit = os.exit
def listdir(p):
return [c['name'] for c in fileio.opendir(p)]
os.listdir = listdir
class Ponysay():
'''
@ -55,7 +111,6 @@ class Ponysay():
if len(self.HOME) == 0:
os.environ['HOME'] = self.HOME = os.path.expanduser('~')
## Load extension and configurations via ponysayrc
for file in ('$XDG_CONFIG_HOME/ponysay/ponysayrc', '$HOME/.config/ponysay/ponysayrc', '$HOME/.ponysayrc', '/etc/ponysayrc'):
file = self.__parseFile(file)
@ -84,17 +139,17 @@ class Ponysay():
# Whether stdin is piped
self.pipelinein = not sys.stdin.isatty()
self.pipelinein = not os.isatty(0) #sys.stdin.isatty()
# Whether stdout is piped
self.pipelineout = not sys.stdout.isatty()
self.pipelineout = not os.isatty(1) #sys.stdout.isatty()
# Whether stderr is piped
self.pipelineerr = not sys.stderr.isatty()
self.pipelineerr = not os.isatty(2) #sys.stderr.isatty()
# Whether KMS is used
self.usekms = KMS.usingKMS(self.linuxvt)
self.usekms = False #KMS.usingKMS(self.linuxvt)
# Mode string that modifies or adds $ variables in the pony image
@ -128,9 +183,9 @@ class Ponysay():
@return The target file name, None if the environment variables are not declared
'''
if '$' in file:
buf = ''
esc = False
var = None
let buf = ''
let esc = False
let var = None
for c in file:
if esc:
buf += c
@ -162,9 +217,9 @@ class Ponysay():
@param directory:str The directory base name
@return :list<str> Absolute directory names
'''
appendset = set()
rc = []
_ponydirs = cls.__share(directory)
let appendset = set()
let rc = []
let _ponydirs = cls.__share(directory)
for ponydir in _ponydirs:
if (ponydir is not None) and os.path.isdir(ponydir) and (ponydir not in appendset):
rc.append(ponydir)
@ -188,7 +243,8 @@ class Ponysay():
return [cat(cls.__parseFile(item), file) for item in [
'$XDG_DATA_HOME/ponysay/',
'$HOME/.local/share/ponysay/',
'/usr/share/ponysay/'
'/usr/share/ponysay/',
'./'
]]
@ -197,7 +253,7 @@ class Ponysay():
'''
Check if ponythink is executed
'''
isthink = sys.argv[0]
let isthink = kuroko.argv[0]
if os.sep in isthink:
isthink = isthink[isthink.rfind(os.sep) + 1:]
if os.extsep in isthink:
@ -217,7 +273,7 @@ class Ponysay():
args.help()
exit(254)
return
self.args = args;
self.args = args
## Emulate termial capabilities
if self.__test_nfdnf('-X'): (self.linuxvt, self.usekms) = (False, False)
@ -229,8 +285,8 @@ class Ponysay():
## Variadic variants of -f, -q &c
for sign in ('-', '+'):
for letter in ('f', 'F', 'q', 'Q'):
ssl = sign + sign + letter
sl = sign + letter
let ssl = sign + sign + letter
let sl = sign + letter
if (ssl in args.opts) and (args.opts[ssl] is not None):
if args.opts[sl] is not None: args.opts[sl] += args.opts[ssl]
else: args.opts[sl] = args.opts[ssl]
@ -343,11 +399,11 @@ class Ponysay():
if args.opts[key] is not None:
return False
return True
keys = ['-f', '+f', '-F', '-q'] ## TODO +q -Q
let keys = ['-f', '+f', '-F', '-q'] ## TODO +q -Q
if test(keys, False):
for ponydir in self.ponydirs:
if os.path.isfile(ponydir + 'best.pony') or os.path.islink(ponydir + 'best.pony'):
pony = os.path.realpath(ponydir + 'best.pony') # Canonical path
let pony = os.path.realpath(ponydir + 'best.pony') # Canonical path
if test(keys, True):
args.opts['-f'] = [pony]
else:
@ -364,8 +420,8 @@ class Ponysay():
@param args:ArgParser Parsed command line arguments
'''
## Read UCS configurations
env_ucs = os.environ['PONYSAY_UCS_ME'] if 'PONYSAY_UCS_ME' in os.environ else ''
ucs_conf = 0
let env_ucs = os.environ['PONYSAY_UCS_ME'] if 'PONYSAY_UCS_ME' in os.environ else ''
let ucs_conf = 0
if env_ucs in ('yes', 'y', '1'): ucs_conf = 1
elif env_ucs in ('harder', 'h', '2'): ucs_conf = 2
@ -410,8 +466,8 @@ class Ponysay():
@param links:map<str, str>? Map to fill with simulated symlink ponies, may be `None`
'''
## Read UCS configurations
env_ucs = os.environ['PONYSAY_UCS_ME'] if 'PONYSAY_UCS_ME' in os.environ else ''
ucs_conf = 0
let env_ucs = os.environ['PONYSAY_UCS_ME'] if 'PONYSAY_UCS_ME' in os.environ else ''
let ucs_conf = 0
if env_ucs in ('yes', 'y', '1'): ucs_conf = 1
elif env_ucs in ('harder', 'h', '2'): ucs_conf = 2
@ -420,20 +476,20 @@ class Ponysay():
return
## Read all lines in all UCS → ASCII map files
maplines = []
let maplines = []
for ucsmap in self.ucsmaps:
if os.path.isfile(ucsmap):
with open(ucsmap, 'rb') as mapfile:
maplines += [line.replace('\n', '') for line in mapfile.read().decode('utf8', 'replace').split('\n')]
## Create UCS → ASCII mapping from read lines
map = {}
stripset = ' \t' # must be string, wtf! and way doesn't python's doc say so
let map = {}
let stripset = ' \t' # must be string, wtf! and way doesn't python's doc say so
for line in maplines:
if not line.startswith('#'):
s = line.index('→')
ucs = line[:s] .strip(stripset)
ascii = line[s + 1:].strip(stripset)
let s = line.index('→')
let ucs = line[:s] .strip(stripset)
let ascii = line[s + 1:].strip(stripset)
map[ascii] = ucs
## Apply UCS → ASCII mapping to ponies, by alias if weak settings
@ -466,31 +522,31 @@ class Ponysay():
selection = [self.__selectAnypony(args)]
## Select a random pony of the choosen ones
pony = selection[random.randrange(0, len(selection))]
let pony = selection[random.randrange(0, len(selection))]
if os.path.exists(pony[0]):
ponyname = pony[0].split(os.sep)[-1]
let ponyname = pony[0].split(os.sep)[-1]
if os.extsep in ponyname:
ponyname = ponyname[:ponyname.rfind(os.extsep)]
return (pony[0], self.__getQuote(ponyname, pony[0]) if pony[2] else None)
else:
possibilities = [f.split(os.sep)[-1][:-5] for f in pony[1]]
let possibilities = [f.split(os.sep)[-1][:-5] for f in pony[1]]
if pony[0] not in possibilities:
if not alt:
autocorrect = SpelloCorrecter(possibilities)
(alternatives, dist) = autocorrect.correct(pony[0])
limit = os.environ['PONYSAY_TYPO_LIMIT'] if 'PONYSAY_TYPO_LIMIT' in os.environ else ''
let autocorrect = SpelloCorrecter(possibilities)
let alternatives, dist = autocorrect.correct(pony[0])
let limit = os.environ['PONYSAY_TYPO_LIMIT'] if 'PONYSAY_TYPO_LIMIT' in os.environ else ''
limit = 5 if len(limit) == 0 else int(limit)
if (len(alternatives) > 0) and (dist <= limit):
(_, files, quote) = pony
let _, files, quote = pony
return self.__getPony([(a, files, quote) for a in alternatives], True)
printerr('I have never heard of anypony named %s' % pony[0]);
printerr('I have never heard of anypony named %s' % pony[0])
if not self.usingstandard:
printerr('Use -f/-q or -F if it a MLP:FiM pony');
printerr('Use -f/-q or -F if it a MLP:FiM pony')
if not self.usingextra:
printerr('Have you tested +f or -F?');
printerr('Have you tested +f or -F?')
exit(252)
else:
file = pony[1][possibilities.index(pony[0])]
let file = pony[1][possibilities.index(pony[0])]
return (file, self.__getQuote(pony[0], file) if pony[2] else None)
@ -501,30 +557,30 @@ class Ponysay():
@param args:ArgParser Parsed command line arguments
@return (name, dirfile, quote):(str, list<str>, bool) The pony name, pony file with the directory, and whether to use ponyquotes
'''
quote = args.opts['-q'] is not None ## TODO +q -Q
standard = (args.opts['-f'] is not None) or (args.opts['-F'] is not None) or (args.opts['-q'] is not None) ## TODO -Q
extra = (args.opts['+f'] is not None) or (args.opts['-F'] is not None) ## TODO +q -Q
let quote = args.opts['-q'] is not None ## TODO +q -Q
let standard = (args.opts['-f'] is not None) or (args.opts['-F'] is not None) or (args.opts['-q'] is not None) ## TODO -Q
let extra = (args.opts['+f'] is not None) or (args.opts['-F'] is not None) ## TODO +q -Q
if not (standard or extra):
standard = True
ponydirs = (self.ponydirs if standard else []) + (self.extraponydirs if extra else []);
quoters = self.__quoters() if standard and quote else None ## TODO +q -Q
let ponydirs = (self.ponydirs if standard else []) + (self.extraponydirs if extra else [])
let quoters = self.__quoters() if standard and quote else None ## TODO +q -Q
if (quoters is not None) and (len(quoters) == 0):
printerr('Princess Celestia! All the ponies are mute!')
exit(250)
## Get all ponies, with quotes
oldponies = {}
let oldponies = {}
self.__getAllPonies(standard, extra, oldponies, quoters)
## Apply restriction
ponies = self.__applyRestriction(oldponies, ponydirs)
let ponies = self.__applyRestriction(oldponies, ponydirs)
## Select one pony and set all information
names = list(ponies.keys())
let names = list(ponies.keys())
if len(names) == 0:
printerr('All the ponies are missing, call the Princess!')
exit(249)
pony = names[random.randrange(0, len(names))]
let pony = names[random.randrange(0, len(names))]
return (pony, [ponies[pony]], quote)
@ -554,7 +610,7 @@ class Ponysay():
for ponydir in directories:
for ponyfile in os.listdir(ponydir):
if endswith(ponyfile, '.pony'):
pony = ponyfile[:-5]
let pony = ponyfile[:-5]
if (pony not in collection) and ((quoters is None) or (pony in quoters)):
collection[pony] = ponydir + ponyfile
@ -575,7 +631,7 @@ class Ponysay():
oldponies = ponies
## Apply dimension restriction
ponies = {}
let ponies = {}
self.__applyDimensionRestriction(ponies, oldponies, ponydirs)
if len(ponies) > 0:
oldponies = ponies
@ -606,9 +662,9 @@ class Ponysay():
@param oldponies:dict<str, str> Collection of original ponies, maps to pony file
@param ponydirs:list<sr> List of pony directories
'''
(termh, termw) = gettermsize()
let termh, termw = gettermsize()
for ponydir in ponydirs:
(fitw, fith) = (None, None)
let fitw, fith = (None, None)
if os.path.exists(ponydir + 'widths'):
fitw = set()
with open(ponydir + 'widths', 'rb') as file:
@ -619,7 +675,7 @@ class Ponysay():
Metadata.getFitting(fith, termh, file)
for ponyfile in oldponies.values():
if ponyfile.startswith(ponydir):
pony = ponyfile[len(ponydir) : -5]
let pony = ponyfile[len(ponydir) : -5]
if (fitw is None) or (pony in fitw):
if (fith is None) or (pony in fith):
ponies[pony] = ponyfile
@ -663,9 +719,9 @@ class Ponysay():
if quotedirs is None: quotedirs = self.quotedirs
## List all unique quote files
quotes = []
quoteshash = set()
_quotes = []
let quotes = []
let quoteshash = set()
let _quotes = []
for quotedir in quotedirs:
_quotes += [item[:item.index('.')] for item in os.listdir(quotedir)]
for quote in _quotes:
@ -675,11 +731,11 @@ class Ponysay():
quotes.append(quote)
## Create a set of all ponies that have quotes
ponies = set()
let ponies = set()
for ponydir in ponydirs:
for pony in os.listdir(ponydir):
if not pony[0] == '.':
p = pony[:-5] # remove .pony
let p = pony[:-5] # remove .pony
for quote in quotes:
if ('+' + p + '+') in ('+' + quote + '+'):
if not p in ponies:
@ -760,8 +816,7 @@ class Ponysay():
@param standard:bool Include standard ponies
@param extra:bool Include extra ponies
'''
pony_dirs = (self.ponydirs if standard else []) + (self.extraponydirs if extra else [])
let pony_dirs = (self.ponydirs if standard else []) + (self.extraponydirs if extra else [])
lists.onelist(pony_dirs, self.__ucsise)
@ -774,7 +829,7 @@ class Ponysay():
@param extra:bool Include extra ponies
'''
## Get all quoters
ponies = list(self.__quoters()) if standard else []
let ponies = list(self.__quoters()) if standard else []
## And now the extra ponies
if extra:
@ -818,10 +873,10 @@ class Ponysay():
return None
## Get all balloons
balloons = {}
let balloons = {}
for balloondir in self.balloondirs:
for balloon in os.listdir(balloondir):
balloonfile = balloon
let balloonfile = balloon
## Use .think if running ponythink, otherwise .say
if self.isthink and endswith(balloon, '.think'):
balloon = balloon[:-6]
@ -840,12 +895,12 @@ class Ponysay():
balloons[name] = name
## Select a random balloon of the choosen ones
balloon = names[random.randrange(0, len(names))]
let balloon = names[random.randrange(0, len(names))]
if balloon not in balloons:
if not alt:
autocorrect = SpelloCorrecter(self.balloondirs, '.think' if self.isthink else '.say')
(alternatives, dist) = autocorrect.correct(balloon)
limit = os.environ['PONYSAY_TYPO_LIMIT'] if 'PONYSAY_TYPO_LIMIT' in os.environ else ''
let autocorrect = SpelloCorrecter(self.balloondirs, '.think' if self.isthink else '.say')
let alternatives, dist = autocorrect.correct(balloon)
let limit = os.environ['PONYSAY_TYPO_LIMIT'] if 'PONYSAY_TYPO_LIMIT' in os.environ else ''
limit = 5 if len(limit) == 0 else int(limit)
if (len(alternatives) > 0) and (dist <= limit):
return self.__getBalloonPath(alternatives, True)
@ -885,12 +940,12 @@ class Ponysay():
@param args:ArgParser Parsed command line arguments
'''
## Get the pony
selection = []
let selection = []
self.__getSelectedPonies(args, selection)
(pony, quote) = self.__getPony(selection, args)
let pony, quote = self.__getPony(selection, args)
## Get message and manipulate it
msg = self.__getMessage(args, quote)
let msg = self.__getMessage(args, quote)
msg = self.__colouriseMessage(args, msg)
msg = self.__compressMessage(args, msg)
@ -901,38 +956,38 @@ class Ponysay():
pony = self.__useImage(pony)
## If KMS is utilies, select a KMS pony file and create it if necessary
pony = KMS.kms(pony, self.HOME, self.linuxvt)
#pony = KMS.kms(pony, self.HOME, self.linuxvt)
## If in Linux VT clean the terminal (See info/pdf-manual [Printing in TTY with KMS])
if self.linuxvt:
print('\033[H\033[2J', end='')
## Get width truncation and wrapping
widthtruncation = self.__getWidthTruncation()
messagewrap = self.__getMessageWrap(args)
let widthtruncation = self.__getWidthTruncation()
let messagewrap = self.__getMessageWrap(args)
## Get balloon object
balloonfile = self.__getBalloonPath(args.opts['-b'] if args.opts['-b'] is not None else None)
let balloonfile = self.__getBalloonPath(args.opts['-b'] if args.opts['-b'] is not None else None)
printinfo('balloon style file: ' + str(balloonfile))
balloon = self.__getBalloon(balloonfile) if args.opts['-o'] is None else None
let balloon = self.__getBalloon(balloonfile) if args.opts['-o'] is None else None
## Get hyphen style
hyphen = self.__getHyphen(args)
let hyphen = self.__getHyphen(args)
## Link and balloon colouring
linkcolour = self.__getLinkColour(args)
ballooncolour = self.__getBalloonColour(args)
let linkcolour = self.__getLinkColour(args)
let ballooncolour = self.__getBalloonColour(args)
## Determine --info/++info settings
minusinfo = args.opts['-i'] is not None
plusinfo = args.opts['+i'] is not None
let minusinfo = args.opts['-i'] is not None
let plusinfo = args.opts['+i'] is not None
## Run cowsay replacement
backend = Backend(message = msg, ponyfile = pony, wrapcolumn = messagewrap, width = widthtruncation, balloon = balloon,
let backend = Backend(message = msg, ponyfile = pony, wrapcolumn = messagewrap, width = widthtruncation, balloon = balloon,
hyphen = hyphen, linkcolour = linkcolour, ballooncolour = ballooncolour, mode = self.mode,
infolevel = 2 if plusinfo else (1 if minusinfo else 0))
backend.parse()
output = backend.output
let output = backend.output
if output.endswith('\n'):
output = output[:-1]
@ -947,7 +1002,7 @@ class Ponysay():
@param args:ArgParser Command line options
@param selection:list<(name:str, file:str, quotes:bool)> List to fill with tuples of selected pony names, pony files and whether quotes are used
'''
(standard, extra) = ([], [])
let standard, extra = [], []
for ponydir in self.ponydirs:
for pony in os.listdir(ponydir):
if endswith(pony, '.pony'):
@ -956,8 +1011,8 @@ class Ponysay():
for pony in os.listdir(ponydir):
if endswith(pony, '.pony'):
extra.append(ponydir + pony)
both = standard + extra
for (opt, ponies, quotes) in [('-f', standard, False), ('+f', extra, False), ('-F', both, False), ('-q', standard, True)]: ## TODO +q -Q
let both = standard + extra
for opt, ponies, quotes in [('-f', standard, False), ('+f', extra, False), ('-F', both, False), ('-q', standard, True)]: ## TODO +q -Q
if args.opts[opt] is not None:
for pony in args.opts[opt]:
selection.append((pony, ponies, quotes))
@ -974,7 +1029,7 @@ class Ponysay():
if quote is not None:
return quote
if args.message is None:
return ''.join(sys.stdin.readlines()).rstrip()
return ''.join(fileio.stdin.readlines()).rstrip()
return args.message
@ -1044,7 +1099,7 @@ class Ponysay():
@return :int? The column the truncate the output at, or `None` to not truncate it
'''
env_width = os.environ['PONYSAY_FULL_WIDTH'] if 'PONYSAY_FULL_WIDTH' in os.environ else None
let env_width = os.environ['PONYSAY_FULL_WIDTH'] if 'PONYSAY_FULL_WIDTH' in os.environ else None
if env_width is None: env_width = 'auto'
return gettermsize()[1] if env_width not in ('yes', 'y', '1') else None
@ -1056,7 +1111,7 @@ class Ponysay():
@param args:ArgParser Command line options
@return :int? The message balloon wrapping column, or `None` if disabled
'''
messagewrap = 65
let messagewrap = 65
if (args.opts['-W'] is not None) and (len(args.opts['-W'][0]) > 0):
messagewrap = args.opts['-W'][0]
if messagewrap[0] in 'nmsNMS': # m is left to n on QWERTY and s is left to n on Dvorak
@ -1075,10 +1130,10 @@ class Ponysay():
@param args:ArgParser Command line options
@return :str The hyphen string to use at hyphenation
'''
hyphen = os.environ['PONYSAY_WRAP_HYPHEN'] if 'PONYSAY_WRAP_HYPHEN' in os.environ else None
let hyphen = os.environ['PONYSAY_WRAP_HYPHEN'] if 'PONYSAY_WRAP_HYPHEN' in os.environ else None
if (hyphen is None) or (len(hyphen) == 0):
hyphen = '-'
hyphencolour = ''
let hyphencolour = ''
if args.opts['--colour-wrap'] is not None:
hyphencolour = '\033[' + ';'.join(args.opts['--colour-wrap']) + 'm'
return '\033[31m' + hyphencolour + hyphen
@ -1091,7 +1146,7 @@ class Ponysay():
@param args:ArgParser Command line options
@return :str The colour of balloon links
'''
linkcolour = ''
let linkcolour = ''
if args.opts['--colour-link'] is not None:
linkcolour = '\033[' + ';'.join(args.opts['--colour-link']) + 'm'
return linkcolour
@ -1104,7 +1159,7 @@ class Ponysay():
@param args:ArgParser Command line options
@return :str The colour of balloons
'''
ballooncolour = ''
let ballooncolour = ''
if args.opts['--colour-bubble'] is not None:
ballooncolour = '\033[' + ';'.join(args.opts['--colour-bubble']) + 'm'
return ballooncolour
@ -1117,17 +1172,17 @@ class Ponysay():
@param output:str The output truncated on the width but not on the height
'''
## Load height trunction settings
env_bottom = os.environ['PONYSAY_BOTTOM'] if 'PONYSAY_BOTTOM' in os.environ else None
let env_bottom = os.environ['PONYSAY_BOTTOM'] if 'PONYSAY_BOTTOM' in os.environ else None
if env_bottom is None: env_bottom = ''
env_height = os.environ['PONYSAY_TRUNCATE_HEIGHT'] if 'PONYSAY_TRUNCATE_HEIGHT' in os.environ else None
let env_height = os.environ['PONYSAY_TRUNCATE_HEIGHT'] if 'PONYSAY_TRUNCATE_HEIGHT' in os.environ else None
if env_height is None: env_height = ''
env_lines = os.environ['PONYSAY_SHELL_LINES'] if 'PONYSAY_SHELL_LINES' in os.environ else None
let env_lines = os.environ['PONYSAY_SHELL_LINES'] if 'PONYSAY_SHELL_LINES' in os.environ else None
if (env_lines is None) or (env_lines == ''): env_lines = '2'
## Print the output, truncated on height if so set
lines = gettermsize()[0] - int(env_lines)
let lines = gettermsize()[0] - int(env_lines)
if self.linuxvt or (env_height in ('yes', 'y', '1')):
if env_bottom in ('yes', 'y', '1'):
for line in output.split('\n')[: -lines]:

View file

@ -31,15 +31,16 @@ the colon.
'''
import os
import sys
from subprocess import Popen, PIPE
import kuroko
import fileio
from argparser import *
from ponysay import *
from metadata import *
from ponysay.argparser import ArgParser
from ponysay.ponysay import Ponysay
from ponysay.metadata import Metadata
VERSION = 'dev' # this line should not be edited, it is fixed by the build system
let VERSION = 'dev' # this line should not be edited, it is fixed by the build system
'''
The version of ponysay
'''
@ -54,7 +55,7 @@ def print(text = '', end = '\n'):
@param text:str The text to print (empty string is default)
@param end:str The appendix to the text to print (line breaking is default)
'''
sys.stdout.buffer.write((str(text) + end).encode('utf-8'))
fileio.stdout.buffer.write((str(text) + end).encode('utf-8'))
def printerr(text = '', end = '\n'):
'''
@ -63,7 +64,7 @@ def printerr(text = '', end = '\n'):
@param text:str The text to print (empty string is default)
@param end:str The appendix to the text to print (line breaking is default)
'''
sys.stderr.buffer.write((str(text) + end).encode('utf-8'))
fileio.stderr.buffer.write((str(text) + end).encode('utf-8'))
@ -80,7 +81,7 @@ class PonysayTool():
'''
if args.argcount == 0:
args.help()
exit(255)
os.exit(255)
return
opts = args.opts
@ -88,7 +89,7 @@ class PonysayTool():
if unrecognised or (opts['-h'] is not None) or (opts['+h'] is not None):
args.help(True if opts['+h'] is not None else None)
if unrecognised:
exit(254)
os.exit(254)
elif opts['-v'] is not None:
print('%s %s' % ('ponysay-tool', VERSION))
@ -105,33 +106,33 @@ class PonysayTool():
elif (opts['-b'] is not None) and (len(opts['-b']) == 1):
try:
if opts['--no-term-init'] is None:
print('\033[?1049h', end='') # initialise terminal
print('\[[?1049h', end='') # initialise terminal
cmd = 'stty %s < %s > /dev/null 2> /dev/null'
cmd %= ('-echo -icanon -echo -isig -ixoff -ixon', os.path.realpath('/dev/stdout'))
Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE).wait()
print('\033[?25l', end='') # hide cursor
print('\[[?25l', end='') # hide cursor
dir = opts['-b'][0]
if not dir.endswith(os.sep):
dir += os.sep
self.browse(dir, opts['-r'])
finally:
print('\033[?25h', end='') # show cursor
print('\[[?25h', end='') # show cursor
cmd = 'stty %s < %s > /dev/null 2> /dev/null'
cmd %= ('echo icanon echo isig ixoff ixon', os.path.realpath('/dev/stdout'))
Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE).wait()
if opts['--no-term-init'] is None:
print('\033[?1049l', end='') # terminate terminal
print('\[[?1049l', end='') # terminate terminal
elif (opts['--edit'] is not None) and (len(opts['--edit']) == 1):
pony = opts['--edit'][0]
if not os.path.isfile(pony):
printerr('%s is not an existing regular file' % pony)
exit(252)
os.exit(252)
linuxvt = ('TERM' in os.environ) and (os.environ['TERM'] == 'linux')
try:
if opts['--no-term-init'] is None:
print('\033[?1049h', end='') # initialise terminal
if linuxvt: print('\033[?8c', end='') # use full block for cursor (_ is used by default in linux vt)
print('\[[?1049h', end='') # initialise terminal
if linuxvt: print('\[[?8c', end='') # use full block for cursor (_ is used by default in linux vt)
cmd = 'stty %s < %s > /dev/null 2> /dev/null'
cmd %= ('-echo -icanon -echo -isig -ixoff -ixon', os.path.realpath('/dev/stdout'))
Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE).wait()
@ -140,9 +141,9 @@ class PonysayTool():
cmd = 'stty %s < %s > /dev/null 2> /dev/null'
cmd %= ('echo icanon echo isig ixoff ixon', os.path.realpath('/dev/stdout'))
Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE).wait()
if linuxvt: print('\033[?0c', end='') # restore cursor
if linuxvt: print('\[[?0c', end='') # restore cursor
if opts['--no-term-init'] is None:
print('\033[?1049l', end='') # terminate terminal
print('\[[?1049l', end='') # terminate terminal
elif (opts['--edit-rm'] is not None) and (len(opts['--edit-rm']) == 1):
ponyfile = opts['--edit-rm'][0]
@ -174,7 +175,7 @@ class PonysayTool():
if data == '':
if line != '$$$':
printerr('Bad stash')
exit(251)
os.exit(251)
data += '$$$\n'
else:
data += line + '\n'
@ -192,7 +193,7 @@ class PonysayTool():
else:
args.help()
exit(253)
os.exit(253)
def execPonysay(self, args, message = ''):
@ -214,9 +215,9 @@ class PonysayTool():
return args[key] if (args[key] is not None) and isinstance(args[key], list) else [args[key]]
return None
def __contains__(self, key):
return key in args;
return key in args
stdout = sys.stdout
stdout = fileio.stdout
class StringInputStream():
def __init__(self):
self.buf = ''
@ -232,11 +233,11 @@ class PonysayTool():
pass
def isatty(self):
return True
sys.stdout = StringInputStream()
fileio.stdout = StringInputStream()
ponysay = Ponysay()
ponysay.run(PhonyArgParser(args, message))
out = sys.stdout.buf[:-1]
sys.stdout = stdout
out = fileio.stdout.buf[:-1]
fileio.stdout = stdout
return out
@ -249,7 +250,7 @@ class PonysayTool():
'''
## Call `stty` to determine the size of the terminal, this way is better than using python's ncurses
termsize = None
for channel in (sys.stdout, sys.stdin, sys.stderr):
for channel in (fileio.stdout, fileio.stdin, fileio.stderr):
termsize = Popen(['stty', 'size'], stdout=PIPE, stdin=channel, stderr=PIPE).communicate()[0]
if len(termsize) > 0:
termsize = termsize.decode('utf8', 'replace')[:-1].split(' ') # [:-1] removes a \n
@ -275,7 +276,7 @@ class PonysayTool():
ponies.sort()
if len(ponies) == 0:
print('\033[1;31m%s\033[21m;39m' % 'No ponies... press Enter to exit.')
print('\[[1;31m%s\[[22m;39m' % 'No ponies... press Enter to exit.')
input()
panelw = Backend.len(max(ponies, key = Backend.len))
@ -300,14 +301,14 @@ class PonysayTool():
ponyfile = (ponydir + '/' + ponies[ponyindex] + '.pony').replace('//', '/')
pony = self.execPonysay({'-f' : ponyfile, '-W' : 'none', '-o' : None}).split('\n')
preprint = '\033[H\033[2J'
preprint = '\[[H\[[2J'
if pony[0].startswith(preprint):
pony[0] = pony[0][len(preprint):]
ponyheight = len(pony)
ponywidth = Backend.len(max(pony, key = Backend.len))
AUTO_PUSH = '\033[01010~'
AUTO_POP = '\033[10101~'
AUTO_PUSH = '\[[01010~'
AUTO_POP = '\[[10101~'
pony = '\n'.join(pony).replace('\n', AUTO_PUSH + '\n' + AUTO_POP)
colourstack = ColourStack(AUTO_PUSH, AUTO_POP)
buf = ''
@ -317,7 +318,7 @@ class PonysayTool():
if (oldx != x) or (oldy != y):
(oldx, oldy) = (x, y)
print('\033[H\033[2J', end='')
print('\[[H\[[2J', end='')
def getprint(pony, ponywidth, ponyheight, termw, termh, px, py):
ponyprint = pony
@ -338,7 +339,7 @@ class PonysayTool():
elif px > 0:
ponyprint = [px * ' ' + line for line in ponyprint]
ponyprint = [(line if Backend.len(line) <= termw else line[:findcolumn(line, termw)]) for line in ponyprint]
ponyprint = ['\033[21;39;49;0m%s\033[21;39;49;0m' % line for line in ponyprint]
ponyprint = ['\[[22;39;49;0m%s\[[22;39;49;0m' % line for line in ponyprint]
return '\n'.join(ponyprint)
if quotes:
@ -361,24 +362,24 @@ class PonysayTool():
for line in ponies[panely:]:
cury += 1
if os.path.islink((ponydir + '/' + line + '.pony').replace('//', '/')):
line = '\033[34m%s\033[39m' % ((line + ' ' * panelw)[:panelw])
line = '\[[34m%s\[[39m' % ((line + ' ' * panelw)[:panelw])
else:
line = (line + ' ' * panelw)[:panelw]
print('\033[%i;%iH\033[%im%s\033[0m' % (cury, panelx + 1, 1 if panely + cury - 1 == ponyindex else 0, line), end='')
print('\[[%i;%iH\[[%im%s\[[0m' % (cury, panelx + 1, 1 if panely + cury - 1 == ponyindex else 0, line), end='')
elif printpanel >= 0:
for index in (printpanel, ponyindex):
cury = index - panely
if (0 <= cury) and (cury < termh):
line = ponies[cury + panely]
if os.path.islink((ponydir + '/' + line + '.pony').replace('//', '/')):
line = '\033[34m%s\033[39m' % ((line + ' ' * panelw)[:panelw])
line = '\[[34m%s\[[39m' % ((line + ' ' * panelw)[:panelw])
else:
line = (line + ' ' * panelw)[:panelw]
print('\033[%i;%iH\033[%im%s\033[0m' % (cury, panelx + 1, 1 if panely + cury - 1 == ponyindex else 0, line), end='')
print('\[[%i;%iH\[[%im%s\[[0m' % (cury, panelx + 1, 1 if panely + cury - 1 == ponyindex else 0, line), end='')
sys.stdout.buffer.flush()
fileios.stdout.buffer.flush()
if stored is None:
d = sys.stdin.read(1)
d = fileio.stdin.read(1)
else:
d = stored
stored = None
@ -409,20 +410,20 @@ class PonysayTool():
elif ord(d) == ord('Q') - ord('@'):
break
elif ord(d) == ord('X') - ord('@'):
if ord(sys.stdin.read(1)) == ord('C') - ord('@'):
if ord(fileio.stdin.read(1)) == ord('C') - ord('@'):
break
elif d == '\033':
d = sys.stdin.read(1)
elif d == '\[':
d = fileio.stdin.read(1)
if d == '[':
d = sys.stdin.read(1)
d = fileio.stdin.read(1)
if d == 'A': stored = chr(ord('P') - ord('@')) if (not quotes) and (not info) else 'W'
elif d == 'B': stored = chr(ord('N') - ord('@')) if (not quotes) and (not info) else 'S'
elif d == 'C': stored = chr(ord('N') - ord('@')) if (not quotes) and (not info) else 'D'
elif d == 'D': stored = chr(ord('P') - ord('@')) if (not quotes) and (not info) else 'A'
elif d == '1':
if sys.stdin.read(1) == ';':
if sys.stdin.read(1) == '5':
d = sys.stdin.read(1)
if fileio.stdin.read(1) == ';':
if fileio.stdin.read(1) == '5':
d = fileio.stdin.read(1)
if d == 'A': stored = 'W'
elif d == 'B': stored = 'S'
elif d == 'C': stored = 'D'
@ -446,7 +447,7 @@ class PonysayTool():
def __getitem__(self, key):
return [self.value] if key == self.key else None
def __contains__(self, key):
return key == self.key;
return key == self.key
class StringInputStream():
def __init__(self):
@ -464,36 +465,36 @@ class PonysayTool():
def isatty(self):
return True
stdout = sys.stdout
stdout = fileio.stdout
term = os.environ['TERM']
os.environ['TERM'] = 'linux'
sys.stdout = StringInputStream()
fileio.stdout = StringInputStream()
ponysay = Ponysay()
ponysay.run(PhonyArgParser('--onelist', None))
stdponies = sys.stdout.buf[:-1].split('\n')
stdponies = fileio.stdout.buf[:-1].split('\n')
sys.stdout = StringInputStream()
fileio.stdout = StringInputStream()
ponysay = Ponysay()
ponysay.run(PhonyArgParser('++onelist', None))
extraponies = sys.stdout.buf[:-1].split('\n')
extraponies = fileio.stdout.buf[:-1].split('\n')
for pony in stdponies:
printerr('Genering standard kmspony: %s' % pony)
sys.stderr.buffer.flush();
sys.stdout = StringInputStream()
fileio.stderr.buffer.flush()
fileio.stdout = StringInputStream()
ponysay = Ponysay()
ponysay.run(PhonyArgParser('--pony', pony))
for pony in extraponies:
printerr('Genering extra kmspony: %s' % pony)
sys.stderr.buffer.flush();
sys.stdout = StringInputStream()
fileio.stderr.buffer.flush()
fileio.stdout = StringInputStream()
ponysay = Ponysay()
ponysay.run(PhonyArgParser('++pony', pony))
os.environ['TERM'] = term
sys.stdout = stdout
fileio.stdout = stdout
def generateDimensions(self, ponydir, ponies = None):
@ -523,8 +524,8 @@ class PonysayTool():
return [('none' if self.balloon else None)]
return None
def __contains__(self, key):
return key in ('-f', '-W', '-b');
stdout = sys.stdout
return key in ('-f', '-W', '-b')
stdout = fileio.stdout
class StringInputStream():
def __init__(self):
self.buf = ''
@ -540,7 +541,7 @@ class PonysayTool():
pass
def isatty(self):
return True
sys.stdout = StringInputStream()
fileio.stdout = StringInputStream()
ponysay = Ponysay()
ponysay.run(PhonyArgParser(True))
printpony = sys.stdout.buf[:-1].split('\n')
@ -697,7 +698,7 @@ class PonysayTool():
if key == '-W': return ['n']
return None
def __contains__(self, key):
return key in ('-f', '-W');
return key in ('-f', '-W')
data = {}
@ -750,7 +751,7 @@ class PonysayTool():
printpony = sys.stdout.buf[:-1].split('\n')
sys.stdout = stdout
preprint = '\033[H\033[2J'
preprint = '\[[H\[[2J'
if printpony[0].startswith(preprint):
printpony[0] = printpony[0][len(preprint):]
ponyheight = len(printpony) - len(ponyfile.split('\n')) + 1 - 2 # using fallback balloon
@ -765,8 +766,8 @@ class PonysayTool():
termsize = [int(item) for item in termsize]
break
AUTO_PUSH = '\033[01010~'
AUTO_POP = '\033[10101~'
AUTO_PUSH = '\[[01010~'
AUTO_POP = '\[[10101~'
modprintpony = '\n'.join(printpony).replace('\n', AUTO_PUSH + '\n' + AUTO_POP)
colourstack = ColourStack(AUTO_PUSH, AUTO_POP)
buf = ''
@ -774,12 +775,12 @@ class PonysayTool():
buf += c + colourstack.feed(c)
modprintpony = buf.replace(AUTO_PUSH, '').replace(AUTO_POP, '')
printpony = [('\033[21;39;49;0m%s%s\033[21;39;49;0m' % (' ' * (termsize[1] - ponywidth), line)) for line in modprintpony.split('\n')]
printpony = [('\[[22;39;49;0m%s%s\[[22;39;49;0m' % (' ' * (termsize[1] - ponywidth), line)) for line in modprintpony.split('\n')]
print(preprint, end='')
print('\n'.join(printpony), end='')
print('\033[H', end='')
print('\[[H', end='')
print('Please see the info manual for details on how to fill out this form')
print()
@ -885,17 +886,17 @@ class TextArea(): # TODO support small screens (This is being work on in GNU-Po
killptr = None
def status(text):
print('\033[%i;%iH\033[7m%s\033[27m\033[%i;%iH' % (termh - 1, 1, ' (' + text + ') ' + '-' * (termw - len(' (' + text + ') ')), self.top + y, innerleft + x), end='')
print('\[[%i;%iH\[[7m%s\[[27m\[[%i;%iH' % (termh - 1, 1, ' (' + text + ') ' + '-' * (termw - len(' (' + text + ') ')), self.top + y, innerleft + x), end='')
status('unmodified')
print('\033[%i;%iH' % (self.top, innerleft), end='')
print('\[[%i;%iH' % (self.top, innerleft), end='')
def alert(text):
if text is None:
alert('')
else:
print('\033[%i;%iH\033[2K%s\033[%i;%iH' % (termh, 1, text, self.top + y, innerleft + x), end='')
print('\[[%i;%iH\[[2K%s\[[%i;%iH' % (termh, 1, text, self.top + y, innerleft + x), end='')
modified = False
override = False
@ -904,28 +905,28 @@ class TextArea(): # TODO support small screens (This is being work on in GNU-Po
stored = chr(ord('L') - ord('@'))
alerted = False
edited = False
print('\033[%i;%iH' % (self.top + y, innerleft + x), end='')
print('\[[%i;%iH' % (self.top + y, innerleft + x), end='')
while True:
if (oldmark is not None) and (oldmark >= 0):
if oldmark < oldx:
print('\033[%i;%iH\033[49m%s\033[%i;%iH' % (self.top + oldy, innerleft + oldmark, datalines[oldy][oldmark : oldx], self.top + y, innerleft + x), end='')
print('\[[%i;%iH\[[49m%s\[[%i;%iH' % (self.top + oldy, innerleft + oldmark, datalines[oldy][oldmark : oldx], self.top + y, innerleft + x), end='')
elif oldmark > oldx:
print('\033[%i;%iH\033[49m%s\033[%i;%iH' % (self.top + oldy, innerleft + oldx, datalines[oldy][oldx : oldmark], self.top + y, innerleft + x), end='')
print('\[[%i;%iH\[[49m%s\[[%i;%iH' % (self.top + oldy, innerleft + oldx, datalines[oldy][oldx : oldmark], self.top + y, innerleft + x), end='')
if (mark is not None) and (mark >= 0):
if mark < x:
print('\033[%i;%iH\033[44;37m%s\033[49;39m\033[%i;%iH' % (self.top + y, innerleft + mark, datalines[y][mark : x], self.top + y, innerleft + x), end='')
print('\[[%i;%iH\[[44;37m%s\[[49;39m\[[%i;%iH' % (self.top + y, innerleft + mark, datalines[y][mark : x], self.top + y, innerleft + x), end='')
elif mark > x:
print('\033[%i;%iH\033[44;37m%s\033[49;39m\033[%i;%iH' % (self.top + y, innerleft + x, datalines[y][x : mark], self.top + y, innerleft + x), end='')
print('\[[%i;%iH\[[44;37m%s\[[49;39m\[[%i;%iH' % (self.top + y, innerleft + x, datalines[y][x : mark], self.top + y, innerleft + x), end='')
if y != oldy:
if (oldy > 0) and (leftlines[oldy - 1] == leftlines[oldy]) and (leftlines[oldy] == leftlines[-1]):
print('\033[%i;%iH\033[34m%s\033[39m' % (self.top + oldy, self.left, '>'), end='')
print('\[[%i;%iH\[[34m%s\[[39m' % (self.top + oldy, self.left, '>'), end='')
else:
print('\033[%i;%iH\033[34m%s:\033[39m' % (self.top + oldy, self.left, leftlines[oldy]), end='')
print('\[[%i;%iH\[[34m%s:\[[39m' % (self.top + oldy, self.left, leftlines[oldy]), end='')
if (y > 0) and (leftlines[y - 1] == leftlines[y]) and (leftlines[y] == leftlines[-1]):
print('\033[%i;%iH\033[1;34m%s\033[21;39m' % (self.top + y, self.left, '>'), end='')
print('\[[%i;%iH\[[1;34m%s\[[22;39m' % (self.top + y, self.left, '>'), end='')
else:
print('\033[%i;%iH\033[1;34m%s:\033[21;39m' % (self.top + y, self.left, leftlines[y]), end='')
print('\033[%i;%iH' % (self.top + y, innerleft + x), end='')
print('\[[%i;%iH\[[1;34m%s:\[[22;39m' % (self.top + y, self.left, leftlines[y]), end='')
print('\[[%i;%iH' % (self.top + y, innerleft + x), end='')
(oldy, oldx, oldmark) = (y, x, mark)
if edited:
edited = False
@ -980,10 +981,10 @@ class TextArea(): # TODO support small screens (This is being work on in GNU-Po
mark = None
killptr = len(killring) - 1
yanked = killring[killptr]
print('\033[%i;%iH%s' % (self.top + y, innerleft + x, yanked + datalines[y][x:]), end='')
print('\[[%i;%iH%s' % (self.top + y, innerleft + x, yanked + datalines[y][x:]), end='')
datalines[y] = datalines[y][:x] + yanked + datalines[y][x:]
x += len(yanked)
print('\033[%i;%iH' % (self.top + y, innerleft + x), end='')
print('\[[%i;%iH' % (self.top + y, innerleft + x), end='')
elif ord(d) == ord('X') - ord('@'):
alert('C-x')
alerted = True
@ -1034,7 +1035,7 @@ class TextArea(): # TODO support small screens (This is being work on in GNU-Po
datalines[y] = dataline = dataline[:x - removed] + dataline[x:]
x -= removed
mark = None
print('\033[%i;%iH%s%s\033[%i;%iH' % (self.top + y, innerleft, dataline, ' ' * removed, self.top + y, innerleft + x), end='')
print('\[[%i;%iH%s%s\[[%i;%iH' % (self.top + y, innerleft, dataline, ' ' * removed, self.top + y, innerleft + x), end='')
edited = True
elif ord(d) < ord(' '):
if ord(d) == ord('P') - ord('@'):
@ -1055,14 +1056,14 @@ class TextArea(): # TODO support small screens (This is being work on in GNU-Po
elif ord(d) == ord('F') - ord('@'):
if x < len(datalines[y]):
x += 1
print('\033[C', end='')
print('\[[C', end='')
else:
alert('At end')
alerted = True
elif ord(d) == ord('B') - ord('@'):
if x > 0:
x -= 1
print('\033[D', end='')
print('\[[D', end='')
else:
alert('At beginning')
alerted = True
@ -1074,17 +1075,17 @@ class TextArea(): # TODO support small screens (This is being work on in GNU-Po
x = 0
stored = chr(ord('L') - ord('@'))
elif ord(d) == ord('L') - ord('@'):
empty = '\033[0m' + (' ' * self.width + '\n') * len(datalines)
print('\033[%i;%iH%s' % (self.top, self.left, empty), end='')
empty = '\[[0m' + (' ' * self.width + '\n') * len(datalines)
print('\[[%i;%iH%s' % (self.top, self.left, empty), end='')
for row in range(0, len(leftlines)):
leftline = leftlines[row] + ':'
if (leftlines[row - 1] == leftlines[row]) and (leftlines[row] == leftlines[-1]):
leftline = '>'
print('\033[%i;%iH\033[%s34m%s\033[%s39m' % (self.top + row, self.left, '1;' if row == y else '', leftline, '21;' if row == y else ''), end='')
print('\[[%i;%iH\[[%s34m%s\[[%s39m' % (self.top + row, self.left, '1;' if row == y else '', leftline, '22;' if row == y else ''), end='')
for row in range(0, len(datalines)):
print('\033[%i;%iH%s\033[49m' % (self.top + row, innerleft, datalines[row]), end='')
print('\033[%i;%iH' % (self.top + y, innerleft + x), end='')
elif d == '\033':
print('\[[%i;%iH%s\[[49m' % (self.top + row, innerleft, datalines[row]), end='')
print('\[[%i;%iH' % (self.top + y, innerleft + x), end='')
elif d == '\[':
d = sys.stdin.read(1)
if d == '[':
d = sys.stdin.read(1)
@ -1119,7 +1120,7 @@ class TextArea(): # TODO support small screens (This is being work on in GNU-Po
alerted = True
continue
datalines[y] = dataline = dataline[:x] + dataline[x + removed:]
print('\033[%i;%iH%s%s\033[%i;%iH' % (self.top + y, innerleft, dataline, ' ' * removed, self.top + y, innerleft + x), end='')
print('\[[%i;%iH%s%s\[[%i;%iH' % (self.top + y, innerleft, dataline, ' ' * removed, self.top + y, innerleft + x), end='')
mark = None
edited = True
else:
@ -1150,18 +1151,18 @@ class TextArea(): # TODO support small screens (This is being work on in GNU-Po
additional = len(killring[killptr]) - len(yanked)
x += additional
datalines[y] = dataline
print('\033[%i;%iH%s%s\033[%i;%iH' % (self.top + y, innerleft, dataline, ' ' * max(0, -additional), self.top + y, innerleft + x), end='')
print('\[[%i;%iH%s%s\[[%i;%iH' % (self.top + y, innerleft, dataline, ' ' * max(0, -additional), self.top + y, innerleft + x), end='')
else:
stored = chr(ord('Y') - ord('@'))
else:
stored = chr(ord('Y') - ord('@'))
elif d == 'O':
d = sys.stdin.read(1)
d = fileio.stdin.read(1)
if d == 'H':
x = 0
elif d == 'F':
x = len(datalines[y])
print('\033[%i;%iH' % (self.top + y, innerleft + x), end='')
print('\[[%i;%iH' % (self.top + y, innerleft + x), end='')
elif d == '\n':
stored = chr(ord('N') - ord('@'))
else:
@ -1172,7 +1173,7 @@ class TextArea(): # TODO support small screens (This is being work on in GNU-Po
if (not override) or (x == len(dataline)):
print(insert + dataline[x:], end='')
if len(dataline) - x > 0:
print('\033[%iD' % (len(dataline) - x), end='')
print('\[[%iD' % (len(dataline) - x), end='')
datalines[y] = dataline[:x] + insert + dataline[x:]
if (mark is not None) and (mark >= 0):
if mark >= x:
@ -1185,46 +1186,46 @@ class TextArea(): # TODO support small screens (This is being work on in GNU-Po
HOME = os.environ['HOME'] if 'HOME' in os.environ else os.path.expanduser('~')
let HOME = os.environ['HOME'] if 'HOME' in os.environ else os.path.expanduser('~')
'''
The user's home directory
'''
pipelinein = not sys.stdin.isatty()
let pipelinein = not os.isatty(0)
'''
Whether stdin is piped
'''
pipelineout = not sys.stdout.isatty()
let pipelineout = not os.isatty(1)
'''
Whether stdout is piped
'''
pipelineerr = not sys.stderr.isatty()
let pipelineerr = not os.isatty(2)
'''
Whether stderr is piped
'''
usage_program = '\033[34;1mponysay-tool\033[21;39m'
let usage_program = '\[[34;1mponysay-tool\[[22;39m'
usage = '\n'.join(['%s %s' % (usage_program, '(--help | --version | --kms)'),
'%s %s' % (usage_program, '(--edit | --edit-rm) \033[33mPONY-FILE\033[39m'),
'%s %s' % (usage_program, '--edit-stash \033[33mPONY-FILE\033[39m > \033[33mSTASH-FILE\033[39m'),
'%s %s' % (usage_program, '--edit-apply \033[33mPONY-FILE\033[39m < \033[33mSTASH-FILE\033[39m'),
'%s %s' % (usage_program, '(--dimensions | --metadata) \033[33mPONY-DIR\033[39m'),
'%s %s' % (usage_program, '--browse \033[33mPONY-DIR\033[39m [-r \033[33mRESTRICTION\033[39m]*'),
let usage = '\n'.join([' '.join((usage_program, '(--help | --version | --kms)')),
' '.join((usage_program, '(--edit | --edit-rm) \[[33mPONY-FILE\[[39m')),
' '.join((usage_program, '--edit-stash \[[33mPONY-FILE\[[39m > \[[33mSTASH-FILE\[[39m')),
' '.join((usage_program, '--edit-apply \[[33mPONY-FILE\[[39m < \[[33mSTASH-FILE\[[39m')),
' '.join((usage_program, '(--dimensions | --metadata) \[[33mPONY-DIR\[[39m')),
' '.join((usage_program, '--browse \[[33mPONY-DIR\[[39m [-r \[[33mRESTRICTION\[[39m]*')),
])
usage = usage.replace('\033[', '\0')
usage = usage.replace('\[[', 'あ')
for sym in ('[', ']', '(', ')', '|', '...', '*'):
usage = usage.replace(sym, '\033[2m' + sym + '\033[22m')
usage = usage.replace('\0', '\033[')
usage = usage.replace(sym, '\[[2m' + sym + '\[[22m')
usage = usage.replace('あ', '\[[')
'''
Argument parsing
'''
opts = ArgParser(program = 'ponysay-tool',
let opts = ArgParser(program = 'ponysay-tool',
description = 'Tool chest for ponysay',
usage = usage,
longdescription = None)
@ -1244,7 +1245,7 @@ opts.add_argumented( ['--edit-rm'], arg = 'PONY-FILE', help = 'Remove
opts.add_argumented( ['--edit-apply'], arg = 'PONY-FILE', help = 'Apply metadata from stdin to a pony file')
opts.add_argumented( ['--edit-stash'], arg = 'PONY-FILE', help = 'Print applyable metadata from a pony file')
unrecognised = not opts.parse()
let unrecognised = not opts.parse()
'''
Whether at least one unrecognised option was used
'''

View file

@ -29,8 +29,7 @@ that line FREE: yes, is included inside the image between two $$$
lines and the FREE is and upper case and directly followed by
the colon.
'''
from common import *
from ponysay.common import printerr, printinfo, gettermsize, endswith
class SpelloCorrecter(): # Naïvely and quickly ported and adapted from optimised Java, may not be the nicest, or even fast, Python code
@ -74,18 +73,18 @@ class SpelloCorrecter(): # Naïvely and quickly ported and adapted from optimise
for y in range(0, 128):
self.M[y] = [0] * 128
self.M[y][0] = y
m0 = self.M[0]
x = 127
let m0 = self.M[0]
let x = 127
while x > -1:
m0[x] = x
x -= 1
previous = ''
self.dictionary[-1] = previous;
let previous = ''
self.dictionary[-1] = previous
if ending is not None:
for directory in directories:
files = os.listdir(directory)
let files = os.listdir(directory)
files.sort()
for filename in files:
if (not endswith(filename, ending)) or (len(filename) - len(ending) > 127):
@ -108,7 +107,7 @@ class SpelloCorrecter(): # Naïvely and quickly ported and adapted from optimise
previous = proper
self.reusable[self.dictionaryEnd] = prevCommon
else:
files = directories
let files = directories
files.sort()
for proper in files:
if len(proper) > 127:
@ -167,20 +166,20 @@ class SpelloCorrecter(): # Naïvely and quickly ported and adapted from optimise
@param used:str The word to correct, it must satisfy all restrictions
'''
self.closestDistance = 0x7FFFFFFF
previous = self.dictionary[-1]
prevLen = 0
usedLen = len(used)
let previous = self.dictionary[-1]
let prevLen = 0
let usedLen = len(used)
proper = None
prevCommon = 0
let proper = None
let prevCommon = 0
d = len(self.dictionary) - 1
let d = len(self.dictionary) - 1
while d > self.dictionaryEnd:
d -= 1
proper = self.dictionary[d]
if abs(len(proper) - usedLen) <= self.closestDistance:
if previous == self.dictionary[d + 1]:
prevCommon = self.reusable[d];
prevCommon = self.reusable[d]
else:
prevCommon = min(prevLen, len(proper))
for i in range(0, prevCommon):
@ -188,8 +187,8 @@ class SpelloCorrecter(): # Naïvely and quickly ported and adapted from optimise
prevCommon = i
break
skip = min(prevLen, len(proper))
i = prevCommon
let skip = min(prevLen, len(proper))
let i = prevCommon
while i < skip:
for u in range(0, usedLen):
if (used[u] == previous[i]) or (used[u] == proper[i]):
@ -197,13 +196,13 @@ class SpelloCorrecter(): # Naïvely and quickly ported and adapted from optimise
break
i += 1
common = min(skip, min(usedLen, len(proper)))
let common = min(skip, min(usedLen, len(proper)))
for i in range(0, common):
if used[i] != proper[i]:
common = i
break
distance = self.__distance(proper, skip, len(proper), used, common, usedLen)
let distance = self.__distance(proper, skip, len(proper), used, common, usedLen)
if self.closestDistance > distance:
self.closestDistance = distance
@ -211,7 +210,7 @@ class SpelloCorrecter(): # Naïvely and quickly ported and adapted from optimise
elif self.closestDistance == distance:
self.corrections.append(proper)
previous = proper;
previous = proper
if distance >= 0x7FFFFF00:
prevLen = distance & 255
else:

View file

@ -29,7 +29,7 @@ that line FREE: yes, is included inside the image between two $$$
lines and the FREE is and upper case and directly followed by
the colon.
'''
from common import *
from ponysay.common import printerr, printinfo, gettermsize, endswith
@ -46,7 +46,7 @@ class UCS():
@param char:chr The character to test
@return :bool Whether the character is a combining character
'''
o = ord(char)
let o = ord(char)
if (0x0300 <= o) and (o <= 0x036F): return True
if (0x20D0 <= o) and (o <= 0x20FF): return True
if (0x1DC0 <= o) and (o <= 0x1DFF): return True
@ -62,7 +62,7 @@ class UCS():
@param string:str A text to count combining characters in
@return :int The number of combining characters in the string
'''
rc = 0
let rc = 0
for char in string:
if UCS.isCombining(char):
rc += 1