AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 22.01.2013, 20:49   #1  
alex55 is offline
alex55
MCTS
MCBMSS
 
224 / 145 (5) +++++
Регистрация: 13.02.2007
Адрес: Москва
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  
dech is offline
dech
Участник
Аватар для dech
Самостоятельные клиенты AX
 
642 / 347 (13) ++++++
Регистрация: 25.06.2009
Адрес: Омск
Записей в блоге: 3
Вместо removeAllLeftSpaces() можно использовать strltrim().
Сразу 10 строк кода долой.
Кстати, в AX 3.0 зависает напрочь.
__________________
// no comments

Последний раз редактировалось dech; 23.01.2013 в 13:38.
За это сообщение автора поблагодарили: alex55 (1).
Старый 24.01.2013, 00:14   #3  
alex55 is offline
alex55
MCTS
MCBMSS
 
224 / 145 (5) +++++
Регистрация: 13.02.2007
Адрес: Москва
Цитата:
Сообщение от dech Посмотреть сообщение
Вместо removeAllLeftSpaces() можно использовать strltrim().
Сразу 10 строк кода долой.
Спасибо! Да, думаю strltrim() будет вполне достаточно, заменил в новой версии.

Цитата:
Сообщение от dech Посмотреть сообщение
Кстати, в AX 3.0 зависает напрочь.
Видимо 3-ка была немного шокирована используемыми регулярками.

Попробуйте менее универсальный вариант, например:
#define.AllNonSpaceCharsBeforeSecondLeftBorder('<[\.\_a-Z0-9\[\]]*')

Возможно его придется дополнить некоторыми символами при необходимости, спец-символа для всех непробельных символов в match-style regexp я не нашел. 3-ку вообще сейчас не использую, так что проверяю только в "поддерживаемых" версиях.
Старый 24.01.2013, 22:27   #4  
alex55 is offline
alex55
MCTS
MCBMSS
 
224 / 145 (5) +++++
Регистрация: 13.02.2007
Адрес: Москва
Доработано:
- Устранено возможное срабатывание индикации синтаксических ошибок в окне кода после обработки блока объявления переменных;

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  
macklakov is offline
macklakov
NavAx
Аватар для macklakov
 
2,129 / 916 (35) +++++++
Регистрация: 03.04.2002
Забавная штучка. Есть надежда, что она эволюционирует во что-то вроде Ctrl+K+D из VS?
__________________
Isn't it nice when things just work?
Старый 25.01.2013, 08:39   #6  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,429 / 1772 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от alex55 Посмотреть сообщение
- Выравнивание второй границы слева по максимальному значению в блоке;
А что такое вторая граница?

Предлагаю следующие направления для развития:
Что будет если выделить строки не целиком, а частично? С использованием ALT-O?
Что будет если в коде есть закоментированные строки?


Цитата:
Сообщение от dech Посмотреть сообщение
Кстати, в AX 3.0 зависает напрочь.
Axapta виснет на TextBuffer::replace
Старый 25.01.2013, 12:39   #7  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
Скрипт не пробовал, поэтому про него писать не буду, хотя думаю, что в общем случае вещь полезная однозначно.

А для меня просто выравнивание индентации кода - это как шаманский ритуал после завершения кодирования, чтоб меньше ломалось поэтому делаю всегда вручную
Старый 25.01.2013, 19:52   #8  
alex55 is offline
alex55
MCTS
MCBMSS
 
224 / 145 (5) +++++
Регистрация: 13.02.2007
Адрес: Москва
Цитата:
Сообщение от macklakov Посмотреть сообщение
Забавная штучка. Есть надежда, что она эволюционирует во что-то вроде Ctrl+K+D из VS?
Пока в планах только доработка "полу-автоматического" выравнивания для основных типов блоков. Смысл дальнейшей доработки еще не очевиден.
Старый 25.01.2013, 20:07   #9  
alex55 is offline
alex55
MCTS
MCBMSS
 
224 / 145 (5) +++++
Регистрация: 13.02.2007
Адрес: Москва
Цитата:
Сообщение от alex55 Посмотреть сообщение
Видимо 3-ка была немного шокирована используемыми регулярками.

Попробуйте менее универсальный вариант, например:
#define.AllNonSpaceCharsBeforeSecondLeftBorder('<[\.\_a-Z0-9\[\]]*')
Упс.. Бэкслэши все же двойные должны быть в этом случае:

