mirror of
https://github.com/erkin/ponysay.git
synced 2024-11-22 04:27:58 +01:00
move documentation to be below the declaration and not above, this makes it parsable by python's help command, althought it is not as pretty, but hay, help() is awesome
Signed-off-by: Mattias Andrée <maandree@operamail.com>
This commit is contained in:
parent
a18804002b
commit
ecdac1b6a1
12 changed files with 583 additions and 579 deletions
|
@ -33,35 +33,38 @@ from common import *
|
|||
|
||||
|
||||
|
||||
ARGUMENTLESS = 0
|
||||
'''
|
||||
Option takes no arguments
|
||||
'''
|
||||
ARGUMENTLESS = 0
|
||||
|
||||
ARGUMENTED = 1
|
||||
'''
|
||||
Option takes one argument per instance
|
||||
'''
|
||||
ARGUMENTED = 1
|
||||
|
||||
VARIADIC = 2
|
||||
'''
|
||||
Option consumes all following arguments
|
||||
'''
|
||||
VARIADIC = 2
|
||||
|
||||
'''
|
||||
Simple argument parser
|
||||
'''
|
||||
|
||||
|
||||
class ArgParser():
|
||||
'''
|
||||
Constructor.
|
||||
The short description is printed on same line as the program name
|
||||
|
||||
@param program:str The name of the program
|
||||
@param description:str Short, single-line, description of the program
|
||||
@param usage:str Formated, multi-line, usage text
|
||||
@param longdescription:str Long, multi-line, description of the program, may be `None`
|
||||
Simple argument parser
|
||||
'''
|
||||
|
||||
def __init__(self, program, description, usage, longdescription = None):
|
||||
'''
|
||||
Constructor.
|
||||
The short description is printed on same line as the program name
|
||||
|
||||
@param program:str The name of the program
|
||||
@param description:str Short, single-line, description of the program
|
||||
@param usage:str Formated, multi-line, usage text
|
||||
@param longdescription:str Long, multi-line, description of the program, may be `None`
|
||||
'''
|
||||
self.linuxvt = ('TERM' in os.environ) and (os.environ['TERM'] == 'linux')
|
||||
self.__program = program
|
||||
self.__description = description
|
||||
|
@ -72,41 +75,41 @@ class ArgParser():
|
|||
self.optmap = {}
|
||||
|
||||
|
||||
'''
|
||||
Add option that takes no arguments
|
||||
|
||||
@param alternatives:list<str> Option names
|
||||
@param help:str Short description, use `None` to hide the option
|
||||
'''
|
||||
def add_argumentless(self, alternatives, help = None):
|
||||
'''
|
||||
Add option that takes no arguments
|
||||
|
||||
@param alternatives:list<str> Option names
|
||||
@param help:str Short description, use `None` to hide the option
|
||||
'''
|
||||
self.__arguments.append((ARGUMENTLESS, alternatives, None, help))
|
||||
stdalt = alternatives[0]
|
||||
self.opts[stdalt] = None
|
||||
for alt in alternatives:
|
||||
self.optmap[alt] = (stdalt, ARGUMENTLESS)
|
||||
|
||||
'''
|
||||
Add option that takes one argument
|
||||
|
||||
@param alternatives:list<str> Option names
|
||||
@param arg:str The name of the takes argument, one word
|
||||
@param help:str Short description, use `None` to hide the option
|
||||
'''
|
||||
def add_argumented(self, alternatives, arg, help = None):
|
||||
'''
|
||||
Add option that takes one argument
|
||||
|
||||
@param alternatives:list<str> Option names
|
||||
@param arg:str The name of the takes argument, one word
|
||||
@param help:str Short description, use `None` to hide the option
|
||||
'''
|
||||
self.__arguments.append((ARGUMENTED, alternatives, arg, help))
|
||||
stdalt = alternatives[0]
|
||||
self.opts[stdalt] = None
|
||||
for alt in alternatives:
|
||||
self.optmap[alt] = (stdalt, ARGUMENTED)
|
||||
|
||||
'''
|
||||
Add option that takes all following argument
|
||||
|
||||
@param alternatives:list<str> Option names
|
||||
@param arg:str The name of the takes arguments, one word
|
||||
@param help:str Short description, use `None` to hide the option
|
||||
'''
|
||||
def add_variadic(self, alternatives, arg, help = None):
|
||||
'''
|
||||
Add option that takes all following argument
|
||||
|
||||
@param alternatives:list<str> Option names
|
||||
@param arg:str The name of the takes arguments, one word
|
||||
@param help:str Short description, use `None` to hide the option
|
||||
'''
|
||||
self.__arguments.append((VARIADIC, alternatives, arg, help))
|
||||
stdalt = alternatives[0]
|
||||
self.opts[stdalt] = None
|
||||
|
@ -114,13 +117,13 @@ class ArgParser():
|
|||
self.optmap[alt] = (stdalt, VARIADIC)
|
||||
|
||||
|
||||
'''
|
||||
Parse arguments
|
||||
|
||||
@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):
|
||||
'''
|
||||
Parse arguments
|
||||
|
||||
@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
|
||||
'''
|
||||
self.argcount = len(argv) - 1
|
||||
self.files = []
|
||||
|
||||
|
@ -242,10 +245,10 @@ class ArgParser():
|
|||
return self.rc
|
||||
|
||||
|
||||
'''
|
||||
Prints a colourful help message
|
||||
'''
|
||||
def help(self):
|
||||
'''
|
||||
Prints a colourful help message
|
||||
'''
|
||||
print('\033[1m%s\033[21m %s %s' % (self.__program, '-' if self.linuxvt else '—', self.__description))
|
||||
print()
|
||||
if self.__longdescription is not None:
|
||||
|
|
151
src/backend.py
151
src/backend.py
|
@ -36,25 +36,26 @@ from ucs import *
|
|||
|
||||
|
||||
|
||||
'''
|
||||
Super-ultra-extreme-awesomazing replacement for cowsay
|
||||
'''
|
||||
class Backend():
|
||||
'''
|
||||
Constructor
|
||||
|
||||
@param message:str The message spoken by the pony
|
||||
@param ponyfile:str The pony file
|
||||
@param wrapcolumn:int The column at where to wrap the message, `None` for no wrapping
|
||||
@param width:int The width of the screen, `None` if truncation should not be applied
|
||||
@param balloon:Balloon The balloon style object, `None` if only the pony should be printed
|
||||
@param hyphen:str How hyphens added by the wordwrapper should be printed
|
||||
@param linkcolour:str How to colour the link character, empty string if none
|
||||
@param ballooncolour:str How to colour the balloon, empty string if none
|
||||
@param mode:str Mode string for the pony
|
||||
@parma infolevel:int 2 if ++info is used, 1 if --info is used and 0 otherwise
|
||||
Super-ultra-extreme-awesomazing replacement for cowsay
|
||||
'''
|
||||
|
||||
def __init__(self, message, ponyfile, wrapcolumn, width, balloon, hyphen, linkcolour, ballooncolour, mode, infolevel):
|
||||
'''
|
||||
Constructor
|
||||
|
||||
@param message:str The message spoken by the pony
|
||||
@param ponyfile:str The pony file
|
||||
@param wrapcolumn:int The column at where to wrap the message, `None` for no wrapping
|
||||
@param width:int The width of the screen, `None` if truncation should not be applied
|
||||
@param balloon:Balloon The balloon style object, `None` if only the pony should be printed
|
||||
@param hyphen:str How hyphens added by the wordwrapper should be printed
|
||||
@param linkcolour:str How to colour the link character, empty string if none
|
||||
@param ballooncolour:str How to colour the balloon, empty string if none
|
||||
@param mode:str Mode string for the pony
|
||||
@parma infolevel:int 2 if ++info is used, 1 if --info is used and 0 otherwise
|
||||
'''
|
||||
self.message = message
|
||||
self.ponyfile = ponyfile
|
||||
self.wrapcolumn = None if wrapcolumn is None else wrapcolumn - (0 if balloon is None else balloon.minwidth)
|
||||
|
@ -78,10 +79,10 @@ class Backend():
|
|||
self.pony = None
|
||||
|
||||
|
||||
'''
|
||||
Process all data
|
||||
'''
|
||||
def parse(self):
|
||||
'''
|
||||
Process all data
|
||||
'''
|
||||
self.__loadFile()
|
||||
|
||||
if self.pony.startswith('$$$\n'):
|
||||
|
@ -126,14 +127,14 @@ class Backend():
|
|||
self.__truncate()
|
||||
|
||||
|
||||
'''
|
||||
Format metadata to be nicely printed, this include bold keys
|
||||
|
||||
@param info:str The metadata
|
||||
@return :str The metadata nicely formated
|
||||
'''
|
||||
@staticmethod
|
||||
def formatInfo(info):
|
||||
'''
|
||||
Format metadata to be nicely printed, this include bold keys
|
||||
|
||||
@param info:str The metadata
|
||||
@return :str The metadata nicely formated
|
||||
'''
|
||||
info = info.split('\n')
|
||||
tags = ''
|
||||
comment = ''
|
||||
|
@ -156,10 +157,10 @@ class Backend():
|
|||
return tags + comment
|
||||
|
||||
|
||||
'''
|
||||
Remove padding spaces fortune cookies are padded with whitespace (damn featherbrains)
|
||||
'''
|
||||
def __unpadMessage(self):
|
||||
'''
|
||||
Remove padding spaces fortune cookies are padded with whitespace (damn featherbrains)
|
||||
'''
|
||||
lines = self.message.split('\n')
|
||||
for spaces in (128, 64, 32, 16, 8, 4, 2, 1):
|
||||
padded = True
|
||||
|
@ -176,10 +177,10 @@ class Backend():
|
|||
self.message = '\n'.join(lines)
|
||||
|
||||
|
||||
'''
|
||||
Converts all tabs in the message to spaces by expanding
|
||||
'''
|
||||
def __expandMessage(self):
|
||||
'''
|
||||
Converts all tabs in the message to spaces by expanding
|
||||
'''
|
||||
lines = self.message.split('\n')
|
||||
buf = ''
|
||||
for line in lines:
|
||||
|
@ -203,18 +204,18 @@ class Backend():
|
|||
self.message = buf[:-1]
|
||||
|
||||
|
||||
'''
|
||||
Loads the pony file
|
||||
'''
|
||||
def __loadFile(self):
|
||||
'''
|
||||
Loads the pony file
|
||||
'''
|
||||
with open(self.ponyfile, 'rb') as ponystream:
|
||||
self.pony = ponystream.read().decode('utf8', 'replace')
|
||||
|
||||
|
||||
'''
|
||||
Truncate output to the width of the screen
|
||||
'''
|
||||
def __truncate(self):
|
||||
'''
|
||||
Truncate output to the width of the screen
|
||||
'''
|
||||
if self.width is None:
|
||||
return
|
||||
lines = self.output.split('\n')
|
||||
|
@ -237,10 +238,10 @@ class Backend():
|
|||
self.output = self.output[:-1]
|
||||
|
||||
|
||||
'''
|
||||
Process the pony file and generate output to self.output
|
||||
'''
|
||||
def __processPony(self):
|
||||
'''
|
||||
Process the pony file and generate output to self.output
|
||||
'''
|
||||
self.output = ''
|
||||
|
||||
AUTO_PUSH = '\033[01010~'
|
||||
|
@ -307,7 +308,7 @@ class Backend():
|
|||
w -= x;
|
||||
else:
|
||||
w = int(w)
|
||||
balloon = self.__getballoon(w, h, x, justify, indent)
|
||||
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]:
|
||||
|
@ -383,15 +384,15 @@ class Backend():
|
|||
self.output = '\n'.join(self.output)
|
||||
|
||||
|
||||
'''
|
||||
Gets colour code att the currect offset in a buffer
|
||||
|
||||
@param input:str The input buffer
|
||||
@param offset:int The offset at where to start reading, a escape must begin here
|
||||
@return :str The escape sequence
|
||||
'''
|
||||
@staticmethod
|
||||
def getColour(input, offset):
|
||||
'''
|
||||
Gets colour code att the currect offset in a buffer
|
||||
|
||||
@param input:str The input buffer
|
||||
@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]
|
||||
i += 1
|
||||
|
@ -439,14 +440,14 @@ class Backend():
|
|||
return rc
|
||||
|
||||
|
||||
'''
|
||||
Calculates the number of visible characters in a text
|
||||
|
||||
@param input:str The input buffer
|
||||
@return :int The number of visible characters
|
||||
'''
|
||||
@staticmethod
|
||||
def len(input):
|
||||
'''
|
||||
Calculates the number of visible characters in a text
|
||||
|
||||
@param input:str The input buffer
|
||||
@return :int The number of visible characters
|
||||
'''
|
||||
(rc, i, n) = (0, 0, len(input))
|
||||
while i < n:
|
||||
c = input[i]
|
||||
|
@ -459,18 +460,18 @@ class Backend():
|
|||
return rc
|
||||
|
||||
|
||||
'''
|
||||
Generates a balloon with the message
|
||||
|
||||
@param width:int The minimum width of the balloon
|
||||
@param height:int The minimum height of the balloon
|
||||
@param innerleft:int The left column of the required span, excluding that of `left`
|
||||
@param justify:str Balloon placement justification, 'c' → centered,
|
||||
'l' → left (expand to right), 'r' → right (expand to left)
|
||||
@param left:int The column where the balloon starts
|
||||
@return :str The balloon the the message as a string
|
||||
'''
|
||||
def __getballoon(self, width, height, innerleft, justify, left):
|
||||
def __getBalloon(self, width, height, innerleft, justify, left):
|
||||
'''
|
||||
Generates a balloon with the message
|
||||
|
||||
@param width:int The minimum width of the balloon
|
||||
@param height:int The minimum height of the balloon
|
||||
@param innerleft:int The left column of the required span, excluding that of `left`
|
||||
@param justify:str Balloon placement justification, 'c' → centered,
|
||||
'l' → left (expand to right), 'r' → right (expand to left)
|
||||
@param left:int The column where the balloon starts
|
||||
@return :str The balloon the the message as a string
|
||||
'''
|
||||
wrap = None
|
||||
if self.wrapcolumn is not None:
|
||||
wrap = self.wrapcolumn - left
|
||||
|
@ -508,14 +509,14 @@ class Backend():
|
|||
return rc
|
||||
|
||||
|
||||
'''
|
||||
Wraps the message
|
||||
|
||||
@param message:str The message to wrap
|
||||
@param wrap:int The width at where to force wrapping
|
||||
@return :str The message wrapped
|
||||
'''
|
||||
def __wrapMessage(self, message, wrap):
|
||||
'''
|
||||
Wraps the message
|
||||
|
||||
@param message:str The message to wrap
|
||||
@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 ''
|
||||
wraplimit = 8 if len(wraplimit) == 0 else int(wraplimit)
|
||||
|
||||
|
@ -579,11 +580,11 @@ class Backend():
|
|||
nbsp = b[map[mm + x]] == ' ' # nbsp
|
||||
m = map[mm + x]
|
||||
|
||||
if ('' in b[bisub : m]) and not nbsp: # sort hyphen
|
||||
if ('' in b[bisub : m]) and not nbsp: # soft hyphen
|
||||
hyphen = m - 1
|
||||
while b[hyphen] != '': # sort hyphen
|
||||
while b[hyphen] != '': # soft hyphen
|
||||
hyphen -= 1
|
||||
while map[mm + x] > hyphen: ## Only looking backward, if foreward is required the word is probabily not hyphenated correctly
|
||||
while map[mm + x] > hyphen: ## Only looking backward, if forward is required the word is probabily not hyphenated correctly
|
||||
x -= 1
|
||||
x += 1
|
||||
m = map[mm + x]
|
||||
|
|
|
@ -34,36 +34,37 @@ from ucs import *
|
|||
|
||||
|
||||
|
||||
'''
|
||||
Balloon format class
|
||||
'''
|
||||
class Balloon():
|
||||
'''
|
||||
Constructor
|
||||
|
||||
@param link:str The \-directional balloon line character
|
||||
@param linkmirror:str The /-directional balloon line character
|
||||
@param linkcross:str The /-directional balloon crossing a \-directional ballonon line character
|
||||
@param ww:str See the info manual
|
||||
@param ee:str See the info manual
|
||||
@param nw:list<str> See the info manual
|
||||
@param nnw:list<str> See the info manual
|
||||
@param n:list<str> See the info manual
|
||||
@param nne:list<str> See the info manual
|
||||
@param ne:list<str> See the info manual
|
||||
@param nee:str See the info manual
|
||||
@param e:str See the info manual
|
||||
@param see:str See the info manual
|
||||
@param se:list<str> See the info manual
|
||||
@param sse:list<str> See the info manual
|
||||
@param s:list<str> See the info manual
|
||||
@param ssw:list<str> See the info manual
|
||||
@param sw:list<str> See the info manual
|
||||
@param sww:str See the info manual
|
||||
@param w:str See the info manual
|
||||
@param nww:str See the info manual
|
||||
Balloon format class
|
||||
'''
|
||||
|
||||
def __init__(self, link, linkmirror, linkcross, ww, ee, nw, nnw, n, nne, ne, nee, e, see, se, sse, s, ssw, sw, sww, w, nww):
|
||||
'''
|
||||
Constructor
|
||||
|
||||
@param link:str The \-directional balloon line character
|
||||
@param linkmirror:str The /-directional balloon line character
|
||||
@param linkcross:str The /-directional balloon crossing a \-directional ballonon line character
|
||||
@param ww:str See the info manual
|
||||
@param ee:str See the info manual
|
||||
@param nw:list<str> See the info manual
|
||||
@param nnw:list<str> See the info manual
|
||||
@param n:list<str> See the info manual
|
||||
@param nne:list<str> See the info manual
|
||||
@param ne:list<str> See the info manual
|
||||
@param nee:str See the info manual
|
||||
@param e:str See the info manual
|
||||
@param see:str See the info manual
|
||||
@param se:list<str> See the info manual
|
||||
@param sse:list<str> See the info manual
|
||||
@param s:list<str> See the info manual
|
||||
@param ssw:list<str> See the info manual
|
||||
@param sw:list<str> See the info manual
|
||||
@param sww:str See the info manual
|
||||
@param w:str See the info manual
|
||||
@param nww:str See the info manual
|
||||
'''
|
||||
(self.link, self.linkmirror, self.linkcross) = (link, linkmirror, linkcross)
|
||||
(self.ww, self.ee) = (ww, ee)
|
||||
(self.nw, self.ne, self.se, self.sw) = (nw, ne, se, sw)
|
||||
|
@ -86,16 +87,16 @@ class Balloon():
|
|||
self.minheight = minN + minS
|
||||
|
||||
|
||||
'''
|
||||
Generates a balloon with a message
|
||||
|
||||
@param minw:int The minimum number of columns of the balloon
|
||||
@param minh:int The minimum number of lines of the balloon
|
||||
@param lines:list<str> The text lines to display
|
||||
@param lencalc:int(str) Function used to compute the length of a text line
|
||||
@return :str The balloon as a formated string
|
||||
'''
|
||||
def get(self, minw, minh, lines, lencalc):
|
||||
'''
|
||||
Generates a balloon with a message
|
||||
|
||||
@param minw:int The minimum number of columns of the balloon
|
||||
@param minh:int The minimum number of lines of the balloon
|
||||
@param lines:list<str> The text lines to display
|
||||
@param lencalc:int(str) Function used to compute the length of a text line
|
||||
@return :str The balloon as a formated string
|
||||
'''
|
||||
## Get dimension
|
||||
h = self.minheight + len(lines)
|
||||
w = self.minwidth + lencalc(max(lines, key = lencalc))
|
||||
|
@ -138,15 +139,15 @@ class Balloon():
|
|||
return '\n'.join(rc)
|
||||
|
||||
|
||||
'''
|
||||
Creates the balloon style object
|
||||
|
||||
@param balloonfile:str The file with the balloon style, may be `None`
|
||||
@param isthink:bool Whether the ponythink command is used
|
||||
@return :Balloon Instance describing the balloon's style
|
||||
'''
|
||||
@staticmethod
|
||||
def fromFile(balloonfile, isthink):
|
||||
'''
|
||||
Creates the balloon style object
|
||||
|
||||
@param balloonfile:str The file with the balloon style, may be `None`
|
||||
@param isthink:bool Whether the ponythink command is used
|
||||
@return :Balloon Instance describing the balloon's style
|
||||
'''
|
||||
## Use default balloon if none is specified
|
||||
if balloonfile is None:
|
||||
if isthink:
|
||||
|
|
|
@ -33,19 +33,20 @@ from common import *
|
|||
|
||||
|
||||
|
||||
'''
|
||||
ANSI colour stack
|
||||
|
||||
This is used to make layers with independent coloursations
|
||||
'''
|
||||
class ColourStack():
|
||||
'''
|
||||
Constructor
|
||||
ANSI colour stack
|
||||
|
||||
@param autopush:str String that, when used, will create a new independently colourised layer
|
||||
@param autopop:str String that, when used, will end the current layer and continue of the previous layer
|
||||
This is used to make layers with independent coloursations
|
||||
'''
|
||||
|
||||
def __init__(self, autopush, autopop):
|
||||
'''
|
||||
Constructor
|
||||
|
||||
@param autopush:str String that, when used, will create a new independently colourised layer
|
||||
@param autopop:str String that, when used, will end the current layer and continue of the previous layer
|
||||
'''
|
||||
self.autopush = autopush
|
||||
self.autopop = autopop
|
||||
self.lenpush = len(autopush)
|
||||
|
@ -56,24 +57,24 @@ class ColourStack():
|
|||
self.seq = None
|
||||
|
||||
|
||||
'''
|
||||
Create a new independently colourised layer
|
||||
|
||||
@return :str String that should be inserted into your buffer
|
||||
'''
|
||||
def push(self):
|
||||
'''
|
||||
Create a new independently colourised layer
|
||||
|
||||
@return :str String that should be inserted into your buffer
|
||||
'''
|
||||
self.stack.insert(0, [self.bufproto, None, None, [False] * 9])
|
||||
if len(self.stack) == 1:
|
||||
return None
|
||||
return '\033[0m'
|
||||
|
||||
|
||||
'''
|
||||
End the current layer and continue of the previous layer
|
||||
|
||||
@return :str String that should be inserted into your buffer
|
||||
'''
|
||||
def pop(self):
|
||||
'''
|
||||
End the current layer and continue of the previous layer
|
||||
|
||||
@return :str String that should be inserted into your buffer
|
||||
'''
|
||||
old = self.stack.pop(0)
|
||||
rc = '\033[0;'
|
||||
if len(self.stack) == 0: # last resort in case something made it pop too mush
|
||||
|
@ -87,14 +88,14 @@ class ColourStack():
|
|||
return rc[:-1] + 'm'
|
||||
|
||||
|
||||
'''
|
||||
Use this, in sequence, for which character in your buffer that contains yor autopush and autopop
|
||||
string, the automatically get push and pop string to insert after each character
|
||||
|
||||
@param :chr One character in your buffer
|
||||
@return :str The text to insert after the input character
|
||||
'''
|
||||
def feed(self, char):
|
||||
'''
|
||||
Use this, in sequence, for which character in your buffer that contains yor autopush and autopop
|
||||
string, the automatically get push and pop string to insert after each character
|
||||
|
||||
@param :chr One character in your buffer
|
||||
@return :str The text to insert after the input character
|
||||
'''
|
||||
if self.seq is not None:
|
||||
self.seq += char
|
||||
if (char == '~') or (('a' <= char) and (char <= 'z')) or (('A' <= char) and (char <= 'Z')):
|
||||
|
|
|
@ -38,40 +38,40 @@ from subprocess import Popen, PIPE
|
|||
|
||||
|
||||
|
||||
VERSION = 'dev' # this line should not be edited, it is fixed by the build system
|
||||
'''
|
||||
The version of ponysay
|
||||
'''
|
||||
VERSION = 'dev' # this line should not be edited, it is fixed by the build system
|
||||
|
||||
|
||||
|
||||
'''
|
||||
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)
|
||||
'''
|
||||
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'))
|
||||
|
||||
'''
|
||||
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'):
|
||||
'''
|
||||
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)
|
||||
'''
|
||||
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'):
|
||||
'''
|
||||
/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)
|
||||
'''
|
||||
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:
|
||||
|
@ -80,23 +80,23 @@ def printinfo(text = '', end = '\n'):
|
|||
fd3.write(str(text) + end)
|
||||
|
||||
|
||||
'''
|
||||
Checks whether a text ends with a specific text, but has more
|
||||
|
||||
@param text:str The text to test
|
||||
@param ending:str The desired end of the text
|
||||
@return :bool The result of the test
|
||||
'''
|
||||
def endswith(text, ending):
|
||||
'''
|
||||
Checks whether a text ends with a specific text, but has more
|
||||
|
||||
@param text:str The text to test
|
||||
@param ending:str The desired end of the text
|
||||
@return :bool The result of the test
|
||||
'''
|
||||
return text.endswith(ending) and not (text == ending)
|
||||
|
||||
|
||||
'''
|
||||
Gets the size of the terminal in (rows, columns)
|
||||
|
||||
@return (rows, columns):(int, int) The number or lines and the number of columns in the terminal's display area
|
||||
'''
|
||||
def gettermsize():
|
||||
'''
|
||||
Gets the size of the terminal in (rows, columns)
|
||||
|
||||
@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]
|
||||
|
|
31
src/kms.py
31
src/kms.py
|
@ -33,18 +33,19 @@ from common import *
|
|||
|
||||
|
||||
|
||||
'''
|
||||
KMS support utilisation
|
||||
'''
|
||||
class KMS():
|
||||
'''
|
||||
Identifies whether KMS support is utilised
|
||||
|
||||
@param linuxvt:bool Whether Linux VT is used
|
||||
@return :bool Whether KMS support is utilised
|
||||
KMS support utilisation
|
||||
'''
|
||||
|
||||
@staticmethod
|
||||
def usingkms(linuxvt):
|
||||
'''
|
||||
Identifies whether KMS support is utilised
|
||||
|
||||
@param linuxvt:bool Whether Linux VT is used
|
||||
@return :bool Whether KMS support is utilised
|
||||
'''
|
||||
## KMS is not utilised if Linux VT is not used
|
||||
if not linuxvt:
|
||||
return False
|
||||
|
@ -64,16 +65,16 @@ class KMS():
|
|||
return env_kms != ''
|
||||
|
||||
|
||||
'''
|
||||
Returns the file name of the input pony converted to a KMS pony, or if KMS is not used, the input pony itself
|
||||
|
||||
@param pony:str Choosen pony file
|
||||
@param home:str The home directory
|
||||
@param linuxvt:bool Whether Linux VT is used
|
||||
@return :str Pony file to display
|
||||
'''
|
||||
@staticmethod
|
||||
def kms(pony, home, linuxvt):
|
||||
'''
|
||||
Returns the file name of the input pony converted to a KMS pony, or if KMS is not used, the input pony itself
|
||||
|
||||
@param pony:str Choosen pony file
|
||||
@param home:str The home directory
|
||||
@param linuxvt:bool Whether Linux VT is used
|
||||
@return :str Pony file to display
|
||||
'''
|
||||
## If not in Linux VT, return the pony as is
|
||||
if not linuxvt:
|
||||
return pony
|
||||
|
|
69
src/list.py
69
src/list.py
|
@ -34,17 +34,18 @@ from ucs import *
|
|||
|
||||
|
||||
|
||||
'''
|
||||
File listing functions
|
||||
'''
|
||||
class List():
|
||||
'''
|
||||
Columnise a list and prints it
|
||||
|
||||
@param ponies:list<(str, str)> All items to list, each item should have to elements: unformated name, formated name
|
||||
File listing functions
|
||||
'''
|
||||
|
||||
@staticmethod
|
||||
def __columnise(ponies):
|
||||
'''
|
||||
Columnise a list and prints it
|
||||
|
||||
@param ponies:list<(str, str)> All items to list, each item should have to elements: unformated name, formated name
|
||||
'''
|
||||
## Get terminal width, and a 2 which is the space between columns
|
||||
termwidth = gettermsize()[1] + 2
|
||||
## Sort the ponies, and get the cells' widths, and the largest width + 2
|
||||
|
@ -90,17 +91,17 @@ class List():
|
|||
## Print the matrix, with one extra blank row
|
||||
print('\n'.join([''.join(line)[:-2] for line in lines]))
|
||||
print()
|
||||
|
||||
|
||||
'''
|
||||
Lists the available ponies
|
||||
|
||||
@param ponydirs:itr<str> The pony directories to use
|
||||
@param quoters:__in__(str)→bool Set of ponies that of quotes
|
||||
@param ucsiser:(list<str>)?→void Function used to UCS:ise names
|
||||
'''
|
||||
|
||||
@staticmethod
|
||||
def simplelist(ponydirs, quoters = [], ucsiser = None):
|
||||
'''
|
||||
Lists the available ponies
|
||||
|
||||
@param ponydirs:itr<str> The pony directories to use
|
||||
@param quoters:__in__(str)→bool Set of ponies that of quotes
|
||||
@param ucsiser:(list<str>)?→void Function used to UCS:ise names
|
||||
'''
|
||||
for ponydir in ponydirs: # Loop ponydirs
|
||||
## Get all ponies in the directory
|
||||
_ponies = os.listdir(ponydir)
|
||||
|
@ -122,15 +123,15 @@ class List():
|
|||
List.__columnise([(pony, '\033[1m' + pony + '\033[21m' if pony in quoters else pony) for pony in ponies])
|
||||
|
||||
|
||||
'''
|
||||
Lists the available ponies with alternatives inside brackets
|
||||
|
||||
@param ponydirs:itr<str> The pony directories to use
|
||||
@param quoters:__in__(str)→bool Set of ponies that of quotes
|
||||
@param ucsiser:(list<str>, map<str, str>)?→void Function used to UCS:ise names
|
||||
'''
|
||||
@staticmethod
|
||||
def linklist(ponydirs = None, quoters = [], ucsiser = None):
|
||||
'''
|
||||
Lists the available ponies with alternatives inside brackets
|
||||
|
||||
@param ponydirs:itr<str> The pony directories to use
|
||||
@param quoters:__in__(str)→bool Set of ponies that of quotes
|
||||
@param ucsiser:(list<str>, map<str, str>)?→void Function used to UCS:ise names
|
||||
'''
|
||||
## Get the size of the terminal
|
||||
termsize = gettermsize()
|
||||
|
||||
|
@ -200,15 +201,15 @@ class List():
|
|||
List.__columnise(list(ponies))
|
||||
|
||||
|
||||
'''
|
||||
Lists the available ponies on one column without anything bold or otherwise formated
|
||||
|
||||
@param standard:itr<str>? Include standard ponies
|
||||
@param extra:itr<str>? Include extra ponies
|
||||
@param ucsiser:(list<str>)?→void Function used to UCS:ise names
|
||||
'''
|
||||
@staticmethod
|
||||
def onelist(standarddirs, extradirs = None, ucsiser = None):
|
||||
'''
|
||||
Lists the available ponies on one column without anything bold or otherwise formated
|
||||
|
||||
@param standard:itr<str>? Include standard ponies
|
||||
@param extra:itr<str>? Include extra ponies
|
||||
@param ucsiser:(list<str>)?→void Function used to UCS:ise names
|
||||
'''
|
||||
## Get all pony files
|
||||
_ponies = []
|
||||
if standarddirs is not None:
|
||||
|
@ -237,14 +238,14 @@ class List():
|
|||
print(pony)
|
||||
|
||||
|
||||
'''
|
||||
Prints a list of all balloons
|
||||
|
||||
@param balloondirs:itr<str> The balloon directories to use
|
||||
@param isthink:bool Whether the ponythink command is used
|
||||
'''
|
||||
@staticmethod
|
||||
def balloonlist(balloondirs, isthink):
|
||||
'''
|
||||
Prints a list of all balloons
|
||||
|
||||
@param balloondirs:itr<str> The balloon directories to use
|
||||
@param isthink:bool Whether the ponythink command is used
|
||||
'''
|
||||
## Get the size of the terminal
|
||||
termsize = gettermsize()
|
||||
|
||||
|
|
|
@ -33,18 +33,19 @@ from common import *
|
|||
|
||||
|
||||
|
||||
'''
|
||||
Metadata functions
|
||||
'''
|
||||
class Metadata():
|
||||
'''
|
||||
Make restriction test logic function
|
||||
|
||||
@param restriction:list<string> Metadata based restrictions
|
||||
@return :dict<str, str>→bool Test function
|
||||
Metadata functions
|
||||
'''
|
||||
|
||||
@staticmethod
|
||||
def makeRestrictionLogic(restriction):
|
||||
'''
|
||||
Make restriction test logic function
|
||||
|
||||
@param restriction:list<string> Metadata based restrictions
|
||||
@return :dict<str, str>→bool Test function
|
||||
'''
|
||||
def get_test(cell):
|
||||
strict = cell[0][-1] != '?'
|
||||
key = cell[0]
|
||||
|
@ -109,15 +110,15 @@ class Metadata():
|
|||
return Logic(table)
|
||||
|
||||
|
||||
'''
|
||||
Get ponies that pass restriction
|
||||
|
||||
@param ponydir:str Pony directory, must end with `os.sep`
|
||||
@param logic:(str)→bool Restriction test functor
|
||||
@return :list<str> Passed ponies
|
||||
'''
|
||||
@staticmethod
|
||||
def restrictedPonies(ponydir, logic):
|
||||
'''
|
||||
Get ponies that pass restriction
|
||||
|
||||
@param ponydir:str Pony directory, must end with `os.sep`
|
||||
@param logic:(str)→bool Restriction test functor
|
||||
@return :list<str> Passed ponies
|
||||
'''
|
||||
import pickle
|
||||
passed = []
|
||||
if os.path.exists(ponydir + 'metadata'):
|
||||
|
@ -131,15 +132,15 @@ class Metadata():
|
|||
return passed
|
||||
|
||||
|
||||
'''
|
||||
Get ponies that fit the terminal
|
||||
|
||||
@param fitting:add(str)→void The set to fill
|
||||
@param requirement:int The maximum allowed value
|
||||
@param file:istream The file with all data
|
||||
'''
|
||||
@staticmethod
|
||||
def getfitting(fitting, requirement, file):
|
||||
'''
|
||||
Get ponies that fit the terminal
|
||||
|
||||
@param fitting:add(str)→void The set to fill
|
||||
@param requirement:int The maximum allowed value
|
||||
@param file:istream The file with all data
|
||||
'''
|
||||
data = file.read() # not too much data, can load everything at once
|
||||
ptr = 0
|
||||
while data[ptr] != 47: # 47 == ord('/')
|
||||
|
|
320
src/ponysay.py
320
src/ponysay.py
|
@ -3,13 +3,31 @@
|
|||
|
||||
'''
|
||||
ponysay - Ponysay, cowsay reimplementation for ponies
|
||||
|
||||
Copyright (C) 2012, 2013 Erkin Batu Altunbaş et al.
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
If you intend to redistribute ponysay or a fork of it commercially,
|
||||
it contains aggregated images, some of which may not be commercially
|
||||
redistribute, you would be required to remove those. To determine
|
||||
whether or not you may commercially redistribute an image make use
|
||||
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 *
|
||||
|
@ -22,29 +40,29 @@ from metadata import *
|
|||
|
||||
|
||||
|
||||
'''
|
||||
This is the mane class of ponysay
|
||||
'''
|
||||
class Ponysay():
|
||||
'''
|
||||
Constructor
|
||||
This is the mane class of ponysay
|
||||
'''
|
||||
|
||||
def __init__(self):
|
||||
'''
|
||||
The user's home directory
|
||||
Constructor
|
||||
'''
|
||||
|
||||
# The user's home directory
|
||||
self.HOME = os.environ['HOME'] if 'HOME' in os.environ else ''
|
||||
if len(self.HOME) == 0:
|
||||
os.environ['HOME'] = self.HOME = os.path.expanduser('~')
|
||||
|
||||
|
||||
'''
|
||||
Parse a file name encoded with environment variables
|
||||
|
||||
@param file The encoded file name
|
||||
@return The target file name, None if the environment variables are not declared
|
||||
'''
|
||||
def parsefile(file):
|
||||
'''
|
||||
Parse a file name encoded with environment variables
|
||||
|
||||
@param file The encoded file name
|
||||
@return The target file name, None if the environment variables are not declared
|
||||
'''
|
||||
if '$' in file:
|
||||
buf = ''
|
||||
esc = False
|
||||
|
@ -88,21 +106,15 @@ class Ponysay():
|
|||
os.environ['HOME'] = self.HOME = os.path.expanduser('~')
|
||||
|
||||
|
||||
'''
|
||||
Whether any unrecognised options was parsed, this should be set by the invoker before run()
|
||||
'''
|
||||
# Whether any unrecognised options was parsed, this should be set by the invoker before run()
|
||||
self.unrecognised = False
|
||||
|
||||
|
||||
'''
|
||||
Whether the program is execute in Linux VT (TTY)
|
||||
'''
|
||||
# Whether the program is execute in Linux VT (TTY)
|
||||
self.linuxvt = ('TERM' in os.environ) and (os.environ['TERM'] == 'linux')
|
||||
|
||||
|
||||
'''
|
||||
Whether the script is executed as ponythink
|
||||
'''
|
||||
# Whether the script is executed as ponythink
|
||||
self.isthink = sys.argv[0]
|
||||
if os.sep in self.isthink:
|
||||
self.isthink = self.isthink[self.isthink.rfind(os.sep) + 1:]
|
||||
|
@ -111,31 +123,21 @@ class Ponysay():
|
|||
self.isthink = self.isthink.endswith('think')
|
||||
|
||||
|
||||
'''
|
||||
Whether stdin is piped
|
||||
'''
|
||||
# Whether stdin is piped
|
||||
self.pipelinein = not sys.stdin.isatty()
|
||||
|
||||
'''
|
||||
Whether stdout is piped
|
||||
'''
|
||||
# Whether stdout is piped
|
||||
self.pipelineout = not sys.stdout.isatty()
|
||||
|
||||
'''
|
||||
Whether stderr is piped
|
||||
'''
|
||||
# Whether stderr is piped
|
||||
self.pipelineerr = not sys.stderr.isatty()
|
||||
|
||||
|
||||
'''
|
||||
Whether KMS is used
|
||||
'''
|
||||
# Whether KMS is used
|
||||
self.usekms = KMS.usingkms(self.linuxvt)
|
||||
|
||||
|
||||
'''
|
||||
Mode string that modifies or adds $ variables in the pony image
|
||||
'''
|
||||
# Mode string that modifies or adds $ variables in the pony image
|
||||
self.mode = ''
|
||||
|
||||
|
||||
|
@ -152,9 +154,7 @@ class Ponysay():
|
|||
]]
|
||||
|
||||
|
||||
'''
|
||||
The directories where pony files are stored, ttyponies/ are used if the terminal is Linux VT (also known as TTY) and not with KMS
|
||||
'''
|
||||
# The directories where pony files are stored, ttyponies/ are used if the terminal is Linux VT (also known as TTY) and not with KMS
|
||||
appendset = set()
|
||||
self.xponydirs = []
|
||||
_ponydirs = share('ponies/')
|
||||
|
@ -171,9 +171,7 @@ class Ponysay():
|
|||
appendset.add(ponydir)
|
||||
|
||||
|
||||
'''
|
||||
The directories where pony files are stored, extrattyponies/ are used if the terminal is Linux VT (also known as TTY) and not with KMS
|
||||
'''
|
||||
# The directories where pony files are stored, extrattyponies/ are used if the terminal is Linux VT (also known as TTY) and not with KMS
|
||||
appendset = set()
|
||||
self.extraxponydirs = []
|
||||
_extraponydirs = share('extraponies/')
|
||||
|
@ -190,9 +188,7 @@ class Ponysay():
|
|||
appendset.add(extraponydir)
|
||||
|
||||
|
||||
'''
|
||||
The directories where quotes files are stored
|
||||
'''
|
||||
# The directories where quotes files are stored
|
||||
appendset = set()
|
||||
self.quotedirs = []
|
||||
_quotedirs = share('quotes/')
|
||||
|
@ -202,9 +198,7 @@ class Ponysay():
|
|||
appendset.add(quotedir)
|
||||
|
||||
|
||||
'''
|
||||
The directories where balloon style files are stored
|
||||
'''
|
||||
# The directories where balloon style files are stored
|
||||
appendset = set()
|
||||
self.balloondirs = []
|
||||
_balloondirs = share('balloons/')
|
||||
|
@ -214,9 +208,7 @@ class Ponysay():
|
|||
appendset.add(balloondir)
|
||||
|
||||
|
||||
'''
|
||||
ucsmap files
|
||||
'''
|
||||
# ucsmap files
|
||||
appendset = set()
|
||||
self.ucsmaps = []
|
||||
_ucsmaps = share('ucsmap/')
|
||||
|
@ -227,24 +219,24 @@ class Ponysay():
|
|||
|
||||
|
||||
|
||||
'''
|
||||
Starts the part of the program the arguments indicate
|
||||
|
||||
@param args:ArgParser Parsed command line arguments
|
||||
'''
|
||||
def run(self, args):
|
||||
'''
|
||||
Starts the part of the program the arguments indicate
|
||||
|
||||
@param args:ArgParser Parsed command line arguments
|
||||
'''
|
||||
if (args.argcount == 0) and not self.pipelinein:
|
||||
args.help()
|
||||
exit(254)
|
||||
return
|
||||
|
||||
'''
|
||||
Test arguments written in negation-free disjunctive normal form
|
||||
|
||||
@param keys:*str|itr<str> A list of keys and set of keys, any of which must exists, a set of keys only passes if all of those exists
|
||||
@return :bool Whether the check passed
|
||||
'''
|
||||
def test(*keys):
|
||||
'''
|
||||
Test arguments written in negation-free disjunctive normal form
|
||||
|
||||
@param keys:*str|itr<str> A list of keys and set of keys, any of which must exists, a set of keys only passes if all of those exists
|
||||
@return :bool Whether the check passed
|
||||
'''
|
||||
for key in keys:
|
||||
if isinstance(key, str):
|
||||
if args.opts[key] is not None:
|
||||
|
@ -328,21 +320,21 @@ class Ponysay():
|
|||
## Methods that run before the mane methods ##
|
||||
##############################################
|
||||
|
||||
'''
|
||||
Use extra ponies
|
||||
'''
|
||||
def __extraponies(self):
|
||||
'''
|
||||
Use extra ponies
|
||||
'''
|
||||
## Change ponydir to extraponydir
|
||||
self.ponydirs[:] = self.extraponydirs
|
||||
self.quotedirs[:] = [] ## TODO +q
|
||||
|
||||
|
||||
'''
|
||||
Use best.pony if nothing else is set
|
||||
|
||||
@param args:ArgParser Parsed command line arguments
|
||||
'''
|
||||
def __bestpony(self, args):
|
||||
'''
|
||||
Use best.pony if nothing else is set
|
||||
|
||||
@param args:ArgParser Parsed command line arguments
|
||||
'''
|
||||
## Set best.pony as the pony to display if none is selected
|
||||
def test(keys, strict):
|
||||
if strict:
|
||||
|
@ -368,12 +360,12 @@ class Ponysay():
|
|||
break
|
||||
|
||||
|
||||
'''
|
||||
Apply pony name remapping to args according to UCS settings
|
||||
|
||||
@param args:ArgParser Parsed command line arguments
|
||||
'''
|
||||
def __ucsremap(self, args):
|
||||
'''
|
||||
Apply pony name remapping to args according to UCS settings
|
||||
|
||||
@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
|
||||
|
@ -413,13 +405,13 @@ class Ponysay():
|
|||
## Auxiliary methods ##
|
||||
#######################
|
||||
|
||||
'''
|
||||
Apply UCS:ise pony names according to UCS settings
|
||||
|
||||
@param ponies:list<str> List of all ponies (of interrest)
|
||||
@param links:map<str, str>? Map to fill with simulated symlink ponies, may be `None`
|
||||
'''
|
||||
def __ucsise(self, ponies, links = None):
|
||||
'''
|
||||
Apply UCS:ise pony names according to UCS settings
|
||||
|
||||
@param ponies:list<str> List of all ponies (of interrest)
|
||||
@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
|
||||
|
@ -460,18 +452,18 @@ class Ponysay():
|
|||
ponies[j] = map[ponies[j]]
|
||||
|
||||
|
||||
'''
|
||||
Returns one file with full path and ponyquote that should be used, names is filter for names, also accepts filepaths
|
||||
|
||||
@param selection:(name:str, dirs:itr<str>, quote:bool)? Parsed command line arguments as name–directories–quoting tubles:
|
||||
name: The pony name
|
||||
dirfiles: Files, with the directory, in the pony directories
|
||||
quote: Whether to use ponyquotes
|
||||
@param args:ArgParser Parsed command line arguments
|
||||
@param alt:bool For method internal use...
|
||||
@return (path, quote):(str, str?) The file name of a pony, and the ponyquote that should be used if any
|
||||
'''
|
||||
def __getpony(self, selection, args, alt = False):
|
||||
'''
|
||||
Returns one file with full path and ponyquote that should be used, names is filter for names, also accepts filepaths
|
||||
|
||||
@param selection:(name:str, dirs:itr<str>, quote:bool)? Parsed command line arguments as name–directories–quoting tubles:
|
||||
name: The pony name
|
||||
dirfiles: Files, with the directory, in the pony directories
|
||||
quote: Whether to use ponyquotes
|
||||
@param args:ArgParser Parsed command line arguments
|
||||
@param alt:bool For method internal use...
|
||||
@return (path, quote):(str, str?) The file name of a pony, and the ponyquote that should be used if any
|
||||
'''
|
||||
## If there is no selected ponies, choose all of them
|
||||
if (selection is None) or (len(selection) == 0):
|
||||
quote = args.opts['-q'] is not None ## TODO +q -Q
|
||||
|
@ -570,14 +562,14 @@ class Ponysay():
|
|||
return (file, self.__getquote(pony[0], file) if pony[2] else None)
|
||||
|
||||
|
||||
'''
|
||||
Select a quote for a pony
|
||||
|
||||
@param pony:str The pony name
|
||||
@param file:str The pony's file name
|
||||
@return :str A quote from the pony, with a failure fall back message
|
||||
'''
|
||||
def __getquote(self, pony, file):
|
||||
'''
|
||||
Select a quote for a pony
|
||||
|
||||
@param pony:str The pony name
|
||||
@param file:str The pony's file name
|
||||
@return :str A quote from the pony, with a failure fall back message
|
||||
'''
|
||||
quote = []
|
||||
if (os.path.dirname(file) + os.sep).replace(os.sep + os.sep, os.sep) in self.ponydirs:
|
||||
realpony = pony
|
||||
|
@ -596,14 +588,14 @@ class Ponysay():
|
|||
return quote
|
||||
|
||||
|
||||
'''
|
||||
Returns a set with all ponies that have quotes and are displayable
|
||||
|
||||
@param ponydirs:itr<str>? The pony directories to use
|
||||
@param quotedirs:itr<str>? The quote directories to use
|
||||
@return :set<str> All ponies that have quotes and are displayable
|
||||
'''
|
||||
def __quoters(self, ponydirs = None, quotedirs = None):
|
||||
'''
|
||||
Returns a set with all ponies that have quotes and are displayable
|
||||
|
||||
@param ponydirs:itr<str>? The pony directories to use
|
||||
@param quotedirs:itr<str>? The quote directories to use
|
||||
@return :set<str> All ponies that have quotes and are displayable
|
||||
'''
|
||||
if ponydirs is None: ponydirs = self.ponydirs
|
||||
if quotedirs is None: quotedirs = self.quotedirs
|
||||
|
||||
|
@ -633,15 +625,15 @@ class Ponysay():
|
|||
return ponies
|
||||
|
||||
|
||||
'''
|
||||
Returns a list with all (pony, quote file) pairs
|
||||
|
||||
@param ponydirs:itr<str>? The pony directories to use
|
||||
@param quotedirs:itr<str>? The quote directories to use
|
||||
@param ponies:itr<str>? The ponies to use
|
||||
@return (pony, quote):(str, str) All ponies–quote file-pairs
|
||||
'''
|
||||
def __quotes(self, ponydirs = None, quotedirs = None, ponies = None):
|
||||
'''
|
||||
Returns a list with all (pony, quote file) pairs
|
||||
|
||||
@param ponydirs:itr<str>? The pony directories to use
|
||||
@param quotedirs:itr<str>? The quote directories to use
|
||||
@param ponies:itr<str>? The ponies to use
|
||||
@return (pony, quote):(str, str) All ponies–quote file-pairs
|
||||
'''
|
||||
if ponydirs is None: ponydirs = self.ponydirs
|
||||
if quotedirs is None: quotedirs = self.quotedirs
|
||||
|
||||
|
@ -678,45 +670,45 @@ class Ponysay():
|
|||
## Listing methods ##
|
||||
#####################
|
||||
|
||||
'''
|
||||
Lists the available ponies
|
||||
|
||||
@param ponydirs:itr<str>? The pony directories to use
|
||||
'''
|
||||
def list(self, ponydirs = None):
|
||||
'''
|
||||
Lists the available ponies
|
||||
|
||||
@param ponydirs:itr<str>? The pony directories to use
|
||||
'''
|
||||
List.simplelist(self.ponydirs if ponydirs is None else ponydirs,
|
||||
self.__quoters(), lambda x : self.__ucsise(x))
|
||||
|
||||
|
||||
'''
|
||||
Lists the available ponies with alternatives inside brackets
|
||||
|
||||
@param ponydirs:itr<str> The pony directories to use
|
||||
'''
|
||||
def linklist(self, ponydirs = None):
|
||||
'''
|
||||
Lists the available ponies with alternatives inside brackets
|
||||
|
||||
@param ponydirs:itr<str> The pony directories to use
|
||||
'''
|
||||
List.linklist(self.ponydirs if ponydirs is None else ponydirs,
|
||||
self.__quoters(), lambda x, y : self.__ucsise(x, y))
|
||||
|
||||
|
||||
'''
|
||||
Lists the available ponies on one column without anything bold or otherwise formated
|
||||
|
||||
@param standard:bool Include standard ponies
|
||||
@param extra:bool Include extra ponies
|
||||
'''
|
||||
def onelist(self, standard = True, extra = False):
|
||||
'''
|
||||
Lists the available ponies on one column without anything bold or otherwise formated
|
||||
|
||||
@param standard:bool Include standard ponies
|
||||
@param extra:bool Include extra ponies
|
||||
'''
|
||||
List.onelist(self.ponydirs if standard else None,
|
||||
self.extraponydirs if extra else None,
|
||||
lambda x : self.__ucsise(x))
|
||||
|
||||
|
||||
'''
|
||||
Lists with all ponies that have quotes and are displayable, on one column without anything bold or otherwise formated
|
||||
|
||||
@param standard:bool Include standard ponies
|
||||
@param extra:bool Include extra ponies
|
||||
'''
|
||||
def quoters(self, standard = True, extra = False):
|
||||
'''
|
||||
Lists with all ponies that have quotes and are displayable, on one column without anything bold or otherwise formated
|
||||
|
||||
@param standard:bool Include standard ponies
|
||||
@param extra:bool Include extra ponies
|
||||
'''
|
||||
## Get all quoters
|
||||
ponies = list(self.__quoters()) if standard else []
|
||||
|
||||
|
@ -742,21 +734,21 @@ class Ponysay():
|
|||
## Balloon methods ##
|
||||
#####################
|
||||
|
||||
'''
|
||||
Prints a list of all balloons
|
||||
'''
|
||||
def balloonlist(self):
|
||||
'''
|
||||
Prints a list of all balloons
|
||||
'''
|
||||
List.balloonlist(self.balloondirs, self.isthink)
|
||||
|
||||
|
||||
'''
|
||||
Returns one file with full path, names is filter for style names, also accepts filepaths
|
||||
|
||||
@param names:list<str> Balloons to choose from, may be `None`
|
||||
@param alt:bool For method internal use
|
||||
@param :str The file name of the balloon, will be `None` iff `names` is `None`
|
||||
'''
|
||||
def __getballoonpath(self, names, alt = False):
|
||||
'''
|
||||
Returns one file with full path, names is filter for style names, also accepts filepaths
|
||||
|
||||
@param names:list<str> Balloons to choose from, may be `None`
|
||||
@param alt:bool For method internal use
|
||||
@param :str The file name of the balloon, will be `None` iff `names` is `None`
|
||||
'''
|
||||
## Stop if their is no choosen balloon
|
||||
if names is None:
|
||||
return None
|
||||
|
@ -799,13 +791,13 @@ class Ponysay():
|
|||
return balloons[balloon]
|
||||
|
||||
|
||||
'''
|
||||
Creates the balloon style object
|
||||
|
||||
@param balloonfile:str The file with the balloon style, may be `None`
|
||||
@return :Balloon Instance describing the balloon's style
|
||||
'''
|
||||
def __getballoon(self, balloonfile):
|
||||
'''
|
||||
Creates the balloon style object
|
||||
|
||||
@param balloonfile:str The file with the balloon style, may be `None`
|
||||
@return :Balloon Instance describing the balloon's style
|
||||
'''
|
||||
return Balloon.fromFile(balloonfile, self.isthink)
|
||||
|
||||
|
||||
|
@ -814,20 +806,20 @@ class Ponysay():
|
|||
## Displaying methods ##
|
||||
########################
|
||||
|
||||
'''
|
||||
Prints the name of the program and the version of the program
|
||||
'''
|
||||
def version(self):
|
||||
'''
|
||||
Prints the name of the program and the version of the program
|
||||
'''
|
||||
## Prints the "ponysay $VERSION", if this is modified, ./dev/dist.sh must be modified accordingly
|
||||
print('%s %s' % ('ponysay', VERSION))
|
||||
|
||||
|
||||
'''
|
||||
Print the pony with a speech or though bubble. message, pony and wrap from args are used.
|
||||
|
||||
@param args:ArgParser Parsed command line arguments
|
||||
'''
|
||||
def print_pony(self, args):
|
||||
'''
|
||||
Print the pony with a speech or though bubble. message, pony and wrap from args are used.
|
||||
|
||||
@param args:ArgParser Parsed command line arguments
|
||||
'''
|
||||
## Get the pony
|
||||
(selection, standard, extra) = ([], [], [])
|
||||
for ponydir in self.ponydirs:
|
||||
|
|
|
@ -39,44 +39,45 @@ from ponysay import *
|
|||
from metadata import *
|
||||
|
||||
|
||||
VERSION = 'dev' # this line should not be edited, it is fixed by the build system
|
||||
'''
|
||||
The version of ponysay
|
||||
'''
|
||||
VERSION = 'dev' # this line should not be edited, it is fixed by the build system
|
||||
|
||||
|
||||
|
||||
'''
|
||||
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)
|
||||
'''
|
||||
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'))
|
||||
|
||||
'''
|
||||
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'):
|
||||
'''
|
||||
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)
|
||||
'''
|
||||
sys.stderr.buffer.write((str(text) + end).encode('utf-8'))
|
||||
|
||||
|
||||
|
||||
'''
|
||||
This is the mane class of ponysay-tool
|
||||
'''
|
||||
class PonysayTool():
|
||||
'''
|
||||
Starts the part of the program the arguments indicate
|
||||
|
||||
@param args:ArgParser Parsed command line arguments
|
||||
This is the mane class of ponysay-tool
|
||||
'''
|
||||
|
||||
def __init__(self, args):
|
||||
'''
|
||||
Starts the part of the program the arguments indicate
|
||||
|
||||
@param args:ArgParser Parsed command line arguments
|
||||
'''
|
||||
if args.argcount == 0:
|
||||
args.help()
|
||||
exit(255)
|
||||
|
@ -194,13 +195,13 @@ class PonysayTool():
|
|||
exit(253)
|
||||
|
||||
|
||||
'''
|
||||
Execute ponysay!
|
||||
|
||||
@param args Arguments
|
||||
@param message Message
|
||||
'''
|
||||
def execPonysay(self, args, message = ''):
|
||||
'''
|
||||
Execute ponysay!
|
||||
|
||||
@param args Arguments
|
||||
@param message Message
|
||||
'''
|
||||
class PhonyArgParser():
|
||||
def __init__(self, args, message):
|
||||
self.argcount = len(args) + (0 if message is None else 1)
|
||||
|
@ -239,13 +240,13 @@ class PonysayTool():
|
|||
return out
|
||||
|
||||
|
||||
'''
|
||||
Browse ponies
|
||||
|
||||
@param ponydir:str The pony directory to browse
|
||||
@param restriction:list<str> Restrictions on listed ponies, may be None
|
||||
'''
|
||||
def browse(self, ponydir, restriction):
|
||||
'''
|
||||
Browse ponies
|
||||
|
||||
@param ponydir:str The pony directory to browse
|
||||
@param restriction:list<str> Restrictions on listed ponies, may be None
|
||||
'''
|
||||
## 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):
|
||||
|
@ -431,10 +432,10 @@ class PonysayTool():
|
|||
(x, y) = (0, 0)
|
||||
|
||||
|
||||
'''
|
||||
Generate all kmsponies for the current TTY palette
|
||||
'''
|
||||
def generateKMS(self):
|
||||
'''
|
||||
Generate all kmsponies for the current TTY palette
|
||||
'''
|
||||
class PhonyArgParser():
|
||||
def __init__(self, key, value):
|
||||
self.argcount = 3
|
||||
|
@ -495,13 +496,13 @@ class PonysayTool():
|
|||
sys.stdout = stdout
|
||||
|
||||
|
||||
'''
|
||||
Generate pony dimension file for a directory
|
||||
|
||||
@param ponydir:str The directory
|
||||
@param ponies:itr<str>? Ponies to which to limit
|
||||
'''
|
||||
def generateDimensions(self, ponydir, ponies = None):
|
||||
'''
|
||||
Generate pony dimension file for a directory
|
||||
|
||||
@param ponydir:str The directory
|
||||
@param ponies:itr<str>? Ponies to which to limit
|
||||
'''
|
||||
dimensions = []
|
||||
ponyset = None if (ponies is None) or (len(ponies) == 0) else set(ponies)
|
||||
for ponyfile in os.listdir(ponydir):
|
||||
|
@ -581,13 +582,13 @@ class PonysayTool():
|
|||
file.flush()
|
||||
|
||||
|
||||
'''
|
||||
Generate pony metadata collection file for a directory
|
||||
|
||||
@param ponydir:str The directory
|
||||
@param ponies:itr<str>? Ponies to which to limit
|
||||
'''
|
||||
def generateMetadata(self, ponydir, ponies = None):
|
||||
'''
|
||||
Generate pony metadata collection file for a directory
|
||||
|
||||
@param ponydir:str The directory
|
||||
@param ponies:itr<str>? Ponies to which to limit
|
||||
'''
|
||||
if not ponydir.endswith('/'):
|
||||
ponydir += '/'
|
||||
def makeset(value):
|
||||
|
@ -663,12 +664,12 @@ class PonysayTool():
|
|||
file.flush()
|
||||
|
||||
|
||||
'''
|
||||
Edit a pony file's metadata
|
||||
|
||||
@param ponyfile:str A pony file to edit
|
||||
'''
|
||||
def editmeta(self, ponyfile):
|
||||
'''
|
||||
Edit a pony file's metadata
|
||||
|
||||
@param ponyfile:str A pony file to edit
|
||||
'''
|
||||
(data, meta, image) = 3 * [None]
|
||||
|
||||
with open(ponyfile, 'rb') as file:
|
||||
|
@ -838,32 +839,32 @@ class PonysayTool():
|
|||
|
||||
|
||||
|
||||
'''
|
||||
GNU Emacs alike text area
|
||||
'''
|
||||
class TextArea(): # TODO support small screens
|
||||
class TextArea(): # TODO support small screens (This is being work on in GNU-Pony/featherweight)
|
||||
'''
|
||||
Constructor
|
||||
|
||||
@param fields:list<str> Field names
|
||||
@param datamap:dist<str,str> Data map
|
||||
@param left:int Left position of the component
|
||||
@param top:int Top position of the component
|
||||
@param width:int Width of the component
|
||||
@param height:int Height of the component
|
||||
@param termsize:(int,int) The height and width of the terminal
|
||||
GNU Emacs alike text area
|
||||
'''
|
||||
def __init__(self, fields, datamap, left, top, width, height, termsize):
|
||||
'''
|
||||
Constructor
|
||||
|
||||
@param fields:list<str> Field names
|
||||
@param datamap:dist<str,str> Data map
|
||||
@param left:int Left position of the component
|
||||
@param top:int Top position of the component
|
||||
@param width:int Width of the component
|
||||
@param height:int Height of the component
|
||||
@param termsize:(int,int) The height and width of the terminal
|
||||
'''
|
||||
(self.fields, self.datamap, self.left, self.top, self.width, self.height, self.termsize) \
|
||||
= (fields, datamap, left, top, width - 1, height, termsize)
|
||||
|
||||
|
||||
'''
|
||||
Execute text reading
|
||||
|
||||
@param saver Save method
|
||||
'''
|
||||
def run(self, saver):
|
||||
'''
|
||||
Execute text reading
|
||||
|
||||
@param saver Save method
|
||||
'''
|
||||
innerleft = UCS.dispLen(max(self.fields, key = UCS.dispLen)) + self.left + 3
|
||||
|
||||
leftlines = []
|
||||
|
@ -1183,25 +1184,25 @@ class TextArea(): # TODO support small screens
|
|||
|
||||
|
||||
|
||||
HOME = os.environ['HOME'] if 'HOME' in os.environ else os.path.expanduser('~')
|
||||
'''
|
||||
The user's home directory
|
||||
'''
|
||||
HOME = os.environ['HOME'] if 'HOME' in os.environ else os.path.expanduser('~')
|
||||
|
||||
pipelinein = not sys.stdin.isatty()
|
||||
'''
|
||||
Whether stdin is piped
|
||||
'''
|
||||
pipelinein = not sys.stdin.isatty()
|
||||
|
||||
pipelineout = not sys.stdout.isatty()
|
||||
'''
|
||||
Whether stdout is piped
|
||||
'''
|
||||
pipelineout = not sys.stdout.isatty()
|
||||
|
||||
pipelineerr = not sys.stderr.isatty()
|
||||
'''
|
||||
Whether stderr is piped
|
||||
'''
|
||||
pipelineerr = not sys.stderr.isatty()
|
||||
|
||||
|
||||
usage_program = '\033[34;1mponysay-tool\033[21;39m'
|
||||
|
@ -1241,10 +1242,10 @@ 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()
|
||||
'''
|
||||
Whether at least one unrecognised option was used
|
||||
'''
|
||||
unrecognised = not opts.parse()
|
||||
|
||||
PonysayTool(args = opts)
|
||||
|
||||
|
|
|
@ -33,24 +33,25 @@ from common import *
|
|||
|
||||
|
||||
|
||||
'''
|
||||
Class used for correcting spellos and typos,
|
||||
|
||||
Note that this implementation will not find that correctly spelled word are correct faster than it corrects words.
|
||||
It is also limited to words of size 0 to 127 (inclusive)
|
||||
'''
|
||||
class SpelloCorrecter(): # Naïvely and quickly ported and adapted from optimised Java, may not be the nicest, or even fast, Python code
|
||||
'''
|
||||
Constructor
|
||||
Class used for correcting spellos and typos,
|
||||
|
||||
@param directories:list<str> List of directories that contains the file names with the correct spelling
|
||||
@param ending:str The file name ending of the correctly spelled file names, this is removed for the name
|
||||
|
||||
-- OR -- (emulated overloading [overloading is absent in Python])
|
||||
|
||||
@param directories:list<str> The file names with the correct spelling
|
||||
Note that this implementation will not find that correctly spelled word are correct faster than it corrects words.
|
||||
It is also limited to words of size 0 to 127 (inclusive)
|
||||
'''
|
||||
|
||||
def __init__(self, directories, ending = None):
|
||||
'''
|
||||
Constructor
|
||||
|
||||
@param directories:list<str> List of directories that contains the file names with the correct spelling
|
||||
@param ending:str The file name ending of the correctly spelled file names, this is removed for the name
|
||||
|
||||
-- OR -- (emulated overloading [overloading is absent in Python])
|
||||
|
||||
@param directories:list<str> The file names with the correct spelling
|
||||
'''
|
||||
self.weights = {'k' : {'c' : 0.25, 'g' : 0.75, 'q' : 0.125},
|
||||
'c' : {'k' : 0.25, 'g' : 0.75, 's' : 0.5, 'z' : 0.5, 'q' : 0.125},
|
||||
's' : {'z' : 0.25, 'c' : 0.5},
|
||||
|
@ -145,13 +146,13 @@ class SpelloCorrecter(): # Naïvely and quickly ported and adapted from optimise
|
|||
# index -= 1;
|
||||
|
||||
|
||||
'''
|
||||
Finds the closests correct spelled word
|
||||
|
||||
@param used:str The word to correct
|
||||
@return (words, distance):(list<string>, int) A list the closest spellings and the weighted distance
|
||||
'''
|
||||
def correct(self, used):
|
||||
'''
|
||||
Finds the closests correct spelled word
|
||||
|
||||
@param used:str The word to correct
|
||||
@return (words, distance):(list<string>, int) A list the closest spellings and the weighted distance
|
||||
'''
|
||||
if len(used) > 127:
|
||||
return ([used], 0)
|
||||
|
||||
|
@ -159,12 +160,12 @@ class SpelloCorrecter(): # Naïvely and quickly ported and adapted from optimise
|
|||
return (self.corrections, self.closestDistance)
|
||||
|
||||
|
||||
'''
|
||||
Finds the closests correct spelled word
|
||||
|
||||
@param used:str The word to correct, it must satisfy all restrictions
|
||||
'''
|
||||
def __correct(self, used):
|
||||
'''
|
||||
Finds the closests correct spelled word
|
||||
|
||||
@param used:str The word to correct, it must satisfy all restrictions
|
||||
'''
|
||||
self.closestDistance = 0x7FFFFFFF
|
||||
previous = self.dictionary[-1]
|
||||
prevLen = 0
|
||||
|
@ -217,18 +218,18 @@ class SpelloCorrecter(): # Naïvely and quickly ported and adapted from optimise
|
|||
prevLen = len(proper)
|
||||
|
||||
|
||||
'''
|
||||
Calculate the distance between a correct word and a incorrect word
|
||||
|
||||
@param proper:str The correct word
|
||||
@param y0:int The offset for `proper`
|
||||
@param yn:int The length, before applying `y0`, of `proper`
|
||||
@param used:str The incorrect word
|
||||
@param x0:int The offset for `used`
|
||||
@param xn:int The length, before applying `x0`, of `used`
|
||||
@return :float The distance between the words
|
||||
'''
|
||||
def __distance(self, proper, y0, yn, used, x0, xn):
|
||||
'''
|
||||
Calculate the distance between a correct word and a incorrect word
|
||||
|
||||
@param proper:str The correct word
|
||||
@param y0:int The offset for `proper`
|
||||
@param yn:int The length, before applying `y0`, of `proper`
|
||||
@param used:str The incorrect word
|
||||
@param x0:int The offset for `used`
|
||||
@param xn:int The length, before applying `x0`, of `used`
|
||||
@return :float The distance between the words
|
||||
'''
|
||||
my = self.M[y0]
|
||||
for y in range(y0, yn):
|
||||
best = 0x7FFFFFFF
|
||||
|
|
39
src/ucs.py
39
src/ucs.py
|
@ -33,18 +33,19 @@ from common import *
|
|||
|
||||
|
||||
|
||||
'''
|
||||
UCS utility class
|
||||
'''
|
||||
class UCS():
|
||||
'''
|
||||
Checks whether a character is a combining character
|
||||
|
||||
@param char:chr The character to test
|
||||
@return :bool Whether the character is a combining character
|
||||
UCS utility class
|
||||
'''
|
||||
|
||||
@staticmethod
|
||||
def isCombining(char):
|
||||
'''
|
||||
Checks whether a character is a combining character
|
||||
|
||||
@param char:chr The character to test
|
||||
@return :bool Whether the character is a combining character
|
||||
'''
|
||||
o = ord(char)
|
||||
if (0x0300 <= o) and (o <= 0x036F): return True
|
||||
if (0x20D0 <= o) and (o <= 0x20FF): return True
|
||||
|
@ -53,14 +54,14 @@ class UCS():
|
|||
return False
|
||||
|
||||
|
||||
'''
|
||||
Gets the number of combining characters in a string
|
||||
|
||||
@param string:str A text to count combining characters in
|
||||
@return :int The number of combining characters in the string
|
||||
'''
|
||||
@staticmethod
|
||||
def countCombining(string):
|
||||
'''
|
||||
Gets the number of combining characters in a string
|
||||
|
||||
@param string:str A text to count combining characters in
|
||||
@return :int The number of combining characters in the string
|
||||
'''
|
||||
rc = 0
|
||||
for char in string:
|
||||
if UCS.isCombining(char):
|
||||
|
@ -68,13 +69,13 @@ class UCS():
|
|||
return rc
|
||||
|
||||
|
||||
'''
|
||||
Gets length of a string not counting combining characters
|
||||
|
||||
@param string:str The text of which to determine the monospaced width
|
||||
@return The determine the monospaced width of the text, provided it does not have escape sequnces
|
||||
'''
|
||||
@staticmethod
|
||||
def dispLen(string):
|
||||
'''
|
||||
Gets length of a string not counting combining characters
|
||||
|
||||
@param string:str The text of which to determine the monospaced width
|
||||
@return The determine the monospaced width of the text, provided it does not have escape sequnces
|
||||
'''
|
||||
return len(string) - UCS.countCombining(string)
|
||||
|
||||
|
|
Loading…
Reference in a new issue