This commit is contained in:
Pablo Lezaeta 2012-10-25 00:57:06 -03:00
commit ed4e30e3f5
7 changed files with 377 additions and 180 deletions

View file

@ -2,6 +2,19 @@ Version 2.9
New extraponies: molestia (Tumblr)
The option -q works like -f and -F, it takes one argument, and may be used multiple
times for more arguments.
The old option -q is renamed to --q.
The options --f and --F has been added.
Weighted distance for autocorrection on pony names and boolean style name is set to 5, rather
than unlimited. Currently this cannot be modified (without editing the source code.)
If file descriptor 3 is definied when ponysay is executed, extra information is printed to it.
Version 2.8
New ponies: airheart, bastionyorsets, gustavelegrand, milkyway, peppermoon, pinkacopter, pinkiefly,

View file

@ -53,8 +53,8 @@ Now every time you open a terminal a pony should give your fortune
### Pony quotes
Running `ponysay -q` will give you a random pony saying one it its quote from MLP:FiM. Add one or more argument after `-q` to sepecify a
set of ponies from which one will be selected randomly.
Running `ponysay -q` will give you a random pony saying one it its quote from MLP:FiM.
Just as with `-`f, `-q` can be used multiple time to to sepecify a set of ponies from which one will be selected randomly.
When running `ponysay -l` or `ponysay -L` the ponies which have quotes will be printed bold or bright (depending on terminal).

View file

@ -23,13 +23,14 @@ ro=0
(hash makeinfo 2>/dev/null) || (bo=1 ; echo 'Missing makeinfo, install texinfo [build optional]')
(hash install-info 2>/dev/null) || (bo=1 ; echo 'Missing install-info, install info [build optional]')
(hash stty 2>/dev/null) || (rr=1 ; echo 'Missing stty, install coreutils [runtime required]')
(hash python 2>/dev/null) || (rr=1 ; echo 'Missing python, install python>=3 [runtime required]')
(hash python 2>/dev/null) || (rr=1 ; echo 'Missing python, install python>=3 [build+runtime required]')
(hash cut 2>/dev/null) && (hash python 2>/dev/null) &&
(test ! $(env python --version 2>&1 | cut -d ' ' -f 2 | cut -d '.' -f 1) = 3) && (
(hash python3 2>/dev/null) ||
(rr=1 ; echo 'Missing python>=3, install python (may be named python3) [runtime required]'))
(rr=1 ; echo 'Missing python>=3, install python (may be named python3) [build+runtime required]'))
(hash stty 2>/dev/null) || (rr=1 ; echo 'Missing stty, install coreutils [runtime required]')
(hash tty2colourfultty 2>/dev/null) || (ro=1 ; echo 'Missing tty2colourfultty, install util-say [runtime optional]')
(hash ponysay2ttyponysay 2>/dev/null) || (ro=1 ; echo 'Missing ponysay2ttyponysay, install util-say [runtime optional]')

View file

@ -76,8 +76,8 @@ multiple times, and one of the will be selected randomly.
.B \-q, \-\-quote [\fIname\fP...]
By using this option, a pony will be printed with quotes from her in My Little Pony:
Friendship is Magic. The pony will be selected randomly, unless at least one pony
is added as an argument after \fI-q\fP. If one or more ponies are added after \fI-q\fP
the pony will be selected randomly from that set of ponies.
is added as an argument to \fI-q\fP. If one or more ponies are added as an argument
to \fI-q\fP the pony will be selected randomly from that set of ponies.
.TP
.B \-W, \-\-wrap \fIcolumn\fP
The screen column where the message should be wrapped.

View file

