emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [0] ob-rust, support for rust code blocks
@ 2017-12-18 13:44 Andrés Saraos Luna
  2017-12-19 23:16 ` Nicolas Goaziou
  0 siblings, 1 reply; 2+ messages in thread
From: Andrés Saraos Luna @ 2017-12-18 13:44 UTC (permalink / raw)
  To: emacs-orgmode


[-- Attachment #1.1: Type: text/plain, Size: 861 bytes --]

Hi all,

As a toy project I've written a simple ob-rust, mainly in order to prepare some simple demos using rust.

It works well for all the simple examples provided in the ob-rust-test.org file. Its shortcomings are
documented in the ob-rust.el file itself.

Since I'm not completely sure of the submission protocol for new features, the new file lives in
contrib for now, although it doesn't depend on anything outside of `ob' really so maybe it could be
added to core?

As far as testing is concerned, since I don't know how to use the database used by `org-test-at-id' I
hardcoded the name of the testing file, I'd be happy to change that if necessary.

Here's hoping this is useful for others, and since this is my first time writing anything functional
in elisp I'm gladly open for any hints to improve the code.

---
Andrés Saraos Luna

[-- Attachment #1.2: Type: text/html, Size: 1157 bytes --]

[-- Attachment #2: ob-rust.patch --]
[-- Type: text/plain, Size: 16285 bytes --]

From 0a91c2b0d43e6e8f19d023208e78b07722a5dc33 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9s=20Saraos=20Luna?= <saraoslunaandres@gmail.com>
Date: Mon, 18 Dec 2017 10:28:07 +0100
Subject: [PATCH] ob-rust.el, adds working version of rust evaluation in org
 source blocks
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Andrés Saraos Luna <saraoslunaandres@gmail.com>

* contrib/lisp/ob-rust.el: Support for limited rust source code in org
  babel.

* testing/examples/ob-rust-test.org: Test all implemented features of
  ob-rust in the form of named Org source blocks.

* testing/lisp/test-ob-rust.el: Defines the tests.

TINYCHANGE
---
 contrib/lisp/ob-rust.el           | 207 ++++++++++++++++++++++++++++++++++++++
 testing/examples/ob-rust-test.org |  82 +++++++++++++++
 testing/lisp/test-ob-rust.el      | 110 ++++++++++++++++++++
 3 files changed, 399 insertions(+)
 create mode 100644 contrib/lisp/ob-rust.el
 create mode 100644 testing/examples/ob-rust-test.org
 create mode 100644 testing/lisp/test-ob-rust.el

diff --git a/contrib/lisp/ob-rust.el b/contrib/lisp/ob-rust.el
new file mode 100644
index 000000000..daa206228
--- /dev/null
+++ b/contrib/lisp/ob-rust.el
@@ -0,0 +1,207 @@
+;;; ob-rust.el --- Babel Functions for rust -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 Free Software Foundation, Inc.
+
+;; Author: Andrés Saraos Luna
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Org-Babel support for evaluating rust code.
+;;
+;; A currently very limited implementation:
+;;  - arrays, vecs, lists or tables are not yet supported as header
+;;  arguments
+;;  - no error handling
+;;  - only :results output is supported
+;;  - cargo is completely ignored
+
+(require 'ob)
+
+(defvar org-babel-tangle-lang-exts)
+(add-to-list 'org-babel-tangle-lang-exts '("rust" . "rs"))
+
+(defcustom org-babel-rust-command "rustc"
+  "Name of the rust command."
+  :group 'org-babel
+  :type 'string)
+
+(defun org-babel-execute:rust (body params)
+  (let* ((full-body (org-babel-expand-body:rust body params))
+         (cmpflag (or (cdr (assq :cmpflag params)) ""))
+         (cmdline (or (cdr (assq :cmdline params)) ""))
+         (default-directory org-babel-temporary-directory)
+         (src-file (org-babel-temp-file "rust-src-" ".rs"))
+         (exe-file (org-babel-rust-exe-file src-file cmpflag))
+         (results))
+    (with-temp-file src-file
+      (insert full-body)
+      (when (require 'rust-mode nil t)
+        (rust-format-buffer)))
+    (org-babel-eval
+     (format "%s %s %s" org-babel-rust-command cmpflag src-file) "")
+    (setq results (org-babel-eval (format "%s %s" exe-file cmdline) ""))
+    (org-babel-reassemble-table
+     (org-babel-result-cond (cdr (assq :result-params params))
+       (org-babel-read results)
+       (let ((tmp-file (org-babel-temp-file "rs-")))
+         (with-temp-file tmp-file (insert results))
+         (org-babel-import-elisp-from-file tmp-file)))
+     (org-babel-pick-name
+      (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
+     (org-babel-pick-name
+      (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))
+
+(defun org-babel-expand-body:rust (body params)
+  "Expand a block of rust code with org-babel according to its
+header arguments."
+  (let* ((main-p (not (string= (cdr (assq :main params)) "no")))
+         (uses (org-babel-read (cdr (assq :use params)) nil))
+         (vars (org-babel--get-vars params)))
+    (when (stringp uses)
+      (setq uses (split-string uses)))
+    (mapconcat
+     'identity
+     (list
+      ;; uses
+      (mapconcat
+       (lambda (use) (format "use %s;" use))
+       uses
+       "\n")
+      ;; main vith vars if present
+      (org-babel-rust-ensure-main-wrap body vars))
+     "\n\t")))
+
+(defun org-babel-prep-session:rust (_session _params)
+  "This function does nothing as C is a compiled language with no
+support for sessions"
+  (error "no support for sessions"))
+
+(defun org-babel-load-session:rust (_session _body _params)
+  "This function does nothing as C is a compiled language with no
+support for sessions"
+  (error "no support for sessions"))
+
+;;; Helper functions.
+
+(defun org-babel-rust-exe-file (src-file cmpflag)
+  "Compute the executable name according to the parameters given
+to the command line. It assumes that the source file has been
+created at (org-babel-temporary-directory). For spaces to be
+correctly recognized they need to be escaped."
+  (if (string= cmpflag "")
+      (file-name-sans-extension src-file)
+    (let* ((flag-list (split-string cmpflag " "))
+           (out-file (nth 1 (member "-o" flag-list)))
+           (out-dir (nth 1 (member "--out-dir" flag-list))))
+      (cond
+       (out-file
+        (if (string-match-p "^/" out-file) ;naive absolute file path detection
+            (expand-file-name out-file "/")
+          (expand-file-name out-file org-babel-temporary-directory)))
+       (out-dir
+        (expand-file-name (file-name-base src-file) (file-name-as-directory out-dir)))
+       (t
+        (file-name-sans-extension src-file))))))
+
+(defun org-babel-rust-ensure-main-wrap (body vars)
+  "Wrap BODY in a \"main\" function call if none exist. Inserts
+the variables right after the main declaration, regardless of the
+\"main\" existence."
+  (let ((rust-main-regexp "^[ \t]*fn[ \t\n\r]*main[ \t]*()[ \t\n]*{[ \t]*")
+        (rust-main-wrapper "fn main() {\n\t%s\n\t%s\n}")
+        (pos nil))
+    (if (string-match rust-main-regexp body)
+        (progn
+          (setq pos (match-end 0))
+          (concat
+           (substring body 0 pos)
+           "\n"
+           (mapconcat 'org-babel-rust-var-to-rust vars "\n")
+           (substring body pos nil)))
+      (format
+       rust-main-wrapper
+       (mapconcat 'org-babel-rust-var-to-rust vars "\n")
+       body))))
+
+(defun org-babel-rust-val-to-rust-type (val)
+  "Infers the correct rust data type from the value of the given
+argument."
+  (cond
+   ((symbolp val)
+    (cond
+     ((= (length (symbol-name val)) 1) 'char)
+     ((or (string= val "true") (string= val "false")) 'bool)
+     (t '&str)))
+   ((stringp val)
+    (cond
+     ((or (string= val "true") (string= val "false")) 'bool)
+     (t '&str)))
+   ((integerp val)
+    'isize)
+   ((floatp val)
+    'f64)
+   (t
+    nil)))
+
+(defun org-babel-rust-var-to-rust (var-pairs)
+  "Formats a given variable name, variable value pair according
+to its type in correct rust.
+
+The variable name follows the following rules :
+
+- if the name starts with \"mut_\", the variable will be declared
+as mutable in rust code, and be referenced by its name minus the
+\"mut\",
+
+- if the name is followed by a \":\", the text preceding the
+\"=\" sign will be treated as its type. If no type is given one
+will be infered."
+  (let* ((var (car var-pairs))
+         (val (cdr var-pairs))
+         (value-type (org-babel-rust-val-to-rust-type val))
+         (var-s (symbol-name var))
+         (var-regexp "\\(^mut_\\)?\\([[:alnum:]_]+\\)\\(: ?[[:alnum:]]+\\)?[ \t]*$")
+         (mut
+          (progn
+            (string-match var-regexp var-s)
+            (match-string 1 var-s)))
+         (var-name
+          (progn
+            (string-match var-regexp var-s)
+            (match-string 2 var-s)))
+         (var-type
+          (or
+           (progn
+             (string-match var-regexp var-s)
+             (match-string 3 var-s))
+           (format ":%s" (symbol-name (org-babel-rust-val-to-rust-type val)))))
+         (pre (format "let %s"
+                      (if (string-match "^mut_" var-s)
+                          (concat "mut " (substring var-s (match-end 0) nil))
+                        var)))
+         (value (cond
+                 ((string-match-p ": ?[iuf]" var-type) (format "%s" val))
+                 ((string-match-p ": ?bool" var-type) (format "%s" val))
+                 ((string-match-p ": ?char" var-type) (format "'%s'" val))
+                 (t (format "\"%s\"" val)))))
+    (setq mut (when mut "mut "))
+    (concat "let " mut var-name var-type " = " value ";")))
+
+(provide 'ob-rust)
diff --git a/testing/examples/ob-rust-test.org b/testing/examples/ob-rust-test.org
new file mode 100644
index 000000000..b2c862bb7
--- /dev/null
+++ b/testing/examples/ob-rust-test.org
@@ -0,0 +1,82 @@
+#+Title: a collection of examples for ob-rust tests
+#+OPTIONS: ^:nil
+
+#+name: test-simple
+#+BEGIN_SRC rust :results silent
+  fn main() {
+      let answer = 42;
+      println!("{}", answer);
+  }
+#+END_SRC
+
+#+name: test-main-wrapper
+#+BEGIN_SRC rust :results silent
+  let answer = 42;
+  println!("{}", answer);
+#+END_SRC
+
+#+name: test-var-integer
+#+BEGIN_SRC rust :var answer=42 :results silent
+  println!("{}", answer);
+#+END_SRC
+
+#+name: test-var-float
+#+BEGIN_SRC rust :var pi=3.14 :results silent
+  println!("{}", pi);
+#+END_SRC
+
+#+name: test-var-char
+#+BEGIN_SRC rust :var answer='x' :results silent
+  println!("{}", answer);
+#+END_SRC
+
+#+name: test-var-string
+#+BEGIN_SRC rust :var answer="GOAT" :results silent
+  println!("{}", answer);
+#+END_SRC
+
+#+name: test-var-bool-true
+#+BEGIN_SRC rust :var test='true :results silent
+  if test {
+    println!("42");
+  }
+#+END_SRC
+
+#+name: test-var-bool-false
+#+BEGIN_SRC rust :var test="false" :results silent
+  if !test {
+    println!("42");
+  }
+#+END_SRC
+
+#+name: test-var-mutable
+#+BEGIN_SRC rust :var mut_answer=41 :results silent
+  answer = 42;
+  println!("{}", answer);
+#+END_SRC
+
+#+name: test-var-given-type
+#+BEGIN_SRC rust :var answer:i32=40 :results silent
+  let additional_answer: i32 = 2;
+  println!("{}", answer + additional_answer);
+#+END_SRC
+
+#+name: test-var-mutable-and-given-type
+#+BEGIN_SRC rust :var mut_answer:i32=40 :results silent
+  let additional_answer: i32 = 2;
+  answer = answer + additional_answer;
+  println!("{}", answer);
+#+END_SRC
+
+#+name: test-var-no-main-wrapper
+#+BEGIN_SRC rust :var answer=42 :results silent
+  fn main() {
+      println!("{}", answer);
+  }
+#+END_SRC
+
+#+name: test-uses-and-command-line-arguments
+#+BEGIN_SRC rust :use std::env :cmdline 1 2 bonjour :results silent
+  let args: Vec<String> = env::args().collect();
+  println!("{}, {}, {}", args[1], args[2], args[3]);
+#+END_SRC
diff --git a/testing/lisp/test-ob-rust.el b/testing/lisp/test-ob-rust.el
new file mode 100644
index 000000000..a48ec8a35
--- /dev/null
+++ b/testing/lisp/test-ob-rust.el
@@ -0,0 +1,110 @@
+;;; test-ob-rust.el --- tests for ob-rust.el
+
+;; Copyright (c) 2017 Andrés Saraos Luna
+;; Authors: Andrés Saraos Luna
+
+;; This file is not part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+(ert-deftest ob-rust/simple ()
+  (when (executable-find org-babel-rust-command)
+    (with-temp-buffer
+      (insert-file-contents "ob-rust-test.org")
+      (org-babel-goto-named-src-block "test-simple")
+      (should (= 42 (org-babel-execute-src-block))))))
+
+(ert-deftest ob-rust/main-wrapper ()
+  (when (executable-find org-babel-rust-command)
+    (with-temp-buffer
+      (insert-file-contents "ob-rust-test.org")
+      (org-babel-goto-named-src-block "test-main-wrapper")
+      (should (= 42 (org-babel-execute-src-block))))))
+
+(ert-deftest ob-rust/var-integer ()
+  (when (executable-find org-babel-rust-command)
+    (with-temp-buffer
+      (insert-file-contents "ob-rust-test.org")
+      (org-babel-goto-named-src-block "test-var-integer")
+      (should (= 42 (org-babel-execute-src-block))))))
+
+(ert-deftest ob-rust/var-float ()
+  (when (executable-find org-babel-rust-command)
+    (with-temp-buffer
+      (insert-file-contents "ob-rust-test.org")
+      (org-babel-goto-named-src-block "test-var-float")
+      (should (= 3.14 (org-babel-execute-src-block))))))
+
+(ert-deftest ob-rust/var-char ()
+  (when (executable-find org-babel-rust-command)
+    (with-temp-buffer
+      (insert-file-contents "ob-rust-test.org")
+      (org-babel-goto-named-src-block "test-var-char")
+      (should (string= "x" (org-babel-execute-src-block))))))
+
+(ert-deftest ob-rust/var-string ()
+  (when (executable-find org-babel-rust-command)
+    (with-temp-buffer
+      (insert-file-contents "ob-rust-test.org")
+      (org-babel-goto-named-src-block "test-var-string")
+      (should (string= "GOAT" (org-babel-execute-src-block))))))
+
+(ert-deftest ob-rust/var-bool-true ()
+  (when (executable-find org-babel-rust-command)
+    (with-temp-buffer
+      (insert-file-contents "ob-rust-test.org")
+      (org-babel-goto-named-src-block "test-var-bool-true")
+      (should (= 42 (org-babel-execute-src-block))))))
+
+(ert-deftest ob-rust/var-bool-false ()
+  (when (executable-find org-babel-rust-command)
+    (with-temp-buffer
+      (insert-file-contents "ob-rust-test.org")
+      (org-babel-goto-named-src-block "test-var-bool-false")
+      (should (= 42 (org-babel-execute-src-block))))))
+
+(ert-deftest ob-rust/var-mutable ()
+  (when (executable-find org-babel-rust-command)
+    (with-temp-buffer
+      (insert-file-contents "ob-rust-test.org")
+      (org-babel-goto-named-src-block "test-var-mutable")
+      (should (= 42 (org-babel-execute-src-block))))))
+
+(ert-deftest ob-rust/var-given-type ()
+  (when (executable-find org-babel-rust-command)
+    (with-temp-buffer
+      (insert-file-contents "ob-rust-test.org")
+      (org-babel-goto-named-src-block "test-var-given-type")
+      (should (= 42 (org-babel-execute-src-block))))))
+
+(ert-deftest ob-rust/var-mutable-and-given-type ()
+  (when (executable-find org-babel-rust-command)
+    (with-temp-buffer
+      (insert-file-contents "ob-rust-test.org")
+      (org-babel-goto-named-src-block "test-var-mutable-and-given-type")
+      (should (= 42 (org-babel-execute-src-block))))))
+
+(ert-deftest ob-rust/var-no-main-wrapper ()
+  (when (executable-find org-babel-rust-command)
+    (with-temp-buffer
+      (insert-file-contents "ob-rust-test.org")
+      (org-babel-goto-named-src-block "test-var-no-main-wrapper")
+      (should (= 42 (org-babel-execute-src-block))))))
+
+(ert-deftest ob-rust/uses-and-command-line-arguments ()
+  (when (executable-find org-babel-rust-command)
+    (with-temp-buffer
+      (insert-file-contents "ob-rust-test.org")
+      (org-babel-goto-named-src-block "test-uses-and-command-line-arguments")
+      (should (equal '((1 . (2 . ("bonjour")))) (org-babel-execute-src-block))))))
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [0] ob-rust, support for rust code blocks
  2017-12-18 13:44 [0] ob-rust, support for rust code blocks Andrés Saraos Luna
@ 2017-12-19 23:16 ` Nicolas Goaziou
  0 siblings, 0 replies; 2+ messages in thread
From: Nicolas Goaziou @ 2017-12-19 23:16 UTC (permalink / raw)
  To: Andrés Saraos Luna; +Cc: emacs-orgmode

Hello,

Andrés Saraos Luna <saraoslunaandres@gmail.com> writes:

> As a toy project I've written a simple ob-rust, mainly in order to
> prepare some simple demos using rust.

Thank you.

There is another "ob-rust.el" at
<https://github.com/micanzhang/ob-rust>. Would it make sense to join
efforts with its author?

> Since I'm not completely sure of the submission protocol for new
> features, the new file lives in contrib for now, although it doesn't
> depend on anything outside of `ob' really so maybe it could be added
> to core?

You need to sign FSF papers for that. Even if it doesn't land in master,
I suggest to start the process as it could take some time, depending on
your country. It would be nice to sort out the issue about 

> As far as testing is concerned, since I don't know how to use the
> database used by `org-test-at-id' I hardcoded the name of the testing
> file, I'd be happy to change that if necessary.

You don't need to use `org-test-at-id'. I even suggest to stay away from
it, as it makes debugging harder. Instead, you could make tests
self-sufficient, e.g.:

    (should
     (equal 42
            (org-test-with-temp-text "
    <point>#+name: test-simple
    #+BEGIN_SRC rust :results silent
      fn main() {
          let answer = 42;
          println!("{}", answer);
      }
    #+END_SRC"
          (org-babel-execute-src-block))))

Note that `should' is in the outer part of the test.

> Here's hoping this is useful for others, and since this is my first
> time writing anything functional in elisp I'm gladly open for any
> hints to improve the code.

I have a few suggestion. In particular docstrings should start with one
(or two) sentence(s) filling the first line. Additional sentences need
to start on subsequent lines.

Also, you need to add two spaces at the end of sentences.

> * contrib/lisp/ob-rust.el: Support for limited rust source code in org
>   babel.
>
> * testing/examples/ob-rust-test.org: Test all implemented features of
>   ob-rust in the form of named Org source blocks.
>
> * testing/lisp/test-ob-rust.el: Defines the tests.
>
> TINYCHANGE

This is not a TINYCHANGE :)

> +;; Org-Babel support for evaluating rust code.

Babel support for...

> +;; A currently very limited implementation:
> +;;  - arrays, vecs, lists or tables are not yet supported as header
> +;;  arguments
> +;;  - no error handling
> +;;  - only :results output is supported
> +;;  - cargo is completely ignored
> +
> +(require 'ob)
> +
> +(defvar org-babel-tangle-lang-exts)
> +(add-to-list 'org-babel-tangle-lang-exts '("rust" . "rs"))
> +
> +(defcustom org-babel-rust-command "rustc"
> +  "Name of the rust command."
> +  :group 'org-babel
> +  :type 'string)
> +
> +(defun org-babel-execute:rust (body params)

This function is missing a docstring.

> +  (let* ((full-body (org-babel-expand-body:rust body params))
> +         (cmpflag (or (cdr (assq :cmpflag params)) ""))
> +         (cmdline (or (cdr (assq :cmdline params)) ""))
> +         (default-directory org-babel-temporary-directory)
> +         (src-file (org-babel-temp-file "rust-src-" ".rs"))
> +         (exe-file (org-babel-rust-exe-file src-file cmpflag))
> +         (results))
> +    (with-temp-file src-file
> +      (insert full-body)
> +      (when (require 'rust-mode nil t)
> +        (rust-format-buffer)))
> +    (org-babel-eval
> +     (format "%s %s %s" org-babel-rust-command cmpflag src-file) "")
> +    (setq results (org-babel-eval (format "%s %s" exe-file cmdline) ""))
> +    (org-babel-reassemble-table
> +     (org-babel-result-cond (cdr (assq :result-params params))
> +       (org-babel-read results)
> +       (let ((tmp-file (org-babel-temp-file "rs-")))
> +         (with-temp-file tmp-file (insert results))
> +         (org-babel-import-elisp-from-file tmp-file)))
> +     (org-babel-pick-name
> +      (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
> +     (org-babel-pick-name
> +      (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))
> +
> +(defun org-babel-expand-body:rust (body params)
> +  "Expand a block of rust code with org-babel according to its
> +header arguments."

The sentence must fit on a single line.

Also "Org Babel"

> +(defun org-babel-prep-session:rust (_session _params)
> +  "This function does nothing as C is a compiled language with no
> +support for sessions"
> +  (error "no support for sessions"))

C -> Rust

> +(defun org-babel-load-session:rust (_session _body _params)
> +  "This function does nothing as C is a compiled language with no
> +support for sessions"
> +  (error "no support for sessions"))

Ditto.
> +  (let* ((var (car var-pairs))
> +         (val (cdr var-pairs))
> +         (value-type (org-babel-rust-val-to-rust-type val))
> +         (var-s (symbol-name var))
> +         (var-regexp "\\(^mut_\\)?\\([[:alnum:]_]+\\)\\(: ?[[:alnum:]]+\\)?[ \t]*$")
> +         (mut
> +          (progn
> +            (string-match var-regexp var-s)
> +            (match-string 1 var-s)))
> +         (var-name
> +          (progn
> +            (string-match var-regexp var-s)
> +            (match-string 2 var-s)))
> +         (var-type
> +          (or
> +           (progn
> +             (string-match var-regexp var-s)
> +             (match-string 3 var-s))

You shouldn't match multiple times. Match once and get match strings.

Regards,

-- 
Nicolas Goaziou

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-12-19 23:16 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-18 13:44 [0] ob-rust, support for rust code blocks Andrés Saraos Luna
2017-12-19 23:16 ` Nicolas Goaziou

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).