aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG13
-rw-r--r--README.md4
-rw-r--r--balloons/cowsay.say2
-rwxr-xr-xdependency-test.sh7
-rw-r--r--manuals/manpage.04
-rw-r--r--manuals/ponysay.texinfo111
-rwxr-xr-xponysay.py412
7 files changed, 375 insertions, 178 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 68e5281..94c0239 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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,
diff --git a/README.md b/README.md
index 1e4fd52..7681e8a 100644
--- a/README.md
+++ b/README.md
@@ -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).
diff --git a/balloons/cowsay.say b/balloons/cowsay.say
index bb486db..51942fa 100644
--- a/balloons/cowsay.say
+++ b/balloons/cowsay.say
@@ -6,7 +6,7 @@ s:-
w:|
e: |
-ww:<
+ww:<
ee: >
nw: _
diff --git a/dependency-test.sh b/dependency-test.sh
index 3c5301b..ec97d29 100755
--- a/dependency-test.sh
+++ b/dependency-test.sh
@@ -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]')
diff --git a/manuals/manpage.0 b/manuals/manpage.0
index 9627f62..5407e2c 100644
--- a/manuals/manpage.0
+++ b/manuals/manpage.0
@@ -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.
diff --git a/manuals/ponysay.texinfo b/manuals/ponysay.texinfo
index c287457..0d2c68e 100644
--- a/manuals/ponysay.texinfo
+++ b/manuals/ponysay.texinfo
@@ -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
diff --git a/ponysay.py b/ponysay.py
index b7abe7f..de6997a 100755
--- a/ponysay.py
+++ b/ponysay.py
@@ -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 pony–quote-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]
@@ -1178,6 +1234,8 @@ class ArgParser():
break
self.message = ' '.join(self.files) if len(self.files) > 0 else None
+
+ return self.rc
'''
@@ -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,13 +1444,42 @@ 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
'''
def __expandMessage(self):
@@ -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)
-
- 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
+ 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;
+ if mm + x not in map: # Too much whitespace ?
+ cols = 0
+ break
+ 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
+ m = map[mm + x]
+
+ mm += x - (0 if nbsp else 1) ## − 1 so we have space for a hythen
+
+ for bb in b[bisub : m]:
+ buf += bb
+ buf += '\n' if nbsp else '\0\n'
+ cols -= x - (0 if nbsp else 1)
+ bisub = m
+
+ w = iwrap
+ if indent != -1:
+ buf += line[:indent]
- mm += x - (0 if nbsp else 1) ## − 1 so we have space for a hythen
-
- 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]
-
- 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]
- 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:
+ if cols > w:
buf += '\n'
w = wrap
if indent != -1:
- buf + line[:indent]
+ 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
+ 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
+ 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:
@@ -2022,7 +2128,7 @@ class SpelloCorrecter(): # Naïvely and quickly proted and adapted from optimise
# break
# previous = proper
# self.reusable[self.dictionaryEnd] = prevCommon
- # index -= 1;
+ # index -= 1;
'''
@@ -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.parse()
+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')
+
+'''
+Whether at least one unrecognised option was used
+'''
+unrecognised = not opts.parse()