@ -116,7 +116,7 @@ way over e-mail.
@cindex invoking
@cindex options
@cindex arguments
@pindex ponythink
@pindex @command{ponythink}
The format for running the @command{ponysay} program is:
@ -172,7 +172,7 @@ In versions earlier than version 2.0, the if the pony were a file name it had to
include a `@code{/}'. This is not longer required and any existing pony name
supersedes file names.
@item -F
@item -F PONY
@itemx ++file PONY
@itemx ++pony PONY
@opindex @option{-F}
@ -181,6 +181,54 @@ supersedes file names.
Just as @option{-F}, but it uses extra (non-MLP:FiM) ponies instead of standard
(MLP:FiM) ponies
@item -q PONY
@itemx --quote PONY
@opindex @option{-q}
@opindex @option{--quote}
@cindex quotes
@cindex pony quotes
By using this option, a pony will be printed with quotes from her in My Little Pony:
Friendship is Magic. The pony will be selected randomly, unless at least one pony
is added as an argument to @option{-q}. If one or more ponies are added as an argument
to @option{-q}, the pony will be selected randomly from that set of ponies.
This option requires the extension @command{ponyquotes4ponysay}, which is included
by default since version 1.2.
The argument can be a file name, but only if it ends with @file{.pony}.
@item --f [PONY...]
@itemx --files [PONY...]
@itemx --ponies [PONY...]
@opindex @option{--f}
@opindex @option{--files}
@opindex @option{--ponies}
Variadic variant of @option{-f}, meaning that all arguments added after this one
will parsed as an argument to this option. Additionally, those options are added
to @option{-f}.
@item --F [PONY...]
@itemx ++files [PONY...]
@itemx ++ponies [PONY...]
@opindex @option{--F}
@opindex @option{++files}
@opindex @option{++ponies}
Variadic variant of @option{-F}, meaning that all arguments added after this one
will parsed as an argument to this option. Additionally, those options are added
to @option{-F}.
@item --q [PONY...]
@itemx --quotes [PONY...]
@opindex @option{--q}
@opindex @option{--quotes}
@cindex quotes
@cindex pony quotes
Variadic variant of @option{-q}, meaning that all arguments added after this one
will parsed as an argument to this option. Additionally, those options are added
to @option{-q}.
An important feature of this options, is that you can but it in the end of the
command line, without any argument to get a quote from any pony with a quote.
@item -b STYLE
@itemx --bubble STYLE
@itemx --balloon STYLE
@ -192,19 +240,6 @@ balloon name printed by @option{ponysay -B}. This option can be used multiple
times to specify a set of styles from which one will be selected randomly. If no
balloon style is specified a fallback style will be used.
@item -q [PONY...]
@itemx --quote [PONY...]
@opindex @option{-q}
@opindex @option{--quote}
By using this option, a pony will be printed with quotes from her in My Little Pony:
Friendship is Magic. The pony will be selected randomly, unless at least one pony
is added as an argument after @option{-q}. If one or more ponies are added after
@option{-q}, the pony will be selected randomly from that set of ponies.
This option requires the extension @command{ponyquotes4ponysay}, which is included
by default since version 1.2.
The argument can be a file name, but only if it ends with @file{.pony}.
@item -W COLUMN
@itemx --wrap COLUMN
@opindex @option{-W}
@ -289,7 +324,8 @@ The first list are the MLP:FiM and the second one are non-MLP:FiM.
@opindex @option{-o}
@opindex @option{--pony-only}
@opindex @option{--ponyonly}
Print just the pony, nothing else like the speech balloon.
Print just the pony, nothing else like the speech balloon. Naturally the
@command{ponysay} will not wait for a message from stdin.
@item -X
@itemx --256-colours
@ -376,11 +412,13 @@ this file should be a symbolic link to the pony you want as a default. If it is
a symbolic link, @option{-q} cannot determine which quotes to use.
@node Advanced usage
@chapter Advanced usage of @command{ponysay}.
@cindex advanced usage
@menu
* Extra information:: Displaying extra information.
* Fortune cookies:: Displaying with fortune cookies.
* Ponification:: Ponify your fortune cookies.
* Running on TTY:: Running on TTY (Linux VT).
@ -388,9 +426,28 @@ a symbolic link, @option{-q} cannot determine which quotes to use.
@end menu
@node Extra information
@section Extra information
@cindex file descriptor 3
@cindex extra information
@cindex verbose mode
@pindex @command{tee}
If file descriptor 3 is definied when @command{ponysay} is executed, extra information
is printed to it. The printed information includes the name of the pony file, the name
of the balloon style file, and if definied in the pony file, file meta data and comment.
In most shells, a file descriptor 3 can defined using @command{3> FILE}, and linked to
stderr using @command{3>&2}. For example, you can print the information to @file{~/info}
by running @command{ponysay I\'m just the cutest pony! | 3> ~/info}.
The message is not stored this way, for that you can use @command{tee}. However, if you
use @option{-q} the quote file is printed to file descriptor 3.
@node Fortune cookies
@section Fortune cookies
@pindex fortune
@pindex @command{fortune}
@cindex startup
@cindex on startup
@cindex @file{.bashrc}
@ -410,7 +467,7 @@ described in the previous paragraph every time you open a terminal.
@section Ponification
@cindex ponification
@cindex text ponification
@pindex ponypipe
@pindex @command{ponypipe}
You can ponify messages (i.e. replaces words search as `everyone' with `everypony') by
using @code{fortune | ponypipe} instead of using @command{fortune}. @command{ponypipe}
@ -447,7 +504,7 @@ You should read more about this in @ref{KMS ponies}.
@node Running on screen
@section Running on @command{screen}
@pindex screen
@pindex @command{screen}
@cindex @file{.bashrc}
@cindex @file{~/.bashrc}
@ -667,7 +724,7 @@ run on it.
@node Cowsay
@section Cowsay
@pindex cowsay
@pindex @command{cowsay}
This section describes the limitation of @command{cowsay}, but since version 2.1
@command{cowsay} is no longer used because of it. So none of the following limitations
@ -1951,8 +2008,22 @@ sequences.
@itemize @bullet
@item
New extraponies: @file{molestia} (Tumblr)
@item
The option @option{-q} works like @option{-f} and @option{-F}, it takes one argument, and
may be used multiple times for more arguments.
@item
The old option @option{-q} is renamed to @option{--q}.
@item
The options @option{--f} and @option{--F} has been added.
@item
Weighted distance for autocorrection on pony names and boolean style name is set to 5, rather
than unlimited. Currently this cannot be modified (without editing the source code.)
@item
If file descriptor 3 is definied when @command{ponysay} is executed, extra information is
printed to it.
@end itemize
@heading Version 2.8
@itemize @bullet
@item

