Pandoc은 각종 포맷 상호간의 변환을 수행할 수 있는 유틸리티로 Markdown, HTML 사이의 변환도 지원한다. 지원되는 포맷은 홈페이지서 다음과 같은 다이어그램으로 설명하고 있다.




설치

  1. https://github.com/jgm/pandoc/releases 에서 Pandoc 최신 버전을 다운받아 설치한다.

Markdown -> HTML 변환

  • Markdown을 HTML로 변환 (-o <출력파일명>을 생략하면 화면으로 출력된다.)
    pandoc -f markdown -t html <입력파일명> -o <출력파일명>
    
  • Github 스타일 Markdown을 HTML로 변환 (-o <출력파일명>을 생략하면 화면으로 출력된다.)
    pandoc -f markdown_github -t html <입력파일명> -o <출력파일명>
    

기타 변환

  • 미디어 위키를 HTML로 변환 (미디어 위키 특징 : Markdown에서 사용할 수 없는 테이블 문법을 사용할 수 있어 참고할 만하다.)
    pandoc -s -f mediawiki -t html <입력파일명> -o <출력파일명>
    

참고 사이트


<테스트 환경>
- OS : Windows 7 (64bit)
- Pandoc 버전 : 2.0.5


,

(point)

현재 위치를 반환. 1부터 시작. 한글도 1씩 할당.

(point-min)

최소 위치를 반환.

(point-max)

최대 위치를 반환.

(goto-char pos)

커서를 해당 위치로 이동. (pos: 이동할 위치.)

(goto-line line)

커서를 특정 행 번호로 이동. (line: 이동할 행번호.)

(forward-line line)

커서를 현재로부터 주어진 라인 수만큼 이동한다. (line: 이동할 라인 수.)

(search-forward "target-string" limit-of-search fail-fn repeat-count)

문자열을 검색하여 발견된 검색어 바로 뒤에 커서를 위치시킨다. 발견시 t를 반환한다.

  • target-string : 검색어.
  • limit-of-search : 최대 검색 범위를 위치로 제공하면 현재 위치에서 해당 위치 사이에서 검색. (nil : 제한 없음.)
  • fail-fn : 검색 실패시 실행할 구문 또는 nil(signal을 발생시킴) 또는 t(무시)로 설정할 수 있다.
  • repeat-count : 검색 횟수. 없으면 1회, 마이너스이면 역방향 검색어.

(number-to-string number)

숫자를 문자열로 변환. (number : 변환할 숫자.)

(delete-char size)

커서로부터 순방향으로 사이즈만큼 지운다. (size : 지울 사이즈.)

(delete-backward-char size)

커서로부터 역방향으로 사이즈만큼 지운다. (size : 지울 사이즈.)

(length str)

문자열의 길이를 반환한다. 한글의 경우도 1로 계산. (str : 문자열.)

(string-width str)

문자열의 보이는 사이즈를 반환한다. 한글의 경우는 2로 계산. (str : 문자열.)

(insert str)

현재 위치에 문자열을 삽입. (str : 삽입할 문자열.)

(sit-for sec)

메세지 등을 출력한 수 일정 시간 대기한다. 키입력이 들어오면 해제됨. (sec : 대기할 초 수)

(sleep-for sec)

메세지 등을 출력한 수 일정 시간 대기한다. 키입력이 들어와도 해제안됨. (sec : 대기할 초 수)

