Org모드에서 스프레드시트 기능과 Babel 섞어쓰기

Posted on Dec 13, 2019

쩌는 Org-mode Spreadsheet 소개 를 읽고 감명 받아서 따라해봅니다.

다른 부분은 만족스러웠는데, 조금 복잡한 elisp식을 쓰기 귀찮으니, 미리 defun / defmacro 으로 정의해놓고 그걸 spreadsheet에서 불러 쓸 수 있을지가 궁금했습니다.

그래서 다음과 같이 해보면 가능할지를 실험:

  1. Org-Babel으로 원하는 함수를 정의한다.

    • 그리고 Org 파일이 로딩될 때 평가하도록 속성을 지정해놓는다.
  2. Spreadsheet에서 불러서 쓸 수 있는지 확인해본다.

우선 C-h a 을 눌러 vsum 을 검색해보니, defun calcFunc-vsum (&rest vecs) 으로 미리 선언되어 있는거 같았습니다. 이런 형태로 내가 정의하는 함수도 구현해보면 될까 싶습니다.

이제부터 작성하는 내용은 HTML으로 렌더링된 내용과 실제로 제가 작성한 Org 파일의 소스에만 드러나는 내용이 다를 수 있으니

https://raw.githubusercontent.com/ageldama/ageldama-github-io-hugo/master/content/posts/2019-12dec/org-spreadsheet-and-babel.org

여기를 참고하며 비교해 읽으시면 좋을거 같습니다.

간단한 함수 2개를 정의해볼게요: str-reverse, str-palindrome?

Org-Babel으로 정의를 하고 테스트를 해보겠습니다.

  (defun str-reverse (s)
    (reverse s))

  (message "Well, `str-reverse' has defined.")
  ;; ~C-c C-c~ to run this snippet
Well, ‘str-reverse’ has defined.

–> 이렇게 #+CALL: str-reverse() 호출해도, 결과로 치환되어 표시됨을 위에서 확인 가능합니다.

그리고 이 파일의 헤더에

#+COMMENT: -*- eval: (let () (org-babel-goto-named-src-block "str-reverse") (org-babel-execute-src-block)); -*-

..와 같이 지정해놓아서, 이맥스에서 이 파일을 열려고 하면, 이맥스는 지정한 코드 블록을 실행할 것인지를 확인할 것입니다. (그냥 무조건 실행하면 바이러스 같은걸 Org 파일만으로 얼마든지 만들 수 있을테니까요.)

여기 https://www.reddit.com/r/emacs/comments/64jhlt/autoexecuting_code_in_org_mode/ 에 나온 방법을 사용했고, 다른 방법으로도 이렇게 Org 파일을 이맥스에서 여는 것만으로도 Org-Babel 블록을 평가하도록 하는게 가능한가 봅니다.

그리고, defun str-reverse (s) 이 잘 동작하나 테스트 해볼게요:

  (list (str-reverse "foobar")
        (str-reverse "")
        (str-reverse "abc"))
raboof cba

..적당한거 같습니다.

이번엔 defun str-palindrome? (s) 을 만들어 봅시다. 그리고 이번에는 testcase을 table으로 만들어 입력에 적용해보겠습니다.

abc abcba madam zoom anna
  (defun str-palindrome? (s)
    (string-equal (str-reverse s) s))

  (mapcar (lambda (i) (mapcar #'str-palindrome? i))
          inputs)
nil t t t nil t

.. 빈 문자열, abcba, madam, anna 은 palindrome이 맞으니 잘 동작하는거 같네요.

이렇게 하기 위해서는 https://orgmode.org/worg/org-contrib/babel/intro.html#arguments-to-source-code-blocks 여기를 참고했습니다.

  1. 테이블에 이름을 할당하고: #+tblname: foobar
  2. #+BEGIN_SRC 에 변수로 바인딩해주고: #+BEGIN_SRC emacs-lisp :var varname=inputs
  3. 코드 안에서 varname 을 리스트로 접근해 사용.

이외에도 R, Python등 실행한 결과로 생성된 파일을 참조해서 inline image으로 표시할 수도 있는거 같으니 정말 유용할거 같습니다.

그래서 정의한 함수를 적용해볼 테이블입니다:

여러개의 Org-Babel 블록을 헤더에 추가하기 귀찮으니 str-reverse 만 시험해봅니다:

String Reverse
abc cba
foobar raboof
madam madam

쨔잔!1

뭔가 잘 된거 같아 기쁩니다.

느낀점

  1. Org 모드에 있는 수많은 기능을 다 알고 매일마다 쓸 필요는 없겠지만,

    • 그래도 뭐가 있는지 한번 살펴보고, 이해하고 그때 그때 필요할 때 적용해 쓰는 습관은 나를 위해 좋을거 같다.
  2. 특히 다이어그램을 그리거나, 코드를 실행한 결과를 삽입하거나, 표를 그리거나 등등에 유용할만한 기능인데 활용을 안해오고 살아서 나 자신이 게으른거 같은 기분.
  3. 이맥스 세상은 역시 리습과 유닉스로 이루어져있다.
  4. 죽여주는 문서로 새로운 것을 배우는 것은 언제나 즐겁다.

    • 혹은 안다고 생각해왔지만 잘 이해 못하던 것을 조금이나마 이해가 깊어지는 경험.
    • 고맙습니다. https://seorenn.github.io/

Footnotes