SublimeText Plugin 작성하기

SublimeText3 플러그인을 만들자.

서브라임텍스트3에서 작성하던 내용을 개인적으로 사용하는 위키(로컬에서 돌리고 있음)에 전송하는 기능을 서브라임 텍스트 플러그인으로 구현하고, 그 과정을 기록한다.

조건들

  • Sublime Text3의 스크립트 구동 언어는 Python3 버전이다.
  • 서브라임에서 제공하는 API를 사용하기위해서는 sublime 패키지가 필요하다.
  • 명령 클래스의 원형은 sublime_plugin 패키지에 정의되어 있다. 커스텀 플러그인은 이 클래스를 상속받아 작성하게 된다.
  • 현재 뷰(편집공간)는 이 클래스의 self.view 속성을 통해서 접근할 수 있다.

이름 규칙

  • 클래스명이 곧 명령 문구가 된다. 공백으로 구분된 후 첫글자가 대문자가 된다. “send2w”라는 명령을 만들고 싶으면 Send2WCommand라는 이름으로 클래스를 작성해야 한다.
  • 실행되는 함수는 run() 메소드이다. 이 메소드는 ‘edit’라는 파라미터를 받는다. (어디쓰는지는 모르겠다.)

디자인

이 플러그인은 다음과 같은 형태로 동작한다.

  • w(개인위키이름)은 로컬에서 웹서버 형태로 돌아간다. (http://w/add)로 POST 전송을 하여 글을 등록할 수 있다. 이 때 전송되는 폼필드들은 다음과 같다.
    • keyword: 위키 키워드. 제목과 동일하게 넣어준다.
    • title: 글의 제목. 별도로 입력받는다.
    • content: 본문. view 상의 내용이다.
  • 글의 제목은 뷰에서 추출하지 않고, 별도의 콘솔패널로부터 입력받는다.

주요 코드

다음은 실제 콘텐츠를 웹서버로 POST 전송하는 부분이다. 별도로 설명이 좀 필요하긴 하지만, 일단 다른 sublime 관련 속성들을 다른곳에서 정의했다고치고, 순수하게 POST 전송의 구현에만 집중해서 보자.

인코딩

전송할 값은 URL로 인코드되어야 한다. 파이썬2에서는 urllib.urlencode()라는 함수를 썼는데 파이썬3에서는 urllib.parse.urlencode()라는 함수로 변경됐다. 또한 파이썬2에서는 이 함수는 임의의 데이터를 인코딩할 수 있었던데 비해, 파이썬3에서는 (문자열, 문자열)의 튜플로 이루어진 데이터여야 한다.

또한 이렇게 URL로 인코딩한 결과는 다시 utf-8 등으로 인코딩하여 바이트스트림으로 변환해야 한다. (파이썬3에서는 내부적으로 문자열은 유니코드 스트링이며, 외부와 통신할 때는 utf-8등의 인코딩 규격으로 인코딩한 바이트스트림을 전송해야 한다.)

전송

urlopen 함수는 파이썬2에서는 urllib2 패키지의 것을 주로 사용했는데, 파이썬3에서는 urllib.request에 들어있다. 그리고 url만 인자로 주는 것 외에 Request 객체를 넘길 수 있다. 객체화된 요청을 전송하는 경우, 헤더나

따라서 실제 전송을 맡은 함수는 다음과 같이 코딩된다.

def send(self, keyword):
    data = [
        ('title': keyword),
        ('keyword': keyword),
        ('content': self.buffer_text) #별도로 정의해야함.
        ]
    # 데이터 인코딩
    encoded_data = urllib.parse.urlencode(data).encode('utf-8')
    # http 요청 헤더를 작성
    headers = {
        'Content-type': 'application/x-www-form-urlencode',
        'Accept': 'text/html'
    }
    request = urllib.request.Request('http://w/add', 
                data=data,
                headers=headers,
                method='POST')
    response = urllib.request.urlopen(request)
    return resoponse.read()

뷰 내의 컨텐츠 얻기

컨텐츠는 좀 요상한 방식으로 얻어온다. TextCommand에는 view 속성이 있어서 명령을 호출한 view에 접근하게 되는데, 이 view에 대해서 substr() 함수로 뷰 컨텐츠내 일부를 가져올 수 있다. 따라서

self.buffer_text = self.view.substr(sublime.Region(0, self.view.size()))

이렇게 얻는다.

제목 입력 받기

윈도의 input_panel을 이용해서 추가 텍스트를 입력받을 수 있다. 윈도 객체는 self.view.window() 함수를 통해서 참조를 얻을 수 있으며 이 객체의 show_input_panel 함수를 통해서 호출한다.

show_input_panel(caption, initial_text, on_doen, on_change, on_cancel)

이 정의된 파라미터이다. 따라서

self.view.window().show_input_panel('title: ', '', self.send, None, None) 

으로 호출하면 된다.

전체 코드

전체 코드는 아래 gist 스니핏 참고

명령세팅

명령의 팔레트 표시 정보 등을 다음과 같이 저장한다.

//Send2W.sublime-commands
[{
    "caption": "Send Text to w",
    "command": "send_ws"
}]