(thing-at-point 'word)

커서가 위치하는 곳의 단어를 얻는다.

(thing-at-point 'line)

커서가 위치하는 곳의 한 라인을 얻는다. 개행 문자도 포함.

(message string), (message format-string ...)

메세지를 출력한다.

(kill-new string)

문자열을 클립보드에 저장한다. (string : 저장할 문자열)

(yank)

클립보드의 내용을 현재 위치에 붙여넣는다.

(cl-search str1 str2)

첫번째 문자열이 두번째 문자열에 포함되는지 검사한 후 발견 위치(0부터 시작)를 반환한다. 발견되지 않을 경우 nil을 반환한다. 문자열 뿐만 아니라 시퀀스 전체에 대해 사용가능하다.

(sort line-list 'string<)

문자열의 리스트를 정렬한다. (line-list : 정렬할 문자열 리스트)

(substring string from to)

문자열의 일부를 자른다. (string : 자를 문자열, from : 시작 위치(0부터 시작), to : 끝 위치)

(format-time-string "%Y-%m-%d")

날짜 포맷에 일치하는 현재 날짜를 반환한다.

(read-string str)

미니 버퍼로부터 문자열을 입력받는다. (str : 입력시 미니 버퍼에 표시할 메세지)

(line-beginning-position)

현재 줄의 시작 위치를 반환한다.

(line-end-position)

현재 줄이 끝나는 위치를 반환한다.

(beginning-of-line)

현재 줄의 시작 위치로 커서를 이동시킨다.

(end-of-line)

현재 줄이 끝나는 위치로 커서를 이동시킨다.

region-beginning

선택 영역의 시작 위치를 반환한다.

region-end

선택 영역이 끝나는 위치를 반환한다.

use-region-p

선택 영역의 사용 여부를 반환한다.

buffer-file-name

[변수] 현재 버퍼의 절대 경로

buffer-file-truename

[변수] 현재 버퍼의 경로 (~/..와 같이 C-x f, C-x C-b에서 실제로 보여지는 경로)

default-directory

[변수] 현재 버퍼의 기본 디렉토리


<테스트 환경>
 - OS : Windows 7 (32bit)
 - Emacs 버전 : Emacs 24.3 윈도우용


,

Emacs의 가장 큰 차별점이라고 할 수 있는 emacs lisp를 활용한 버퍼 현실 조작에 필요한 내용을 정리해보았다.


사용자 함수 정의

  • .emacs 파일에 아래와 같은 방법으로 사용자 함수를 정의할 수 있다.
    (defun 함수명 ()
     (interactive)
     함수 내용
     )
    
    다음은 미니버퍼창에 간단히 메세지를 표시하는 예제이다.
    (defun my-func ()
      (interactive)
      (message "hello")
      )
    
  • 이렇게 정의한 함수는 언제든지 M-x를 누른 후, 함수명을 입력하여 실행할 수 있다.
  • 그런데 사용자 함수를 .emacs 파일에 직접 정의할 경우, 함수 내부에서 한글 사용시 문제가 발생한다. 이 경우, <emacs 설치 경로>/site-lisp 위치에 외부 파일을 생성하고 이 파일에 사용자 함수를 정의한 뒤, 아래와 같이 .emacs 파일에서 이를 읽어들이면 문제가 생기지 않는다.
    (load-library "외부 파일명")
    
    ==> [참고] UTF–8 한글 정상적으로 표시되도록 설정 방법
  • Emacs 실행 중에 위의 외부 정의 파일을 수정했을 경우에, 수정 내용을 바로 반영하기 위해서는, M-x를 누른 후 load-file을 입력하고 해당 파일의 경로를 입력하면 된다.

버퍼 조작 관련 유용한 함수들

외부 프로그램에서 함수 실행

  • emacsclient 실행시에 -e 인수를 사용하면 외부에서 내장 함수 혹은 사용자 함수를 실행할 수 있다.
     
    emacsclientw.exe -e "emacs lisp 표현식"
    
  • 윈도우 환경이라면, 아래와 같은 내용으로 배치파일을 작성하여 사용하는 것도 편리하다.
    emacsclientw.exe -n -e "%1"
    


    <테스트 환경>
     - OS : Windows 7 (32bit)
     - Emacs 버전 : Emacs 24.3 윈도우용
    
,

위의 두 글을 참고하면 웹페이지의 특정 class에 해당하는 부분을 추출하여 텔레그램 채널로 보내는 것이 가능하다.


사전 준비사항

  1. app template을 사용하여 프로젝트를 생성한다.

    lein new app clj-test-02
    

  2. project.clj 파일의 dependencies 부분에 아래와 같이 필요한 모듈을 정의한다.

    (defproject clj-test-02 "0.1.0-SNAPSHOT"
      :description "FIXME: write description"
      :url "http://example.com/FIXME"
      :license {:name "Eclipse Public License"
                :url "http://www.eclipse.org/legal/epl-v10.html"}
      :dependencies [[org.clojure/clojure "1.8.0"][clj-http "2.2.0"] [enlive "1.1.6" :exclusions [org.clojure/clojure]]]
      :main ^:skip-aot clj-test-02.core
      :target-path "target/%s"
      :profiles {:uberjar {:aot :all}})
    
    

예제

(ns clj-test-02.core
 (:gen-class)
 (:require [net.cgrand.enlive-html :as html])
 (:require [clj-http.client :as client]))

(use 'clojure.pprint)

(defn html-data []
  ;; clj-html 모듈을 사용하여 웹페이지의 내용을 가져온다.

  (html/html-resource (java.io.StringReader.
      (:body (client/get "http://httpbin.org"))))
)

(defn -main [& args]
  
  (pprint (client/post "https://api.telegram.org//bot<텔레그램 봇 토큰>/sendMessage" 
    {:body (format "{\"chat_id\": \"@<채널 ID>\", \"text\": \"%s\"}"
             (first (:content (first (html/select (html-data) [:.bash])))))
     :headers {"Content-Type" "application/json"}}))
)


<테스트 환경>
- OS : Windows 7
- Leiningen 버전 : 1.0.0
,

사전 준비사항

  1. app template을 사용하여 프로젝트를 생성한다.

    lein new app clj-test-01
    

  2. project.clj 파일의 dependencies 부분에 아래와 같이 필요한 모듈을 정의한다.

    (defproject clj-test-01 "0.1.0-SNAPSHOT"
      :description "FIXME: write description"
      :url "http://example.com/FIXME"
      :license {:name "Eclipse Public License"
                :url "http://www.eclipse.org/legal/epl-v10.html"}
      :dependencies [[org.clojure/clojure "1.8.0"] [clj-http "2.2.0"] [enlive "1.1.6" :exclusions [org.clojure/clojure]]]
      :main ^:skip-aot clj-test-01.core
      :target-path "target/%s"
      :profiles {:uberjar {:aot :all}})
    
    

HTML 파싱 예제

(ns clj-test-01.core
  (:gen-class) 
  (:require [net.cgrand.enlive-html :as html])
  (:require [clj-http.client :as client]))

(use 'clojure.pprint)

(defn html-data []
  ;; clj-html 모듈을 사용하여 웹페이지의 내용을 가져온다.

  (html/html-resource (java.io.StringReader.
      (:body (client/get "http://httpbin.org"))))
)

(defn -main [& args]
  
  ;; 태그로 찾기
  (pprint (html/select (html-data) [:a]))
  
  ;; id로 찾기
  (pprint (html/select (html-data) [:#AUTHOR]))
  
  ;; class로 찾기
  (pprint (html/select (html-data) [:.bash]))
  
  ;; 태그와 class를 조합해서 찾기
  (pprint (html/select (html-data) [:code.bash]))

)

반환값

html/select 함수의 결과는 아래와 같이 맵의 리스트 형태로 반환된다.

({:tag :a, :attrs {:href "http://httpbin.org"}, :content ("HTTP")}
  ... )

각각의 맵은 태그에 대한 정보를 담고 있는데, 태그의 내용물(content)이 단순 텍스트일 경우에 :content 부에 문자열의 리스트의 형태로 들어가며, 또다른 태그일 경우는 :content 부에 다시 맵의 리스트 형태로 들어간다.


태그의 내용물이 단순 텍스트일 때, 그 첫번째 문자열을 얻는 구문은 아래와 같이 된다.
(first (:content (first (html/select (html-data) [:.bash]))))

참고사이트


<테스트 환경>
- OS : Windows 7
- Leiningen 버전 : 1.0.0
,

react-native init시 아래와 같이 Unexpected token … 에러가 발생하는 경우

SyntaxError: Unexpected token ...
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:373:25)
    at Module._extensions..js (module.js:416:10)
    at Object.require.extensions.(anonymous function) [as .js] (C:\example01\node_modules\babel-register\lib\node.js:152:7)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (C:/example01/node_modules/react-native/local-cli/server/runServer.js:18:18)
    at Module._compile (module.js:409:26)

node.js를 최신 버전으로 재설치하여 해결이 되었다.

기존 버전: 4.4.7
업그레이드후 최신 버전: 6.11.2
,
  1. .emacs 파일에 다음과 같이 함수를 정의한다.
    (defun delete-this-buffer-and-file ()
      "Removes file connected to current buffer and kills buffer."
      (interactive)
      (let ((filename (buffer-file-name))
            (buffer (current-buffer))
            (name (buffer-name)))
        (if (not (and filename (file-exists-p filename)))
            (error "Buffer '%s' is not visiting a file!" name)
          (when (yes-or-no-p "Are you sure you want to remove this file? ")
            (delete-file filename)
            (kill-buffer buffer)
            (message "File '%s' successfully removed" filename)))))
    


  2. 위 함수에 키를 바인딩한다.(C-c k)
    (global-set-key (kbd "C-c k") 'delete-this-buffer-and-file)
    


<테스트 환경>
OS : Windows 7
Emacs 버전 : Emacs 24.3 윈도우
,

React Native는 react 문법을 사용하여 WebApp이 아닌 모바일 Native 앱을 작성할 수 있게 하는 기능을 제공한다.(안드로이드, 아이폰 지원)

  • [참고] 데스크탑용으로는 Native 어플리케이션 작성을 지원하는 react-native-macos(OSX용), react-native-windows(윈도우용)가 있고, WebApp 형태로 작성할 경우 OS별 테마가 적용된 react component인 react-desktop이 있다.


사전 설치 요구사항

  • Node.js


  • 안드로이드 스튜디오


안드로이드 스튜디오 세팅

  1. SDK Manager를 실행한다.


  2. Android 6.0 SDK(Marshmallow, API Level = 23)를 설치한다. (주의: 현재 Android 7.0 SDK는 지원하지 않는다)


  3. AVD Manager를 실행한다.


  4. 6.0 SDK를 사용하여 AVD를 생성한다.


React Native 설치

  1. 커맨드라인 상에서 아래와 같이 입력하여 React Native를 설치한다.
    npm install -g react-native-cli
    


샘플 프로젝트 생성 및 실행

  1. 커맨드라인 상에서 아래와 같이 입력하면 샘플 프로젝트가 생성된다.

    react-native init 생성할-프로젝트명
    

    => [참고] react-native init시 Unexpected token … 에러가 발생하는 경우


  2. AVD(안드로이드 에뮬레이터)가 실행되어 있는 상태에서 아래와 같이 입력하면 프로젝트가 빌드되어 에뮬레이터 상에 실행되는 것을 볼 수 있다.

    react-native run-android
    


  3. [참고] IOS용 실행 커맨드는 참고로 다음과 같다.

    react-native run-ios
    


참고 사이트

<테스트 환경>
- OS : Windows 7
- 안드로이드 스튜디오 버전 : 2.3.3
- node.js 버전 : 6.11.2
- react-native-cli 버전 : 2.0.1


,