View file

@ -47,6 +47,29 @@ programs by default, report them to Princess Celestia so she can banish them to
def print(text = '', end = '\n'):
sys.stdout.buffer.write((str(text) + end).encode('utf-8'))
'''
stderr equivalent to print()
@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)
'''
def printerr(text = '', end = '\n'):
sys.stderr.buffer.write((str(text) + end).encode('utf-8'))
fd3 = None
'''
/proc/self/fd/3 equivalent to print()
@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)
'''
def printinfo(text = '', end = '\n'):
global fd3
if os.path.exists('/proc/self/fd/3'):
if fd3 is None:
fd3 = os.fdopen(3, 'w')
fd3.write(str(text) + end)
'''
Checks whether a text ends with a specific text, but has more
@ -56,7 +79,7 @@ Checks whether a text ends with a specific text, but has more
@return :bool The result of the test
'''
def endswith(text, ending):
return text.endswith(ending) and not (text == ending);
return text.endswith(ending) and not (text == ending)
@ -72,6 +95,7 @@ class Ponysay():
def __init__(self, args):
if (args.argcount == 0) and not pipelinein:
args.help()
exit(254)
return
## Modifyable global variables
@ -82,18 +106,23 @@ class Ponysay():
global extraponydirs
## Emulate termial capabilities
if args.opts['-X'] is not None:
linuxvt = False
usekms = False
elif args.opts['-V'] is not None:
linuxvt = True
usekms = False
elif args.opts['-K'] is not None:
linuxvt = True
usekms = True
if args.opts['-X'] is not None: (linuxvt, usekms) = (False, False)
elif args.opts['-V'] is not None: (linuxvt, usekms) = (True, False)
elif args.opts['-K'] is not None: (linuxvt, usekms) = (True, True)
ponydirs = vtponydirs if linuxvt and not usekms else xponydirs
extraponydirs = extravtponydirs if linuxvt and not usekms else extraxponydirs
## Variadic variants of -f, -F and -q
if args.opts['--f'] is not None:
if args.opts['-f'] is not None: args.opts['-f'] += args.opts['--f']
else: args.opts['-f'] = args.opts['--f']
if args.opts['--F'] is not None:
if args.opts['-F'] is not None: args.opts['-F'] += args.opts['--F']
else: args.opts['-F'] = args.opts['--F']
if args.opts['--q'] is not None:
if args.opts['-q'] is not None: args.opts['-q'] += args.opts['--q']
else: args.opts['-q'] = args.opts['--q']
## Run modes
if args.opts['-h'] is not None: args.help()
elif args.opts['--quoters'] is not None: self.quoters()
@ -124,10 +153,26 @@ class Ponysay():
self.__ucsremap(args)
if args.opts['-o'] is not None:
mode += '$/= $$\\= $'
args.message = ''
## The stuff
if args.opts['-q'] is not None: self.quote(args)
else: self.print_pony(args)
if args.opts['-q'] is not None:
warn = (args.opts['-f'] is not None) or (args.opts['-F'] is not None)
if (len(args.opts['-q']) == 1) and ((args.opts['-q'][0] == '-f') or (args.opts['-q'][0] == '-F')):
warn = True
if args.opts['-q'][0] == '-f':
args.opts['-q'] = args.files
if args.opts['-f'] is not None:
args.opts['-q'] += args.opts['-f']
self.quote(args)
if warn:
printerr('-q cannot be used at the same time as -f or -F.')
elif not unrecognised:
self.print_pony(args)
else:
args.help()
exit(255)
return
##############################################
@ -289,7 +334,7 @@ class Ponysay():
if not alt:
autocorrect = SpelloCorrecter(ponydirs, '.pony')
(alternatives, dist) = autocorrect.correct(pony)
if len(alternatives) > 0:
if (len(alternatives) > 0) and (dist <= 5): # TODO the limit `dist` should be configureable
return self.__getponypath(alternatives, True)
sys.stderr.write('I have never heard of anypony named %s\n' % (pony));
exit(1)
@ -362,10 +407,13 @@ class Ponysay():
'''
def __gettermsize(self):
## Call `stty` to determine the size of the terminal, this way is better then using python's ncurses
termsize = Popen(['stty', 'size'], stdout=PIPE, stdin=sys.stderr).communicate()[0]
termsize = termsize.decode('utf8', 'replace')[:-1].split(' ') # [:-1] removes a \n
termsize = [int(item) for item in termsize]
return termsize
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
return (24, 80) # fall back to minimal sane size
@ -642,9 +690,9 @@ class Ponysay():
if balloon not in balloons:
if not alt:
autocorrect = SpelloCorrecter(balloondirs, '.think' if isthink else '.say')
alternatives = autocorrect.correct(balloon)[0]
if len(alternatives) > 0:
return self.__getponypath(alternatives, True)
(alternatives, dist) = autocorrect.correct(balloon)
if (len(alternatives) > 0) and (dist <= 5): # TODO the limit `dist` should be configureable
return self.__getballoonpath(alternatives, True)
sys.stderr.write('That balloon style %s does not exist\n' % (balloon));
exit(1)
else:
@ -661,8 +709,8 @@ class Ponysay():
## Use default balloon if none is specified
if balloonfile is None:
if isthink:
return Balloon('o', 'o', '( ', ' )', [' _'], ['_'], ['_'], ['_'], ['_ '], ' )', ' )', ' )', ['- '], ['-'], ['-'], ['-'], [' -'], '( ', '( ', '( ')
return Balloon('\\', '/', '< ', ' >', [' _'], ['_'], ['_'], ['_'], ['_ '], ' \\', ' |', ' /', ['- '], ['-'], ['-'], ['-'], [' -'], '\\ ', '| ', '/ ')
return Balloon('o', 'o', '( ', ' )', [' _'], ['_'], ['_'], ['_'], ['_ '], ' )', ' )', ' )', ['- '], ['-'], ['-'], ['-'], [' -'], '( ', '( ', '( ')
return Balloon('\\', '/', '< ', ' >', [' _'], ['_'], ['_'], ['_'], ['_ '], ' \\', ' |', ' /', ['- '], ['-'], ['-'], ['-'], [' -'], '\\ ', '| ', '/ ')
## Initialise map for balloon parts
map = {}
@ -671,7 +719,8 @@ class Ponysay():
## Read all lines in the balloon file
with open(balloonfile, 'rb') as balloonstream:
data = [line.replace('\n', '') for line in balloonstream.read().decode('utf8', 'replace').split('\n')]
data = balloonstream.read().decode('utf8', 'replace')
data = [line.replace('\n', '') for line in data.split('\n')]
## Parse the balloon file, and fill the map
last = None
@ -740,6 +789,7 @@ class Ponysay():
## Get the pony
pony = self.__getponypath(args.opts['-f'])
printinfo('pony file: ' + pony)
## Use PNG file as pony file
if endswith(pony.lower(), '.png'):
@ -763,7 +813,9 @@ class Ponysay():
messagewrap = int(args.opts['-W'][0]) if args.opts['-W'] is not None else None
## Get balloon object
balloon = self.__getballoon(self.__getballoonpath(args.opts['-b'])) if args.opts['-o'] is None else None
balloonfile = self.__getballoonpath(args.opts['-b'])
printinfo('balloon style file: ' + str(balloonfile))
balloon = self.__getballoon(balloonfile) if args.opts['-o'] is None else None
## Get hyphen style
hyphencolour = ''
@ -839,6 +891,7 @@ class Ponysay():
## Select a random ponyquote-pair, load it and print it
if not len(pairs) == 0:
pair = pairs[random.randrange(0, len(pairs))]
printinfo('quote file: ' + pair[1])
with open(pair[1], 'rb') as qfile:
args.message = qfile.read().decode('utf8', 'replace').strip()
args.opts['-f'] = [pair[0]]
@ -1067,7 +1120,8 @@ class ArgParser():
'''
Parse arguments
@param args:list<str> The command line arguments, should include the execute file at index 0, `sys.argv` is default
@param args:list<str> The command line arguments, should include the execute file at index 0, `sys.argv` is default
@return :bool Whether no unrecognised option is used
'''
def parse(self, argv = sys.argv):
self.argcount = len(argv) - 1
@ -1083,9 +1137,11 @@ class ArgParser():
tmpdashed = False
get = 0
dontget = 0
self.rc = True
def unrecognised(arg):
sys.stderr.write('%s: warning: unrecognised option %s\n' % (self.__program, arg))
self.rc = False
while len(deque) != 0:
arg = deque[0]
@ -1179,6 +1235,8 @@ class ArgParser():
self.message = ' '.join(self.files) if len(self.files) > 0 else None
return self.rc
'''
Prints a colourful help message
@ -1294,7 +1352,7 @@ class Balloon():
minN = len(max([ne, nne, n, nnw, nw], key = len))
minS = len(max([se, sse, s, ssw, sw], key = len))
self.minwidth = minE + minE
self.minwidth = minE + minE
self.minheight = minN + minS
@ -1326,7 +1384,7 @@ class 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])
if outer + inner >= w:
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:
rc.append(self.nw[j] + self.n[j] * (w - outer) + self.ne[j])
@ -1337,7 +1395,7 @@ class 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])
if outer + inner >= w:
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:
rc.append(self.sw[j] + self.s[j] * (w - outer) + self.se[j])
@ -1365,7 +1423,7 @@ class Backend():
def __init__(self, message, ponyfile, wrapcolumn, width, balloon, hyphen, linkcolour, ballooncolour):
self.message = message
self.ponyfile = ponyfile
self.wrapcolumn = wrapcolumn
self.wrapcolumn = None if wrapcolumn is None else wrapcolumn - balloon.minwidth
self.width = width
self.balloon = balloon
self.hyphen = hyphen
@ -1386,12 +1444,41 @@ class Backend():
'''
def parse(self):
self.__expandMessage()
self.__unpadMessage()
self.__loadFile()
if self.pony.startswith('$$$\n'):
self.pony = self.pony[4:]
infoend = self.pony.index('\n$$$\n')
printinfo(self.pony[:infoend])
self.pony = self.pony[infoend + 5:]
self.pony = mode + self.pony
self.__processPony()
self.__truncate()
'''
Remove padding spaces fortune cookies are padded with whitespace (damn featherbrains)
'''
def __unpadMessage(self):
lines = self.message.split('\n')
for spaces in (8, 4, 2, 1):
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]
while line.startswith(' ' * spaces):
line = line[spaces:]
lines[i] = line
lines = [line.rstrip(' ') for line in lines]
self.message = '\n'.join(lines)
'''
Converts all tabs in the message to spaces by expanding
'''
@ -1475,10 +1562,10 @@ class Backend():
while i < n:
c = self.pony[i]
if c == '\t':
n += 8 - (indent & 7)
ed = ' ' * (7 - (indent & 7))
n += 7 - (indent & 7)
ed = ' ' * (8 - (indent & 7))
c = ' '
self.pony = self.pony[:i] + ed + self.pony[i:]
self.pony = self.pony[:i] + ed + self.pony[i + 1:]
i += 1
if c == '$':
if dollar is not None:
@ -1669,131 +1756,149 @@ class Backend():
@return :str The message wrapped
'''
def __wrapMessage(self, message, wrap):
AUTO_PUSH = '\033[0101y0~'
AUTO_POP = '\033[10101~'
msg = message.replace('\n', AUTO_PUSH + '\n' + AUTO_POP);
cstack = ColourStack(AUTO_PUSH, AUTO_POP)
buf = ''
for c in msg:
buf += c + cstack.feed(c)
lines = buf.replace(AUTO_PUSH, '').replace(AUTO_POP, '').split('\n')
buf = ''
for line in lines:
b = [None] * len(line)
map = {}
(bi, cols, w) = (0, 0, wrap)
(indent, indentc) = (-1, 0)
try:
AUTO_PUSH = '\033[01010~'
AUTO_POP = '\033[10101~'
msg = message.replace('\n', AUTO_PUSH + '\n' + AUTO_POP);
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')
buf = ''
(i, n) = (0, len(line))
while i <= n:
d = None
if i < n:
d = line[i]
i += 1
if d == '\033': # TODO this should use self.__getcolour()
## Invisible stuff
b[bi] = d
bi += 1
b[bi] = line[i]
d = line[i]
bi += 1
for line in lines:
b = [None] * len(line)
map = {0 : 0}
(bi, cols, w) = (0, 0, wrap)
(indent, indentc) = (-1, 0)
(i, n) = (0, len(line))
while i <= n:
d = None
if i < n:
d = line[i]
i += 1
if d == '[':
while True:
b[bi] = line[i]
d = line[i]
bi += 1
i += 1
if (('a' <= d) and (d <= 'z')) or (('A' <= d) and (d <= 'Z')) or (d == '~'):
break
elif d == ']':
if d == '\033': # TODO this should use self.__getcolour()
## Invisible stuff
b[bi] = d
bi += 1
b[bi] = line[i]
d = line[i]
bi += 1
i += 1
if d == 'P':
for j in range(0, 7):
if d == '[':
while True:
b[bi] = line[i]
d = line[i]
bi += 1
i += 1
elif (d is not None) and (d != ' '):
## Fetch word
if indent == -1:
indent = i - 1
for j in range(0, indent):
if line[j] == ' ':
indentc += 1
b[bi] = d
bi += 1
if (not UCS.isCombining(d)) and (d != '­'):
cols += 1
map[cols] = bi
else:
## Wrap?
mm = 0
bisub = 0
iwrap = wrap - (0 if indent == 1 else indentc)
if (('a' <= d) and (d <= 'z')) or (('A' <= d) and (d <= 'Z')) or (d == '~'):
break
elif d == ']':
b[bi] = line[i]
d = line[i]
bi += 1
i += 1
if d == 'P':
for j in range(0, 7):
b[bi] = line[i]
bi += 1
i += 1
elif (d is not None) and (d != ' '):
## Fetch word
if indent == -1:
indent = i - 1
for j in range(0, indent):
if line[j] == ' ':
indentc += 1
b[bi] = d
bi += 1
if (not UCS.isCombining(d)) and (d != '­'):
cols += 1
map[cols] = bi
else:
## Wrap?
mm = 0
bisub = 0
iwrap = wrap - (0 if indent == 1 else indentc)
while ((w > 8) and (cols > w + 5)) or (cols > iwrap): # TODO make configurable
## wrap
x = w;
nbsp = b[map[mm + x]] == ' '
m = map[mm + x]
if ('­' in b[bisub : m]) and not nbsp:
hyphen = m - 1
while b[hyphen] != '­':
hyphen -= 1
while map[mm + x] > hyphen: ## Only looking backward, if foreward is required the word is probabily not hyphenated correctly
x -= 1
x += 1
while ((w > 8) and (cols > w + 5)) or (cols > iwrap): # TODO make configurable
## wrap
x = w;
if mm + x not in map: # Too much whitespace ?
cols = 0
break
nbsp = b[map[mm + x]] == ' '
m = map[mm + x]
mm += x - (0 if nbsp else 1) ## 1 so we have space for a hythen
if ('­' in b[bisub : m]) and not nbsp:
hyphen = m - 1
while b[hyphen] != '­':
hyphen -= 1
while map[mm + x] > hyphen: ## Only looking backward, if foreward is required the word is probabily not hyphenated correctly
x -= 1
x += 1
m = map[mm + x]
for bb in b[bisub : m]:
buf += bb
buf += '\n' if nbsp else '\0\n'
cols -= x - (0 if nbsp else 1)
bisub = m
mm += x - (0 if nbsp else 1) ## 1 so we have space for a hythen
w = iwrap
if indent != -1:
buf += line[:indent]
for bb in b[bisub : m]:
buf += bb
buf += '\n' if nbsp else '\0\n'
cols -= x - (0 if nbsp else 1)
bisub = m
for j in range(bisub, bi):
b[j - bisub] = b[j]
bi -= bisub
w = iwrap
if indent != -1:
buf += line[:indent]
if cols > w:
buf += '\n'
w = wrap
if indent != -1:
buf += line[:indent]
w -= indentc
for bb in b[:bi]:
buf += bb
w -= cols
cols = 0
bi = 0
if d is None:
i += 1
else:
if w > 0:
buf += ' '
w -= 1
else:
for j in range(bisub, bi):
b[j - bisub] = b[j]
bi -= bisub
if cols > w:
buf += '\n'
w = wrap
if indent != -1:
buf + line[:indent]
buf += line[:indent]
w -= indentc
buf += '\n'
for bb in b[:bi]:
buf += bb
w -= cols
cols = 0
bi = 0
if d is None:
i += 1
else:
if w > 0:
buf += ' '
w -= 1
else:
buf += '\n'
w = wrap
if indent != -1:
buf + line[:indent]
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))
return rc
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))
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))
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
'''
@ -1825,7 +1930,7 @@ class ColourStack():
@return :str String that should be inserted into your buffer
'''
def push(self):
self.stack = [[self.bufproto, None, None, [False] * 9]] + self.stack
self.stack.insert(0, [self.bufproto, None, None, [False] * 9])
if len(self.stack) == 1:
return None
return '\033[0m'
@ -1837,9 +1942,10 @@ class ColourStack():
@return :str String that should be inserted into your buffer
'''
def pop(self):
old = self.stack[0]
self.stack = self.stack[1:]
old = self.stack.pop(0)
rc = '\033[0;'
if len(self.stack) == 0: # last resort in case something made it pop too mush
push()
new = self.stack[0]
if new[1] is not None: rc += new[1] + ';'
if new[2] is not None: rc += new[2] + ';'
@ -1984,7 +2090,7 @@ class SpelloCorrecter(): # Naïvely and quickly proted and adapted from optimise
m0[x] = x
x -= 1
previous = ""
previous = ''
self.dictionary[-1] = previous;
for directory in directories:
@ -2270,8 +2376,8 @@ usage_saythink = '\033[34;1m(ponysay | ponythink)\033[21;39m'
usage_common = '[-c] [-W\033[4mCOLUMN\033[24m] [-b\033[4mSTYLE\033[24m]'
usage_listhelp = '(-l | -L | -B | +l | +L | -v | -h)'
usage_file = '[-f\033[4mPONY\033[24m]* [[--] \033[4mmessage\033[24m]'
usage_xfile = '[-F\033[4mPONY\033[24m]* [[--] \033[4mmessage\033[24m]'
usage_quote = '-q [\033[4mPONY\033[24m*]'
usage_xfile = '(-F\033[4mPONY\033[24m)* [[--] \033[4mmessage\033[24m]'
usage_quote = '(-q \033[4mPONY\033[24m)*'
usage = '%s %s\n%s %s %s\n%s %s %s\n%s %s %s' % (usage_saythink, usage_listhelp,
usage_saythink, usage_common, usage_file,
@ -2325,9 +2431,15 @@ opts.add_argumented( ['-W', '--wrap'], arg = 'COLUMN', help =
opts.add_argumented( ['-b', '--bubble', '--balloon'], arg = 'STYLE', help = 'Select a balloon style.')
opts.add_argumented( ['-f', '--file', '--pony'], arg = 'PONY', help = 'Select a pony.\nEither a file name or a pony name.')
opts.add_argumented( ['-F', '++file', '++pony'], arg = 'PONY', help = 'Select a non-MLP:FiM pony.')
opts.add_variadic( ['-q', '--quote'], arg = 'PONY', help = 'Select a ponies which will quote themself.')
opts.add_argumented( ['-q', '--quote'], arg = 'PONY', help = 'Select a pony which will quote herself.')
opts.add_variadic( ['--f', '--files', '--ponies'], arg = 'PONY')
opts.add_variadic( ['--F', '++files', '++ponies'], arg = 'PONY')
opts.add_variadic( ['--q', '--quotes'], arg = 'PONY')
opts.parse()
'''
Whether at least one unrecognised option was used
'''
unrecognised = not opts.parse()