[첫화면으로]ViEditor/마크다운프리뷰

마지막으로 [b]

13 번째 수정본

윈도우 vim 에서 markdown 파일 실시간 미리보기

1. 개요
2. 맥과 리눅스의 경우
3. 필요한 것들 설치
4. 적용법 간단 설명
5. 수정 내역
5.1. instant-markdown-d 패키지
5.1.1. wrapper 스크립트
5.1.2. instant-markdown-d
5.2. vim-instant-markdown 플러그인
5.2.1. 윈도우용 curl 설치
5.2.2. instant-markdown.vim 수정
5.2.3. nodemd.cmd 래퍼
5.2.4. _vimrc 파일
6. 스크린샷
7. 기타&comments

1. 개요

vim 플러그인 중에 vim-instant-markdown(Github: [1])이란 게 있는데, 이걸 설치하고 vim으로 마크다운 형식의 파일(*.md, *.markdown)을 열면 웹브라우저 창이 열리면서 현재 편집 중인 마크다운 파일을 렌더링한 결과물을 실시간으로 보여준다.

문제는 이게 맥과 리눅스에서만 동작하고 윈도우에서는 안 된다는 건데... 윈도우에서 "미리보기가 지원되며 실시간으로 반영되며, 코드 블록과 테이블 문법도 잘 지원되면서 이왕이면 신택스 하일라이트도 되고 무료인" 마크다운 편집기를 찾다 찾다 못 찾아서1... 이 플러그인을 윈도우에서 쓸 수 없을까 하며 토요일 하루밤을 삽질로 보내었다.

문제는 이 플러그인을 쓰는 과정이 세 가지의 조합이라서, 딱 원하는 형태로 만들기가 너무 힘들다는 것.

결국 그럭저럭 쓸 수 있는 상태로 만들었고, 이 페이지에 그 과정을 정리한다. 뭔가 불만족스러운 부분이 많이 남아 있어서, 혹시 누군가 이 글을 보고 도움을 주지 않을까 하는 기대도 있다.

2. 맥과 리눅스의 경우

그냥 플러그인 홈페이지([1])에 가서 시키는 대로 하면 된다.

You first need to have node.js with npm installed.

3. 필요한 것들 설치

일단 윈도우에 필요한 것들을 설치한다.

node.js

instant-markdown-d 패키지

플러그인

그리고 나서 *.md 파일을 편집해보면... 아무 일도 안 일어난다. 이제 고쳐보자.

4. 적용법 간단 설명

5. 수정 내역

5.1. instant-markdown-d 패키지

5.1.1. wrapper 스크립트

이 패키지를 설치한 후 실행하기 위해서 꼬박꼬박
node.exe %APPDATA%\npm\node_modules\instant-markdown-d\instant-markdown-d
라고 실행해도 되긴 하겠지만, 그보다는 편하게
instant-markdown-d
라고 실행할 수 있도록, 래퍼 스크립트가 %APPDATA%\npm\ 폴더에 만들어져 있다. 그런데 막상 이걸 열어보면 sh.exe 를 띄우도록 되어 있어서 동작하지 않는다. node.exe를 실행하도록 수정

[%APPDATA%\npm\instant-markdown-d.cmd 파일]

5.1.2. instant-markdown-d

길게 쓰려니 귀찮아져서, github에 올리고 여기서는 수정 내용에 대해 간단히 적는다.

1) 로컬 웹서버를 띄우면서 웹 브라우저 창도 같이 띄워야 하는데, 맥의 open 대신 명령 프롬프트에서는 start를 써서 띄운다. ([커밋])

2) F5를 눌러 새로 고침하면 그냥 빈 화면만 나오게 되어 있다. 이게 불편하다. 게다가 vim으로 기존 파일을 열었을 때, 분명히 서버도 실행되었는데 브라우저에 빈 화면만 나올 때가 있는데, 이 때 F5를 눌러 갱신할 수 있으면 좋겠다 싶어서, 현재 출력 내용을 저장해두었다가 새로 브라우저에서 접속할 때 그것을 사용하게 한다. ([커밋])

3) 거의 쓸 일이 없긴 하지만, 마크다운 안에 이미지 파일이 있는 경우 현재 플러그인은 그 파일을 이 데몬이 있는 디렉토리를 기준으로 찾는다. 그것을 고쳐서 일단 현재 작업 디렉토리(vim 플러그인을 쓰게 되면 vim의 현재 작업 디렉토리가 됨) 아래에서 먼저 찾아보도록 하였다. ([커밋])

![Alt text](images/myimage.jpg)    # vim의 CWD/images/myimage.jpg 를 먼저 찾음

4) 데몬에서 로그 출력 레벨을 지정하는 구문이 경고가 뜨길래 찾아보니 최신 버전은 로그 레벨 지정을 다른 방식으로 하여야 하는가 봄. 주석 처리함. ([커밋])

5.2. vim-instant-markdown 플러그인

5.2.1. 윈도우용 curl 설치

이 플러그인은 편집 중이던 버퍼의 내용을 curl을 사용하여 node.js 서버에 전송한다. (화면 갱신을 위해서는 PUT, 창을 닫으면 더 이상 남은 마크다운 버퍼가 없으면 DELETE 메소드로 요청을 보냄) 따라서 윈도우용 curl이 깔려 있어야 한다. [cURL - Download]에 가서 win32 또는 win64 버전을 받아 쓴다. 나는 Win64 - MinGW64 버전을 받아서 압축 파일 속에 curl.exe 파일만 뽑아서 PATH 지정이 되어 있는 곳에 넣었다.

5.2.2. instant-markdown.vim 수정

1) gvim 실행 후 마크다운 파일을 제일 처음 열 때 node.js 서버를 띄우게 된다. 그런데 이 때 백그라운드로 띄워야 하는데, 리눅스나 맥의 셸에서는 아주 간단하다.