#define.AllFirstNonSpaceChars('<[\\.\\_a-Z0-9\\[\\]]*')
Старый 25.01.2013, 20:24   #10  
alex55 is offline
alex55
MCTS
MCBMSS
 
224 / 145 (5) +++++
Регистрация: 13.02.2007
Адрес: Москва
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
А что такое вторая граница?
Позиция первого символа в имени переменной для декларативного блока или символа присваивания для блока присваивания.

Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Предлагаю следующие направления для развития:
Что будет если выделить строки не целиком, а частично? С использованием ALT-O?
Спасибо за идеи! В обработке участвуют вертикальные границы выделенного блока, так что с частичным выделением работает нормально (обрабатываются строки, попавшие в выделение).

Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Что будет если в коде есть закоментированные строки?
Кстати да, строки комментариев в рамках блока надо вообще исключать из обработки и оставлять без изменений. Это точно надо допилить.
Старый 25.01.2013, 20:44   #11  
alex55 is offline
alex55
MCTS
MCBMSS
 
224 / 145 (5) +++++
Регистрация: 13.02.2007
Адрес: Москва
Цитата:
Сообщение от kashperuk Посмотреть сообщение
А для меня просто выравнивание индентации кода - это как шаманский ритуал после завершения кодирования, чтоб меньше ломалось поэтому делаю всегда вручную
Вообще говоря в данной реализации оставлена разумная доля шаманства: нужный блок там выделить или даже блок одного типа на несколько блоков разбить для достижения более лучшего фэн-шуя и все такое. И, кроме того, думаю нужным шаманским действием обладает результат выравнивания а не его процесс, так что может все же не стоит отказываться от достижений цивилизации?
Старый 26.01.2013, 18:15   #12  
Alex_KD is offline
Alex_KD
Участник
AxAssist
MCBMSS
Соотечественники
 
522 / 362 (14) ++++++
Регистрация: 06.07.2006
Адрес: Melbourne, Down Under
Пару идей можно почерпнуть тут:AxAssist - ReFormatter

До:



После:



Выложите пару скриншотов чтобы не было вопросов типа "А что такое вторая граница?".
Еще я бы все изменения делал в одной "транзакции", чтобы ctrl-Z нажимать один раз если вдруг чтото не так.
__________________
AxAssist 2012 - Productivity Tool for Dynamics AX 2012/2009/4.0/3.0
Старый 27.01.2013, 00:55   #13  
alex55 is offline
alex55
MCTS
MCBMSS
 
224 / 145 (5) +++++
Регистрация: 13.02.2007
Адрес: Москва
Цитата:
Сообщение от Alex_KD Посмотреть сообщение
Пару идей можно почерпнуть тут:AxAssist - ReFormatter
Спасибо, уже глянул! Не было, кстати, желания сделать опциональную обработку по выделению? По старому коду не всегда целессобразно полный реформатинг делать имхо..

Цитата:
Сообщение от Alex_KD Посмотреть сообщение
Выложите пару скриншотов чтобы не было вопросов типа "А что такое вторая граница?".
Да, надо будет сделать. Думаю допилить сначала, а потом уже скриншотить более-менее завершенную версию.

Цитата:
Сообщение от Alex_KD Посмотреть сообщение
Еще я бы все изменения делал в одной "транзакции", чтобы ctrl-Z нажимать один раз если вдруг чтото не так.
Хорошая идея, спасибо!
Теги
ax2009, ax2012, ax3.0, ax4.0, tools, x++, законченный пример, инструменты, полезное, форматирование кода

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Размер шрифта в окне редактора кода Jox DAX: Администрирование 3 09.11.2022 11:49
Удобство чтения кода - залог и определенная гарантия его работоспособности sukhanchik DAX: Программирование 29 11.04.2013 10:52
Скрипт для переноса данных Ax3.0 (Oracle) - Ax2009 (MSSQL) someOne DAX: Программирование 2 14.06.2011 14:53
axforum blogs: О заполнении Наименования и Кода номенклатуры в печатной форме Накладной (Ax2009 ru7) Blog bot DAX Blogs 0 07.06.2011 09:11
проблема с настройкой штрихового кода Nic DAX: Функционал 4 27.12.2004 09:04
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 04:57.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.