diff --git a/manuals/ponysay.texinfo b/manuals/ponysay.texinfo index 0d8ff159..73e90c0e 100644 --- a/manuals/ponysay.texinfo +++ b/manuals/ponysay.texinfo @@ -261,9 +261,9 @@ If the argument is not a number, but starts instead with @code{n} (for ‘none of the terminal is used. @code{n} and @code{i} is case insensitive, so you may use @code{N} and @code{I} -instead. Additionally, typo correction is for QWERTY and Dvorak is built in to -@command{ponysay}; the nearest key, either to the left or to the right, depending -on which hand is used to press the key, is also allowed. +instead. Additionally, typo correction is for QWERTY (and QWERTZ) and Dvorak is +built in to @command{ponysay}; the nearest key, either to the left or to the +right, depending on which hand is used to press the key, is also allowed. @item -c @itemx --compress @@ -1339,7 +1339,25 @@ without the balloon, respectively, for each pony the the directory. @opindex @option{-r} @opindex @option{--restrict} -TODO... +Running @command{ponysay-tool --browse PONY-DIR}, or @command{ponysay-tool -b PONY-DIR} +will display all ponies in @file{PONY-DIR} for you. You can limit the listed ponies by +using the option @option{--restrict}, or @option{-r}, that works the same was in with +the commands @command{ponysay} and @command{ponythink}. See @ref{Invoking ponysay} for +more infomation about the @option{--restrict} option. + +In this browser you will on the right side have all pony files, in your selected +directory, listed except those that does not match your @option{--restrict} settings. +In the rest of the free space, the pony select in the list is centered. You can move +the pony, in case it is too big, by using the arrows keys with @kbd{control} held down, +or using the @kbd{W}, @kbd{A}, @kbd{S}, @kbd{D} keys (for QWERTY and QWERTZ layout,) +or with the @kbd{<} (or @kbd{Ä}), @kbd{A}, @kbd{O}, @kbd{E} keys (for Dvorak and Svorak +layout.) To recenter the pony press @kbd{C-l} (@kb{dl} with @kbd{control} held down.) + +Browse between ponies using the arrow keys or with @kbd{C-n} and @kbd{C-p}, for next +pony and previous pony, respectivily. Additionally, @kbd{Q} can be used list quotes +for pony, and @kbd{I} for metadata; press the key again to return the pony browsing. + +The tool can be exited using the key combinations @kbd{C-q} or @kbd{C-x C-c}. diff --git a/ponysay-tool.py b/ponysay-tool.py index ead06332..9ba4cc61 100755 --- a/ponysay-tool.py +++ b/ponysay-tool.py @@ -81,6 +81,23 @@ class PonysayTool(): elif (opts['--metadata'] is not None) and (len(opts['--metadata']) == 1): self.generateMetadata(opts['--metadata'][0]) + 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 + 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 + self.browse(opts['-b'][0], opts['-r']) + finally: + print('\033[?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 + elif (opts['--edit'] is not None) and (len(opts['--edit']) == 1): pony = opts['--edit'][0] if not os.path.isfile(pony): @@ -88,18 +105,20 @@ class PonysayTool(): exit(252) linuxvt = ('TERM' in os.environ) and (os.environ['TERM'] == 'linux') try: - print('\033[?1049h', end='') # initialise terminal + 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) cmd = 'stty %s < %s > /dev/null 2> /dev/null' - cmd %= ('-echo -icanon -isig -ixoff -ixon', os.path.realpath('/dev/stdout')) + cmd %= ('-echo -icanon -echo -isig -ixoff -ixon', os.path.realpath('/dev/stdout')) Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE).wait() self.editmeta(pony) finally: cmd = 'stty %s < %s > /dev/null 2> /dev/null' - cmd %= ('echo icanon isig ixoff ixon', os.path.realpath('/dev/stdout')) + 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 - print('\033[?1049l', end='') # terminate terminal + if opts['--no-term-init'] is None: + print('\033[?1049l', end='') # terminate terminal elif (opts['--edit-rm'] is not None) and (len(opts['--edit-rm']) == 1): ponyfile = opts['--edit-rm'][0] @@ -152,6 +171,95 @@ class PonysayTool(): exit(253) + ''' + Browse ponies + + @param ponydir:str The pony directory to browse + @param restriction:list Restrictions on listed ponies, may be None + ''' + def browse(self, ponydir, restriction): + ## 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): + 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] + break + + print('\033[H\033[2J', end='') + + (x, y) = (0, 0) + (oldx, oldy) = (None, None) + (quotes, info) = (False, False) + (ponyindex, oldpony) = (0, None) + + stored = None + while True: + if (ponyindex != oldpony): + oldpony = ponyindex + # TODO load new pony + + if (oldx != x) or (oldy != y): + (oldx, oldy) = (x, y) + # TODO redraw + + sys.stdout.buffer.flush() + if stored is None: + d = sys.stdin.read(1) + else: + d = stored + stored = None + + recenter = False + if (d == 'w') or (d == 'W') or (d == '<') or (d == 'ä') or (d == 'Ä'): # pad ↑ + y -= 1 + elif (d == 's') or (d == 'S') or (d == 'o') or (d == 'O'): # pad ↓ + y += 1 + elif (d == 'd') or (d == 'D') or (d == 'e') or (d == 'E'): # pad → + x += 1 + elif (d == 'a') or (d == 'A'): # pad ← + x -= 1 + elif (d == 'q') or (d == 'Q'): # toggle quotes + quotes = False if info else not quotes + recenter = True + elif (d == 'i') or (d == 'I'): # toggle metadata + info = False if quotes else not info + recenter = True + elif ord(d) == ord('L') - ord('@'): # recenter + recenter = True + elif ord(d) == ord('P') - ord('@'): # previous + ponyindex -= 1 + recenter = True + elif ord(d) == ord('N') - ord('@'): # next + ponyindex += 1 + recenter = True + elif ord(d) == ord('Q') - ord('@'): + break + elif ord(d) == ord('X') - ord('@'): + if ord(sys.stdin.read(1)) == ord('C') - ord('@'): + break + elif d == '\033': + d = sys.stdin.read(1) + if d == '[': + d = sys.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 d == 'A': stored = 'W' + elif d == 'B': stored = 'S' + elif d == 'C': stored = 'D' + elif d == 'D': stored = 'A' + if recenter: + (oldx, oldy) = (None, None) + (x, y) = (0, 0) + + ''' Generate all kmsponies for the current TTY palette ''' @@ -268,7 +376,7 @@ class PonysayTool(): sort(items, key = lambda item : item[0]) for pair in ((widths, 'widths'), (heights, 'heights'), (onlyheights, 'onlyheights')): (items, dimfile) = pair - dimfile = (ponydir + '/' + dimfile).replace('//'. '/') + dimfile = (ponydir + '/' + dimfile).replace('//', '/') ponies = [item[1] for item in items] dims = [] last = -1 @@ -305,7 +413,7 @@ class PonysayTool(): for c in value: if esc: if bracket == 0: - if c not in (',', '\\', '('. ')'): + if c not in (',', '\\', '(', ')'): buf += '\\' buf += c esc = False @@ -449,7 +557,7 @@ class PonysayTool(): ponyheight = len(printpony) - len(ponyfile.split('\n')) + 1 - 2 # using fallback balloon ponywidth = Backend.len(max(printpony, key = Backend.len)) - ## Call `stty` to determine the size of the terminal, this way is better then using python's ncurses + ## 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): termsize = Popen(['stty', 'size'], stdout=PIPE, stdin=channel, stderr=PIPE).communicate()[0] @@ -917,6 +1025,8 @@ if __name__ == '__main__': usage = usage, longdescription = None) + opts.add_argumentless(['--no-term-init']) # for debugging + opts.add_argumentless(['-h', '--help'], help = 'Print this help message.') opts.add_argumentless(['-v', '--version'], help = 'Print the version of the program.') opts.add_argumentless(['--kms'], help = 'Generate all kmsponies for the current TTY palette') diff --git a/ponysay.py b/ponysay.py index ad551432..978f8387 100755 --- a/ponysay.py +++ b/ponysay.py @@ -747,7 +747,7 @@ class Ponysay(): @return (rows, columns):(int, int) The number or lines and the number of columns in the terminal's display area ''' def __gettermsize(self): - ## Call `stty` to determine the size of the terminal, this way is better then using python's ncurses + ## 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: @@ -2217,8 +2217,9 @@ class Backend(): extraleft -= (msgwidth - width) >> 1 if extraleft < 0: extraleft = 0 - if extraleft + msgwidth > wrap: - extraleft -= msgwidth - wrap + if wrap is not None: + if extraleft + msgwidth > wrap: + extraleft -= msgwidth - wrap rc = self.balloon.get(width, height, msg, Backend.len); if extraleft > 0: