Scintilla icon SciTE 루아 스트립트 확장

루아 스크립팅 확장에 관하여

SciTE 루아 스크립트 확장은 루아 5.1을 엔진으로 사용한다. 현재, 모든 표준 라이브러리가 포함되어 있다. 물론 이 목록은 앞으로 개정될 수 있다.

루아는 Copyright (C) 1994-2007 Lua.org, PUC-Rio가 복사권을 가진다. 완전한 루아 라이센스는 설치 디렉토리에 luaCOPYRIGHT 문서에 포함되어 있다. 더 자세한 정보는 www.lua.org를 방문해 루아 언어를 알아보자.

루아가 무엇을 할 수 있는지 알고 싶다면, 공동체 lua-users.org에 방문해서, SciTE에서 루아 사용하기 소개서와 예제 스크립트들을 읽어 보자. SciTE에서 태그를 사용하는 법을 참조하자.

SciTE 특성과 루아 이벤트 / 명령어 처리자

ext.lua.startup.script와 extension.filepattern 특성은 SciTE에서 호출될 명령어와 이벤트 처리자를 정의하는데 사용된다. ext.lua로 시작하는 다른 특성들은 루아의 행위에 영향을 미친다. 더 자세한 정보는 SciTE 문서를 참고하자.

시작 스크립트나 활성 확장 스크립트에서 함수를 정의함으로써 SciTE를 필요에 맞게 재단할 수 있다. 새로운 행위와 기능을 긴밀하게 통합해 추가할 수 있다.

먼저, SciTE 확장 인터페이스에 노출된 이벤트는 무엇이든 다룰 수 있다. 그냥 그 이벤트와 같은 이름으로 함수를 정의하기만 하면 된다. 현재, OnOpen, OnClose, OnSwitchFile, OnSave, OnBeforeSave, OnChar, OnKey, OnSavePointReached, OnSavePointLeft, OnDwellStart, OnDoubleClick, OnMarginClick, 그리고 OnUserListSelection가 지원된다.

이벤트 처리자 함수에 SciTE가 인자를 건네는 이벤트가 있다: OnOpen, OnClose, OnSwitchFile, OnSave, 그리고 OnBeforeSave 이벤트는 첫 인자로 영향받는 버퍼의 파일이름을 받는다. OnChar 처리자는 단-문자를 인자로 예상한다. OnKey 처리자는 정수 키코드와 불리언 shift, control, 그리고 alt 인자를 예상한다. 키코드는 현재 플랫폼 종속적 값이지만 앞으로 바뀔 가능성이 있다. OnDwellStart는 마우스의 위치와 그 마우스 아래의 단어를 받는다. 단어는 마우스가 움직이기 시작하면 비어 있다. OnUserListSelection는 인자를 두 개 받는다: 리스트 유형을 가리키는 숫자와 선택된 아이템 텍스트를 가리키는 문자열을 받는다.

이벤트 처리자는 SciTE가 계속 이벤트를 처리해야 할지 알려주기 위해 불리언 값을 돌려준다. 이벤트를 완전히 처리했고 더 이상 이벤트 처리자가 호출될 필요가 없다는 사실을 알리기 위해 참값을 돌려준다. 거짓값을 돌려주어 다른 확장들에게 같은 이벤트를 처리할 기회를 준다. 모든 경우는 아니지만 많은 경우, 올바른 행위를 하는 이벤트 처리자는 거짓을 돌려준다. 루아에서 유일하게 참이 아닌 값은 falsenil임을 반드시 기억하자. C++과 다르게, 파이썬과 기타 언어는 0을 true로 평가한다.

