├── .gitignore ├── Makefile ├── .travis.yml ├── test-ob-go.org ├── README.org ├── test-ob-go.el └── ob-go.el /.gitignore: -------------------------------------------------------------------------------- 1 | .test-org-id-locations -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test 2 | 3 | test: 4 | @rm -f .test-org-id-locations 5 | emacs -Q --batch -q \ 6 | -L . \ 7 | -l ob-go.el \ 8 | -l test-ob-go.el \ 9 | --eval "(progn \ 10 | (setq org-confirm-babel-evaluate nil) \ 11 | (org-babel-do-load-languages \ 12 | 'org-babel-load-languages '((emacs-lisp . t) \ 13 | (sh . t) \ 14 | (org . t) \ 15 | (go . t))))" \ 16 | -f ob-go-test-runall 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: generic 2 | 3 | env: 4 | matrix: 5 | - EMACS=emacs23 6 | - EMACS=emacs24 7 | - EMACS=emacs-snapshot 8 | 9 | matrix: 10 | allow_failures: 11 | - env: EMACS=emacs-snapshot 12 | 13 | before_install: 14 | - if [ "$EMACS"= "emacs23" ]; then 15 | sudo apt-get -qq update && 16 | sudo apt-get -qq -f install && 17 | sudo apt-get -qq install emacs23 emacs23-el curl org-mode; 18 | fi 19 | - if [ "$EMACS" = "emacs24" ]; then 20 | sudo add-apt-repository -y ppa:cassou/emacs && 21 | sudo apt-get -qq update && 22 | sudo apt-get -qq -f install && 23 | sudo apt-get -qq install emacs24 emacs24-el; 24 | fi 25 | - if [ "$EMACS" = "emacs-snapshot" ]; then 26 | sudo add-apt-repository -y ppa:ubuntu-elisp/ppa && 27 | sudo apt-get -qq update && 28 | sudo apt-get -qq -f install && 29 | sudo apt-get -qq install emacs-snapshot emacs-snapshot-el; 30 | fi 31 | 32 | before_script: 33 | - if [ "$EMACS" = "emacs23" ]; then 34 | curl 'http://orgmode.org/org-8.2.5h.tar.gz' \ 35 | | tar xzf - --wildcards --strip-components=2 org-8.2.5h/lisp/*.el && 36 | curl 'http://git.savannah.gnu.org/cgit/emacs.git/plain/lisp/emacs-lisp/ert.el?h=emacs-24.3' > ert.el; 37 | fi 38 | 39 | script: make test 40 | -------------------------------------------------------------------------------- /test-ob-go.org: -------------------------------------------------------------------------------- 1 | #+OPTIONS: ^:nil 2 | * Simple tests 3 | :PROPERTIES: 4 | :ID: 412a86b1-644a-45b8-9e6d-bdc2b42d7e20 5 | :END: 6 | #+source: simple 7 | #+BEGIN_SRC go :imports "fmt" :results silent 8 | fmt.Printf("%d", 42) 9 | #+END_SRC 10 | 11 | #+source: integer-var 12 | #+BEGIN_SRC go :var q=12 :imports "fmt" :results silent 13 | fmt.Print(q) 14 | #+END_SRC 15 | 16 | #+source: two-variables 17 | #+BEGIN_SRC go :var q=333 :var p=333 :imports "fmt" :results silent 18 | fmt.Print(q+p) 19 | #+END_SRC 20 | 21 | #+source: two-variables2 22 | #+HEADER: :var q=333 23 | #+HEADER: :var p=333 24 | #+BEGIN_SRC go :imports "fmt" :results silent 25 | fmt.Print(q+p) 26 | #+END_SRC 27 | 28 | #+source: string-var 29 | #+BEGIN_SRC go :var q="golang" :imports "fmt" :results silent 30 | fmt.Print(q) 31 | #+END_SRC 32 | 33 | #+source: basic 34 | #+BEGIN_SRC go :results silent 35 | package main 36 | 37 | import "fmt" 38 | 39 | func main() { 40 | fmt.Println("hello,ob-go") 41 | } 42 | #+END_SRC 43 | 44 | * Array 45 | :PROPERTIES: 46 | :ID: 1e9cf4e3-02df-4f3c-8533-2c0b1ca0a25a 47 | :END: 48 | #+source: array 49 | #+BEGIN_SRC go :imports "fmt" :results vector :results silent 50 | for i := 1; i < 3; i++ { 51 | fmt.Printf("%d\n", i) 52 | } 53 | #+END_SRC 54 | 55 | * Matrix 56 | :PROPERTIES: 57 | :ID: 15000dad-5af1-45e3-ac80-a371335866dc 58 | :END: 59 | #+name: Go-matrix 60 | | 1 | 2 | 61 | | 3 | 4 | 62 | 63 | #+source: list-var 64 | #+BEGIN_SRC go :var a='("abc" "def") :imports "fmt" :results silent 65 | fmt.Printf("%s\n", a[0] + a[1] + string(len(a))) 66 | #+END_SRC 67 | 68 | * Imports 69 | :PROPERTIES: 70 | :ID: e1aaec56-f3c6-4187-a003-5530b3ba956d 71 | :END: 72 | #+source: imports 73 | #+BEGIN_SRC go :imports '("fmt" "math") :results silent 74 | fmt.Printf("%v", math.Pi) 75 | #+END_SRC 76 | 77 | #+source: imports2 78 | #+BEGIN_SRC go :imports "math" :results silent 79 | package main 80 | 81 | import "fmt" 82 | 83 | func main() { 84 | fmt.Printf("%v", math.Pi) 85 | } 86 | #+END_SRC 87 | * Package 88 | :PROPERTIES: 89 | :ID: c44f7afe-d356-4293-ba83-9ac71c7e6049 90 | :END: 91 | 92 | #+source: package 93 | #+BEGIN_SRC go :main no :package main :imports "fmt" :results silent 94 | func main() { 95 | fmt.Printf("works") 96 | } 97 | #+END_SRC 98 | 99 | * Regression tests 100 | :PROPERTIES: 101 | :ID: 3f63c93d-6f17-478d-9817-e5c24a696689 102 | :END: 103 | 104 | #+BEGIN_SRC go :imports "fmt" :results silent 105 | s := "'h' and 'i'" 106 | fmt.Printf("%s\n", s) 107 | #+END_SRC 108 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Readme 2 | 3 | * Introduction 4 | 5 | =ob-go= enables [[http://orgmode.org/worg/org-contrib/babel/intro.html][Org-Babel]] support for evaluating [[http://golang.org/][go]] code. It was 6 | created based on the usage of [[http://orgmode.org/worg/org-contrib/babel/languages/ob-doc-C.html][ob-C]]. The go code is compiled and run 7 | via the =go run= command. If a =main= function isn't present, by 8 | default the code is wrapped in a simple =main= func. If =:package= 9 | option isn't set and no package is declared in the code, then the 10 | =main= package is declared. 11 | 12 | : #+begin_src go :imports "fmt" 13 | : fmt.Println("Hello, 世界") 14 | : #+end_src 15 | : 16 | : #+results: 17 | : : Hello, 世界 18 | 19 | * Language Specific Header Arguments 20 | 21 | In addition to the normal header arguments for Babel, below are some some 22 | headers specific to go. 23 | 24 | - =:args= :: Command line arguments to pass to the executable compiled from 25 | the code block. To pass more than one argument, use a list. 26 | - =:flags= :: Flags to pass to the =go run= command. These are the flags 27 | that you would pass to =go build=. 28 | - =:main= :: If set to =no=, inhibits the auto wrapping of the =main= 29 | function call. Default: yes 30 | - =:imports= :: Shorthand for supplying imports to the app. This should be 31 | used when you're letting the application handle the =main= 32 | function. To supply more, use a list. 33 | - =:package= :: Set the package of the file. *Requires :main no*. If 34 | not set, and code doesn't have a explicit package, then =main= 35 | package is declared. Set to =nil= by using =:package 'discard= 36 | - =:var= :: `ob-go' also supports Babel variables with some limitations. See 37 | `ob-go' for more information about some of the limitations using 38 | =:var=. 39 | 40 | * Additional Examples 41 | 42 | ** Multiple Imports 43 | 44 | : #+begin_src go :imports '("fmt" "time") 45 | : fmt.Println("Current Time:", time.Now()) 46 | : #+end_src 47 | : 48 | : #+RESULTS: 49 | : : Current Time: 2012-04-29 11:47:36.933733 -0700 PDT 50 | 51 | ** Concurrent Prime Sieve 52 | 53 | : #+begin_src go 54 | : // A concurrent prime sieve 55 | : package main 56 | : 57 | : import "fmt" 58 | : 59 | : // Send the sequence 2, 3, 4, ... to channel 'ch'. 60 | : func Generate(ch chan<- int) { 61 | : for i := 2; ; i++ { 62 | : ch <- i // Send 'i' to channel 'ch'. 63 | : } 64 | : } 65 | : 66 | : // Copy the values from channel 'in' to channel 'out', 67 | : // removing those divisible by 'prime'. 68 | : func Filter(in <-chan int, out chan<- int, prime int) { 69 | : for { 70 | : i := <-in // Receive value from 'in'. 71 | : if i%prime != 0 { 72 | : out <- i // Send 'i' to 'out'. 73 | : } 74 | : } 75 | : } 76 | : 77 | : // The prime sieve: Daisy-chain Filter processes. 78 | : func main() { 79 | : ch := make(chan int) // Create a new channel. 80 | : go Generate(ch) // Launch Generate goroutine. 81 | : for i := 0; i < 10; i++ { 82 | : prime := <-ch 83 | : fmt.Println(prime) 84 | : ch1 := make(chan int) 85 | : go Filter(ch, ch1, prime) 86 | : ch = ch1 87 | : } 88 | : } 89 | : #+end_src 90 | : 91 | : #+RESULTS: 92 | : #+begin_example 93 | : 2 94 | : 3 95 | : 5 96 | : 7 97 | : 11 98 | : 13 99 | : 17 100 | : 19 101 | : 23 102 | : 29 103 | : #+end_example 104 | 105 | * Running tests 106 | 107 | Tests can be executed by /make test/ or invoking emacs directly with 108 | the command-line below: 109 | 110 | #+BEGIN_SRC shell 111 | # For Emacs earlier than 24, add -L /path/to/ert 112 | emacs -Q --batch \ 113 | -L . \ 114 | -l ob-go.el \ 115 | -l test-ob-go.el \ 116 | --eval "(progn \ 117 | (setq org-confirm-babel-evaluate nil) \ 118 | (org-babel-do-load-languages \ 119 | 'org-babel-load-languages '((emacs-lisp . t) \ 120 | (sh . t) \ 121 | (org . t) \ 122 | (go . t))))" \ 123 | -f ob-go-test-runall 124 | #+END_SRC 125 | -------------------------------------------------------------------------------- /test-ob-go.el: -------------------------------------------------------------------------------- 1 | ;;; test-ob-go.el --- tests for ob-go.el 2 | 3 | ;; This file is not part of GNU Emacs. 4 | 5 | ;; This program is free software; you can redistribute it and/or modify 6 | ;; it under the terms of the GNU General Public License as published by 7 | ;; the Free Software Foundation, either version 3 of the License, or 8 | ;; (at your option) any later version. 9 | 10 | ;; This program is distributed in the hope that it will be useful, 11 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | ;; GNU General Public License for more details. 14 | 15 | ;; You should have received a copy of the GNU General Public License 16 | ;; along with this program. If not, see . 17 | 18 | ;;; Code: 19 | (require 'ert) 20 | (require 'org-id) 21 | 22 | (defconst ob-go-test-dir 23 | (expand-file-name (file-name-directory (or load-file-name buffer-file-name)))) 24 | 25 | (defconst org-id-locations-file 26 | (expand-file-name ".test-org-id-locations" ob-go-test-dir)) 27 | 28 | (defun ob-go-test-update-id-locations () 29 | (let ((files (directory-files 30 | ob-go-test-dir 'full 31 | "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*\\.org$"))) 32 | (org-id-update-id-locations files))) 33 | 34 | (defmacro org-test-at-id (id &rest body) 35 | "Run body after placing the point in the headline identified by ID." 36 | (declare (indent 1)) 37 | `(let* ((id-location (org-id-find ,id)) 38 | (id-file (car id-location)) 39 | (visited-p (get-file-buffer id-file)) 40 | to-be-removed) 41 | (unwind-protect 42 | (save-window-excursion 43 | (save-match-data 44 | (org-id-goto ,id) 45 | (setq to-be-removed (current-buffer)) 46 | (condition-case nil 47 | (progn 48 | (org-show-subtree) 49 | (org-show-block-all)) 50 | (error nil)) 51 | (save-restriction ,@body))) 52 | (unless (or visited-p (not to-be-removed)) 53 | (kill-buffer to-be-removed))))) 54 | (def-edebug-spec org-test-at-id (form body)) 55 | 56 | (unless (featurep 'ob-go) 57 | (signal 'missing-test-dependency "Support for Go code blocks")) 58 | 59 | (ert-deftest ob-go/assert () 60 | (should t)) 61 | 62 | (ert-deftest ob-go/org-bable-go-package-p () 63 | (should (org-babel-go-package-p "package main")) 64 | (should-not (org-babel-go-package-p "//package main")) 65 | 66 | (should (org-babel-go-package-p "//package main\npackage main")) 67 | ;; fix it 68 | ;; (should-not (org-babel-go-package-p "Package main")) 69 | (should-not (org-babel-go-package-p "packaged"))) 70 | 71 | (ert-deftest ob-go/simple-program () 72 | "Hello world program." 73 | (if (executable-find org-babel-go-command) 74 | (org-test-at-id "412a86b1-644a-45b8-9e6d-bdc2b42d7e20" 75 | (org-babel-next-src-block 1) 76 | (should (= 42 (org-babel-execute-src-block)))))) 77 | 78 | (ert-deftest ob-go/integer-var () 79 | "Test of an integer variable." 80 | (if (executable-find org-babel-go-command) 81 | (org-test-at-id "412a86b1-644a-45b8-9e6d-bdc2b42d7e20" 82 | (org-babel-next-src-block 2) 83 | (should (= 12 (org-babel-execute-src-block)))))) 84 | 85 | (ert-deftest ob-go/two-variables () 86 | "Test of two integer variables." 87 | (if (executable-find org-babel-go-command) 88 | (org-test-at-id "412a86b1-644a-45b8-9e6d-bdc2b42d7e20" 89 | (org-babel-next-src-block 3) 90 | (should (= 666 (org-babel-execute-src-block)))))) 91 | 92 | (ert-deftest ob-go/two-variables2 () 93 | "Test of two integer variables." 94 | (if (executable-find org-babel-go-command) 95 | (org-test-at-id "412a86b1-644a-45b8-9e6d-bdc2b42d7e20" 96 | (org-babel-next-src-block 4) 97 | (should (= 666 (org-babel-execute-src-block)))))) 98 | 99 | (ert-deftest ob-go/string-variables () 100 | "Test the usage of string variables." 101 | (if (executable-find org-babel-go-command) 102 | (org-test-at-id "412a86b1-644a-45b8-9e6d-bdc2b42d7e20" 103 | (org-babel-next-src-block 5) 104 | (should (string-equal "golang" (org-babel-execute-src-block)))))) 105 | 106 | (ert-deftest ob-go/string-variables () 107 | "Test the usage of string variables." 108 | (if (executable-find org-babel-go-command) 109 | (org-test-at-id "412a86b1-644a-45b8-9e6d-bdc2b42d7e20" 110 | (org-babel-next-src-block 6) 111 | (should (string-equal "hello,ob-go" (org-babel-execute-src-block)))))) 112 | 113 | (ert-deftest ob-go/table () 114 | "Test of a table output." 115 | (if (executable-find org-babel-go-command) 116 | (org-test-at-id "1e9cf4e3-02df-4f3c-8533-2c0b1ca0a25a" 117 | (org-babel-next-src-block 1) 118 | (should (equal '((1) (2)) (org-babel-execute-src-block)))))) 119 | 120 | ;; ob-go doesn't handle list variables yet 121 | ;; (ert-deftest ob-go/list-var () 122 | ;; "Test of a list input variable" 123 | ;; (if (executable-find org-babel-go-command) 124 | ;; (org-test-at-id "15000dad-5af1-45e3-ac80-a371335866dc" 125 | ;; (org-babel-next-src-block 1) 126 | ;; (should (string= "abcdef2" (org-babel-execute-src-block)))))) 127 | 128 | (ert-deftest ob-go/imports () 129 | "Test the imports option" 130 | (if (executable-find org-babel-go-command) 131 | (org-test-at-id "e1aaec56-f3c6-4187-a003-5530b3ba956d" 132 | (org-babel-next-src-block 1) 133 | (should (= 3.141592653589793 134 | (org-babel-execute-src-block)))))) 135 | 136 | (ert-deftest ob-go/imports () 137 | "Test the imports option" 138 | (if (executable-find org-babel-go-command) 139 | (org-test-at-id "e1aaec56-f3c6-4187-a003-5530b3ba956d" 140 | (org-babel-next-src-block 2) 141 | (should (= 3.141592653589793 142 | (org-babel-execute-src-block)))))) 143 | 144 | 145 | (ert-deftest ob-go/packages () 146 | (if (executable-find org-babel-go-command) 147 | (org-test-at-id "c44f7afe-d356-4293-ba83-9ac71c7e6049" 148 | (org-babel-next-src-block 1) 149 | (should (string-equal "works" 150 | (org-babel-execute-src-block)))))) 151 | 152 | (ert-deftest ob-go/regression1 () 153 | (if (executable-find org-babel-go-command) 154 | (org-test-at-id "3f63c93d-6f17-478d-9817-e5c24a696689" 155 | (org-babel-next-src-block 1) 156 | (should (string-equal "'h' and 'i'" 157 | (org-babel-execute-src-block)))))) 158 | 159 | (defun ob-go-test-runall () 160 | (progn 161 | (ob-go-test-update-id-locations) 162 | (ert t))) 163 | 164 | (provide 'ob-go-test) 165 | -------------------------------------------------------------------------------- /ob-go.el: -------------------------------------------------------------------------------- 1 | ;;; ob-go.el --- org-babel functions for go evaluation 2 | 3 | ;; Copyright (C) 2012 K. Adam Christensen 4 | 5 | ;; Author: K. Adam Christensen 6 | ;; Keywords: golang, go, literate programming, reproducible research 7 | ;; Homepage: http://orgmode.org 8 | ;; Version: 0.02 9 | 10 | ;;; License: 11 | 12 | ;; This program is free software; you can redistribute it and/or modify 13 | ;; it under the terms of the GNU General Public License as published by 14 | ;; the Free Software Foundation; either version 3, or (at your option) 15 | ;; any later version. 16 | ;; 17 | ;; This program is distributed in the hope that it will be useful, 18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | ;; GNU General Public License for more details. 21 | ;; 22 | ;; You should have received a copy of the GNU General Public License 23 | ;; along with GNU Emacs; see the file COPYING. If not, write to the 24 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 25 | ;; Boston, MA 02110-1301, USA. 26 | 27 | ;;; Commentary: 28 | 29 | ;; Org-Babel support for evaluating go code. 30 | ;; 31 | ;; Much of this is modeled after `ob-C'. Just like the `ob-C', you can specify 32 | ;; :flags headers when compiling with the "go run" command. Unlike `ob-C', you 33 | ;; can also specify :args which can be a list of arguments to pass to the 34 | ;; binary. If you quote the value passed into the list, it will use `ob-ref' 35 | ;; to find the reference data. 36 | ;; 37 | ;; If you do not include a main function or a package name, `ob-go' will 38 | ;; provide it for you and it's the only way to properly use 39 | ;; 40 | ;; very limited implementation: 41 | ;; - currently only support :results output. 42 | ;; - not much in the way of error feedback. 43 | ;; - cannot handle table or list input. 44 | 45 | ;;; Requirements: 46 | 47 | ;; - You must have go1 installed and the go should be in your `exec-path'. If 48 | ;; not, feel free to modify `org-babel-go-command' to the location of your 49 | ;; go command. 50 | ;; 51 | ;; - `go-mode' is also recommended for syntax highlighting and 52 | ;; formatting. Not this particularly needs it, it just assumes you 53 | ;; have it. 54 | 55 | ;;; TODO: 56 | 57 | ;; - Provide better error feedback. 58 | ;; 59 | ;; - Figure out a nice way to handle lists and tables. 60 | ;; 61 | ;; - Do some simple parsing of the go code to insert vars right after the 62 | ;; package declaration. 63 | 64 | ;;; Code: 65 | (require 'org) 66 | (require 'ob) 67 | (require 'ob-eval) 68 | (require 'ob-ref) 69 | 70 | 71 | ;; optionally define a file extension for this language 72 | (add-to-list 'org-babel-tangle-lang-exts '("go" . "go")) 73 | 74 | (defvar org-babel-default-header-args:go '()) 75 | 76 | (defvar org-babel-go-command "go" 77 | "The go command to use to compile and run the go code.") 78 | 79 | (defmacro org-babel-go-as-list (val) 80 | (list 'if (list 'listp val) val (list 'list val))) 81 | 82 | (defun org-babel-expand-body:go (body params &optional processed-params) 83 | "Expand BODY according to PARAMS, return the expanded body." 84 | (let* ((vars (org-babel-go-get-var params)) 85 | (main-p (not (string= (cdr (assoc :main params)) "no"))) 86 | (imports (or (cdr (assoc :imports params)) 87 | (org-babel-read (org-entry-get nil "imports" t)))) 88 | (package (or (cdr (assoc :package params)) 89 | (org-babel-read (org-entry-get nil "package" t)))) 90 | (body (if main-p (org-babel-go-ensure-main-wrap body) body)) 91 | ) 92 | (org-babel-go-custom-vars (org-babel-go-custom-imports (org-babel-go-ensure-package body package) 93 | imports) 94 | vars))) 95 | 96 | (defun org-babel-execute:go (body params) 97 | "Execute a block of Template code with org-babel. This function is 98 | called by `org-babel-execute-src-block'" 99 | (message "executing Go source code block") 100 | (let* ((tmp-src-file (org-babel-temp-file "go-src-" ".go")) 101 | (processed-params (org-babel-process-params params)) 102 | (flags (cdr (assoc :flags processed-params))) 103 | (args (cdr (assoc :args processed-params))) 104 | ;; expand the body with `org-babel-expand-body:go' 105 | (full-body (org-babel-expand-body:go 106 | body params processed-params)) 107 | (coding-system-for-read 'utf-8) ;; use utf-8 with subprocesses 108 | (coding-system-for-write 'utf-8)) 109 | (with-temp-file tmp-src-file (insert full-body)) 110 | 111 | (let 112 | ((results 113 | (org-babel-eval 114 | (format "%s run %s \"%s\" %s" 115 | org-babel-go-command 116 | (mapconcat 'identity (org-babel-go-as-list flags) " ") 117 | (org-babel-process-file-name tmp-src-file) 118 | (mapconcat #'(lambda (a) 119 | ;; If there's a chance that the symbol is a 120 | ;; ref, use that. Otherwise, just return the 121 | ;; string form of the value. 122 | (format "%S" (if (symbolp a) 123 | (let* ((ref (symbol-name a)) 124 | (out (org-babel-read ref))) 125 | (if (equal out ref) 126 | (if (string-match "^\".*\"$" ref) 127 | (read ref) 128 | (org-babel-ref-resolve ref)) 129 | out)) 130 | a))) 131 | (org-babel-go-as-list args) " ")) ""))) 132 | (if results 133 | (org-babel-reassemble-table 134 | (if (or (member "table" (cdr (assoc :result-params processed-params))) 135 | (member "vector" (cdr (assoc :result-params processed-params)))) 136 | (let ((tmp-file (org-babel-temp-file "go-"))) 137 | (with-temp-file tmp-file (insert (org-babel-trim results))) 138 | (org-babel-import-elisp-from-file tmp-file)) 139 | (org-babel-read (org-babel-trim results) t)) 140 | (org-babel-pick-name 141 | (cdr (assoc :colname-names params)) (cdr (assoc :colnames params))) 142 | (org-babel-pick-name 143 | (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params)))) 144 | )))) 145 | 146 | ;; This function should be used to assign any variables in params in 147 | ;; the context of the session environment. 148 | (defun org-babel-prep-session:go (session params) 149 | "This function does nothing as Go is a compiled language with no 150 | support for sessions" 151 | (error "Go is a compiled languages -- no support for sessions")) 152 | 153 | (defun org-babel-go-ensure-main-wrap (body) 154 | "Check to see if main is already defined. If not, add it." 155 | (if (string-match-p "^[ \t]*func main *() *{" body) 156 | body 157 | (concat "func main() {\n" body "\n}\n"))) 158 | 159 | (defun org-babel-go-append-package (package) 160 | "Check to see if package is set. If not, add main unless there is a 'discard value for the package key (allows to tangle many source blocks into one go project)." 161 | (unless (eq package 'discard) 162 | (concat "package " (if (and package (not (string-empty-p package))) package "main")))) 163 | 164 | (defun org-babel-go-ensure-package (body package) 165 | "Ensure package exists." 166 | (if (org-babel-go-package-p body) 167 | body 168 | (concat (org-babel-go-append-package package) "\n" body))) 169 | 170 | (defun org-babel-go-package-p (body) 171 | "Check to see whether package is set or not." 172 | (string-match-p "^[ \t]*package " body)) 173 | 174 | (defun org-babel-go-package-position (body) 175 | (string-match "^[ \t]*package " body)) 176 | 177 | (defun org-babel-go-custom-imports (body imports) 178 | "Append custom import packages." 179 | (let* ((start (string-match "\n" 180 | (substring body 181 | (org-babel-go-package-position body))))) 182 | (concat (substring body 0 start) 183 | "\n" 184 | (org-babel-go-insert-imports imports) 185 | (substring body start)))) 186 | 187 | (defun org-babel-go-insert-imports (imports) 188 | (let ((packages (org-babel-go-as-list imports))) 189 | (if (= (length packages) 0) 190 | "" 191 | (concat "import (" 192 | "\n\t" 193 | (mapconcat #'(lambda (pkg) (format "%S" pkg)) 194 | packages 195 | "\t\n") 196 | "\n)" 197 | "\n")))) 198 | 199 | (defun org-babel-go-custom-vars (body vars) 200 | "Append custom variables at bottom." 201 | (if (= (length vars) 0) 202 | body 203 | (concat body "\n" (mapconcat 'org-babel-go-var-to-go vars "\n")))) 204 | 205 | (defun org-babel-go-get-var (params) 206 | "org-babel-get-header was removed in org version 8.3.3" 207 | (let* ((fversion (org-version)) 208 | (version (string-to-number fversion))) 209 | (if (< version 8.3) 210 | (mapcar #'cdr (org-babel-get-header params :var)) 211 | (org-babel--get-vars params)))) 212 | 213 | (defun org-babel-go-gofmt (body) 214 | "Run gofmt over the body. Why not?" 215 | (with-temp-buffer 216 | (let ((outbuf (current-buffer)) 217 | (coding-system-for-read 'utf-8) ;; use utf-8 with subprocesses 218 | (coding-system-for-write 'utf-8)) 219 | (with-temp-buffer 220 | (insert body) 221 | (shell-command-on-region (point-min) (point-max) "gofmt" 222 | outbuf nil nil))) 223 | (buffer-string))) 224 | 225 | (defun org-babel-go-var-to-go (pair) 226 | "Convert an elisp var into a string of go source code 227 | specifying a var of the same value." 228 | (let ((var (car pair)) 229 | (val (cdr pair))) 230 | (when (symbolp val) 231 | (setq val (symbol-name val))) 232 | ;; TODO(pope): Handle tables and lists. 233 | (format "var %S = %S" var val))) 234 | 235 | (provide 'ob-go) 236 | ;;; ob-go.el ends here 237 | --------------------------------------------------------------------------------