Search code examples
emacsorg-modeliterate-programmingorg-babel

How can I implicitly organize literate code with org-mode?


I'm developing a Stack Exchange mode for Emacs and I'm trying to use literate programming (with org-mode) to organize the project.

I'm finding myself repeating a lot of information. I'm taking a (possibly over-) structured approach to the document. Say I have a heading Questions; under that heading exist subheadings Read and Write, and I have a top-level of

;; some-package.el starts here
<<read methods>>
<<write methods>>
;; some-package.el ends here

How can I alter the properties of the Read and Write headings such that all source code blocks inside, unless otherwise specified, will be placed into their respective noweb tanglings?


Here is what I do currently:

* TODO Stack Mode (Entry Point): =stack-mode=
Stack mode is /the/ major mode.  What do I mean by this?  Stack mode
is the entry point of the whole package.  There is no other way to
obtain the full, original functionality of the package without first
running =M-x stack-mode=.  Stack Mode is the only mode available
interactively.  It is a dispatcher that decides, based on user
preferences, how the whole system shall behave.  It provides the basic
framework upon which the rest of the package is built, and makes sure
all tools are available.

#+name: build-stack-mode
#+begin_src emacs-lisp :tangle elisp/stack.el
  ;; stack.el starts here

  (add-to-list 'load-path "~/github/vermiculus/stack-mode")

  <<stack-require-dependencies>>
  <<stack-setup-customization>>
  <<stack-setup-keymap>>
  <<stack-setup-api>>
  <<stack-load-children>>

  (provide 'stack)

  ; stack.el ends here
#+end_src

Thus, there are a few packages that it itself requires.

JSON (JavaScript Object Notation) is the standard by which we
communicate with Stack Exchange itself.  The details of this
communication has [[id:DC2032C5-BC11-47E2-8DDB-34467C2BC479][already been discussed]] so I will not repeat myself
here.  The JSON package provides many utilities for manipulating JSON
snippets within Emacs Lisp, and is required for the operation of this
package.  =json.el= is included with Emacs 24+ (and can easily be
obtained from the ELPA if missing).
#+name: stack-require-dependencies
#+begin_src emacs-lisp
  (require 'json)
#+end_src

This package also requires =request.el=, a package designed to
simplify making HTTP requests.  =request.el= was written by [[http://stackoverflow.com/users/727827][SX@tkf]] and
is maintained and documented on [[http://tkf.github.com/emacs-request/manual.html][GitHub]]. The package is also available
for automatic install via MELPA.
#+name: stack-require-dependencies
#+begin_src emacs-lisp
  (require 'request)
#+end_src

#+name: stack-require-dependencies
#+begin_src emacs-lisp
  (require 'stack-api)
#+end_src

Simply put, =defgroup= defines a customization group for the graphical
interface within Emacs.  Since it pulls all of the customizable
settings together and how to customize them, it is also useful as a
'word bank' of sorts for customizing the package manually.  Every
customizable variable in the entire package is listed here.
#+name: stack-setup-customization
#+begin_src emacs-lisp
    (defgroup stack-exchange
      nil
      "Stack Exchange mode."
      :group 'environment)
#+end_src

Every mode needs a hook, so we here define one.  This hook is run
/after/ stack-mode is finished loading (when called interactively or
from Emacs Lisp).
#+name: stack-setup-customization
#+begin_src emacs-lisp
  (defvar stack-mode-hook nil)
#+end_src

In addition to a hook, most if not all major modes define their own
key-map.  Stack mode as a whole is no exception, but remembering the
nature of =stack-mode= as a dispatcher, a key-map seems out of place
here.  As such, the official key-map for =stack-mode= defines all keys
to be =nil= except those that are necessary for the smooth use of
Emacs as an operating system.  Such necessary keystrokes include
=C-g=, =M-x=, and others.
#+name: stack-setup-keymap
#+begin_src emacs-lisp
  (defvar stack-mode-map
    (let ((map (make-sparse-keymap)))
      map)
    "Keymap for Stack Exchange major mode.  This keymap is not
    used.")
#+end_src
...

Here is what I'd like to do:

(Ctrl+F for ** and look at the property drawer.)

* TODO Stack Mode (Entry Point): =stack-mode=
Stack mode is /the/ major mode.  What do I mean by this?  Stack mode
is the entry point of the whole package.  There is no other way to
obtain the full, original functionality of the package without first
running =M-x stack-mode=.  Stack Mode is the only mode available
interactively.  It is a dispatcher that decides, based on user
preferences, how the whole system shall behave.  It provides the basic
framework upon which the rest of the package is built, and makes sure
all tools are available.

#+name: build-stack-mode
#+begin_src emacs-lisp :tangle elisp/stack.el
  ;; stack.el starts here

  (add-to-list 'load-path "~/github/vermiculus/stack-mode")

  <<stack-require-dependencies>>
  <<stack-setup-customization>>
  <<stack-setup-keymap>>
  <<stack-setup-api>>
  <<stack-load-children>>

  (provide 'stack)

  ; stack.el ends here
#+end_src
** Require Dependencies
:PROPERTIES:
:noweb-key: stack-require-dependencies
:END:
Thus, there are a few packages that it itself requires.

JSON (JavaScript Object Notation) is the standard by which we
communicate with Stack Exchange itself.  The details of this
communication has [[id:DC2032C5-BC11-47E2-8DDB-34467C2BC479][already been discussed]] so I will not repeat myself
here.  The JSON package provides many utilities for manipulating JSON
snippets within Emacs Lisp, and is required for the operation of this
package.  =json.el= is included with Emacs 24+ (and can easily be
obtained from the ELPA if missing).
#+begin_src emacs-lisp
  (require 'json)
#+end_src

This package also requires =request.el=, a package designed to
simplify making HTTP requests.  =request.el= was written by [[http://stackoverflow.com/users/727827][SX@tkf]] and
is maintained and documented on [[http://tkf.github.com/emacs-request/manual.html][GitHub]]. The package is also available
for automatic install via MELPA.
#+begin_src emacs-lisp
  (require 'request)
#+end_src

#+begin_src emacs-lisp
  (require 'stack-api)
#+end_src
** Customization
:PROPERTIES:
:noweb-key: stack-setup-customization
:END:
Simply put, =defgroup= defines a customization group for the graphical
interface within Emacs.  Since it pulls all of the customizable
settings together and how to customize them, it is also useful as a
'word bank' of sorts for customizing the package manually.  Every
customizable variable in the entire package is listed here.
#+begin_src emacs-lisp
    (defgroup stack-exchange
      nil
      "Stack Exchange mode."
      :group 'environment)
#+end_src

Every mode needs a hook, so we here define one.  This hook is run
/after/ stack-mode is finished loading (when called interactively or
from Emacs Lisp).
#+begin_src emacs-lisp
  (defvar stack-mode-hook nil)
#+end_src
** Keymap
:PROPERTIES:
:noweb-key: stack-setup-keymap
:END:
In addition to a hook, most if not all major modes define their own
key-map.  Stack mode as a whole is no exception, but remembering the
nature of =stack-mode= as a dispatcher, a key-map seems out of place
here.  As such, the official key-map for =stack-mode= defines all keys
to be =nil= except those that are necessary for the smooth use of
Emacs as an operating system.  Such necessary keystrokes include
=C-g=, =M-x=, and others.
#+begin_src emacs-lisp
  (defvar stack-mode-map
    (let ((map (make-sparse-keymap)))
      map)
    "Keymap for Stack Exchange major mode.  This keymap is not
    used.")
#+end_src
** Load Children...

Solution

  • The :noweb-ref header (http://orgmode.org/manual/noweb_002dref.html#noweb_002dref) helps propagate the noweb reference names to sub-trees using property inheritance.