OnClear라는 이벤트 처리자가 하나 더 있다. 이 처리자는 확장 인터페이스에 확실하게 정의되어 있지 않다. 그러나 루아 Lua에 노출되어 있다. SciTE가 특성을 다시 읽을 때마다 (버퍼를 전환하거나 새로 파일을 열 때마다 다시 읽으며, 물론 다른 경우에도 읽을 수 있다), 루아 확장은 바로 전 특성을 읽은 이후로 만들어진 전역변수들을 모두 제거한다. 그리고 전역변수들을 복구해 덮어쓴다. 다음, 기동 스크립트에 OnClear가 정의되어 있다면, 그 함수가 호출된다. 그러므로 그 스크립트도 루아 전역 영역의 바깥에서 만들어진 다른 변화들을 깨끗이 청소할 기회가 있으며 (예를 들어,props 객체에 의해 수정된 동적 특성; 아래 참조) 그리고 현재 버퍼에 대한 지역 특성에 맞게 루아 환경을 재단할 기회가 있다.

이 다음에 SciTE는 특성들을 읽고 정의되어 있다면 마지막으로 확장 스크립트를 적재한다. 그렇지만, OnClear 이벤트가 촉발될 때, 확장 스크립트는 아직 적재되지 않는다. 그리하여, OnClear에는 확장 스크립트가 아니라 오직 기동 스크립트에만 정의할 수 있다.

이베트 처리자와 더불어, 도구 메뉴나 키보드 단축키를 통하여 사용할 수 있는 새로운 명령어를 정의할 수 있다. 루아가 처리할 수 있는 명령어는 subsystem 3를 지정하면 된다. 다음, 루아를 사용하는 명령어를 구현하려면, 그냥 전역 함수를 정의하면 된다. 명령어 이름은 함수 이름이다.

dofiledostring과 같은 미리 정의된 함수를 도구 명령어에서 사용할 수 있다.

명령어 이름 다음에 지정된 것은 무엇이든 루아 함수에 한개짜리 문자열 인자로 건네진다. 명령어의 예로, 내장 dofile 명령어를 사용한다면, 아래와 같다.

command.name.1.*=Run My Script
command.subsystem.1.*=3
command.1.*=dofile $(SciteDefaultHome)/My Script.lua

명령어 줄이 루아 스크립트로 "직접 평가되는 것은 아니라는" 것을 주의하자.

명령어 이름에 부합하는 함수가 없더라도, 아무 에러도 나타나지 않는다. 이는 루아가 이 경우 그 명령어가 다른 어떤 확장, 예를 들어 SciTE Director Extension이라고 간주하기 때문이다. 그렇지만, 그 명령어에 해당하는 함수가 발견되었으나, 실행에 실패하면, 에러가 보고된다.

다중 처리자

이벤트를 처리하는데 여러 스크립트가 필요한 더 복잡한 어플리케이션이라면 Scite Ext Man이 도움이 된다.


미리 정의된 루아 함수와 객체:

루아 스크립트 안에서 다음 함수와 객체를 사용할 수 있다:

  trace(s) - 출력판에 쓴다 (접두사 없고, 새줄문자 없음);
  dostring(s) -루아 문자열로 실행한다. 루아 4'의 dostring과 같다;
  editor - 편집판;
  output - 출력판;
  props - SciTE 특성을 나타내는 의사-테이블;
  buffer - 현재 버퍼나 문서에 연관된 테이블;
  scite - SciTE를 제어하는 함수들에 대한 이름공간.

게다가, Scintilla.iface에 정의된 모든 상수들은 루아 전역 변수로 노출된다. 함수 이름은 SCI_ prefix와 같이 대문자 덩어리로 노출된다.

루아 표준 라이브러리에 정의된 모든 함수와 객체도 역시 사용할 수 있다. dostring은 Lua 5에서 비추천 지위로 격하되었어지만, 도구 명령어에서 사용하면 유용하다는 주장이 있다.

내장 print() 함수에 대한 별명으로 _ALERT() 함수도 정의되어 있다. 이 함수는 주의 메시지를 창에 인쇄한다 (새줄 문자 포함). 이 함수는 루아가 에러 메시지를 사용자에게 제시하는 합리적인 방법을 제공한다. 얼마든지 원하는대로 _ALERT를 다른 정의로 오버라이드해도 좋다.

