Commit 4f8f9765 authored by Raymond Hettinger's avatar Raymond Hettinger

Add optional fillchar argument to ljust(), rjust(), and center() string methods.

parent bd93b3ea
...@@ -546,9 +546,9 @@ objects support: ...@@ -546,9 +546,9 @@ objects support:
Return a copy of the string with only its first character capitalized. Return a copy of the string with only its first character capitalized.
\end{methoddesc} \end{methoddesc}
\begin{methoddesc}[string]{center}{width} \begin{methoddesc}[string]{center}{width\optional{, fillchar}}
Return centered in a string of length \var{width}. Padding is done Return centered in a string of length \var{width}. Padding is done
using spaces. using the specified \var{fillchar} (default is a space).
\end{methoddesc} \end{methoddesc}
\begin{methoddesc}[string]{count}{sub\optional{, start\optional{, end}}} \begin{methoddesc}[string]{count}{sub\optional{, start\optional{, end}}}
...@@ -645,9 +645,10 @@ sequence \var{seq}. The separator between elements is the string ...@@ -645,9 +645,10 @@ sequence \var{seq}. The separator between elements is the string
providing this method. providing this method.
\end{methoddesc} \end{methoddesc}
\begin{methoddesc}[string]{ljust}{width} \begin{methoddesc}[string]{ljust}{width\optional{, fillchar}}
Return the string left justified in a string of length \var{width}. Return the string left justified in a string of length \var{width}.
Padding is done using spaces. The original string is returned if Padding is done using the specified \var{fillchar} (default is a
space). The original string is returned if
\var{width} is less than \code{len(\var{s})}. \var{width} is less than \code{len(\var{s})}.
\end{methoddesc} \end{methoddesc}
...@@ -683,9 +684,10 @@ Like \method{rfind()} but raises \exception{ValueError} when the ...@@ -683,9 +684,10 @@ Like \method{rfind()} but raises \exception{ValueError} when the
substring \var{sub} is not found. substring \var{sub} is not found.
\end{methoddesc} \end{methoddesc}
\begin{methoddesc}[string]{rjust}{width} \begin{methoddesc}[string]{rjust}{width\optional{, fillchar}}
Return the string right justified in a string of length \var{width}. Return the string right justified in a string of length \var{width}.
Padding is done using spaces. The original string is returned if Padding is done using the specified \var{fillchar} (default is a space).
The original string is returned if
\var{width} is less than \code{len(\var{s})}. \var{width} is less than \code{len(\var{s})}.
\end{methoddesc} \end{methoddesc}
......
...@@ -60,7 +60,8 @@ class UserString: ...@@ -60,7 +60,8 @@ class UserString:
# the following methods are defined in alphabetical order: # the following methods are defined in alphabetical order:
def capitalize(self): return self.__class__(self.data.capitalize()) def capitalize(self): return self.__class__(self.data.capitalize())
def center(self, width): return self.__class__(self.data.center(width)) def center(self, width, *args):
return self.__class__(self.data.center(width, *args))
def count(self, sub, start=0, end=sys.maxint): def count(self, sub, start=0, end=sys.maxint):
return self.data.count(sub, start, end) return self.data.count(sub, start, end)
def decode(self, encoding=None, errors=None): # XXX improve this? def decode(self, encoding=None, errors=None): # XXX improve this?
...@@ -97,7 +98,8 @@ class UserString: ...@@ -97,7 +98,8 @@ class UserString:
def istitle(self): return self.data.istitle() def istitle(self): return self.data.istitle()
def isupper(self): return self.data.isupper() def isupper(self): return self.data.isupper()
def join(self, seq): return self.data.join(seq) def join(self, seq): return self.data.join(seq)
def ljust(self, width): return self.__class__(self.data.ljust(width)) def ljust(self, width, *args):
return self.__class__(self.data.ljust(width, *args))
def lower(self): return self.__class__(self.data.lower()) def lower(self): return self.__class__(self.data.lower())
def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars)) def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars))
def replace(self, old, new, maxsplit=-1): def replace(self, old, new, maxsplit=-1):
...@@ -106,7 +108,8 @@ class UserString: ...@@ -106,7 +108,8 @@ class UserString:
return self.data.rfind(sub, start, end) return self.data.rfind(sub, start, end)
def rindex(self, sub, start=0, end=sys.maxint): def rindex(self, sub, start=0, end=sys.maxint):
return self.data.rindex(sub, start, end) return self.data.rindex(sub, start, end)
def rjust(self, width): return self.__class__(self.data.rjust(width)) def rjust(self, width, *args):
return self.__class__(self.data.rjust(width, *args))
def rstrip(self, chars=None): return self.__class__(self.data.rstrip(chars)) def rstrip(self, chars=None): return self.__class__(self.data.rstrip(chars))
def split(self, sep=None, maxsplit=-1): def split(self, sep=None, maxsplit=-1):
return self.data.split(sep, maxsplit) return self.data.split(sep, maxsplit)
......
...@@ -237,37 +237,37 @@ def atol(s, base=10): ...@@ -237,37 +237,37 @@ def atol(s, base=10):
# Left-justify a string # Left-justify a string
def ljust(s, width): def ljust(s, width, *args):
"""ljust(s, width) -> string """ljust(s, width[, fillchar]) -> string
Return a left-justified version of s, in a field of the Return a left-justified version of s, in a field of the
specified width, padded with spaces as needed. The string is specified width, padded with spaces as needed. The string is
never truncated. never truncated. If specified the fillchar is used instead of spaces.
""" """
return s.ljust(width) return s.ljust(width, *args)
# Right-justify a string # Right-justify a string
def rjust(s, width): def rjust(s, width, *args):
"""rjust(s, width) -> string """rjust(s, width[, fillchar]) -> string
Return a right-justified version of s, in a field of the Return a right-justified version of s, in a field of the
specified width, padded with spaces as needed. The string is specified width, padded with spaces as needed. The string is
never truncated. never truncated. If specified the fillchar is used instead of spaces.
""" """
return s.rjust(width) return s.rjust(width, *args)
# Center a string # Center a string
def center(s, width): def center(s, width, *args):
"""center(s, width) -> string """center(s, width[, fillchar]) -> string
Return a center version of s, in a field of the specified Return a center version of s, in a field of the specified
width. padded with spaces as needed. The string is never width. padded with spaces as needed. The string is never
truncated. truncated. If specified the fillchar is used instead of spaces.
""" """
return s.center(width) return s.center(width, *args)
# Zero-fill a number, e.g., (12, 3) --> '012' and (-3, 3) --> '-03' # Zero-fill a number, e.g., (12, 3) --> '012' and (-3, 3) --> '-03'
# Decadent feature: the argument may be a string or a number # Decadent feature: the argument may be a string or a number
......
...@@ -227,7 +227,7 @@ class CommonTest(unittest.TestCase): ...@@ -227,7 +227,7 @@ class CommonTest(unittest.TestCase):
self.checkequal('abc ', 'abc', 'ljust', 6) self.checkequal('abc ', 'abc', 'ljust', 6)
self.checkequal('abc', 'abc', 'ljust', 3) self.checkequal('abc', 'abc', 'ljust', 3)
self.checkequal('abc', 'abc', 'ljust', 2) self.checkequal('abc', 'abc', 'ljust', 2)
self.checkequal('abc*******', 'abc', 'ljust', 10, '*')
self.checkraises(TypeError, 'abc', 'ljust') self.checkraises(TypeError, 'abc', 'ljust')
def test_rjust(self): def test_rjust(self):
...@@ -235,7 +235,7 @@ class CommonTest(unittest.TestCase): ...@@ -235,7 +235,7 @@ class CommonTest(unittest.TestCase):
self.checkequal(' abc', 'abc', 'rjust', 6) self.checkequal(' abc', 'abc', 'rjust', 6)
self.checkequal('abc', 'abc', 'rjust', 3) self.checkequal('abc', 'abc', 'rjust', 3)
self.checkequal('abc', 'abc', 'rjust', 2) self.checkequal('abc', 'abc', 'rjust', 2)
self.checkequal('*******abc', 'abc', 'rjust', 10, '*')
self.checkraises(TypeError, 'abc', 'rjust') self.checkraises(TypeError, 'abc', 'rjust')
def test_center(self): def test_center(self):
...@@ -243,7 +243,7 @@ class CommonTest(unittest.TestCase): ...@@ -243,7 +243,7 @@ class CommonTest(unittest.TestCase):
self.checkequal(' abc ', 'abc', 'center', 6) self.checkequal(' abc ', 'abc', 'center', 6)
self.checkequal('abc', 'abc', 'center', 3) self.checkequal('abc', 'abc', 'center', 3)
self.checkequal('abc', 'abc', 'center', 2) self.checkequal('abc', 'abc', 'center', 2)
self.checkequal('***abc****', 'abc', 'center', 10, '*')
self.checkraises(TypeError, 'abc', 'center') self.checkraises(TypeError, 'abc', 'center')
def test_swapcase(self): def test_swapcase(self):
......
...@@ -12,6 +12,10 @@ What's New in Python 2.4 alpha 1? ...@@ -12,6 +12,10 @@ What's New in Python 2.4 alpha 1?
Core and builtins Core and builtins
----------------- -----------------
- For str and unicode objects, the ljust(), center(), and rjust()
methods now accept an optional argument specifying a fill
character other than a space.
- When method objects have an attribute that can be satisfied either - When method objects have an attribute that can be satisfied either
by the function object or by the method object, the function by the function object or by the method object, the function
object's attribute usually wins. Christian Tismer pointed out that object's attribute usually wins. Christian Tismer pointed out that
......
...@@ -2617,16 +2617,18 @@ pad(PyStringObject *self, int left, int right, char fill) ...@@ -2617,16 +2617,18 @@ pad(PyStringObject *self, int left, int right, char fill)
} }
PyDoc_STRVAR(ljust__doc__, PyDoc_STRVAR(ljust__doc__,
"S.ljust(width) -> string\n" "S.ljust(width[, fillchar]) -> string\n"
"\n" "\n"
"Return S left justified in a string of length width. Padding is\n" "Return S left justified in a string of length width. Padding is\n"
"done using spaces."); "done using the specified fill character (default is a space).");
static PyObject * static PyObject *
string_ljust(PyStringObject *self, PyObject *args) string_ljust(PyStringObject *self, PyObject *args)
{ {
int width; int width;
if (!PyArg_ParseTuple(args, "i:ljust", &width)) char fillchar = ' ';
if (!PyArg_ParseTuple(args, "i|c:ljust", &width, &fillchar))
return NULL; return NULL;
if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) { if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) {
...@@ -2634,21 +2636,23 @@ string_ljust(PyStringObject *self, PyObject *args) ...@@ -2634,21 +2636,23 @@ string_ljust(PyStringObject *self, PyObject *args)
return (PyObject*) self; return (PyObject*) self;
} }
return pad(self, 0, width - PyString_GET_SIZE(self), ' '); return pad(self, 0, width - PyString_GET_SIZE(self), fillchar);
} }
PyDoc_STRVAR(rjust__doc__, PyDoc_STRVAR(rjust__doc__,
"S.rjust(width) -> string\n" "S.rjust(width[, fillchar]) -> string\n"
"\n" "\n"
"Return S right justified in a string of length width. Padding is\n" "Return S right justified in a string of length width. Padding is\n"
"done using spaces."); "done using the specified fill character (default is a space)");
static PyObject * static PyObject *
string_rjust(PyStringObject *self, PyObject *args) string_rjust(PyStringObject *self, PyObject *args)
{ {
int width; int width;
if (!PyArg_ParseTuple(args, "i:rjust", &width)) char fillchar = ' ';
if (!PyArg_ParseTuple(args, "i|c:rjust", &width, &fillchar))
return NULL; return NULL;
if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) { if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) {
...@@ -2656,23 +2660,24 @@ string_rjust(PyStringObject *self, PyObject *args) ...@@ -2656,23 +2660,24 @@ string_rjust(PyStringObject *self, PyObject *args)
return (PyObject*) self; return (PyObject*) self;
} }
return pad(self, width - PyString_GET_SIZE(self), 0, ' '); return pad(self, width - PyString_GET_SIZE(self), 0, fillchar);
} }
PyDoc_STRVAR(center__doc__, PyDoc_STRVAR(center__doc__,
"S.center(width) -> string\n" "S.center(width[, fillchar]) -> string\n"
"\n" "\n"
"Return S centered in a string of length width. Padding is done\n" "Return S centered in a string of length width. Padding is\n"
"using spaces."); "done using the specified fill character (default is a space)");
static PyObject * static PyObject *
string_center(PyStringObject *self, PyObject *args) string_center(PyStringObject *self, PyObject *args)
{ {
int marg, left; int marg, left;
int width; int width;
char fillchar = ' ';
if (!PyArg_ParseTuple(args, "i:center", &width)) if (!PyArg_ParseTuple(args, "i|c:center", &width, &fillchar))
return NULL; return NULL;
if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) { if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) {
...@@ -2683,7 +2688,7 @@ string_center(PyStringObject *self, PyObject *args) ...@@ -2683,7 +2688,7 @@ string_center(PyStringObject *self, PyObject *args)
marg = width - PyString_GET_SIZE(self); marg = width - PyString_GET_SIZE(self);
left = marg / 2 + (marg & width & 1); left = marg / 2 + (marg & width & 1);
return pad(self, left, marg - left, ' '); return pad(self, left, marg - left, fillchar);
} }
PyDoc_STRVAR(zfill__doc__, PyDoc_STRVAR(zfill__doc__,
......
...@@ -4404,19 +4404,47 @@ onError: ...@@ -4404,19 +4404,47 @@ onError:
} }
#endif #endif
/* Argument converter. Coerces to a single unicode character */
static int
convert_uc(PyObject *obj, void *addr)
{
Py_UNICODE *fillcharloc = (Py_UNICODE *)addr;
PyObject *uniobj;
Py_UNICODE *unistr;
uniobj = PyUnicode_FromObject(obj);
if (uniobj == NULL) {
PyErr_SetString(PyExc_TypeError,
"The fill character cannot be converted to Unicode");
return 0;
}
if (PyUnicode_GET_SIZE(uniobj) != 1) {
PyErr_SetString(PyExc_TypeError,
"The fill character must be exactly one character long");
Py_DECREF(uniobj);
return 0;
}
unistr = PyUnicode_AS_UNICODE(uniobj);
*fillcharloc = unistr[0];
Py_DECREF(uniobj);
return 1;
}
PyDoc_STRVAR(center__doc__, PyDoc_STRVAR(center__doc__,
"S.center(width) -> unicode\n\ "S.center(width[, fillchar]) -> unicode\n\
\n\ \n\
Return S centered in a Unicode string of length width. Padding is done\n\ Return S centered in a Unicode string of length width. Padding is\n\
using spaces."); done using the specified fill character (default is a space)");
static PyObject * static PyObject *
unicode_center(PyUnicodeObject *self, PyObject *args) unicode_center(PyUnicodeObject *self, PyObject *args)
{ {
int marg, left; int marg, left;
int width; int width;
Py_UNICODE fillchar = ' ';
if (!PyArg_ParseTuple(args, "i:center", &width)) if (!PyArg_ParseTuple(args, "i|O&:center", &width, convert_uc, &fillchar))
return NULL; return NULL;
if (self->length >= width && PyUnicode_CheckExact(self)) { if (self->length >= width && PyUnicode_CheckExact(self)) {
...@@ -4427,7 +4455,7 @@ unicode_center(PyUnicodeObject *self, PyObject *args) ...@@ -4427,7 +4455,7 @@ unicode_center(PyUnicodeObject *self, PyObject *args)
marg = width - self->length; marg = width - self->length;
left = marg / 2 + (marg & width & 1); left = marg / 2 + (marg & width & 1);
return (PyObject*) pad(self, left, marg - left, ' '); return (PyObject*) pad(self, left, marg - left, fillchar);
} }
#if 0 #if 0
...@@ -5170,16 +5198,18 @@ unicode_length(PyUnicodeObject *self) ...@@ -5170,16 +5198,18 @@ unicode_length(PyUnicodeObject *self)
} }
PyDoc_STRVAR(ljust__doc__, PyDoc_STRVAR(ljust__doc__,
"S.ljust(width) -> unicode\n\ "S.ljust(width[, fillchar]) -> unicode\n\
\n\ \n\
Return S left justified in a Unicode string of length width. Padding is\n\ Return S left justified in a Unicode string of length width. Padding is\n\
done using spaces."); done using the specified fill character (default is a space).");
static PyObject * static PyObject *
unicode_ljust(PyUnicodeObject *self, PyObject *args) unicode_ljust(PyUnicodeObject *self, PyObject *args)
{ {
int width; int width;
if (!PyArg_ParseTuple(args, "i:ljust", &width)) Py_UNICODE fillchar = ' ';
if (!PyArg_ParseTuple(args, "i|O&:ljust", &width, convert_uc, &fillchar))
return NULL; return NULL;
if (self->length >= width && PyUnicode_CheckExact(self)) { if (self->length >= width && PyUnicode_CheckExact(self)) {
...@@ -5187,7 +5217,7 @@ unicode_ljust(PyUnicodeObject *self, PyObject *args) ...@@ -5187,7 +5217,7 @@ unicode_ljust(PyUnicodeObject *self, PyObject *args)
return (PyObject*) self; return (PyObject*) self;
} }
return (PyObject*) pad(self, 0, width - self->length, ' '); return (PyObject*) pad(self, 0, width - self->length, fillchar);
} }
PyDoc_STRVAR(lower__doc__, PyDoc_STRVAR(lower__doc__,
...@@ -5552,16 +5582,18 @@ unicode_rindex(PyUnicodeObject *self, PyObject *args) ...@@ -5552,16 +5582,18 @@ unicode_rindex(PyUnicodeObject *self, PyObject *args)
} }
PyDoc_STRVAR(rjust__doc__, PyDoc_STRVAR(rjust__doc__,
"S.rjust(width) -> unicode\n\ "S.rjust(width[, fillchar]) -> unicode\n\
\n\ \n\
Return S right justified in a Unicode string of length width. Padding is\n\ Return S right justified in a Unicode string of length width. Padding is\n\
done using spaces."); done using the specified fill character (default is a space).");
static PyObject * static PyObject *
unicode_rjust(PyUnicodeObject *self, PyObject *args) unicode_rjust(PyUnicodeObject *self, PyObject *args)
{ {
int width; int width;
if (!PyArg_ParseTuple(args, "i:rjust", &width)) Py_UNICODE fillchar = ' ';
if (!PyArg_ParseTuple(args, "i|O&:rjust", &width, convert_uc, &fillchar))
return NULL; return NULL;
if (self->length >= width && PyUnicode_CheckExact(self)) { if (self->length >= width && PyUnicode_CheckExact(self)) {
...@@ -5569,7 +5601,7 @@ unicode_rjust(PyUnicodeObject *self, PyObject *args) ...@@ -5569,7 +5601,7 @@ unicode_rjust(PyUnicodeObject *self, PyObject *args)
return (PyObject*) self; return (PyObject*) self;
} }
return (PyObject*) pad(self, width - self->length, 0, ' '); return (PyObject*) pad(self, width - self->length, 0, fillchar);
} }
static PyObject* static PyObject*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment