22.01.2013, 20:49 | #1 |
MCTS
|
AXAligner - скрипт редактора для выравнивания X++ кода
Приветствую!
Набросал скрипт для выравнивания X++ кода, желающие могут попробовать beta-версию. Проверял работоспособность в AX 2009 и AX 2012, по идее должен работать и в предыдущих версиях. Возможности: - Обработка блока выделенных строк; - Выравнивание первой границы слева по верхней строке; - Выравнивание второй границы слева по максимальному значению в блоке; Установка: - Добавить в качестве нового метода в класс EditorScripts и скомпилировать. P.S. Конструктивная критика, мысли по доработке и вариации на тему приветствуются. X++: //AXAligner ver. 1.0 beta (for AX 2009, AX 2012) //Developed by alex55 (AXforum.info), 22.01.2013 //Aligns first and second borders from the left for selected block of code public void aAXAligner(Editor _editor) { #define.EmptyString('') #define.Space(' ') #define.AllLeftSpaces('<: *') #define.AllCharsBeforeSecondLeftBorder('<[^: ]*') int i; int leftBorderWidth; int firstRowLength; int maxSecondLeftBorderWidth; int startLine = _editor.selectionStartLine(); int endLine = _editor.selectionEndLine(); Map map = new Map(Types::Integer, Types::Container); TextBuffer textBuffer = new TextBuffer(); str removeAllLeftSpaces(str _row) { ; textBuffer.setText(_row); textBuffer.replace(#AllLeftSpaces, #EmptyString); return textBuffer.getText(); } void getMaxSecondLeftBorderWidth(str _row, int _rowNum) { int newRowLength; int secondLeftBorderWidth; int rowLength; ; _row = removeAllLeftSpaces(_row); rowLength = strlen(_row); textBuffer.setText(_row); textBuffer.replace(#AllCharsBeforeSecondLeftBorder, #EmptyString); textBuffer.replace(#AllLeftSpaces, #EmptyString); newRowLength = strlen(textBuffer.getText()); secondLeftBorderWidth = rowLength - newRowLength; map.insert(_rowNum, [secondLeftBorderWidth, rowLength, _row]); if (secondLeftBorderWidth > maxSecondLeftBorderWidth) { maxSecondLeftBorderWidth = secondLeftBorderWidth; } } str alignSecondLeftBorder(int _rowNum) { int newRowLength; int secondLeftBorderWidth; int rowLength; str secondLeftBorderString; str row; ; [secondLeftBorderWidth, rowLength, row] = map.lookup(_rowNum); secondLeftBorderString = substr(row, 1, secondLeftBorderWidth); secondLeftBorderString += strrep(#Space, maxSecondLeftBorderWidth - secondLeftBorderWidth); return strrep(#Space, leftBorderWidth) + secondLeftBorderString + substr(row, secondLeftBorderWidth + 1, rowLength - secondLeftBorderWidth); } str getEditorRow(int _rowNum) { _editor.gotoLine(_rowNum); return _editor.currentLine(); } void replaceEditorRow(int _rowNum, str _rowValue) { _editor.gotoLine(i); _editor.gotoCol(1); _editor.deleteLines(1); _editor.insertLines('\n'); _editor.gotoLine(_rowNum); _editor.gotoCol(1); _editor.insertLines(_rowValue); } ; firstRowLength = strlen(getEditorRow(startLine)); leftBorderWidth = firstRowLength - strlen(removeAllLeftSpaces(getEditorRow(startLine))); for (i = startLine; i <= endLine; i++) { getMaxSecondLeftBorderWidth(getEditorRow(i), i); } for (i = startLine; i <= endLine; i++) { replaceEditorRow(i, alignSecondLeftBorder(i)); } } |
|
|
За это сообщение автора поблагодарили: perestoronin (1). |
23.01.2013, 12:14 | #2 |
Участник
|
Вместо removeAllLeftSpaces() можно использовать strltrim().
Сразу 10 строк кода долой. Кстати, в AX 3.0 зависает напрочь.
__________________
// no comments Последний раз редактировалось dech; 23.01.2013 в 13:38. |
|
|
За это сообщение автора поблагодарили: alex55 (1). |
24.01.2013, 00:14 | #3 |
MCTS
|
Цитата:
Видимо 3-ка была немного шокирована используемыми регулярками. Попробуйте менее универсальный вариант, например: #define.AllNonSpaceCharsBeforeSecondLeftBorder('<[\.\_a-Z0-9\[\]]*') Возможно его придется дополнить некоторыми символами при необходимости, спец-символа для всех непробельных символов в match-style regexp я не нашел. 3-ку вообще сейчас не использую, так что проверяю только в "поддерживаемых" версиях. |
|
24.01.2013, 22:27 | #4 |
MCTS
|
Доработано:
- Устранено возможное срабатывание индикации синтаксических ошибок в окне кода после обработки блока объявления переменных; X++: //AXAligner ver. 1.1 beta (for AX 2009, AX 2012) //Developed by alex55 (AXforum.info), 23.01.2013 //Home page: axforum.info/forums/showthread.php?t=45984 //Aligns first and second borders from the left for selected block of a code public void aAXAligner(Editor _editor) { #define.EmptyString('') #define.Space(' ') #define.LineDelimiter('\n') #define.FirstColumnNum(1) #define.OneLine(1) #define.AllFirstNonSpaceChars('<[^: ]*') int i; int leftBorderWidth; int firstRowLength; int maxSecondLeftBorderWidth = 0; int startLine = _editor.selectionStartLine(); int endLine = _editor.selectionEndLine(); int columnNum = _editor.selectionEndCol(); List list = new List(Types::Container); TextBuffer textBuffer = new TextBuffer(); ListIterator iterator; void getMaxSecondLeftBorderWidth(str _row) { int newRowLength; int secondLeftBorderWidth; int rowLength; ; _row = strltrim(_row); rowLength = strlen(_row); textBuffer.setText(_row); textBuffer.replace(#AllFirstNonSpaceChars, #EmptyString); newRowLength = strlen(strltrim(textBuffer.getText())); secondLeftBorderWidth = rowLength - newRowLength; list.addEnd([secondLeftBorderWidth, rowLength, _row]); if (secondLeftBorderWidth > maxSecondLeftBorderWidth) { maxSecondLeftBorderWidth = secondLeftBorderWidth; } } str alignSecondLeftBorder() { int secondLeftBorderWidth; int rowLength; str secondLeftBorderString; str row; ; [secondLeftBorderWidth, rowLength, row] = iterator.value(); secondLeftBorderString = substr(row, 1, secondLeftBorderWidth); secondLeftBorderString += strrep(#Space, maxSecondLeftBorderWidth - secondLeftBorderWidth); return strrep(#Space, leftBorderWidth) + secondLeftBorderString + substr(row, secondLeftBorderWidth + 1, rowLength - secondLeftBorderWidth); } str getEditorRow(int _rowNum) { _editor.gotoLine(_rowNum); return _editor.currentLine(); } void replaceEditorRow(int _rowNum, str _row) { _editor.gotoLine(_rowNum); _editor.gotoCol(#FirstColumnNum); _editor.deleteLines(#OneLine); _editor.insertLines(#LineDelimiter); _editor.gotoLine(_rowNum); _editor.gotoCol(#FirstColumnNum); _editor.insertLines(_row); } //Fixes editor's errors indication void refreshEditor() { _editor.gotoLine(endLine + 1); _editor.gotoCol(#FirstColumnNum); _editor.insertLines(#LineDelimiter); _editor.gotoLine(endLine + 1); _editor.deleteLines(#OneLine); _editor.gotoLine(endLine); _editor.gotoCol(columnNum); } ; if (startLine >= endLine) { return; } firstRowLength = strlen(getEditorRow(startLine)); leftBorderWidth = firstRowLength - strlen(strltrim(getEditorRow(startLine))); for (i = startLine; i <= endLine; i++) { getMaxSecondLeftBorderWidth(getEditorRow(i)); } iterator = new ListIterator(list); i = startLine; while (iterator.more()) { replaceEditorRow(i, alignSecondLeftBorder()); iterator.next(); i++; } refreshEditor(); } |
|
25.01.2013, 07:51 | #5 |
NavAx
|
Забавная штучка. Есть надежда, что она эволюционирует во что-то вроде Ctrl+K+D из VS?
__________________
Isn't it nice when things just work? |
|
25.01.2013, 08:39 | #6 |
Участник
|
А что такое вторая граница?
Предлагаю следующие направления для развития: Что будет если выделить строки не целиком, а частично? С использованием ALT-O? Что будет если в коде есть закоментированные строки? Axapta виснет на TextBuffer::replace |
|
25.01.2013, 12:39 | #7 |
Участник
|
Скрипт не пробовал, поэтому про него писать не буду, хотя думаю, что в общем случае вещь полезная однозначно.
А для меня просто выравнивание индентации кода - это как шаманский ритуал после завершения кодирования, чтоб меньше ломалось поэтому делаю всегда вручную |
|
25.01.2013, 19:52 | #8 |
MCTS
|
|
|
25.01.2013, 20:07 | #9 |
MCTS
|
Цитата:
#define.AllFirstNonSpaceChars('<[\\.\\_a-Z0-9\\[\\]]*') |
|
25.01.2013, 20:24 | #10 |
MCTS
|
Позиция первого символа в имени переменной для декларативного блока или символа присваивания для блока присваивания.
Цитата:
Кстати да, строки комментариев в рамках блока надо вообще исключать из обработки и оставлять без изменений. Это точно надо допилить. |
|
25.01.2013, 20:44 | #11 |
MCTS
|
Вообще говоря в данной реализации оставлена разумная доля шаманства: нужный блок там выделить или даже блок одного типа на несколько блоков разбить для достижения более лучшего фэн-шуя и все такое. И, кроме того, думаю нужным шаманским действием обладает результат выравнивания а не его процесс, так что может все же не стоит отказываться от достижений цивилизации?
|
|
26.01.2013, 18:15 | #12 |
Участник
|
Пару идей можно почерпнуть тут:AxAssist - ReFormatter
До: После: Выложите пару скриншотов чтобы не было вопросов типа "А что такое вторая граница?". Еще я бы все изменения делал в одной "транзакции", чтобы ctrl-Z нажимать один раз если вдруг чтото не так.
__________________
AxAssist 2012 - Productivity Tool for Dynamics AX 2012/2009/4.0/3.0 |
|
27.01.2013, 00:55 | #13 |
MCTS
|
Цитата:
Сообщение от Alex_KD
Пару идей можно почерпнуть тут:AxAssist - ReFormatter
Цитата:
Хорошая идея, спасибо! |
|
Теги |
ax2009, ax2012, ax3.0, ax4.0, tools, x++, законченный пример, инструменты, полезное, форматирование кода |
|
|