#-*- coding: utf-8 -*- # Copyright 2008-2010 Mir Calculate Ltd. http://www.calculate-linux.org # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from re import search, compile, S from cl_utils import _toUNICODE def prettyColumnStr(*cols): '''Функция преобразования строк в текстовые колонки. Если указанный текст не помещается в колонку, то строка переносится на следующую этой же колонки перенос текста идет по словам, и текст выравнивается по ширине колонки за счет дополнительных пробелов между словами. Если в строке используется перенос строки, то текст переносится не просто на следующую строку, а также на следующую строку колонки, причем если используется \r текст выравнива- ется по ширине, а если \n, то просто перевод строки. Параметры: cols множестово пар: текст, ширина колонки, причем, если у последней колонки не указывать ширину, то она будет выведена вся. Возвращаемые параметры: строка, которую можно использовать для вывода на экран Пример: columnWrite( "Some text", 10, "Next column", 20 ) ''' # шаблон поиска переводов строк wherenr = compile( '[\n\r]', S ) retstr = "" # перевести кортеж в список, т.к. изменяется cols = list(cols) # перевести текст в юникод, заодно перевести числа в строку noconvert = False space = u' ' nospace = u'' for i in xrange(0,len(cols),2): cols[i] = _toUNICODE(cols[i]) # флаг "есть еще текст для вывода" repeat = True while repeat: # сбросить итератор на первый элемент q = 0 repeat = False # пока не закончили перебирать параметры (перебираем по парам) while q < len(cols): # если это последний параметр, и для него не указана ширина if q == len(cols)-1: # выводим его полностью не смотря на ширину окна retstr += cols[q] + " " cols[q] = '' else: # вывести часть строки не больше указанной ширины колонки partstr = cols[q][:cols[q+1]] # искать перевод строки с полученной части brfind = wherenr.search(partstr) # если это не последняя колонка if q + 2 < len(cols): # добавить разделитель между колонками cellspacing = space else: # разделитель не нужен cellspacing = nospace # если перевод строки найден, то if brfind != None: # для текущего вывода в колонку # берем часть строки до перевода partstr = partstr[:brfind.start()] # остальная часть идет в остаток (без перевода) cols[q] = cols[q][brfind.start()+1:] # # если используется перевод каретки # if brfind.group() == '\r': # # то выравниваем по ширине колонки # partstr = partstr.ljust(cols[q+1], ' ') # else: # # добавить отступы чтобы закончить колонку partstr = partstr.ljust(cols[q+1], ' ') # если взята часть строки elif len(partstr) == cols[q+1] and partstr != cols[q]: # если взята часть строки (разрыв в слове) if cols[q][cols[q+1]] != ' ': # ищем ближайший пробел справа spacepos = partstr.rfind(' ') # если пробел найти не удалось if spacepos == -1: # то на вывод идет часть строки равной ширине cols[q] = cols[q][cols[q+1]:] # если пробел найден else: # обрезаем строку до найденного пробела partstr = partstr[:spacepos] cols[q] = cols[q][spacepos+1:] # если взята часть строки (разрыв на пробеле) else: # ислючить переносной пробел cols[q] = cols[q][cols[q+1]+1:] # выровнить текст по ширине колонки partstr = partstr.ljust(cols[q+1], ' ') #partstr = justify(partstr, cols[q+1]) # остатки строки else: # добавить отступы чтобы закончить колонку partstr = partstr.ljust(cols[q+1], ' ') cols[q] = '' retstr+= partstr + cellspacing # остальную часть строки оставить на следующую итерацию # если от строки что то осаталось if len(cols[q]) > 0: # отметить запуск еще одной итерации по параметрам repeat = True # следующая пара q += 2 # колонки отображены retstr += "\n" return retstr.encode('utf8') def columnStr(*cols): '''Вывод данных по колонкам, причем, если данные не вмещаются в указнаную колонку, то они переносятся на следующую строку в нужную колонку. В строку. Параметры: cols множестово пар: текст, ширина колонки, причем, если у последней колонки не указывать ширину, то она будет выведена вся. Возвращаемые параметры: строка, которую можно использовать для вывода на экран Пример: columnWrite( "Some text", 10, "Next column", 20 ) ''' retstr = "" # перевести кортеж в список, т.к. изменяется cols = list(cols) # перевести текст в юникод, заодно перевести числа в строку for i in xrange(0,len(cols),2): cols[i] = (str(cols[i])).decode('utf8') # флаг "есть еще текст для вывода" repeat = True while repeat: # сбросить итератор на первый элемент q = 0 repeat = False # пока не закончили перебирать параметры (перебираем по парам) while q < len(cols): # если это последний параметр, и для него не указана ширина if q == len(cols)-1: # выводим его полностью не смотря на ширину окна retstr += cols[q] + " " cols[q] = '' else: # вывести часть строки не больше указанной ширины колонки retstr+=(cols[q][:cols[q+1]].ljust(cols[q+1])).encode('utf8') \ + " " # остальную часть строки оставить на следующую итерацию cols[q] = cols[q][cols[q+1]:] # если от строки что то осаталось if len(cols[q]) > 0: # отметить запуск еще одной итерации по параметрам repeat = True # следующая пара q += 2 # колонки отображены retstr += "\n" return retstr def columnWrite(*cols): '''Вывод данных по колонкам, причем, если данные не вмещаются в указнаную колонку, то они переносятся на следующую строку в нужную колонку. Параметры: cols множестово пар: текст, ширина колонки, причем, если у последней колонки не указывать ширину, то она будет выведена вся. Пример: columnWrite( "Some text", 10, "Next column", 20 ) ''' # перевести кортеж в список, т.к. изменяется cols = list(cols) # перевести текст в юникод, заодно перевести числа в строку for i in xrange(0,len(cols),2): cols[i] = (str(cols[i])).decode('utf8') # флаг "есть еще текст для вывода" repeat = True while repeat: # сбросить итератор на первый элемент q = 0 repeat = False # пока не закончили перебирать параметры (перебираем по парам) while q < len(cols): # если это последний параметр, и для него не указана ширина if q == len(cols)-1: # выводим его полностью не смотря на ширину окна print cols[q].encode('utf8'), cols[q] = '' else: # вывести часть строки не больше указанной ширины колонки print (cols[q][:cols[q+1]].ljust(cols[q+1])).encode('utf8'), # остальную часть строки оставить на следующую итерацию cols[q] = cols[q][cols[q+1]:] # если от строки что то осаталось if len(cols[q]) > 0: # отметить запуск еще одной итерации по параметрам repeat = True # следующая пара q += 2 # колонки отображены print def justify(s,width): '''Выровнить текст по ширине Параметры: s выводимая строка width ширина на которую надо выровнить строку Возвращаямые параметры: Выровненная строка ''' # если подана строка без пробелов - прекратить обработку if s.find(' ') == -1: return s pos = 0 # переводим в юникод для правильного вычисления длины try: s = s.decode( 'utf-8' ) # пропуск если это не utf-8 except UnicodeEncodeError: pass # пока длина строки меньше указанной while len(s) < width: # находим очередной пробел pos = s.find( ' ', pos ) # если не найден искать сначала if pos == -1: pos = s.find(' ') # вставить в позицию еще один пробел s = s[:pos] +' ' +s[pos:] # оставить удвоенный пробел pos += 3 # вернуть строку в utf8 если она пришла в utf8 return s.encode('utf-8')