function! s:startDaemon(initialMD)
" instant-markdown-d 를 백그라운드로 실행하고
" 처음에 버퍼에 들어있는 텍스트 a:initialMD를 표준 입력으로 전달하면
" node.js 서버가 그걸 받아서 렌더링 후 출력한다
    call s:system("instant-markdown-d &>/dev/null &", a:initialMD)
endfu

&>/dev/null을 써서 출력은 그냥 버리도록 하고, 끝에 &를 붙여 백그라운드로 실행한다. 그런데 윈도우 명령 프롬프트에서 똑같이 동작하게 하자니 정말 뜻대로 되지 않는다2. 이 한 줄을 고치는데 몇 시간 시행착오를 겪었다. 결론을 얘기하면, ([커밋])

function! s:startDaemon(initialMD)
" 래퍼 스크립트를 만들어서 그것을 실행하되, 실행할 때는 표준 입력을 주지 않음
    call s:system("nodemd.cmd", "")
" 서버가 뜬 후 약간 기다려야 제대로 소켓이 연결된다
    sleep 1
" 그 다음 현재 버퍼의 내용을 가지고 화면을 갱신하도록 함
    call s:refreshView()
endfu

이 래퍼 스크립트의 내용은 아래에 설명.

2) 화면 갱신 또는 서버 종료를 지시하는 요청을 curl을 보낼 때도, 백그라운드로 수행할 수 없어서 그냥 포어그라운드로 수행하도록 한다. 억지로 start 같은 걸 쓰면 프롬프트 창을 새로 띄우느라 더 버벅인다. ([커밋])

-    call s:system("curl -X PUT -T - http://localhost:8090/ &>/dev/null &",
+    call s:system("curl -X PUT -T - http://localhost:8090/",

3) curl을 백그라운드로 실행하지 못하기 때문에, 한 글자 한 글자 타이핑할 때마다 갱신 요청을 보낼 수가 없다. 키보드 입력 속도를 따라잡지 못한다. 별 수 없이 g:instant_markdown_slow 옵션을 주어, 입력을 멈추고 몇 초 지나거나 입력 모드에서 빠져나갈 때만 갱신 요청이 날아가게 해야 한다. 그런데 막상 해보니까, 입력 모드에서 입력을 하다가 잠깐 멈추고 기다리고 있을 때 갱신이 안 되더라. 그래서 입력 모드에서 커서가 일정 시간(약 5초인 듯) 멈춰 있는 경우를 추가로 명시해준다. ([커밋])

-          au CursorHold,BufWrite,InsertLeave <buffer> call s:temperedRefresh()
+          au CursorHold,CursorHoldI,BufWrite,InsertLeave <buffer> call s:temperedRefresh()

5.2.3. nodemd.cmd 래퍼

위에 언급한, node.js 서버를 띄우는 래퍼 스크립트를 만든다. nodemd.cmd 라는 이름으로 저장해서 PATH 지정이 된 경로에 넣는다.

@echo off
REM /B를 쓰면 서버의 표준 출력이 임시디렉토리에 생성된 파일에 리다이렉션됨.
REM cmd /c 를 명시적으로 넣지 않으면 나중에 서버가 종료되었을 때 프롬프트 창이 사라지지 않음
REM start /B cmd /c instant-markdown-d %*

REM 또는

REM 서버에서 나오는 출력을 파일에 담지 않고 그냥 보고 싶으면
REM /B를 없애면 출력이 표준 출력으로 나옴
REM 생성된 프롬프트 창으로 포커스가 이동하지 않도록 /MIN을 써서 생성 즉시 최소화
REM 종료 후 창이 닫혀야 하니 역시 cmd /c
start /MIN cmd /c instant-markdown-d %*

래퍼 스크립트의 내용은 덜렁 한 줄이다. 그럼 이 한 줄을 그냥 vim script 에 넣으면 안 될까?

" 이유는 모르겠는데 안 됨
    call s:system("start /MIN cmd /c instant-markdown-d", "")

이렇게 하고 실행하면 vim이 에러를 내뿜는데(게다가 서버가 제대로 뜰 때도 있고 아닐 때도 있다-_-) 이유를 알려면 vim 문서를 들여다봐야 할 것 같다.

5.2.4. _vimrc 파일

위에서 말했듯이 타이핑할 때마다 갱신 요청을 하지 않도록 옵션을 명시해준다.

let g:instant_markdown_slow = 1

6. 스크린샷

동영상으로 찍으면 더 좋았겠는데 귀찮아서... 플러그인 깃헙 저장소([1])에 가보면 gif 스샷도 있다.

7. 기타&comments

이 작업 다 하고나서야 알았는데 플러그인 페이지에 누가 윈도에서 되게 수정해서 pull request 날린 게 있더라 ([2])... 내가 제대로 삽질했구나 해서 망연자실했는데, 저 코드가 문제가 있는지(본인이 잘 되니까 올렸을 텐데) 서버가 백그라운드로 돌지 못해서 vim이 진행을 못하는 등의 몇 가지 문제가 있음. 하지만 몇몇 부분은 이쪽 코드에 적용해도 될 것 같다. 나중에 시간 있을 때...

이름:  
Homepage:
내용:
 

컴퓨터분류
각주:
1. 내가 써 본 것 중에는 [Haroopad]가 그나마 나았다.
2. [How can I execute a Windows command line in background? - Super User], [/dev/null in Windows? - Stack Overflow]

이 수정본 편집일: 2016-2-21 11:59 pm (변경사항 [d])
2384 hits | Permalink | 변경내역 보기 [h] | 현재 수정본 보기 | 13 번째 수정본 소스 보기