[T.Viewer 개발일기] 11. ACE Editor 나의 경험담 2020. 8. 6. 01:09

Tizen Log Viewer 개발은 Web 기반 ACE Editor가 있었기에 쉽고 즐겁게 진행할 수 있었던 것 같다. 귀찮고 복잡한 일들의 상당수를 editor가 처리해주었다.ㅋ

Ace editor는 웹을 위한 고성능 코드 에디터를 표방하는 오픈소스 커뮤니티 프로젝트이다. vim 이나 sublime과 어깨를 나란히 한다고 한다니, 별 하나 드리고 시작한다.

https://ace.c9.io/

Ace is an embeddable code editor written in JavaScript. It matches the features and performance of native editors such as Sublime, Vim and TextMate.

Edit mode

Ace editor를 사용하는 방법은 설명도 잘되어 있고, 예제도 잘 나와있어서 쉽게 적용할 수 있었다. 그마나 조금 복잡했던 부분이 edit mode에 대한 부분인데, 편집하는 대상의 모드에 따른 동작을 재정의 할 수 있게 설계되어있다. 이런 방식이 복잡하다는 것을 알고 있는지 Best practice를 잘 정리해 두어서 테스트를 하면서 금방 이해할 수 있었다. Best Practice로 잘 쓰게 만드는 것! 진짜 중요하다!

Creating or Extending an Edit Mode

위의 내용을 바탕으로 내가 구성한 내용을 아래 붙인다. 거의 그대로 가져왔고, 디버그 레벨에 따라 token을 달리 적용해야하기 때문에 Rule 부분만 추가해 주었다.

const ace = require("ace-builds/src-noconflict/ace.js");

export default class AceEditor {
    static init() {
        ace.define('ace/mode/log', (require, exports) => {
            const oop = require("ace/lib/oop");
            const TextMode = require("ace/mode/text").Mode;
            const LogHighlightRules = require("ace/mode/log_highlight_rules").LogHighlightRules;

            const Mode = function() {
                this.HighlightRules = LogHighlightRules;
            };
            oop.inherits(Mode, TextMode);

            exports.Mode = Mode;
        });

        ace.define('ace/mode/log_highlight_rules', (require, exports) => {
            const oop = require("ace/lib/oop");
            const TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;

//07-10 14:51:21.337+0900 D/RESOURCED( 2617): heart-battery.c:....
// D/RESOURCED( 2617): heart-battery.c:....

            const verboseRule = {
                token: "verbose",
                regex: "^V.*|^[0-9].{23}V.*"
            };

            const debugRule = {
                token: "debug",
                regex: "^D.*|^[0-9].{23}D.*"
            };

            const LogHighlightRules = function() {
                this.$rules = {
                    start: [verboseRule, debugRule],
                };
            }

            oop.inherits(LogHighlightRules, TextHighlightRules);
            exports.LogHighlightRules = LogHighlightRules;
        });
    }

    static createViewer(DOMElement, globalSettings) {
        const viewer = ace.edit(DOMElement);

        viewer.setOptions({
            wrap: true,
            readOnly: true,
            highlightActiveLine: false,
            showPrintMargin: false,
            mode: "ace/mode/log",
            fontFamily: "Consolas, monaco, 'Courier New', Courier, monospace",
            fontSize: globalSettings.fontSize + "px"
        });

        return viewer;
    }
}

token은 정규식에 해당하는 text를 <span class="ace_<token>"> 이런 태그로 감싸주어서 커스텀한 스타일을 적용할 수 있도록 해주는 것이다. 블로그나 깃헙에서 흔히 볼 수 있는 Syntax highlight 기능을 위한 동작이라고 보면 된다. 나는 로그 한 줄을 통째로 변경하도록 적용하였다.

When one is found, the resulting text is wrapped within a tag, where is defined as the token property.

token 이외에도 state 에 대해서도 잘 설명이 되어 있다. t.viwer의 경우 state 변경은 필요없어서 따로 사용하지 않았는데, 참 설계를 잘 했다는 생각이 든다. 자세한 내용을 아래 링크를 타고 들어가서 확인.

Ace editor - higlighter

search box

이걸 또 어떻게 구현하나...고민하고 있었는데, 헐. 그냥 되네? 단, 아래 extension을 추가해줘야 한다. 한 것도 없이 잘되니까 민망하면서도 든든.

    require("ace-builds/src-noconflict/ext-searchbox.js");

clear

화면을 싹 지우는 클리어 버튼에 대한 동작으로 쓸 method를 딱히 못 찾아서 구글링 해봤는데, 넘 간단!

    this.viewer.setValue('');

text append

로그 뷰어이다 보니 새로운 로그를 아래 쪽에 밀어 넣어야 하는데, append method가 없네. 커서를 옮겨서 넣어보기도 했는데, 그럴 경우 클릭한 위치에 로그가 들어가버리는 문제가 생긴다. 확실한 방법은 아애 제일 아래쪽에 넣는 것이다.ㅎ

    let session = this.viewer.session;
    session.insert({
        row: session.getLength(),
        column: 0
    }, line.line);

wrap

줄바꿈은 그냥 옵션에서 설정 가능하다.

    viewer.setOptions({
        wrap: true,
        readOnly: true,

동적으로 적용하려면 session.setUseWrapMode 메소드 사용하면 된다.

    this.viewer.session.setUseWrapMode();

font size

폰트 사이즈도 손 쉽게 척척!

    this.viewer.setFontSize("20px");

auto scroll

text가 입력될 때 가장 아래쪽으로 이동하면 되니까. scrollToLine을 사용하면 된다.

    this.viewer.scrollToLine(this.viewer.session.getLength());

마치며

Ace editor가 없었더라면 어땠을까? 아마 다른 이름의 오픈소스 프로젝트가 있었겠지?ㅎ 요즘은 참 좋은 세상이다. 있으면 좋을 법한 좋은 프로젝트들이 잘 관리되고, 널리 사용되면서 개발 생산성이 엄청 좋아졌다. 겸손하게 감사를 표한다.

댓글