BioInfo
Junior Member | Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Код: -- Форматер кода для LUA -- Автор: Маслов Дмитрий -- -- Принцип действия: -- Текст разбивается на лексемы (слова) -- Лексемы выстраивыаются нужным образом -- -- В планах развития: -- 1. Формирование вертикальных блоков функции и условий при достижении правой границы -- 2. Отступы между блоками функций -- 3. Установка второго стиля кода, когда начало блока не отделяется новой строкой -- 4. Портировать форматер на лексер С++ -- 5. Не разворачивать блоки if exp then param end, если блок из одного параметра -- .. Добавить кучу настроек под нужды общества --------------------------------------------------------------------------------------- -- Стиль для блоков -- -- Стиль № 0 --* имя блока --* do --* ... --* end -- -- Стиль № 1 --* имя блока do --* ... --* end local block_style = 0; --------------------------------------------------------------------------------------- local function GetEOL() local eol = "\r\n" if editor.EOLMode == SC_EOL_CR then eol = "\r" elseif editor.EOLMode == SC_EOL_LF then eol = "\n" end return eol end -- возвражает количество слов найденных в тексте и таблицу с ними local function GetLexemas( text ) local result = {}; local count = 0; local pos = 0; local text_len = string.len( text ); while true do -- убираем пробелы в начале while ( pos < text_len ) do local char = string.char( text:byte( pos+1 ) ); if ( char == " " or char == "\t" or char == "\r" or char == "\n" ) then pos = pos + 1; else break; end end -- проверка на конец if ( pos == text_len ) then break; end -- собираем лексему local one_word = string.char( text:byte( pos + 1 ) ); local double_word = one_word..string.char( text:byte( pos + 2 ) ); local threed_word = double_word..string.char( text:byte( pos + 3 ) ); local q_word = threed_word..string.char( text:byte( pos + 4 ) ); -- 1. Проверяем трех составные слова: ... if ( threed_word == '...' ) then -- сохраняем слово в таблицу count = count + 1; result[ count ] = threed_word; pos = pos + 3; else -- 2. Проверяем двусоставные слова: .. | <= | >= | == | ~= if ( double_word == '..' or double_word == '<=' or double_word == '>=' or double_word == '==' or double_word == '~=' ) then -- сохраняем слово в таблицу count = count + 1; result[ count ] = double_word; pos = pos + 2; else -- 3. Проверяем комментарий: --[[ | -- local isComment = false; local comment_end = ''; if ( q_word == '--[[' ) -- потоковй комментарий then isComment = true; comment_end = ']]'; elseif ( double_word == '--' ) -- строчный комментарий then isComment = true; end if ( isComment == true ) then -- отделяем комментарий local comment = ''; if ( comment_end:len() == 0 ) -- по концу строки then while true do pos = pos + 1; if ( pos == text_len ) then break; end local char = string.char( text:byte( pos ) ) if ( char == "\n" or char == "\r" ) then break; end comment = comment..char; end else while true do pos = pos + 1; if ( pos == text_len ) then break; end local char1 = string.char( text:byte( pos ) ) local char2 = string.char( text:byte( pos + 1 ) ) comment = comment..char1; if ( comment_end == char1..char2 ) then comment = comment..char2; pos = pos + 1; break; end end end -- сохраняем слово в таблицу count = count + 1; result[ count ] = comment; else -- 4. Проверяем текстовое поле: " | ' local text_end = ''; if ( one_word == '\'' ) then text_end = '\''; end if ( one_word == '\"' ) then text_end = '\"'; end if ( text_end ~= '' ) then local text_field=''; while true do pos = pos + 1; if ( pos == text_len ) then break; end local char = string.char( text:byte( pos ) ) local char_prev = string.char( text:byte( pos - 1 ) ) local char_prev_prev = string.char( text:byte( pos - 2 ) ) text_field = text_field..char; if ( char == text_end and text_field ~= text_end and ( char_prev ~= '\\' or char_prev_prev == '\\' ) ) then break; end end -- сохраняем слово в таблицу count = count + 1; result[ count ] = text_field; else -- 5. Проверяем односоставные слова if ( one_word == '+' or one_word == '-' or one_word == '*' or one_word == '/' or one_word == '%' or one_word == '^' or one_word == '#' or one_word == ';' or one_word == ':' or one_word == ',' or one_word == '.' or one_word == '(' or one_word == ')' or one_word == '{' or one_word == '}' or one_word == '[' or one_word == ']' or one_word == '=' or one_word == '<' or one_word == '>' ) then pos = pos + 1; -- сохраняем слово в таблицу count = count + 1; result[ count ] =one_word; else -- 6. Проверяем остальные слова local word = ''; while ( pos < text_len ) do local char = string.char( text:byte( pos + 1 ) ); if ( char == '+' or char == '-' or char == '*' or char == '/' or char == '%' or char == '^' or char == '#' or char == ';' or char == ':' or char == ',' or char == '.' or char == '(' or char == ')' or char == '{' or char == '}' or char == '[' or char == ']' or char == '=' or char == '<' or char == '>' or char == ' ' or char == '\'' or char == '\"' or char == '~' or char == "\n" or char == "\r" ) then break; else word = word..char; end pos = pos + 1; end -- сохраняем слово в таблицу count = count + 1; result[ count ] = word; end end end end end end return count, result; end -- Получить отступ в строке local function GetLineIndentation( num_line ) if ( num_line < 0 ) then num_line = 0 end if ( num_line >= editor.LineCount ) then num_line = editor.LineCount - 1 end return ( editor.LineIndentation[num_line] / editor.Indent ) end --[lua] Расчет начала блока в lua - блока функции local isFunctionBlockBeginLua = false; local lastParamBlockBeginLua = ''; local function IsBlockBeginLua( str ) local result = false; if ( str == 'function' ) then isFunctionBlockBeginLua = true; end if ( lastParamBlockBeginLua == ')' and str ~= ')' ) then isFunctionBlockBeginLua = false; end if ( str == ')' ) then result = isFunctionBlockBeginLua; end lastParamBlockBeginLua = str; return result; end --[lua] Расчет конца вырожения в lua - может не оканчиватся точкой с запятой local lastParamNewLineBeforLua = nil; local function IsNewLineBeforLua( str ) local ret = false if ( str ~= nil and lastParamNewLineBeforLua ~= nil ) then if ( str ~= '+' and str ~= ')' and str ~= '}' and str ~= ']' and str ~= '-' and str ~= '*' and str ~= '/' and str ~= '^' and str ~= '%' and str ~= '..' and str ~= '<' and str ~= '<=' and str ~= '>' and str ~= '>=' and str ~= '==' and str ~= '~=' and str ~= '[' and str ~= '{' and str ~= '(' and str ~= ';' and str ~= '.' and str ~= ',' and str ~= ':' and str ~= '=' and str ~= 'do' and str ~= 'else' and str ~= 'repeat' and str ~= 'then' and str ~= 'until' and str ~= 'in' and str ~= 'and' and str ~= 'or' and str ~= '...' ) and ( lastParamNewLineBeforLua ~= '+' and lastParamNewLineBeforLua ~= 'do' and lastParamNewLineBeforLua ~= 'else' and lastParamNewLineBeforLua ~= 'elseif' and lastParamNewLineBeforLua ~= 'for' and lastParamNewLineBeforLua ~= 'function' and lastParamNewLineBeforLua ~= 'if' and lastParamNewLineBeforLua ~= 'local' and lastParamNewLineBeforLua ~= 'not' and lastParamNewLineBeforLua ~= 'repeat' and lastParamNewLineBeforLua ~= 'return' and lastParamNewLineBeforLua ~= 'then' and lastParamNewLineBeforLua ~= 'until' and lastParamNewLineBeforLua ~= 'while' and lastParamNewLineBeforLua ~= '-' and lastParamNewLineBeforLua ~= '-' and lastParamNewLineBeforLua ~= '-' and lastParamNewLineBeforLua ~= '*' and lastParamNewLineBeforLua ~= '/' and lastParamNewLineBeforLua ~= '^' and lastParamNewLineBeforLua ~= '%' and lastParamNewLineBeforLua ~= '..' and lastParamNewLineBeforLua ~= '<' and lastParamNewLineBeforLua ~= '<=' and lastParamNewLineBeforLua ~= '>' and lastParamNewLineBeforLua ~= '>=' and lastParamNewLineBeforLua ~= '==' and lastParamNewLineBeforLua ~= '~=' and lastParamNewLineBeforLua ~= '[' and lastParamNewLineBeforLua ~= '{' and lastParamNewLineBeforLua ~= '(' and lastParamNewLineBeforLua ~= ';' and lastParamNewLineBeforLua ~= '.' and lastParamNewLineBeforLua ~= ',' and lastParamNewLineBeforLua ~= ':' and lastParamNewLineBeforLua ~= '=' and lastParamNewLineBeforLua ~= 'in' and lastParamNewLineBeforLua ~= 'and' and lastParamNewLineBeforLua ~= 'or' and lastParamNewLineBeforLua ~= '...' ) then ret = true; end end lastParamNewLineBeforLua = str; return ret; end -- начало блока? local function IsBlockBeginLang( str ) return str =='do' or str == 'repeat' or str == 'then' or str == 'else'; end local function IsBlockBegin( str ) return IsBlockBeginLang( str ) or IsBlockBeginLua( str ); end -- конец блока? local function IsBlockEnd( str ) return str == 'end' or str == 'until' or str == 'elseif' or str == 'else'; end -- это комментарий? local function IsComment( str ) return str ~= nil and str:sub( 1, 2 ) == '--'; end -- это вплотную прилигающее слово? local function IsLeftSidedWord( str ) return str == ';' or str == '(' or str == ',' or str == '.' or str == '[' or str == '..' or str == ':'; end -- после этого слова нужно всегда делать отступ? local function IsLeftNoSidedWord( str ) return str == 'or' or str == 'and' or str == 'not' or str == 'for' or str == 'if' or str == 'while' or str == 'return' or str == 'elseif'; end -- после этого слова не нужно делать отступ? local function IsRightSidedWord( str ) return str == '..' or str == '.' or str == ':'; end -- с этого слова начинается строка? local function IsNewLineBefor( str ) return str == 'local' or str == 'for' or str == 'if' or str == 'while' or str == 'function' or str == 'return' or str == 'break' or ( block_style == 0 and IsBlockBeginLang( str ) ) or IsBlockEnd( str ) or IsComment( str ); end -- после этого слова начинается строка? local function IsNewLineAfter( str ) return str == ';' or IsBlockBegin( str ) or str == 'end' or IsComment( str ); end -- MAIN -- local sel_start = editor.SelectionStart; local sel_end = editor.SelectionEnd; local line_start = editor:LineFromPosition( sel_start ) + 1; local line_indent = GetLineIndentation( line_start ); -- Если ничего не выделено, то берем весь текст if sel_start == sel_end then --[[тест]] line_start = 0 sel_start = 0 sel_end = editor:PositionFromLine( editor.LineCount ); line_indent = 0; end local line_indent = GetLineIndentation( editor:LineFromPosition( editor.SelectionStart ) ); local text, lenght = editor:GetSelText(); local count, tbl = GetLexemas(text); local out_text = ''; local curr_line_indent = line_indent; local in_new_line = true; for i = 1, count do local lexBefor = tbl[ i - 1 ]; local lexCurr = tbl[ i ]; local lexNext = tbl[ i + 1 ]; -- нужен ли пробел? local word_prefix = ' '; if ( IsLeftSidedWord( lexCurr ) and not IsLeftNoSidedWord( lexBefor ) ) or ( in_new_line == true ) or ( IsRightSidedWord( lexBefor ) ) then word_prefix = ''; end -- вставлять ли новую строку? local paste_new_line = IsNewLineBeforLua( lexNext ) or IsNewLineAfter( lexCurr ) or ( not IsNewLineBefor( lexCurr ) and IsNewLineBefor( lexNext ) ); if IsBlockBegin( lexCurr ) then curr_line_indent = curr_line_indent + 1; end if IsBlockEnd( lexNext ) and ( curr_line_indent > 0 ) then curr_line_indent = curr_line_indent - 1; end out_text = out_text..word_prefix..lexCurr; in_new_line = false; if ( paste_new_line == true ) then out_text = out_text..GetEOL()..string.rep( ' ', curr_line_indent ); in_new_line = true; end end print( out_text ); |
| Всего записей: 83 | Зарегистр. 30-04-2007 | Отправлено: 00:44 18-05-2008 | Исправлено: BioInfo, 01:42 18-05-2008 |
|