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

마지막으로 [b]

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

1. 개요
2. 맥과 리눅스의 경우
3. 필요한 것들 설치
4. 적용법 간단 요약
5. 스크린샷
6. 알려진 문제점(또는 한계)
7. 수정 내역
7.1. instant-markdown-d nodejs 패키지
7.1.1. wrapper 스크립트
7.1.2. instant-markdown-d
7.2. vim-instant-markdown 플러그인
7.2.1. 윈도우용 curl 설치
7.2.2. instant-markdown.vim 수정
7.2.3. nodemd.cmd 래퍼
7.2.4. _vimrc 파일
8. 기타&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. 적용법 간단 요약

바로 써보고 싶은 사람들을 위한 간단 요약. 일단 설치까지 된 상태에서 다음 사항들을 적용한다.

1. [instant-markdown-d.cmd]을 받아서 %APPDATA%\npm\instant-markdown-d.cmd를 덮어쓴다.

2. [instant-markdown-d]을 받아서 %APPDATA%\npm\node_modules\instant-markdown-d\instant-markdown-d를 덮어쓴다.

3. https://curl.haxx.se/download.html 여기에서 Win32 또는 Win64 버전의 curl을 받아, curl.exe 파일을 적당한 폴더에 두고 PATH 지정을 한다.

4. [instant-markdown.vim]을 받아서 VIM설치폴더\vimfiles\after\ftplugin\markdown\instant-markdown.vim을 덮어쓴다.

5. [nodemd.cmd]을 받아서 적당한 폴더에 두고 PATH 지정을 한다.

6. 사용 중인 vim설정 파일(아마도 _vimrc)에 다음 라인을 추가한다.

let g:instant_markdown_slow = 1

7. gvim으로 .md 파일을 열어서 편집한다. 그러면 잠시 후에 기본 브라우저의 창이 뜨면서 localhost:8090에 연결이 이루어지고 파일의 내용을 렌더링한 결과가 보인다.

8. 렌더링 결과는 편집하는 동안 자동으로 반영이 되긴 하는데, 한 글자 타이핑할 때마다 바로바로 반영되지는 않는다. 몇 초간 입력이 없거나, ESC를 눌러 입력 모드를 벗어나거나, 파일을 저장할 때 갱신된다.

5. 스크린샷

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

6. 알려진 문제점(또는 한계)

1. 이유를 알 수 없지만 node.js서버가 뜨지 않고 웹브라우저 창도 안 뜨는 경우가 가끔 있다.

2. 서버와 창까지 뜨긴 했는데 마크다운 텍스트가 있음에도 불구하고 빈 화면이 나오는 경우가 있다. 이 경우 페이지를 새로 고침하면 나올 것이다.

3. gvim 프로세스를 하나만 띄운 상태에서 탭이나 split 등으로 여러 마크다운 파일을 수정하는 경우는 파일을 옮겨다닐 때마다 해당 파일 쪽의 내용을 렌더링해주지만, 프로세스를 둘 이상 띄워서 오갈 경우는 제대로 반영되지 않아서 다음 번 갱신을 기다리거나 강제로 갱신시켜줘야 한다. 게다가 이때 gvim 창 하나를 완전히 닫으면 서버도 같이 종료되므로 다른 창에서도 더 이상 미리보기를 볼 수 없다.(다시 서버를 띄우게 할 수는 있는데 그렇게 고쳤다가 다른 문제가 생길 것 같아서 미룸. 어차피 한 번에 여러 마크다운 파일을 동시에 수정할 일도 드물 것 같고.)

7. 수정 내역

이 절은 어디를 어떻게 고쳐야 했는지를 적은 것이다. vim script에 능통한 누군가가 더 좋은 방법을 알려주길 바람.

7.1. instant-markdown-d nodejs 패키지

[Commits · gypark/instant-markdown-d · GitHub] - 이 변경 관련 커밋 로그

7.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 파일]

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

7.2. vim-instant-markdown 플러그인

[Commits · gypark/vim-instant-markdown · GitHub] - 이 변경 관련 커밋 로그

7.2.1. 윈도우용 curl 설치

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

7.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()

7.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 문서를 들여다봐야 할 것 같다.

7.2.4. _vimrc 파일

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

let g:instant_markdown_slow = 1

8. 기타&comments

웬만하면 그냥 하루패드 쓰세요 -_-;;; vim 키바인딩도 지원함. 전에 좀 쓰다가 불편했던 게 저장을 안 한 채로 종료하면 그대로 확인 과정 없이 꺼져버리는 거였는데, 그 문제는 해결되었더라.

이 작업 다 하고나서야 알았는데 플러그인 페이지에 누가 윈도에서 되게 수정해서 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-22 1:25 am (변경사항 [d])
1814 hits | Permalink | 변경내역 보기 [h] | 페이지 소스 보기