props 의사-테이블은 이름으로 특성을 읽고 쓸 수 있도록 해준다.여 props["property.name"]와 같이 보통의 루아 테이블-접근 의미구조를 사용하면 된다. 루아 테이블처럼, 키에 nil을 할당하여 설정을 지울 수 있다.

루아에서 값을 특성에 할당하면, 그 설정에 대하여 환경설정 파일에 지정된 어떤 값이든 오버라이드한다. 아래의 파일 특성은 바뀌지 않는다. 그래서 나중에 루아에서 nil을 같은 특성에 할당하면, 실행-시간 설정이 지워지므로, 파일-기반의 특성 설정이 다시 한 번 뚫고 나타날 수 있다.

편집판과 출력판은 다음 특성과 메쏘드를 지원한다:

  textrange(startPos, endPos) - 지정된 범위의 텍스트를 얻는다.

  findtext(text, [flags], [startPos, [endPos]])
    - 첫 일치의 시작과 끝을 돌려준다. 일치가 없으면 nil을 돌려준다.
    - 플래그는 0이거나 (기본값), SCFIND 상수들 의 조합일 수 있다.
      예를 들어 SCFIND_WHOLEWORD, SCFIND_MATCHCASE, 그리고 SCFIND_REGEXP

  match(text, [flags], [startPos])
    - 일치된 것들을 회돌이 할 수 있게 발생자를 돌려준다.
      예, for m in editor:match(text, flags) do ... end
    - 일체 객체는 (i.e. the loop counter m in the above
      example) 읽기-전용 특성으로 pos와 len 그리고 text를 지원하며;
      또한 검색과 교체를 위해 함수 교체를 지원한다(replaceText).
    - 일치를 회돌이하는 동안, 그 회돌이 계수기의 replace 메쏘드 말고,
      문서가 다른 메쏘드에 의하여 수정되면,
      이 때문에 일치 발생자가 위치를 잃어버릴 가능성이 있다.
    - 또한, 일치 객체를 나중에 회돌이 바깥에서 접근하기 위해,
      저장하려고 시도하지 않는다; 그 때 쯤이면 일치 객체는 쓸모가 없다.

  append(text) - 텍스트를 문서의 끝에 추가한다.
  insert(pos, text) - 텍스트를 지정된 위치에 삽입한다.
  remove(startPos, endPos) - 범위의 텍스트를 삭제한다.

Scintilla.iface에 정의된 대부분의 함수는 pane 메쏘드에도 노출된다. 매개변수가 단순한 함수들은 (string, boolean, 그리고 수치 유형) 완벽하게 지원된다. 예를 들어 editor:InsertText(pos, text)는 실질적으로 editor:insert(pos, text)와 같은 일을 한다. stringresult 매개변수를 가지는 함수들은 반환 값에 문자열을 포함한다. strings과 stringresults에 대하여, 그 함수가 길이를 그의 첫 매개변수로 받는다고 문서화되어 있더라도, 루아에서 그 길이를 건네지 않는다. 대신에, 문맥에서 추론한다.

