2016-01-26 2 views
2

Я работаю над форматированием, который займет длинную строку и отформатирует ее в ряд строк, разбитых словом в пределах определенного символьного предела. Например, Он ест хлеб, разорваны на каждые 8 ​​символов, возвращает что-то вроде:Lua: Разрывы строк в строках

He eats 
the 
bread 

Это потому, что «он ест» содержит 7 символов, и «хлеб» содержит 9, так что это должен разорваться на «the» и продолжить «хлеб».

Скрипт работает чудесно, благодаря помощи других участников. Однако теперь у меня есть новая задача.

Я использую бесплатную коробку для ввода ряда строк. Это для программы под названием MUSHclient, если кто-то знаком с ней. utils.editbox открывает текстовое поле редактора и позволяет получить бесплатную форму и возвращает результат как строку . Например:

result = utils.editbox("What are you typing?") 

сохраняет ответ напечатанный в result, который является string типа. Я хочу правильно разбить строки, но я не могу понять, как это сделать. Если я print(result), она возвращает что-то вроде следующего:

This is the result of three separate paragraphs. 

As you can see, there is a line break between each paragraph. 

So the result contains line breaks, or control characters. 

Теперь мне удалось экстраполировать отдельные линии, но не переносы строк между ними, используя следующий код:

for line in result:gmatch("[^%c]+%c?") do 
    Send(note_wrap(line)) 
end 

Как могу ли я экстраполяровать для разломов строк, а также текстового контента?

Редактировать Для справки, функция note_wrap выглядит следующим образом:

function note_wrap(str, limit, indent, indent1) 
    indent = indent or "" 
    indent1 = indent1 or indent 
    limit = limit or 79 
    local here = 1-#indent1 
    local last_color = '' 
    return indent1..str:gsub("(%s+)()(%S+)()", 
    function(sp, st, word, fi) 
     local delta = 0 
     local color_before_current_word = last_color 
     word:gsub('()@([@%a])', 
     function(pos, c) 
      if c == '@' then 
      delta = delta + 1 
      elseif c == 'x' then 
      delta = delta + 5 
      last_color = word:sub(pos, pos+4) 
      else     
      delta = delta + 2 
      last_color = word:sub(pos, pos+1) 
      end 
     end) 
     here = here + delta 
     if fi-here > limit then 
     here = st - #indent + delta 
     return "\n"..indent..color_before_current_word..word 
     end 
    end) 
end 

Причина этого кода, чтобы быть в состоянии принять @rHe ест @ x123the хлеба, игнорировать цветовые коды (указано на @ < письма> или @x < цифры>) и возвращает вышеупомянутый результат:

He eats 
the 
bread 

но вставить цветовые коды S о это возвращает:

@rHe eats 
@x123the 
bread 

Если это может быть изменено, чтобы распознавать новые линии и поставить реальную новую линию, которая была бы сказочно.

Редактировать 2 Решение Tried Paul, и это не делает то, что мне нужно. Возможно, я не был достаточно ясен, поэтому я попытаюсь разобраться в этом редактировании.

Когда я ввожу в поле свободной формы, я хочу, чтобы информация была представлена ​​точно так же, как есть, но отформатирована, чтобы правильно сломаться и сохранить введенные новые строки.Например, если я пишу это в свободной форме коробки:

Mary had a little lamb, little lamb, little lamb 
Mary had a little lamb 
It's fleece was white as snow 

с помощью кода Павла, и установив строку 79, я получаю:

Mary had a little lamb, little lamb, little lamb 

Mary had a little lamb 

It's fleece was white as snow 

И это не то, что я хочу. Я бы хотел, чтобы он возвращал его так же, как он был написан, и, при необходимости, разбивая линию. Так что, если у меня был предел 20 символов, было бы вернуть:

Mary had a little 
lamb, little lamb, 
little lamb 
Mary had a little 
lamb 
It's fleece was 
white as snow 

Если я добавил вручную разрывы строк, я хочу, чтобы уважать тех, так что если я ударил дважды вернуться после первой строки, это» d также имеют разрыв строки в первой строке. Например, если я написал это сообщение в поле свободной формы, я бы хотел, чтобы он уважал каждый новый абзац и все соответствующие строки. Надеюсь, это прояснит ситуацию.

ответ

1

я использую что-то вроде этого в моем коде (это предполагает, что \n является разделитель строки):

local function formatUpToX(s, x, indent) 
    x = x or 79 
    indent = indent or "" 
    local t = {""} 
    local function cleanse(s) return s:gsub("@x%d%d%d",""):gsub("@r","") end 
    for prefix, word, suffix, newline in s:gmatch("([ \t]*)(%S*)([ \t]*)(\n?)") do 
    if #(cleanse(t[#t])) + #prefix + #cleanse(word) > x and #t > 0 then 
     table.insert(t, word..suffix) -- add new element 
    else -- add to the last element 
     t[#t] = t[#t]..prefix..word..suffix 
    end 
    if #newline > 0 then table.insert(t, "") end 
    end 
    return indent..table.concat(t, "\n"..indent) 
end 
print(formatUpToX(result, 20)) 
print(formatUpToX("@rHe eats @x123the bread", 8, " ")) 

cleanse функция удаляет любую разметку, которая должна быть включена в строку, но не нужно считать против предела.

Для примера у вас есть, я получаю следующий результат (используя 20 как предел для первого фрагмента и 8 для второй):

This is the result 
of three separate 
paragraphs. 

As you can see, 
there is a line 
break between each 
paragraph. 

So the result 
contains line 
breaks, or control 
characters. 

    @rHe eats 
    @x123the 
    bread 
+0

Позвольте мне представить вам код формата я в настоящее время. Возможно, вы можете изменить это, чтобы он сломался там, где он должен был сломаться. Я бы использовал ваш, но там должно быть больше изменений. См. Редактирование в нескольких. И спасибо до сих пор! – Josh

+1

Если вы просто хотите убедиться, что '@ r' и' @ xNNN' не учитываются в лимитном лимите, это должно быть легко добавить; Я скоро отправлю сообщение. –

+1

Я также добавил отступ, подобный тому, который у вас есть (он не включен в лимит). Если вам нужен 'indent1', вы можете просто добавить его к результату. –

Смежные вопросы