keymod 매개변수 유형은 부분적으로 지원한다. iface 함수가 keymod를 받도록 정의되어 있다면, 상당하는 루아 함수는 숫자 두 개를 예상한다: 첫째 숫자는 키 코드이고 (예를 들어, SCK_LEFT 또는 string.byte("'"), 그리고 두 번째는 수식자이다 (예, SCMOD_CTRL).

매개변수가 더 복잡한 함수는 지원되지 않는다.

숫치 유형을 돌려주도록 선언된 함수는 반환 값에 그 결과를 추가해 돌려준다. 그 함수에 stringresult로 있다면, 그것이 먼저 오고 뒤를 이어 숫치 반환 값이 따른다.

iface 파일에서 어떤 함수들은 'fun'이 아니라 'get' 또는 'set' 으로 정의된다. 이런 함수들은 일반적으로 예를 들어 editor.TabSize = 8와 같이 특성으로 루아에 노출된다. 매개변수를 받는 획득자(getter)와 설정자(setter)도 있다. 가능하면, 이런 함수들은 루아에 노출된다. 이런 함수들은 editor.StyleBold[SCE_PROPS_DEFAULT] = true와 같이 가능하면 지표화된 특성으로 루아에 노출된다. 그렇지만, iface 함수가 get / set으로 설정되어 있으나 루아 특성에 짝짓기 되지 못하면, 대신에 루아 함수로 노출된다.

가능한 Scintilla 호출 목록은 API 파일 포맷이다. Scintilla API는 ScintillaDoc에 기술되어 있다.

scite 이름공간에는 다음 함수가 포함되어 있다:

  scite.Open(filename)
    - 파일을 새 버퍼에 연다.
    - 이미 열려 있다면 그 파일의 버퍼를 활성화한다.

  scite.SendEditor(SCI_constant, ...)
    - 메시지를 편집판에 전송한다.
    - 상응하는 iface 함수나 특성과 동등하다.

  scite.SendOutput(SCI_constant, ...)
    - 메시지를 출력판에 보낸다.

  scite.ConstantName(number)
    - Scintilla / SciTE 상수의 심볼 이름을 돌려준다.

  scite.MenuCommand(IDM_constant)
    - SciTE.h에 정의된, 그에 상응하는 IDM_ 명령어와 동등하다.

Open은 특별한 주의가 요구된다. 버퍼가 SciTE에서 바뀌면, 루아 전역 이름공간은 초기 상태로 재설정되고, 그 새 버퍼에 연관된 확장 스크립트가 적재된다. 그리하여, Open을 호출하면, 현재 스크립트가 실행되고 있는 환경이 바뀔 수 있다. 가능하면, 혼란을 피하기 위하여 그냥 scite.Open 후에 반환하는 것이 좋다. 그러나 그것이 불가능하다면, 부작용이 있다는 사실을 꼭 기억하자. 전역 변수와 다르게 지역 변수는 버퍼가 변한 후에도 스크립트가 반환될 때까지 유지된다.

SendEditorSendOuput 함수는 편집판과 출력판 객체의 기능을 복제한다. 그래서 Scintilla C++ 개발자는 더 익숙한 인터페이스로 접근할 수 있다. 루아를 사용하여 C++ 코드의 원형을 만들 경우에 유용하다. 내부적으로 SendEditorSendOutput는 그에 상응하는 iface 함수나 특성으로 번역된다. 그래서 인자와 반환된 유형은 동일하다. (특성에 대한 호출 관례가 명백하게 다르다고 할지라도 말이다.)

ConstantName 함수는 디버그 메시지를 만들거나 SciTE LuaExtension이 매크로 기록을 지원하도록 확장할 경우 유용하다.

MenuCommand 함수는 SciTE.h에 정의된 SciTE'의 메뉴 명령어를 사용할 수 있게 해준다.

줄 입력기로 사용자 인터페이스 관리하기

간단한 사용자 인터페이스를 Lua에서 정의할 수 있다. 찾기 바꾸기 한줄 입력기와 비슷하다. 예제는 아래와 같다

줄들은 StripShow로 나타내는데 사용자 인터페이스를 기술하는 문자열을 받아서 어플리케이션 창의 하단에 한 줄로 구성하여 보여준다. 다섯개 요소를 지원된다: 라벨, 편집 텍스트, 콤보 박스, 기본 버튼들이 그것이다. 서로 다르게 구별 문자열을 두르는데: 각각 라벨에는 '; 편집 텍스트에는 []; 콤보 박스는 {}; 버튼은 (); 그리고 기본 버튼은 (())으로 둘러싼다. 새줄 문자도 가능하며 !는 닫힌 상자를 보여준다 (윈도우즈 전용).

기본 버튼은 ((OK))와 같은 모습이며 엔터키를 누르면 촉발시킬 수 있다. 버튼에는 &을 앞에 꾸민 가속 키가 포함될 수 있다(맥 불가). 라벨에도 가속키를 정의할 수 있는데 초점을 받는 다음 원소로 초점이 이동한다. 문자 그대로의 엠퍼센드는 &&로 정의된다. 예를 들어, 다음 코드는

       scite.StripShow("!'Explanation:'{}(&Search)\n'Name:'[Name](OK)(Cancel)")
화면과 같이 줄 입력기를 보여준다. 빈 문자열을 건네면 닫힌다.

GTK+에서 테이블이 조감에 사용되며 다른 플랫폼에서도 그 접근법을 따른다. 그러나 아직까지 GTK+ 플랫폼에 미치지 못한다 - 편집 텍스트와 콤보 박스가 담긴 컬럼은 확대될 수 있다. 그리고 다른 컬럼은 자연스러운 너비에 맞게 너비가 고정된다.

사용자로부터의 이벤트는 스크립트로 다시 전해진다. OnStrip 함수를 통하는데 이 함수는 원소 번호와 (0에서부터 고정 텍스트 요소들 포함) 바뀔 유형 (clicked=1, change=2, focusIn=3, focusOut=4)을 취한다. 'clicked'는 버튼 눌림, 편집 텍스트나 콤보 박스의 편집 텍스트 부분에 변화가 있으면 'change' 그리고 'focusIn'와 'focusOut'은 사용자가 요소들 사이에 초점을 이동시킬 때 사용된다. 편집 텍스트나 콤보 박스의 값은 StripValue(element)로 열람할 수 있다.

현재로서는 이런 이벤트들에 버그와 한계가 좀 있다. 텍스트만 편집할 때라면 초점 이벤트가 일어나지 않을 수도 있다. 콤보 박스 목록에서 한 항목을 선택하더라도 'change' 이벤트가 전송되지 않을 수 있다.

콤보 박스의 편집 부분과 편집 텍스트는 StripSet(element, value)로 설정하고 콤보 박스의 목록 부분은 StripSetList(element, value)으로 설정한다. 여기에서 'value' 안의 항목들은 새줄문자로 가른다.

Lua 5.1

루아 5.1에서 언어를 다루는 방식에 크게 변화가 있었지만, 대부분의 호환 옵션이 켜저 있다.
호환성을 나열하면 다음과 같다:
- table.getn은 여전히 작동하지만, '#' 연산자가 사용되어야 한다
- Lua 5.0의 varargs는 여전히 사용가능하다
- Lua 5.0의 math.mod을 여전히 사용할 수 있을 뿐만 아니라, 5.1의 math.fmod로 사용할 수 있다
- Lua 5.0의 string.gfind는 여전히 사용가능하며, 5.1의 string.gmatch도 사용할 수 있다
- [C API] Lua 5.0의 luaL_openlib 행위는 여전히 사용가능하다
바뀐 것:
- table.setn는 추천되지 않는다
- loadlib는 패키지 테이블 안으로 이동되었다 (package.loadlib)
- Lua 5.0의 기다란 문자열 내포는 에러를 일으킨다

루아 비활성화

루아는 현재 필요시에만 적재된다. 처음 사용되기 전까지는 말이다. 루아를 사용하려면 ext.lua.startup.script 특성을 통하거나, 루아 파일이름을 extension.filepattern 특성에 지정하거나, 아니면 확장 메커니즘을 사용하여 도구 메뉴를 정의하면 된다 (예, subsystem 3). 이런 일을 하지 않는다면 루아 스크립트 엔진은 적재되지 않는다. 실용적 목적으로, SciTE는 루아가 추가되기 전과 똑같이 행위해야 한다.

그럼에도 불구하고, 루아 지원없이 SciTE를 빌드하는 것이 여전히 가능하다. 이렇게 하려면, 그냥 빌드할 때 NO_LUA 변수를 설정하자. 예를 들어, MSVC라면 nmake -f scite.mak -DNO_LUA; 또는 GNU 도구라면 make NO_LUA=1.