├── .gitignore ├── HISTORY.org ├── README.org ├── old ├── .nosearch ├── old-outorg.el ├── old-readme.org └── old-readme.txt ├── outorg-test.el └── outorg.el /.gitignore: -------------------------------------------------------------------------------- 1 | # Dirs 2 | old/* 3 | # Compiled 4 | *.elc 5 | -------------------------------------------------------------------------------- /HISTORY.org: -------------------------------------------------------------------------------- 1 | * TODO Version 2.1 2 | 3 | ** TODO quit byte-compiler 4 | ** TODO improve MELPA-package 5 | ** TODO update README 6 | ** TODO set version number 7 | ** TODO announce in org-mode mailing-list 8 | ** TODO announce in emacs-user mailing-list 9 | 10 | 11 | 12 | * TODO Version 2.0 13 | 14 | ** TODO improve MELPA-package 15 | ** DONE create new ert-buffer-report github repo 16 | - State "DONE" from "TODO" [2014-09-21 So 13:16] 17 | ** DONE add hint to outorg-export repo during loading 18 | - State "DONE" from "TODO" [2014-09-21 So 13:15] 19 | ** TODO clean test file 20 | ** DONE update comment-section 21 | - State "DONE" from "TODO" [2014-09-20 Sa 14:39] 22 | ** DONE port org-mode's marker tracking to outorg 23 | - State "DONE" from "TODO" [2014-09-20 Sa 14:38] 24 | ** DONE test conversion process for side-effects 25 | - State "DONE" from "TODO" [2014-09-20 Sa 14:37] 26 | ** DONE (almost) handle special multi-line comments 27 | - State "DONE" from "TODO" [2014-09-20 Sa 14:36] 28 | ** DONE rewrite conversion functions 29 | - State "DONE" from "TODO" [2014-09-20 Sa 14:35] 30 | ** DONE quite byte-compiler 31 | - State "DONE" from "TODO" [2014-09-21 So 02:07] 32 | ** DONE update README 33 | - State "DONE" from "TODO" [2014-09-20 Sa 14:58] 34 | ** DONE set version number 35 | - State "DONE" from "TODO" [2014-09-20 Sa 14:57] 36 | ** DONE announce in org-mode mailing-list 37 | - State "DONE" from "TODO" [2014-09-21 So 13:16] 38 | ** DONE announce in emacs-user mailing-list 39 | - State "DONE" from "TODO" [2014-09-21 So 13:16] 40 | 41 | 42 | * DONE Version 1.0 43 | CLOSED: [2013-05-03 Fr 19:14] 44 | :LOGBOOK: 45 | - State "DONE" from "NEXT" [2013-05-03 Fr 19:14] 46 | :END: 47 | 48 | ** DONE add menu to outorg-edit-buffer 49 | CLOSED: [2013-05-03 Fr 19:12] 50 | :LOGBOOK: 51 | - State "DONE" from "TODO" [2013-05-03 Fr 19:12] 52 | :END: 53 | [2013-03-19 Di 16:14] 54 | ** DONE check headline not uncommented bug in html 55 | CLOSED: [2013-05-03 Fr 19:13] 56 | :LOGBOOK: 57 | - State "DONE" from "TODO" [2013-05-03 Fr 19:13] 58 | :END: 59 | [2013-02-20 Mi 14:47] 60 | ** CANCELLED check with java :CANCELLED: 61 | CLOSED: [2013-05-03 Fr 19:13] 62 | :LOGBOOK: 63 | - State "CANCELLED" from "TODO" [2013-05-03 Fr 19:13] \\ 64 | later 65 | :END: 66 | [2013-02-16 Sa 23:40] 67 | ** CANCELLED check with C :CANCELLED: 68 | CLOSED: [2013-05-03 Fr 19:13] 69 | :LOGBOOK: 70 | - State "CANCELLED" from "TODO" [2013-05-03 Fr 19:13] \\ 71 | later 72 | :END: 73 | [2013-02-16 Sa 23:40] 74 | ** CANCELLED check with R :CANCELLED: 75 | CLOSED: [2013-05-03 Fr 19:13] 76 | :LOGBOOK: 77 | - State "CANCELLED" from "TODO" [2013-05-03 Fr 19:13] \\ 78 | later 79 | :END: 80 | [2013-02-16 Sa 23:39] 81 | ** CANCELLED check with html :CANCELLED: 82 | CLOSED: [2013-05-03 Fr 19:13] 83 | :LOGBOOK: 84 | - State "CANCELLED" from "TODO" [2013-05-03 Fr 19:13] \\ 85 | later 86 | :END: 87 | [2013-02-16 Sa 23:39] 88 | ** CANCELLED check with latex :CANCELLED: 89 | CLOSED: [2013-05-03 Fr 19:12] 90 | :LOGBOOK: 91 | - State "CANCELLED" from "TODO" [2013-05-03 Fr 19:12] \\ 92 | later 93 | :END: 94 | [2013-02-16 Sa 23:39] 95 | ** DONE keybindings for commands 96 | CLOSED: [2013-03-19 Di 16:13] 97 | :LOGBOOK: 98 | - State "DONE" from "TODO" [2013-03-19 Di 16:13] 99 | :END: 100 | [2013-02-16 Sa 23:25] 101 | ** DONE work out the edit-buffer and tmp-file naming scheme 102 | CLOSED: [2013-02-16 Sa 23:25] 103 | :LOGBOOK: 104 | - State "DONE" from "TODO" [2013-02-16 Sa 23:25] 105 | :END: 106 | [2013-02-16 Sa 02:35] 107 | ** DONE rename outorg2 to outorg and (old) outorg to old-outorg. 108 | CLOSED: [2013-02-16 Sa 02:34] 109 | :LOGBOOK: 110 | - State "DONE" from "TODO" [2013-02-16 Sa 02:34] 111 | :END: 112 | [2013-02-16 Sa 02:29] 113 | ** DONE fix issue with indented comments when 'comment-region' is applied to indented text. 114 | CLOSED: [2013-02-16 Sa 14:09] 115 | :LOGBOOK: 116 | - State "DONE" from "TODO" [2013-02-16 Sa 14:09] 117 | :END: 118 | [2013-02-16 Sa 02:26] 119 | ** DONE fix double insertion bug (when edit-buffer killed without saving??) 120 | CLOSED: [2013-02-20 Mi 17:56] 121 | :LOGBOOK: 122 | - State "DONE" from "TODO" [2013-02-20 Mi 17:56] 123 | - State "TODO" from "DONE" [2013-02-20 Mi 14:48] 124 | - State "DONE" from "TODO" [2013-02-16 Sa 02:28] 125 | :END: 126 | [2013-02-14 Do 17:37] 127 | ** DONE add special marker to narrowed buffers to remember point-position 128 | CLOSED: [2013-02-16 Sa 20:29] 129 | :LOGBOOK: 130 | - State "DONE" from "TODO" [2013-02-16 Sa 20:29] 131 | :END: 132 | [2013-02-14 Do 17:18] 133 | ** DONE add persistent header line to edit-buffer 134 | CLOSED: [2013-02-14 Do 17:18] 135 | :LOGBOOK: 136 | - State "DONE" from "" [2013-02-14 Do 17:18] 137 | :END: 138 | [2013-02-14 Do 17:15] 139 | ** DONE move outxxtra.el to its own github repo 140 | CLOSED: [2013-02-14 Do 17:15] 141 | :LOGBOOK: 142 | - State "DONE" from "TODO" [2013-02-14 Do 17:15] 143 | :END: 144 | [2013-02-14 Do 17:14] 145 | ** DONE special minor-mode for edit-buffer 146 | CLOSED: [2013-02-16 Sa 02:28] 147 | :LOGBOOK: 148 | - State "DONE" from "TODO" [2013-02-16 Sa 02:28] 149 | :END: 150 | [2013-02-13 Mi 01:42] 151 | *** DONE outorg-keybindings in edit-buffer 152 | CLOSED: [2013-02-16 Sa 02:28] 153 | :LOGBOOK: 154 | - State "DONE" from "TODO" [2013-02-16 Sa 02:28] 155 | :END: 156 | [2013-02-13 Mi 01:44] 157 | *** DONE kill-buffer actions 158 | CLOSED: [2013-02-16 Sa 02:28] 159 | :LOGBOOK: 160 | - State "DONE" from "TODO" [2013-02-16 Sa 02:28] 161 | :END: 162 | [2013-02-13 Mi 01:44] 163 | **** DONE reset window-config 164 | CLOSED: [2013-02-16 Sa 02:28] 165 | :LOGBOOK: 166 | - State "DONE" from "TODO" [2013-02-16 Sa 02:28] 167 | :END: 168 | [2013-02-13 Mi 01:45] 169 | **** DONE save dangling edits in tmp-file 170 | CLOSED: [2013-02-16 Sa 02:28] 171 | :LOGBOOK: 172 | - State "DONE" from "TODO" [2013-02-16 Sa 02:28] 173 | :END: 174 | [2013-02-13 Mi 01:44] 175 | **** DONE reset-global-vars 176 | CLOSED: [2013-02-16 Sa 02:28] 177 | :LOGBOOK: 178 | - State "DONE" from "TODO" [2013-02-16 Sa 02:28] 179 | :END: 180 | [2013-02-13 Mi 01:45] 181 | ** DONE fix bug eob when last line was line of code (conversion to org) 182 | CLOSED: [2013-02-14 Do 17:11] 183 | :LOGBOOK: 184 | - State "DONE" from "TODO" [2013-02-14 Do 17:11] 185 | :END: 186 | [2013-02-13 Mi 01:39] 187 | ** DONE refactor outxxtra.el (only extensions to out-xtra.el) 188 | CLOSED: [2013-02-14 Do 17:11] 189 | :LOGBOOK: 190 | - State "DONE" from "TODO" [2013-02-14 Do 17:11] 191 | :END: 192 | [2013-02-13 Mi 01:38] 193 | ** DONE refactor outorg2.el (only Org-style editing) 194 | CLOSED: [2013-02-14 Do 17:11] 195 | :LOGBOOK: 196 | - State "DONE" from "TODO" [2013-02-14 Do 17:11] 197 | :END: 198 | [2013-02-13 Mi 01:37] 199 | ** CANCELLED announce new version in PicoLisp mailing-list :CANCELLED: 200 | CLOSED: [2013-05-03 Fr 19:14] 201 | :LOGBOOK: 202 | - State "CANCELLED" from "TODO" [2013-05-03 Fr 19:14] \\ 203 | enough publicity 204 | :END: 205 | [2013-02-13 Mi 01:37] 206 | ** DONE change version number (comment and const) 207 | CLOSED: [2013-05-03 Fr 19:14] 208 | :LOGBOOK: 209 | - State "DONE" from "TODO" [2013-05-03 Fr 19:14] 210 | :END: 211 | [2013-02-13 Mi 01:37] 212 | ** CANCELLED fix menu :CANCELLED: 213 | CLOSED: [2013-02-14 Do 17:12] 214 | :LOGBOOK: 215 | - State "CANCELLED" from "TODO" [2013-02-14 Do 17:12] \\ 216 | related to outxxtra.el 217 | :END: 218 | [2013-02-13 Mi 01:37] 219 | ** DONE develop README to Worg article 220 | CLOSED: [2013-03-19 Di 16:13] 221 | :LOGBOOK: 222 | - State "DONE" from "TODO" [2013-03-19 Di 16:13] 223 | :END: 224 | [2013-02-13 Mi 01:37] 225 | ** DONE write installation guide (with outline-magic) 226 | CLOSED: [2013-03-19 Di 16:13] 227 | :LOGBOOK: 228 | - State "DONE" from "TODO" [2013-03-19 Di 16:13] 229 | :END: 230 | [2013-02-13 Mi 01:37] 231 | ** CANCELLED check keybindings, compare to org :CANCELLED: 232 | CLOSED: [2013-02-14 Do 17:13] 233 | :LOGBOOK: 234 | - State "CANCELLED" from "TODO" [2013-02-14 Do 17:13] \\ 235 | related to outxxtra.el 236 | :END: 237 | [2013-02-13 Mi 01:36] 238 | ** CANCELLED fix demote and promote subtree :CANCELLED: 239 | CLOSED: [2013-02-14 Do 17:11] 240 | :LOGBOOK: 241 | - State "CANCELLED" from "TODO" [2013-02-14 Do 17:11] \\ 242 | related to outxxtra.el 243 | :END: 244 | [2013-02-13 Mi 01:36] 245 | ** CANCELLED check with different languages (comment-end true, e..g. HTML) :CANCELLED: 246 | CLOSED: [2013-02-14 Do 17:13] 247 | :LOGBOOK: 248 | - State "CANCELLED" from "TODO" [2013-02-14 Do 17:13] \\ 249 | related to outxxtra.el 250 | :END: 251 | [2013-02-13 Mi 01:36] 252 | ** CANCELLED check with different languages (comment-end false, e.g. R, Java) :CANCELLED: 253 | CLOSED: [2013-02-14 Do 17:13] 254 | :LOGBOOK: 255 | - State "CANCELLED" from "TODO" [2013-02-14 Do 17:13] \\ 256 | related to outxxtra.el 257 | :END: 258 | [2013-02-13 Mi 01:36] 259 | 260 | 261 | * Version 0.9 262 | ** DONE announce new version in Org-mode mailing-list 263 | CLOSED: [2013-02-12 Di 00:08] 264 | :LOGBOOK: 265 | - State "DONE" from "TODO" [2013-02-12 Di 00:08] 266 | :END: 267 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | * outorg :noexport: 2 | 3 | Outorg is for editing comment-sections of source-code files in temporary Org-mode buffers. It turns conventional literate-programming upside-down in that the default mode is the programming-mode, and special action has to be taken to switch to the text-mode (i.e. Org-mode). 4 | 5 | Outorg depends on Outshine, i.e. outline-minor-mode with outshine extensions activated. An outshine buffer is structured like an org-mode buffer, only with outcommented headlines. While in Org-mode text is text and source-code is 'hidden' inside of special src-blocks, in an outshine buffer source-code is source-code and text is 'hidden' as comments. 6 | 7 | Thus org-mode and programming-mode are just two different views on the outshine-style structured source-file, and outorg is the tool to switch between these two views. When switching from a programming-mode to org-mode, the comments are converted to text and the source-code is put into src-blocks. When switching back from org-mode to the programming-mode, the process is reversed - the text is outcommented again and the src-blocks that enclose the source-code are removed. 8 | 9 | When the code is more important than the text, i.e. when the task is "literate /programming/" rather than "/literate/ programming," it is often more convenient to work in a programming-mode and switch to org-mode once in a while than vice-versa. Outorg is really fast, even big files with 10k lines are converted in a second or so, and the user decides if he wants to convert just the current subtree (done instantly) or the whole buffer. Since text needs no session handling or variable passing or other special treatment, the outorg approach is much simpler than the Org-Babel approach. However, the full power of Org-Babel is available once the *outorg-edit-buffer* has popped up. 10 | 11 | * Contents :TOC: 12 | - [[#installation][Installation]] 13 | - [[#usage][Usage]] 14 | - [[#changelog][Changelog]] 15 | - [[#bugs-and-shortcomings][Bugs and Shortcomings]] 16 | - [[#credits][Credits]] 17 | - [[#license][License]] 18 | 19 | * Installation :noexport_1: 20 | 21 | ** MELPA 22 | 23 | If you install from MELPA, you're done. 24 | 25 | ** Manual 26 | 27 | First install [[https://github.com/alphapapa/outshine][Outshine]], then =(require 'outorg)= in your init file. 28 | 29 | * Usage 30 | 31 | Outorg assumes that you set =outline-minor-mode-prefix= in your init-file to =M-#=, like this: 32 | 33 | #+BEGIN_SRC elisp 34 | ;; Must be set before outline is loaded 35 | (defvar outline-minor-mode-prefix "\M-#") 36 | #+END_SRC 37 | 38 | Outorg's main command is =outorg-edit-as-org= (by default, bound to =M-# #=), to be used in source-code buffers where =outline-minor-mode= is activated with =outshine= extensions. The Org-mode edit-buffer popped up by this command is called *outorg-edit-buffer* and has =outorg-edit-minor-mode= activated, a minor-mode with only 2 commands: 39 | 40 | + =outorg-copy-edits-and-exit= (=M-#=) 41 | + =outorg-save-edits-to-tmp-file= (=C-x C-s=) 42 | 43 | If you want to insert Org-mode source-code or example blocks in comment-sections, i.e. you don't want outorg to remove the enclosing blocks, simply outcomment them in the outorg-edit buffer before calling =outorg-copy-edits-and-exit=. 44 | 45 | * Changelog :noexport_1: 46 | 47 | ** 2.1-pre 48 | 49 | *Additions*: 50 | + Convert readme to Org. 51 | + Display blank lines between code blocks and regular text when editing. 52 | + Use =SRC= blocks more often (i.e. when the source buffer has a major mode). 53 | 54 | *Fixes:* 55 | + Use =setq-local= instead of =org-set-local= 56 | + Verify =outline-minor-mode= is active before trying to edit. 57 | + Display the actual keybinding of =outorg-copy-edits-and-exit= in the header line of the edit buffer. 58 | 59 | ** Pre-2.1 changelog 60 | 61 | | date | author(s) | version | 62 | |-------------------+-------------------+-----------| 63 | | <2014-09-20 Sa> | Thorsten Jolitz | 2.0 | 64 | | <2013-05-03 Fr> | Thorsten Jolitz | 1.0 | 65 | | <2013-02-11 Mo> | Thorsten Jolitz | 0.9 | 66 | 67 | * Bugs and Shortcomings 68 | 69 | Outorg started out purely line-based, it only worked with one-line comments, i.e. with comment-sections like those produced by =comment-region= (a command that comments or uncomments each line in the region). It was enhanced later on to recognize comment regions too, i.e. those special multi-line comments found in many programming languages. But using outorg on such multi-line comments will probably change their syntax back to single-line whenever =comment-region= uses this style. 70 | 71 | * Credits 72 | 73 | Outorg was originally written by [[https://github.com/tj64][Thorsten Jolitz]], who transferred maintainership to Adam Porter in April 2017. 74 | 75 | * License 76 | 77 | GPLv2 or later. 78 | 79 | * Tests :noexport: 80 | 81 | *Note:* The tests are currently non-functional. They should be updated using =assess= rather than =ert-buffer=. 82 | 83 | A special kind of test has been developed for outorg using the =ert-buffer= library, the so called 'conversion test'. It has the following steps: 84 | 85 | 1. programming-mode -> org-mode 86 | 87 | 2. edit in org-mode, store undo-information 88 | 89 | 3. org-mode -> programming-mode 90 | 91 | 4. programming-mode -> org-mode (again) 92 | 93 | 5. undo edits 94 | 95 | 6. org-mode -> programming-mode (again) 96 | 97 | After these 4 conversions, the original programming-mode buffer must be unchanged when the conversion process is perfect, i.e. does not introduce any changes itself. See =outorg-test.el= for details. 98 | -------------------------------------------------------------------------------- /old/.nosearch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alphapapa/outorg/ef0f86f4b893b30be8bcf8b43a5ec357a6c70f07/old/.nosearch -------------------------------------------------------------------------------- /old/old-outorg.el: -------------------------------------------------------------------------------- 1 | ;; * outorg.el --- Org-style outline navigation and comment editing 2 | 3 | ;; ** Copyright 4 | 5 | ;; Copyright (C) 2013 Thorsten Jolitz 6 | ;; This file is not (yet) part of GNU Emacs 7 | 8 | ;; Author: Thorsten Jolitz (format "tjolitz%sgmail%s" "@" ".com") 9 | 10 | ;; ** Credits 11 | 12 | ;; This library is based on, or rather an extension of, Per Abrahamsen's 13 | ;; 'out-xtra.el' (http://tinyurl.com/aql9p97), and may replace it many cases. 14 | ;; Some new ideas were taken from Fabrice Niessen's '.emacs' 15 | ;; (http://www.mygooglest.com/fni/dot-emacs.html#sec-2), and some inspiration 16 | ;; from Eric Schulte's and Dan Davidson's 'Org-babel' 17 | ;; (http://orgmode.org/worg/org-contrib/babel/). 18 | 19 | ;; ** Commentary 20 | 21 | ;; This file provides (almost) the same nice extra features for outline minor 22 | ;; mode like Per Abrahamsen's 'out-xtra': 23 | 24 | ;; - Change default minor mode key prefix to `C-c'. 25 | ;; - Complete keybindings and menu support. 26 | ;; - Add command to show top level headers. 27 | ;; - Add command to hide all other entries than the one containing point. 28 | 29 | ;; `outorg' follows a different idea than `out-xtra': it consists of generic 30 | ;; functionality that that calculates the adequate outline-regexp and 31 | ;; outline-level for the active major-mode, rather than defining several blocks 32 | ;; of major-mode specific functionality. 33 | 34 | ;; New features of `outorg' are: 35 | 36 | ;; 1. Generic functionality that should work whereever `comment-region' and 37 | ;; `uncomment-region' work. 38 | 39 | ;; 2. Fontification of headlines (copied from Fabrice Niessen's 40 | ;; '.emacs') 41 | 42 | ;; 3. Toggling between editing in Lisp mode and in Org mode, similar to the 43 | ;; editing of source-code blocks in Org-mode. 44 | 45 | ;; It is highly recommended to use `outorg' together with `outline-magic' for 46 | ;; the Org-style `outline-cycle' command. 47 | 48 | ;; ** Emacs Version 49 | 50 | ;; `outorg.el' works with [GNU Emacs 24.2.1 (x86_64-unknown-linux-gnu, GTK+ 51 | ;; Version 3.6.4) of 2013-01-20 on eric]. No attempts of testing with older 52 | ;; versions or other types of Emacs have be made (yet). 53 | 54 | ;; ** Installation 55 | 56 | ;; Insert 57 | ;; (require 'outorg) 58 | ;; in your .emacs file to install. If you want a different prefix 59 | ;; key, insert first 60 | ;; (defvar outline-minor-mode-prefix "\C-c") 61 | ;; or whatever. The prefix can only be changed before outline (minor) 62 | ;; mode is loaded. 63 | 64 | ;; ** ChangeLog 65 | 66 | ;; | date | author(s) | version | 67 | ;; |-----------------+-----------------+---------| 68 | ;; | <2013-02-11 Mo> | Thorsten Jolitz | 0.9 | 69 | 70 | ;; ** Bugs 71 | 72 | ;; `outorg' is line-based, it only works with 'one-line' comments, i.e. with 73 | ;; comment-sections like those produced by `comment-region' (a command that 74 | ;; comments or uncomments each line in the region). Those special multi-line 75 | ;; comments found in many programming languages are not recognized and lead to 76 | ;; undefined behaviour. 77 | 78 | ;; * Requires 79 | 80 | (require 'outline) 81 | (require 'org) 82 | 83 | ;; * Variables 84 | 85 | ;; ** Consts 86 | 87 | (defconst outorg-version "0.9" 88 | "outorg version number.") 89 | 90 | ;; ** Vars 91 | 92 | (defvar outline-minor-mode-prefix "\C-c" 93 | "New outline-minor-mode prefix.") 94 | 95 | (defvar outorg-edit-whole-buffer-p nil 96 | "Non-nil if the whole code-buffer is edited.") 97 | 98 | (defvar outorg-initial-window-config nil 99 | "Initial window-configuration when editing as Org.") 100 | 101 | ;; ** Hooks 102 | 103 | (defvar outorg-hook nil 104 | "Functions to run after `outorg' is loaded.") 105 | 106 | ;; ** Customs 107 | 108 | ;; *** Custom Groups 109 | 110 | ;; (defgroup outorg nil 111 | ;; "Library for outline navigation and Org-mode editing in Lisp buffers." 112 | ;; :prefix "outorg-" 113 | ;; :group 'lisp 'outlines 114 | ;; :link '(url-link "http://emacswiki.org/emacs/OutlineMinorMode")) 115 | 116 | 117 | ;; *** Custom Vars 118 | 119 | ;; * Functions 120 | 121 | ;; ** Non-interactive Functions 122 | 123 | ;; *** Get buffer major mode 124 | 125 | (defun outorg-get-buffer-mode (buffer-or-string) 126 | "Return major mode of BUFFER-OR-STRING." 127 | (with-current-buffer buffer-or-string 128 | major-mode)) 129 | 130 | 131 | ;; *** Calculate the outline-regexp 132 | 133 | (defun outorg-calc-outline-regexp () 134 | "Calculate the outline regexp for the current mode." 135 | (let* ((comment-start-no-space 136 | (replace-regexp-in-string 137 | "[[:space:]]+" "" comment-start)) 138 | (comment-start-region 139 | (if (and 140 | comment-end 141 | (not (string-equal "" comment-end))) 142 | comment-start-no-space 143 | (concat 144 | comment-start-no-space comment-start-no-space)))) 145 | ;; the "^" not needed by outline, but by outorg (?) 146 | (concat "^" comment-start-region " [*]+ "))) 147 | 148 | ;; *** Calculate the outline-level 149 | 150 | (defun outorg-calc-outline-level () 151 | "Calculate the right outline level for the outorg-outline-regexp" 152 | (save-excursion 153 | (save-match-data 154 | (let ((len (- (match-end 0) (match-beginning 0)))) 155 | (- len (+ 2 (* 2 (length (format "%s" comment-start))))))))) 156 | 157 | 158 | ;; *** Fontify the headlines 159 | 160 | ;; Org-style highlighting of the headings 161 | (defun outorg-fontify-headlines (outline-regexp) 162 | ;; (interactive) 163 | ;; (setq outline-regexp (tj/outline-regexp)) 164 | 165 | ;; highlight the headings 166 | ;; see http://www.gnu.org/software/emacs/manual/html_node/emacs/Font-Lock.html 167 | ;; use `M-x customize-apropos-faces' to customize faces 168 | ;; to find the corresponding face for each outline level, see 169 | ;; `org-faces.el' 170 | 171 | ;; Added `\n?', after having read the following chunk of code (from org.el): 172 | ;; `(,(if org-fontify-whole-heading-line 173 | ;; "^\\(\\**\\)\\(\\* \\)\\(.*\n?\\)" 174 | ;; "^\\(\\**\\)\\(\\* \\)\\(.*\\)") 175 | 176 | (let ((org-fontify-whole-heading-line "") ; "\n?") 177 | (heading-1-regexp 178 | (concat (substring outline-regexp 0 -1) 179 | "\\{1\\} \\(.*" org-fontify-whole-heading-line "\\)")) 180 | (heading-2-regexp 181 | (concat (substring outline-regexp 0 -1) 182 | "\\{2\\} \\(.*" org-fontify-whole-heading-line "\\)")) 183 | (heading-3-regexp 184 | (concat (substring outline-regexp 0 -1) 185 | "\\{3\\} \\(.*" org-fontify-whole-heading-line "\\)")) 186 | (heading-4-regexp 187 | (concat (substring outline-regexp 0 -1) 188 | "\\{4,\\} \\(.*" org-fontify-whole-heading-line "\\)")) 189 | (heading-5-regexp 190 | (concat (substring outline-regexp 0 -1) 191 | "\\{5\\} \\(.*" org-fontify-whole-heading-line "\\)"))) 192 | (font-lock-add-keywords 193 | nil 194 | `((,heading-1-regexp 1 'org-level-1 t) 195 | (,heading-2-regexp 1 'org-level-2 t) 196 | (,heading-3-regexp 1 'org-level-3 t) 197 | (,heading-4-regexp 1 'org-level-4 t) 198 | (,heading-5-regexp 1 'org-level-5 t))))) 199 | 200 | ;; *** Set outline-regexp und outline-level 201 | 202 | (defun outorg-set-local-outline-regexp-and-level (regexp &optional fun) 203 | "Set `outline-regexp' locally to REGEXP and `outline-level' to FUN." 204 | (make-local-variable 'outline-regexp) 205 | (setq outline-regexp regexp) 206 | (and fun 207 | (make-local-variable 'outline-level) 208 | (setq outline-level fun))) 209 | 210 | ;; *** Outorg hook-functions 211 | 212 | (defun outorg-hook-function () 213 | "Add this function to outline-minor-mode-hook" 214 | (let ((out-regexp (outorg-calc-outline-regexp))) 215 | (outorg-set-local-outline-regexp-and-level 216 | out-regexp 'outorg-calc-outline-level) 217 | (outorg-fontify-headlines out-regexp))) 218 | 219 | (add-hook 'outline-minor-mode-hook 'outorg-hook-function) 220 | 221 | ;; ** Commands 222 | 223 | ;; *** Edit as Org 224 | 225 | (defun outorg-edit-as-org (arg) 226 | "Convert and copy to temporary Org buffer 227 | With ARG, edit the whole buffer, otherwise the current subtree." 228 | (interactive "P") 229 | (setq outorg-code-buffer-marker (point-marker)) 230 | (and arg (setq outorg-edit-whole-buffer-p t)) 231 | (setq outorg-initial-window-config 232 | (current-window-configuration)) 233 | (outorg-copy-and-convert)) 234 | 235 | (defun outorg-save-edits () 236 | "Replace code-buffer content with (converted) edit-buffer content and 237 | kill edit-buffer" 238 | (interactive) 239 | (widen) 240 | (funcall 241 | (outorg-get-buffer-mode 242 | (marker-buffer outorg-code-buffer-marker))) 243 | (outorg-convert-back-to-code) 244 | (outorg-replace-code-with-edits) 245 | (kill-buffer 246 | (marker-buffer outorg-edit-buffer-marker)) 247 | (set-window-configuration 248 | outorg-initial-window-config) 249 | ;; (switch-to-buffer 250 | ;; (marker-buffer outorg-code-buffer-marker)) 251 | ;; (goto-char 252 | ;; (marker-position outorg-code-buffer-marker)) 253 | (outorg-reset-global-vars)) 254 | 255 | ;; *** Additional outline commands (from `out-xtra'). 256 | 257 | (defun outline-hide-sublevels (keep-levels) 258 | "Hide everything except the first KEEP-LEVEL headers." 259 | (interactive "p") 260 | (if (< keep-levels 1) 261 | (error "Must keep at least one level of headers")) 262 | (setq keep-levels (1- keep-levels)) 263 | (save-excursion 264 | (goto-char (point-min)) 265 | (hide-subtree) 266 | (show-children keep-levels) 267 | (condition-case err 268 | (while (outline-get-next-sibling) 269 | (hide-subtree) 270 | (show-children keep-levels)) 271 | (error nil)))) 272 | 273 | (defun outline-hide-other () 274 | "Hide everything except for the current body and the parent headings." 275 | (interactive) 276 | (outline-hide-sublevels 1) 277 | (let ((last (point)) 278 | (pos (point))) 279 | (while (save-excursion 280 | (and (re-search-backward "[\n\r]" nil t) 281 | (eq (following-char) ?\r))) 282 | (save-excursion 283 | (beginning-of-line) 284 | (if (eq last (point)) 285 | (progn 286 | (outline-next-heading) 287 | (outline-flag-region last (point) ?\n)) 288 | (show-children) 289 | (setq last (point))))))) 290 | 291 | 292 | ;; *** Edit as Org-file 293 | 294 | (defun outorg-copy-and-convert () 295 | "Copy code buffer content to tmp-buffer and convert it to Org syntax. 296 | If WHOLE-BUFFER-P is non-nil, copy the whole buffer, otherwise 297 | the current subtree." 298 | (let* ((edit-buffer 299 | (get-buffer-create "*outorg-edit-buffer*"))) 300 | (save-restriction 301 | (with-current-buffer edit-buffer (erase-buffer)) 302 | (widen) 303 | ;; copy code buffer content 304 | (copy-to-buffer 305 | edit-buffer 306 | (if outorg-edit-whole-buffer-p 307 | (point-min) 308 | (save-excursion 309 | (outline-back-to-heading 'INVISIBLE-OK) 310 | (point))) 311 | (if outorg-edit-whole-buffer-p 312 | (point-max) 313 | (save-excursion 314 | (outline-end-of-subtree) 315 | (point))))) 316 | ;; switch to edit buffer 317 | (if (one-window-p) (split-window-sensibly (get-buffer-window))) 318 | (switch-to-buffer-other-window edit-buffer) 319 | (and outorg-edit-whole-buffer-p 320 | (goto-char 321 | (marker-position outorg-code-buffer-marker))) 322 | (setq outorg-edit-buffer-marker (point-marker))) 323 | ;; activate programming language major mode and convert to org 324 | (funcall (outorg-get-buffer-mode 325 | (marker-buffer outorg-code-buffer-marker))) 326 | (outorg-convert-to-org) 327 | ;; change major mode to org-mode 328 | (org-mode) 329 | (if outorg-edit-whole-buffer-p 330 | (progn 331 | (org-first-headline-recenter) 332 | (hide-sublevels 3) 333 | (goto-char 334 | (marker-position outorg-edit-buffer-marker)) 335 | (show-subtree)) 336 | (goto-char 337 | (marker-position outorg-edit-buffer-marker)) 338 | (show-all))) 339 | 340 | (defun outorg-convert-to-org () 341 | "Convert file content to Org Syntax" 342 | (let* ((last-line-comment-p nil) 343 | (mode-name 344 | (format 345 | "%S" (with-current-buffer 346 | (marker-buffer outorg-code-buffer-marker) 347 | major-mode))) 348 | (splitted-mode-name 349 | (split-string mode-name "-mode")) 350 | (language-name 351 | (if (> (length splitted-mode-name) 1) 352 | (car splitted-mode-name) 353 | (car (split-string mode-name "\\.")))) 354 | (in-org-babel-load-languages-p 355 | (assq 356 | (intern language-name) 357 | org-babel-load-languages))) 358 | (goto-char (point-min)) 359 | (while (not (eobp)) 360 | (cond 361 | ;; empty line (do nothing) 362 | ((looking-at "^[[:space:]]*$")) 363 | ;; comment line after comment line or at 364 | ;; beginning of buffer 365 | ((and 366 | (save-excursion 367 | (eq (comment-on-line-p) (point-at-bol))) 368 | (or (bobp) last-line-comment-p)) 369 | (uncomment-region (point-at-bol) (point-at-eol)) 370 | (setq last-line-comment-p t)) 371 | ;; line of code after comment line 372 | ((and 373 | (save-excursion 374 | (not (eq (comment-on-line-p) (point-at-bol)))) 375 | last-line-comment-p) 376 | (newline) 377 | (forward-line -1) 378 | (insert 379 | (if in-org-babel-load-languages-p 380 | (concat "#+begin_src " language-name) 381 | "#+begin_example")) 382 | (forward-line) 383 | (setq last-line-comment-p nil)) 384 | ;; comment line after line of code 385 | ((and 386 | (save-excursion 387 | (eq (comment-on-line-p) (point-at-bol))) 388 | (not last-line-comment-p)) 389 | (uncomment-region (point-at-bol) (point-at-eol)) 390 | (save-excursion 391 | (forward-line -1) 392 | (unless (looking-at "^[[:space:]]*$") 393 | (newline)) 394 | (if in-org-babel-load-languages-p 395 | (insert "#+end_src") 396 | (insert "#+end_example")) 397 | (newline)) 398 | (setq last-line-comment-p t)) 399 | ;; last line after line of code 400 | ((and 401 | (eq (line-number-at-pos) 402 | (1- (count-lines (point-min) (point-max)))) 403 | (not last-line-comment-p)) 404 | ;; (unless (looking-at "^[[:space:]]*$") 405 | (forward-line) 406 | (newline) 407 | (if in-org-babel-load-languages-p 408 | (insert "#+end_src") 409 | (insert "#+end_example")) 410 | (newline)) 411 | ;; line of code after line of code 412 | (t (setq last-line-comment-p nil))) 413 | (forward-line)))) 414 | 415 | (defun outorg-convert-back-to-code () 416 | "Convert edit-buffer content back to programming language syntax. 417 | Assume that edit-buffer major-mode has been set back to the 418 | programming-language major-mode of the associated code-buffer 419 | before this function is called." 420 | (let* ((inside-code-or-example-block-p nil)) 421 | (goto-char (point-min)) 422 | (while (not (eobp)) 423 | (cond 424 | ;; empty line (do nothing) 425 | ((looking-at "^[[:space:]]*$")) 426 | ;; begin code/example block 427 | ((looking-at "^[ \t]*#\\+begin_?") 428 | (kill-whole-line) 429 | (forward-line -1) 430 | (setq inside-code-or-example-block-p t)) 431 | ;; end code/example block 432 | ((looking-at "^[ \t]*#\\+end_?") 433 | (kill-whole-line) 434 | (forward-line -1) 435 | (setq inside-code-or-example-block-p nil)) 436 | ;; line inside code/example block (do nothing) 437 | (inside-code-or-example-block-p) 438 | ;; not-empty line outside code/example block 439 | (t (comment-region (point-at-bol) (point-at-eol)))) 440 | (forward-line)))) 441 | 442 | (defun outorg-replace-code-with-edits () 443 | "Replace code-buffer contents with edits." 444 | (let* ((edit-buf (marker-buffer outorg-edit-buffer-marker)) 445 | (code-buf (marker-buffer outorg-code-buffer-marker)) 446 | (edit-buf-point-min 447 | (with-current-buffer edit-buf 448 | (point-min))) 449 | (edit-buf-point-max 450 | (with-current-buffer edit-buf 451 | (goto-char (point-max)) 452 | (unless (and (bolp) (looking-at "^$")) 453 | (newline)) 454 | (point)))) 455 | (with-current-buffer code-buf 456 | (if outorg-edit-whole-buffer-p 457 | (progn 458 | (erase-buffer) 459 | (insert-buffer-substring-no-properties 460 | edit-buf edit-buf-point-min edit-buf-point-max) 461 | ;; (goto-char (marker-position outorg-edit-buffer-marker)) 462 | ) 463 | (save-restriction 464 | (narrow-to-region 465 | (save-excursion 466 | (outline-back-to-heading 'INVISIBLE-OK) 467 | (point)) 468 | (save-excursion 469 | (outline-end-of-subtree) 470 | (point))) 471 | (delete-region (point-min) (point-max)) 472 | (insert-buffer-substring-no-properties 473 | edit-buf edit-buf-point-min edit-buf-point-max))) 474 | ;; (save-buffer) 475 | ))) 476 | 477 | (defun outorg-reset-global-vars () 478 | "Reset some global vars defined by outorg to initial values." 479 | (set-marker outorg-code-buffer-marker nil) 480 | (set-marker outorg-edit-buffer-marker nil) 481 | (setq outorg-edit-whole-buffer-p nil) 482 | (setq outorg-initial-window-config nil)) 483 | 484 | ;; * Keybindings. 485 | 486 | ;; We provide bindings for all keys. 487 | ;; FIXME: very old stuff from `out-xtra' - still necesary? 488 | 489 | (if (fboundp 'eval-after-load) 490 | ;; FSF Emacs 19. 491 | (eval-after-load "outline" 492 | '(let ((map (lookup-key outline-minor-mode-map 493 | outline-minor-mode-prefix))) 494 | (define-key map "\C-t" 'hide-body) 495 | (define-key map "\C-a" 'show-all) 496 | (define-key map "\C-c" 'hide-entry) 497 | (define-key map "\C-e" 'show-entry) 498 | (define-key map "\C-l" 'hide-leaves) 499 | (define-key map "\C-k" 'show-branches) 500 | (define-key map "\C-q" 'outline-hide-sublevels) 501 | (define-key map "\C-o" 'outline-hide-other) 502 | ;; TODO differentiate between called in code or edit buffer 503 | (define-key map "'" 'outorg-edit-as-org) 504 | ;; TODO add these keybindings to org-mode keymap (all?) 505 | ;; (define-key map "\C-s" 'outorg-save-edits) 506 | ;; (define-key map "\C-c" 'outorg-save-edits) 507 | ;; (define-key map "'" 'outorg-save-edits) 508 | 509 | (define-key outline-minor-mode-map [menu-bar hide hide-sublevels] 510 | '("Hide Sublevels" . outline-hide-sublevels)) 511 | (define-key outline-minor-mode-map [menu-bar hide hide-other] 512 | '("Hide Other" . outline-hide-other)) 513 | (if (fboundp 'update-power-keys) 514 | (update-power-keys outline-minor-mode-map)))) 515 | 516 | (if (string-match "Lucid" emacs-version) 517 | (progn ;; Lucid Emacs 19 518 | (defconst outline-menu 519 | '(["Up" outline-up-heading t] 520 | ["Next" outline-next-visible-heading t] 521 | ["Previous" outline-previous-visible-heading t] 522 | ["Next Same Level" outline-forward-same-level t] 523 | ["Previous Same Level" outline-backward-same-level t] 524 | "---" 525 | ["Show All" show-all t] 526 | ["Show Entry" show-entry t] 527 | ["Show Branches" show-branches t] 528 | ["Show Children" show-children t] 529 | ["Show Subtree" show-subtree t] 530 | "---" 531 | ["Hide Leaves" hide-leaves t] 532 | ["Hide Body" hide-body t] 533 | ["Hide Entry" hide-entry t] 534 | ["Hide Subtree" hide-subtree t] 535 | ["Hide Other" outline-hide-other t] 536 | ["Hide Sublevels" outline-hide-sublevels t])) 537 | 538 | (defun outline-add-menu () 539 | (set-buffer-menubar (copy-sequence current-menubar)) 540 | (add-menu nil "Outline" outline-menu)) 541 | 542 | (add-hook 'outline-minor-mode-hook 'outline-add-menu) 543 | (add-hook 'outline-mode-hook 'outline-add-menu) 544 | (add-hook 'outline-minor-mode-off-hook 545 | (function (lambda () (delete-menu-item '("Outline"))))))) 546 | 547 | ;; Lucid Emacs or Emacs 18. 548 | (require 'outln-18) 549 | (let ((map (lookup-key outline-minor-mode-map outline-minor-mode-prefix))) 550 | ;; Should add a menu here. 551 | (define-key map "\C-t" 'hide-body) 552 | (define-key map "\C-a" 'show-all) 553 | (define-key map "\C-c" 'hide-entry) 554 | (define-key map "\C-e" 'show-entry) 555 | (define-key map "\C-l" 'hide-leaves) 556 | (define-key map "\C-k" 'show-branches) 557 | (define-key map "\C-q" 'outline-hide-sublevels) 558 | (define-key map "\C-o" 'outline-hide-other))) 559 | 560 | 561 | ;; * Run hooks and provide 562 | 563 | (run-hooks 'outorg-hook) 564 | 565 | (provide 'outorg) 566 | 567 | ;; Local Variables: 568 | ;; coding: utf-8 569 | ;; ispell-local-dictionary: "en_US" 570 | ;; End: 571 | 572 | ;; outorg.el ends here 573 | -------------------------------------------------------------------------------- /old/old-readme.org: -------------------------------------------------------------------------------- 1 | #+TITLE: outorg.el -- reverse org-babel 2 | #+AUTHOR: Thorsten Jolitz 3 | #+EMAIL: tjolitz gmail com 4 | #+DATE: 2013-02-11 Mo 5 | #+DESCRIPTION: 6 | #+KEYWORDS: 7 | #+LANGUAGE: en 8 | #+OPTIONS: H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil -:t f:t *:t <:nil 9 | #+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc 10 | #+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js 11 | #+EXPORT_SELECT_TAGS: export 12 | #+EXPORT_EXCLUDE_TAGS: noexport 13 | #+LINK_UP: 14 | #+LINK_HOME: 15 | #+XSLT: 16 | 17 | 18 | * outorg.el - Org-style comment editing 19 | ** Copyright 20 | 21 | Copyright (C) 2013 Thorsten Jolitz 22 | This file is not (yet) part of GNU Emacs 23 | 24 | Author: Thorsten Jolitz (format "tjolitz%sgmail%s" "@" ".com") 25 | 26 | ** Credits 27 | 28 | This library is inspired by the way source-blocks can be edited in temporary 29 | edit files in Org-mode (http://orgmode.org/worg/org-contrib/babel/). 30 | 31 | ** Commentary 32 | 33 | `outorg' is like "reverse Org-babel": editing of comment-sections from source 34 | code files in temporary Org-mode buffers instead of editing of Org-mode 35 | source-blocks in temporary source-code buffers. 36 | 37 | ** Emacs Version 38 | 39 | `outorg.el' works with [GNU Emacs 24.2.1 (x86_64-unknown-linux-gnu, GTK+ 40 | Version 3.6.4) of 2013-01-20 on eric]. No attempts of testing with older 41 | versions or other types of Emacs have be made (yet). 42 | 43 | ** Installation 44 | 45 | Insert 46 | (require 'outorg) 47 | in your .emacs file to install. If you want a different prefix 48 | key, insert first 49 | (defvar outline-minor-mode-prefix "\C-c") 50 | or whatever. The prefix can only be changed before outline (minor) 51 | mode is loaded. 52 | 53 | ** ChangeLog 54 | 55 | | date | author(s) | version | 56 | |-----------------+-----------------+---------| 57 | | <2013-02-11 Mo> | Thorsten Jolitz | 0.9 | 58 | 59 | ** Bugs 60 | 61 | `outorg' is line-based, it only works with 'one-line' comments, i.e. with 62 | comment-sections like those produced by `comment-region' (a command that 63 | comments or uncomments each line in the region). Those special multi-line 64 | comments found in many programming languages are not recognized and lead to 65 | undefined behaviour. 66 | 67 | -------------------------------------------------------------------------------- /old/old-readme.txt: -------------------------------------------------------------------------------- 1 | Thorsten Jolitz 2 | 3 | 4 | Table of Contents 5 | _________________ 6 | 7 | 1 outorg.el --- Org-style comment editing 8 | .. 1.1 Copyright 9 | .. 1.2 Licence 10 | .. 1.3 Credits 11 | .. 1.4 Commentary 12 | ..... 1.4.1 About outorg 13 | ..... 1.4.2 Installation 14 | ..... 1.4.3 Bugs and Shortcomings 15 | ..... 1.4.4 Emacs Version 16 | .. 1.5 ChangeLog 17 | 18 | 19 | 1 outorg.el --- Org-style comment editing 20 | ========================================= 21 | 22 | 1.1 Copyright 23 | ~~~~~~~~~~~~~ 24 | 25 | Copyright (C) 2013 Thorsten Jolitz 26 | 27 | Author: Thorsten Jolitz 28 | Maintainer: Thorsten Jolitz 29 | Version: 1.0 30 | Created: 11th February 2013 31 | Keywords: outlines, org-mode, editing 32 | 33 | 34 | 1.2 Licence 35 | ~~~~~~~~~~~ 36 | 37 | This file is NOT (yet) part of GNU Emacs. 38 | 39 | This program is free software; you can redistribute it and/or modify 40 | it under the terms of the GNU General Public License as published by 41 | the Free Software Foundation, either version 3 of the License, or (at 42 | your option) any later version. 43 | 44 | This program is distributed in the hope that it will be useful, but 45 | WITHOUT ANY WARRANTY; without even the implied warranty of 46 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 47 | General Public License for more details. 48 | 49 | You should have received a copy of the GNU General Public License 50 | along with this program. If not, see [http://www.gnu.org/licenses/]. 51 | 52 | 53 | 1.3 Credits 54 | ~~~~~~~~~~~ 55 | 56 | This library is inspired by the way source-blocks can be edited in 57 | temporary edit files in Org-mode (see 58 | [http://orgmode.org/worg/org-contrib/babel/]). 59 | 60 | 61 | 1.4 Commentary 62 | ~~~~~~~~~~~~~~ 63 | 64 | 1.4.1 About outorg 65 | ------------------ 66 | 67 | `outorg' is like "reverse Org-Babel": editing of comment-sections from 68 | source code files in temporary Org-mode buffers instead of editing of 69 | Org-mode source-blocks in temporary source-code buffers. 70 | 71 | It should be used together with `outline-minor-mode' and 72 | `outshine.el'. Keep in mind, that `outorg' only works with 73 | outshine-style headlines like those produced by calling 74 | `comment-region' on Org-mode style headlines in a source-code buffer. 75 | Take this file as an example for suitable outline headlines in an 76 | Emacs Lisp buffer. In other major-modes, the `comment-start' character 77 | ';' of Emacs Lisp would be replaced by that of the respective 78 | major-mode, e.g. '#' in PicoLisp mode or '%' in LaTeX mode. 79 | 80 | `outorgs' main command is 81 | 82 | ,--------------------------- 83 | C-c ' (outorg-edit-as-org) 84 | `--------------------------- 85 | 86 | or, depending on the outline-mode prefix 87 | 88 | ,--------------------------- 89 | M-# M-# (outorg-edit-as-org) 90 | `--------------------------- 91 | 92 | used in source-code buffers where `outline-minor-mode' is activated 93 | with `outshine' extensions. The Org-mode edit-buffer popped up by this 94 | command has `outorg-edit-mode' activated, a minor-mode with only 2 95 | commands: 96 | 97 | ,---------------------------------------- 98 | M-# (outorg-copy-edits-and-exit) 99 | C-x C-s (outorg-save-edits-to-tmp-file) 100 | `---------------------------------------- 101 | 102 | If you want to insert Org-mode source-code or example blocks in 103 | comment-sections, simply outcomment them in the outorg-edit buffer 104 | before calling `outorg-copy-edits-and-exit'. 105 | 106 | 107 | 1.4.2 Installation 108 | ------------------ 109 | 110 | Insert 111 | 112 | #+begin_src emacs-lisp 113 | (require 'outorg) 114 | #+end_src 115 | 116 | in your .emacs. 117 | 118 | 1.4.3 Bugs and Shortcomings 119 | --------------------------- 120 | 121 | `outorg' is line-based, it only works with 'one-line' comments, i.e. 122 | with comment-sections like those produced by `comment-region' (a 123 | command that comments or uncomments each line in the region). Those 124 | special multi-line comments found in many programming languages are 125 | not recognized and lead to undefined behaviour. 126 | 127 | 128 | 1.4.4 Emacs Version 129 | ------------------- 130 | 131 | `outorg.el' works with [GNU Emacs 24.2.1 (x86_64-unknown-linux-gnu, 132 | GTK+ Version 3.6.4) of 2013-01-20 on eric]. No attempts of testing 133 | with older versions or other types of Emacs have been made (yet). 134 | 135 | 136 | 1.5 ChangeLog 137 | ~~~~~~~~~~~~~ 138 | 139 | date author(s) version 140 | ---------------------------------------------- 141 | 2013-05-03 Fr Thorsten Jolitz 1.0 142 | 2013-02-11 Mo Thorsten Jolitz 0.9 143 | -------------------------------------------------------------------------------- /outorg-test.el: -------------------------------------------------------------------------------- 1 | ;;; outorg-test.el --- ERT suite for outorg.el 2 | 3 | ;; Maintainer: Adam Porter 4 | ;; Version: 2.0 5 | ;; URL: https://github.com/alphapapa/outorg 6 | 7 | ;;;; MetaData 8 | ;; :PROPERTIES: 9 | ;; :copyright: Thorsten Jolitz 10 | ;; :copyright-years: 2014+ 11 | ;; :version: 2.0 12 | ;; :licence: GPL 2 or later (free software) 13 | ;; :licence-url: http://www.gnu.org/licenses/ 14 | ;; :part-of-emacs: no 15 | ;; :maintainer: Adam Porter 16 | ;; :inspiration: test-org-element.el 17 | ;; :keywords: emacs org-mode ert buffer 18 | ;; :git-repo: https://github.com/alphapapa/outorg 19 | ;; :git-clone: git://github.com/alphapapa/outorg.git 20 | ;; :END: 21 | 22 | 23 | ;;; Requires 24 | 25 | (require 'ert-buffer) 26 | 27 | ;;; Dependencies 28 | 29 | (unless (featurep 'outorg) 30 | (signal 'missing-test-dependency "outorg")) 31 | (unless (featurep 'ert-buffer) 32 | (signal 'missing-test-dependency "ert-buffer")) 33 | 34 | ;;; Variables 35 | 36 | (defvar outorg-test-saved-org-cmd () 37 | "Org command to be used in ERT test.") 38 | 39 | (defvar outorg-test-saved-major-mode nil 40 | "Major mode to be used in ERT test.") 41 | 42 | (defvar outorg-test-saved-prefix-arg nil 43 | "Prefix arg to be used in ERT test.") 44 | 45 | ;; (defvar outorg-test-with-return-p nil 46 | ;; "Test return values too.") 47 | 48 | ;; (defvar outorg-test-with-explain-p nil 49 | ;; "Explain test results.") 50 | 51 | 52 | ;;; Functions 53 | 54 | ;; (defun outorg-test-toggle-with-return () 55 | ;; "Toggles the value of boolean var. 56 | ;; If `outorg-test-with-return-p' is non-nil, a test that includes 57 | ;; expected and actual return values is called." 58 | ;; (interactive) 59 | ;; (if outorg-test-with-return-p 60 | ;; (setq outorg-test-with-return-p nil) 61 | ;; (setq outorg-test-with-return-p t)) 62 | ;; (message "Outorg-test: include return values is %s" 63 | ;; outorg-test-with-return-p)) 64 | 65 | ;; (defun outorg-test-toggle-with-explain () 66 | ;; "Toggles the value of boolean var. 67 | ;; If `outorg-test-with-explain-p' is non-nil, a test that explains 68 | ;; results is called." 69 | ;; (interactive) 70 | ;; (if outorg-test-with-explain-p 71 | ;; (setq outorg-test-with-explain-p nil) 72 | ;; (setq outorg-test-with-explain-p t)) 73 | ;; (message "Outorg-test: explain results is %s" 74 | ;; outorg-test-with-explain-p)) 75 | 76 | (defun outorg-test-cmd () 77 | "Command to be used inside `ert-deftest'" 78 | (interactive) 79 | (let ((pref-arg '(4)) 80 | saved-undo-tree) 81 | ;; set major mode in buffer copy 82 | (if (eq outorg-test-saved-major-mode 'ess-mode) 83 | ;; special case R-mode 84 | (funcall 'R-mode) 85 | (funcall outorg-test-saved-major-mode)) 86 | ;; (funcall outorg-test-saved-major-mode) 87 | ;; 1ST ROUND: convert buffer from source to org 88 | (outorg-edit-as-org 89 | outorg-test-saved-prefix-arg) 90 | ;; activate undo-tree-mode 91 | (undo-tree-mode t) 92 | ;; avoid failing tests due to moving point 93 | (save-excursion 94 | ;; call org cmd (and modify buffer) 95 | (call-interactively 96 | outorg-test-saved-org-cmd)) 97 | ;; necessary (?) HACK to fill buffer-undo-tree 98 | (undo-tree-visualize) 99 | (undo-tree-visualizer-quit) 100 | ;; store buffer-undo-tree 101 | (setq saved-undo-tree buffer-undo-tree) 102 | ;; reconvert buffer from org to source 103 | (outorg-copy-edits-and-exit) 104 | ;; 2ND ROUND: convert buffer from source to org (again) 105 | (outorg-edit-as-org 106 | outorg-test-saved-prefix-arg) 107 | ;; activate undo-tree-mode 108 | (undo-tree-mode t) 109 | ;; undo changes by org cmd 110 | (org-set-local 'buffer-undo-tree saved-undo-tree) 111 | (undo-tree-undo (undo-tree-count buffer-undo-tree)) 112 | ;; reconvert buffer from org to source 113 | (outorg-copy-edits-and-exit))) 114 | 115 | 116 | (defun outorg-test-run-ert (org-cmd &optional USE-PREFIX-ARG-P RETURN-P EXPLAIN-P) 117 | "Prepare and run ERT test. 118 | 119 | This command records the major-mode of current-buffer in global 120 | variable `outorg-test-saved-major-mode', the given 121 | prefix-argument in `outorg-test-saved-prefix-arg' (if 122 | USE-PREFIX-ARG-P is non-nil) and the given ORG-CMD in 123 | `outorg-test-saved-org-cmd', and it copies the content of current 124 | buffer into a temporary *outorg-test-buffer* and sets its 125 | major-mode. 126 | 127 | After this preparation it calls either 128 | 129 | - `outorg-test-conversion-with-equal' :: RETURN-P and EXPLAIN-P 130 | are both nil 131 | 132 | - `outorg-test-conversion-with-equal-explain' :: RETURN-P is 133 | nil, EXPLAIN-P is non-nil 134 | 135 | - `outorg-test-conversion-with-equal-return' :: RETURN-P is 136 | non-nil, EXPLAIN-P is nil 137 | 138 | - `outorg-test-conversion-with-equal-return-explain' :: RETURN-P 139 | and EXPLAIN-P are both non-nil 140 | 141 | depending on the values of optional function arguments RETURN-P 142 | and EXPLAIN-P or on `outorg-test-with-return-p' and 143 | `outorg-test-with-explain-p'. All of these tests make use of the 144 | *outorg-test-buffer* and the three global variables mentioned 145 | above." 146 | (interactive 147 | (if current-prefix-arg 148 | (list 149 | (read-command "Org Command: ") 150 | (y-or-n-p "Use prefix-arg for calling outorg ") 151 | (y-or-n-p "Test return values ") 152 | (y-or-n-p "Explain test results ")) 153 | (list (read-command "Org Command: ")))) 154 | (let ((old-buf (current-buffer)) 155 | (maj-mode (outorg-get-buffer-mode))) 156 | ;; (ret-p (or RETURN-P outorg-test-with-return-p)) 157 | ;; (exp-p (or EXPLAIN-P outorg-test-with-explain-p) 158 | ;; (use-pref-arg-p (or USE-PREFIX-ARG-P 159 | ;; outorg-test-with-return-p)))) 160 | ;; necessary (?) HACK 161 | (setq outorg-test-saved-org-cmd org-cmd) 162 | (setq outorg-test-saved-major-mode maj-mode) 163 | (when USE-PREFIX-ARG-P 164 | (setq outorg-test-saved-prefix-arg current-prefix-arg)) 165 | (save-restriction 166 | (widen) 167 | (with-current-buffer 168 | (get-buffer-create "*outorg-test-buffer*") 169 | (erase-buffer) 170 | (insert-buffer-substring old-buf) 171 | (if (eq maj-mode 'ess-mode) 172 | ;; special case R-mode 173 | (funcall 'R-mode) 174 | (funcall outorg-test-saved-major-mode)) 175 | ;; (funcall maj-mode) 176 | ;; (call-interactively 'ert-run-tests-interactively) 177 | (cond 178 | ((and (org-string-nw-p RETURN-P) 179 | (org-string-nw-p EXPLAIN-P)) 180 | (funcall 181 | 'ert-run-test ;s-interactively 182 | "outorg-test-conversion-with-equal-return-explain")) 183 | ((org-string-nw-p RETURN-P) 184 | (funcall 185 | 'ert-run-test ;s-interactively 186 | "outorg-test-conversion-with-equal-return")) 187 | ((org-string-nw-p EXPLAIN-P) 188 | (funcall 189 | 'ert-run-test ;s-interactively 190 | "outorg-test-conversion-with-equal-explain")) 191 | (t 192 | (funcall 193 | 'ert-run-tests-interactively 194 | "outorg-test-conversion-with-equal"))))))) 195 | 196 | 197 | ;;; Tests 198 | 199 | (ert-deftest outorg-test-conversion-with-equal () 200 | "Test outorg conversion to and from Org. 201 | 202 | This test assumes that it is called via user command 203 | `outorg-test-run-ert' with point in the original programming 204 | language buffer to be converted to Org-mode, and with the prefix 205 | argument that should be used for `outorg-edit-as-org'. It further 206 | relies on the `ert-buffer' library for doing its work. 207 | 208 | Since outorg is about editing (and thus modifying) a buffer in 209 | Org-mode, defining the expected outcome manually would be bit 210 | cumbersome. Therefore so called 'do/undo' tests (invented and 211 | named by the author) are introduced: 212 | 213 | - do :: convert to org, save original state before editing, edit 214 | in org, produce and save the diffs between original and 215 | final state, convert back from org 216 | 217 | - undo :: convert to org again, undo the saved diffs, convert 218 | back from org 219 | 220 | After such an do/undo cyle the test buffer should be in exactly 221 | the same state as before the test, i.e. 222 | 223 | - buffer content after the test should be string-equal to buffer 224 | content before 225 | 226 | - point should be in the same position 227 | 228 | - the mark should be in the same position (or nil) 229 | 230 | These are actually the three criteria checked by the 'ert-buffer' 231 | library, and when one or more of the checks returns nil, the ert 232 | test fails. 233 | 234 | This test is a one-size-fits-all test for outorg, since it 235 | allows, when called via command `outorg-test-run-ert', to execute 236 | arbitrary Org-mode commands in the *outorg-edit-buffer* and undo 237 | the changes later on, checking for any undesired permanent side 238 | effects of the conversion process per se." 239 | (let ((curr-buf-initial-state 240 | (with-current-buffer "*outorg-test-buffer*" 241 | (ert-Buf-from-buffer)))) 242 | (should 243 | (ert-equal-buffer 244 | (outorg-test-cmd) 245 | curr-buf-initial-state 246 | t)))) 247 | 248 | ;; (ert-deftest outorg-test-conversion-with-equal-return () 249 | ;; "Test outorg conversion to and from Org. 250 | 251 | ;; This test takes return values into account. See docstring of 252 | ;; `outorg-test-conversion-with-equal' for more info." 253 | ;; (let ((curr-buf-initial-state 254 | ;; (with-current-buffer "*outorg-test-buffer*" 255 | ;; (ert-Buf-from-buffer)))) 256 | ;; (should 257 | ;; (ert-equal-buffer-return 258 | ;; (outorg-test-cmd) 259 | ;; curr-buf-initial-state 260 | ;; t nil)))) 261 | 262 | ;; (ert-deftest outorg-test-conversion-with-equal-explain () 263 | ;; "Test outorg conversion to and from Org. 264 | 265 | ;; This test explains results. See docstring of 266 | ;; `outorg-test-conversion-with-equal' for more info." 267 | ;; (let ((curr-buf-initial-state 268 | ;; (with-current-buffer "*outorg-test-buffer*" 269 | ;; (ert-Buf-from-buffer)))) 270 | ;; (should 271 | ;; (ert-equal-buffer-explain 272 | ;; (outorg-test-cmd) 273 | ;; curr-buf-initial-state 274 | ;; t)))) 275 | 276 | ;; (ert-deftest outorg-test-conversion-with-equal-return-explain () 277 | ;; "Test outorg conversion to and from Org. 278 | 279 | ;; This test takes return values into account and explains 280 | ;; results. See docstring of `outorg-test-conversion-with-equal' for 281 | ;; more info." 282 | ;; (let ((curr-buf-initial-state 283 | ;; (with-current-buffer "*outorg-test-buffer*" 284 | ;; (ert-Buf-from-buffer)))) 285 | ;; (should 286 | ;; (ert-equal-buffer-return-explain 287 | ;; (outorg-test-cmd) 288 | ;; curr-buf-initial-state 289 | ;; t nil)))) 290 | 291 | 292 | ;;; Run hooks and provide 293 | 294 | (provide 'outorg-test) 295 | 296 | ;;; outorg-test.el ends here 297 | -------------------------------------------------------------------------------- /outorg.el: -------------------------------------------------------------------------------- 1 | ;;; outorg.el --- Org-style comment editing 2 | 3 | ;; Maintainer: Adam Porter 4 | ;; Version: 2.1-pre 5 | ;; URL: https://github.com/alphapapa/outorg 6 | ;; Package-Requires: ((emacs "24.4")) 7 | 8 | ;;;; MetaData 9 | ;; :PROPERTIES: 10 | ;; :copyright: Thorsten Jolitz 11 | ;; :copyright-years: 2013+ 12 | ;; :version: 2.0 13 | ;; :licence: GPL 2 or later (free software) 14 | ;; :licence-url: http://www.gnu.org/licenses/ 15 | ;; :part-of-emacs: no 16 | ;; :maintainer: Adam Porter 17 | ;; :inspiration: org-src 18 | ;; :keywords: emacs org-mode comment-editing 19 | ;; :git-repo: https://github.com/alphapapa/outorg 20 | ;; :git-clone: git://github.com/alphapapa/outorg.git 21 | ;; :END: 22 | 23 | ;;;; Commentary 24 | ;;;;; About outorg 25 | 26 | ;; Outorg is for editing comment-sections of source-code files in 27 | ;; temporary Org-mode buffers. It turns conventional 28 | ;; literate-programming upside-down in that the default mode is the 29 | ;; programming-mode, and special action has to be taken to switch to the 30 | ;; text-mode (i.e. Org-mode). 31 | 32 | ;; Outorg depends on Outshine, i.e. outline-minor-mode with outshine 33 | ;; extensions activated. An outshine buffer is structured like an 34 | ;; org-mode buffer, only with outcommented headlines. While in 35 | ;; Org-mode text is text and source-code is 'hidden' inside of special 36 | ;; src-blocks, in an outshine buffer source-code is source-code and 37 | ;; text is 'hidden' as comments. 38 | 39 | ;; Thus org-mode and programming-mode are just two different views on 40 | ;; the outshine-style structured source-file, and outorg is the tool 41 | ;; to switch between these two views. When switching from a 42 | ;; programming-mode to org-mode, the comments are converted to text 43 | ;; and the source-code is put into src-blocks. When switching back 44 | ;; from org-mode to the programming-mode, the process is reversed - 45 | ;; the text is outcommented again and the src-blocks that enclose the 46 | ;; source-code are removed. 47 | 48 | ;; When the code is more important than the text, i.e. when the task 49 | ;; is rather 'literate PROGRAMMING' than 'LITERATE programming', it is 50 | ;; often more convenient to work in a programming-mode and switch to 51 | ;; org-mode once in a while than vice-versa. Outorg is really fast, 52 | ;; even big files with 10k lines are converted in a second or so, and 53 | ;; the user decides if he wants to convert just the current subtree 54 | ;; (done instantly) or the whole buffer. Since text needs no session 55 | ;; handling or variable passing or other special treatment, the outorg 56 | ;; approach is much simpler than the Org-Babel approach. However, the 57 | ;; full power of Org-Babel is available once the *outorg-edit-buffer* 58 | ;; has popped up. 59 | 60 | ;;;;; Usage 61 | 62 | ;; Outorg (like outshine) assumes that you set 63 | ;; `outline-minor-mode-prefix' in your init-file to 'M-#': 64 | 65 | ;; #+BEGIN_EXAMPLE 66 | ;; ;; must be set before outline is loaded 67 | ;; (defvar outline-minor-mode-prefix "\M-#") 68 | ;; #+END_EXAMPLE 69 | 70 | ;; Outorg's main command is 71 | 72 | ;; #+begin_example 73 | ;; M-# # (or M-x outorg-edit-as-org) 74 | ;; #+end_example 75 | 76 | ;; to be used in source-code buffers where `outline-minor-mode' is 77 | ;; activated with `outshine' extensions. The Org-mode edit-buffer popped 78 | ;; up by this command is called *outorg-edit-buffer* and has 79 | ;; `outorg-edit-minor-mode' activated, a minor-mode with only 2 commands: 80 | 81 | ;; #+begin_example 82 | ;; M-# (outorg-copy-edits-and-exit) 83 | ;; C-x C-s (outorg-save-edits-to-tmp-file) 84 | ;; #+end_example 85 | 86 | ;; If you want to insert Org-mode source-code or example blocks in 87 | ;; comment-sections, i.e. you don't want outorg to remove the 88 | ;; enclosing blocks, simply outcomment them in the outorg-edit buffer 89 | ;; before calling `outorg-copy-edits-and-exit'. 90 | 91 | ;; Note that outorg only treats 'active' src-blocks in a special way - 92 | ;; the blocks whose Babel language is equal to the major-mode of the 93 | ;; associated programming-mode buffer. All other (src-) blocks are 94 | ;; treated like normal text. 95 | 96 | ;; Note further that outorg uses example-blocks as 'fallback' when it 97 | ;; cannot find the major-mode of the programming-mode buffer in the 98 | ;; `org-babel-load-languages'. In this case you should not use 99 | ;; example-blocks for other tasks, since they will be removed when 100 | ;; exiting the *outorg-edit-buffer*, use e.g. quote-blocks or 101 | ;; verse-blocks instead. 102 | 103 | ;;;;; Installation 104 | 105 | ;; You can get outorg.el either from Github (see section MetaData) or 106 | ;; via MELPA. It depends on outshine.el, so you have to install and 107 | ;; configure outshine first to make outorg work. 108 | 109 | ;; Installation is easy, simply insert 110 | 111 | ;; #+begin_example 112 | ;; (require 'outorg) 113 | ;; #+end_example 114 | 115 | ;; in your init file. When you use navi-mode.el too, the third Outshine 116 | ;; library, it suffices to (require 'navi), since it requires the other 117 | ;; two libraries. 118 | 119 | ;;;;; Bugs and Shortcomings 120 | 121 | ;; Outorg started out purely line-based, it only worked with 122 | ;; 'one-line' comments, i.e. with comment-sections like those produced 123 | ;; by `comment-region' (a command that comments or uncomments each 124 | ;; line in the region). It was enhanced later on to recognize comment 125 | ;; regions too, i.e. those special multi-line comments found in many 126 | ;; programming languages. But using outorg on such multi-line comments 127 | ;; will probably change their syntax back to 'single-line', whenever 128 | ;; `comment-region' uses this style. 129 | 130 | ;;;;; Tests 131 | 132 | ;; A special kind of test has been developed for outorg using the 133 | ;; `ert-buffer' library, the so called 'conversion test'. It has the 134 | ;; following steps: 135 | 136 | ;; 1. programming-mode -> org-mode 137 | 138 | ;; 2. edit in org-mode, store undo-information 139 | 140 | ;; 3. org-mode -> programming-mode 141 | 142 | ;; 4. programming-mode -> org-mode (again) 143 | 144 | ;; 5. undo edits 145 | 146 | ;; 6. org-mode -> programming-mode (again) 147 | 148 | ;; After these 4 conversions, the original programming-mode buffer 149 | ;; must be unchanged when the conversion process is perfect, i.e. does 150 | ;; not introduce any changes itself. See `outorg-test.el' for details. 151 | 152 | ;;;;; Emacs Version 153 | 154 | ;; Outorg works with GNU Emacs 24.2.1 or later. No attempts of testing 155 | ;; with older versions or other types of Emacs have been made (yet). 156 | 157 | ;;;; ChangeLog 158 | 159 | ;; | date | author(s) | version | 160 | ;; |-----------------+-----------------+---------| 161 | ;; | <2014-09-20 Sa> | Thorsten Jolitz | 2.0 | 162 | ;; | <2013-05-03 Fr> | Thorsten Jolitz | 1.0 | 163 | ;; | <2013-02-11 Mo> | Thorsten Jolitz | 0.9 | 164 | 165 | ;;; Requires 166 | 167 | (require 'outline) 168 | (require 'org) 169 | (require 'org-watchdoc nil t) 170 | ;; (unless (require 'outorg-export nil t) 171 | ;; (message 172 | ;; "Try library `outorg-export' for automated export to all Org 173 | ;; backends:\n%s" 174 | ;; "https://github.com/jleechpe/outorg-export")) 175 | 176 | (declare-function R-mode "ess-r-d") 177 | (declare-function org-watchdoc-propagate-changes "org-watchdoc") 178 | (declare-function org-watchdoc-set-md5 "org-watchdoc") 179 | 180 | ;;; Mode and Exporter Definitions 181 | ;;;; Outorg Edit minor-mode 182 | 183 | (define-minor-mode outorg-edit-minor-mode 184 | "Minor mode for Org-mode buffers generated by outorg. 185 | There is a mode hook, and two commands: 186 | \\[outorg-copy-edits-and-exit] outorg-copy-edits-and-exit 187 | \\[outorg-save-edits-to-tmp-file] outorg-save-edits-to-tmp-file" 188 | :lighter " Outorg") 189 | 190 | ;;; Variables 191 | ;;;; Consts 192 | 193 | (defconst outorg-version "2.0" 194 | "outorg version number.") 195 | 196 | (defconst outorg-edit-buffer-name "*outorg-edit-buffer*" 197 | "Name of the temporary outorg edit buffer.") 198 | 199 | ;; FIXME org-babel names should be correct, but major-mode names need 200 | ;; to be cross-checked! 201 | (defconst outorg-language-name-assocs 202 | '((abc-mode . abc) 203 | (asymptote-mode . asymptote) 204 | (awk-mode . awk) 205 | (c-mode . C) ; 206 | (c++-mode . cpp) ; 207 | (calc-mode . calc) ; 208 | (clojure-mode . clojure) 209 | (css-mode . css) 210 | (d-mode . D) ; 211 | (ditaa-mode . ditaa) 212 | (dot-mode . dot) 213 | (emacs-lisp-mode . emacs-lisp) ; 214 | (eukleides-mode . eukleides) 215 | (fomus-mode . fomus) 216 | (fortran-mode . F90) 217 | (gnuplot-mode . gnuplot) 218 | (groovy-mode . groovy) 219 | (haskell-mode . haskell) 220 | (j-mode . J) 221 | (java-mode . java) 222 | (javascript-mode . js) 223 | (julia-mode . julia) 224 | (latex-mode . latex) ; 225 | (ledger-mode . ledger) 226 | (lilypond-mode . ly) 227 | (lisp-mode . lisp) 228 | (make-mode . makefile) 229 | (mathomatic-mode . mathomatic) 230 | (matlab-mode . matlab) 231 | (maxima-mode . max) 232 | (mscgen-mode . mscgen) 233 | (tuareg-mode . ocaml) ; 234 | (octave-mode . octave) 235 | (org-mode . org) ; 236 | (oz-mode . oz) 237 | (perl-mode . perl) 238 | (picolisp-mode . picolisp) ; 239 | (plantuml-mode . plantuml) 240 | (python-mode . python) 241 | (ess-mode . R) ; 242 | (ruby-mode . ruby) 243 | (sass-mode . sass) 244 | (scala-mode . scala) 245 | (scheme-mode . scheme) 246 | (shen-mode . shen) 247 | (sh-mode . sh) ; 248 | (sql-mode . sql) 249 | (sqlite-mode . sqlite) 250 | (tcl-mode . tcl)) 251 | "Associations between major-mode-name and org-babel language 252 | names.") 253 | 254 | (defconst outorg-tracked-markers '(point-marker 255 | beg-of-subtree-marker mark-marker) 256 | "Outorg markers to be tracked. The actual marker names are constructed by adding a prefix, either 'outorg-code-buffer-' or 'outorg-edit-buffer-'.") 257 | 258 | (defconst outorg-tracked-org-markers '(org-clock-marker 259 | org-clock-hd-marker org-clock-default-task 260 | org-clock-interrupted-task selected-task org-open-link-marker 261 | org-log-note-marker org-log-note-return-to 262 | org-entry-property-inherited-from) 263 | "Org markers to be tracked by outorg.") 264 | 265 | ;;;; Vars 266 | 267 | (defvar outline-minor-mode-prefix "\C-c" 268 | "New outline-minor-mode prefix.") 269 | 270 | (defvar outorg-edit-whole-buffer-p nil 271 | "Non-nil if the whole code-buffer is edited.") 272 | 273 | (defvar outorg-initial-window-config nil 274 | "Initial window-configuration when editing as Org.") 275 | 276 | (defvar outorg-code-buffer-read-only-p nil 277 | "Remember if code-buffer was read only before editing") 278 | 279 | ;; copied and adapted from ob-core.el 280 | (defvar outorg-temporary-directory) ; FIXME why this duplication? 281 | (unless (or noninteractive (boundp 'outorg-temporary-directory)) 282 | (defvar outorg-temporary-directory 283 | (or (and (boundp 'outorg-temporary-directory) 284 | (file-exists-p outorg-temporary-directory) 285 | outorg-temporary-directory) 286 | (make-temp-file "outorg-" t)) 287 | "Directory to hold outorg's temporary files. 288 | This directory will be removed on Emacs shutdown.")) 289 | 290 | (defvar outorg-last-temp-file nil 291 | "Storage for absolute file name of last saved temp-file.") 292 | 293 | (defvar outorg-called-via-outshine-use-outorg-p nil 294 | "Non-nil if outorg was called via `outshine-use-outorg' command") 295 | 296 | (defvar outorg-oldschool-elisp-headers-p nil 297 | "Non-nil if an Emacs Lisp file uses oldschool headers ';;;+'") 298 | 299 | (defvar outorg-insert-default-export-template-p nil 300 | "Non-nil means either the file specified in 301 | `outorg-export-template-for-org-mode' or a file given by the user 302 | will be inserted at the top of the *outorg-edit-buffer* when it 303 | is opened, and will be removed when it is closed, thus enabling 304 | the user to e.g. define default export options in a file and use 305 | them on-demand in the *outorg-edit-buffer*. The value of this variable is 306 | toggled with command `outorg-toggle-export-template-insertion'.") 307 | ;; (make-variable-buffer-local 'outorg-insert-default-export-template-p) 308 | 309 | (defvar outorg-ask-user-for-export-template-file-p nil 310 | "Non-nil means user is prompted for export-template-file.") 311 | ;; (make-variable-buffer-local 'outorg-ask-user-for-export-template-file-p) 312 | 313 | (defvar outorg-keep-export-template-p nil 314 | "Non-nil means inserted export template is permanent.") 315 | ;; (make-variable-buffer-local 'outorg-keep-export-template-p) 316 | 317 | (defvar outorg-export-template-regexp 318 | (concat 319 | "[[:space:]\n]*" 320 | "# <<<\\*\\*\\* BEGIN EXPORT TEMPLATE [[:ascii:]]+" 321 | "# <<<\\*\\*\\* END EXPORT TEMPLATE \\*\\*\\*>>>[^*]*") 322 | "Regexp used to identify (and delete) export templates.") 323 | 324 | (defvar outorg-propagate-changes-p nil 325 | "Non-nil means propagate changes to associated doc files.") 326 | ;; (make-variable-buffer-local 'outorg-propagate-changes-p) 327 | 328 | (defvar outorg-code-buffer-point-marker (make-marker) 329 | "Marker to store position in code-buffer.") 330 | 331 | (defvar outorg-edit-buffer-point-marker (make-marker) 332 | "Marker to store position in edit-buffer.") 333 | 334 | (defvar outorg-code-buffer-beg-of-subtree-marker (make-marker) 335 | "Marker to store begin of current subtree in 336 | code-buffer.") 337 | 338 | (defvar outorg-edit-buffer-beg-of-subtree-marker (make-marker) 339 | "Marker to store begin of current subtree in 340 | edit-buffer.") 341 | 342 | (defvar outorg-markers-to-move nil 343 | "Markers that should be moved with a cut-and-paste operation. 344 | Those markers are stored together with their positions relative to 345 | the start of the region.") 346 | 347 | (defvar outorg-org-finish-function-called-p nil 348 | "Non-nil if `org-finish-function' was called, nil otherwise.") 349 | 350 | (defvar outorg-beginning-of-comment (make-marker) 351 | "Marker for tracking beginning of comment. 352 | If pt-A < pt-B, the region between A and B is out- or 353 | uncommented.") 354 | 355 | (defvar outorg-beginning-of-code (make-marker) 356 | "Marker for tracking beginning of source code. 357 | If pt-B < pt-C, the region between B and C is wrapped/unwrapped 358 | as source-block.") 359 | 360 | (defvar outorg-end-of-code (make-marker) 361 | "Marker for tracking end of source code. 362 | If pt-B < pt-C, the region between B and C is wrapped/unwrapped 363 | as source-block.") 364 | 365 | ;; ;; pt-A 366 | ;; (defvar outorg-beg-comment-marker (make-marker) 367 | ;; "Outorg marker for tracking begin of comment.") 368 | 369 | ;; ;; pt-B 370 | ;; (defvar outorg-beg-src-marker (make-marker) 371 | ;; "Outorg marker for tracking beginning of source-code.") 372 | 373 | ;; ;; pt-C 374 | ;; (defvar outorg-end-src-marker (make-marker) 375 | ;; "Outorg marker for tracking end of source-code.") 376 | 377 | 378 | ;;;; Hooks 379 | 380 | (defvar outorg-hook nil 381 | "Functions to run after `outorg' is loaded.") 382 | 383 | (defvar outorg-edit-minor-mode-hook nil 384 | "Hook run after `outorg' switched a source code file or subtree to 385 | Org-mode.") 386 | 387 | ;;;; Customs 388 | 389 | ;;;;; Custom Groups 390 | 391 | (defgroup outorg nil 392 | "Library for outline navigation and Org-mode editing in Lisp buffers." 393 | :prefix "outorg-" 394 | :group 'lisp 395 | :link '(url-link 396 | "http://orgmode.org/worg/org-tutorials/org-outside-org.html")) 397 | 398 | ;;;;; Custom Vars 399 | 400 | ;; inspired by 'org-src.el' 401 | (defcustom outorg-edit-buffer-persistent-message t 402 | "Non-nil means show persistent exit help message while in edit-buffer. 403 | The message is shown in the header-line, which will be created in the 404 | first line of the window showing the editing buffer." 405 | :group 'outorg 406 | :type 'boolean) 407 | 408 | (defcustom outorg-unindent-active-source-blocks-p t 409 | "Non-nil means common indentation (e.g. 2 spaces) in the active 410 | source-blocks of the *outorg-edit-buffer* (i.e. those in the 411 | language of the associated source-code buffer, and only in those) 412 | is removed before converting back from Org to source-code." 413 | :group 'outorg 414 | :type 'boolean) 415 | 416 | ;;; Functions 417 | ;;;; Non-interactive Functions 418 | ;;;;; Get Buffer Mode and Language Name 419 | 420 | (defun outorg-comment-on-line () 421 | "Look forward from point for a comment at the start of this 422 | line. If found, move point to the beginning of the text after 423 | `comment-start' syntax, and return the location of the 424 | beginning of the line. If the line does not start with 425 | `comment-start', returns `nil'." 426 | (and (search-forward-regexp (concat "\\(" 427 | (regexp-quote comment-start) 428 | "[[:space:]]*\\)") 429 | (line-end-position) 430 | 1) 431 | (eq (match-beginning 0) (point-at-bol)) 432 | (point-at-bol))) 433 | 434 | (defun outorg-comment-on-line-p () 435 | "Determine if point is on a line that begins with a comment." 436 | (save-excursion 437 | (beginning-of-line) 438 | (outorg-comment-on-line))) 439 | 440 | (defun outorg-comment-search-forward () 441 | "Like `comment-search-forward', but looks only for comments 442 | beginning with `comment-start' syntax at the start of a 443 | line. Point is left at the beginning of the text after the line 444 | comment syntax, while the returned point is at the beginning of 445 | the line." 446 | (while (not (or (eobp) (outorg-comment-on-line))) (forward-line)) 447 | (point-at-bol)) 448 | 449 | ;; copied from http://www.emacswiki.org/emacs/basic-edit-toolkit.el 450 | (defun outorg-region-or-buffer-limits () 451 | "Return the start and end of the region as a list, smallest first. 452 | If the region is not active or empty, then bob and eob are used." 453 | (if (or 454 | (not mark-active) 455 | (null (mark)) 456 | (= (point) (mark))) 457 | (list (point-min) (point-max)) 458 | (if (< (point) (mark)) 459 | (list (point) (mark)) 460 | (list (mark) (point))))) 461 | 462 | (defun outorg-get-buffer-mode (&optional buf-or-strg as-strg-p) 463 | "Return major-mode of BUF-OR-STRG or current-buffer. 464 | 465 | If AS-STRG-P is non-nil, a string is returned instead instead 466 | of a symbol." 467 | (let ((buf (if buf-or-strg 468 | (get-buffer buf-or-strg) 469 | (current-buffer)))) 470 | (with-current-buffer buf 471 | (if as-strg-p (symbol-name major-mode) major-mode)))) 472 | 473 | (defun outorg-get-babel-name (&optional mode-name as-string) 474 | "Return the symbol associated in Org-Babel with MODE-NAME. 475 | 476 | Uses `outorg-language-name-assocs' as association list between 477 | the string returned by `major-mode' in the associated source-code 478 | buffer and the symbol used for that language in 479 | `org-babel-load-languages'. If AS-STRING is non-nil, a string is 480 | returned." 481 | (let* ((mmode (if mode-name 482 | (cond 483 | ((stringp mode-name) (intern mode-name)) 484 | ((symbolp mode-name) mode-name) 485 | (t (error "Mode-Name neither String nor Symbol"))) 486 | major-mode)) 487 | (bname (or (cdr (assoc mmode outorg-language-name-assocs)) 488 | ;; Not found in alist; just use major-mode name without "-mode" suffix 489 | (intern (replace-regexp-in-string "-mode$" "" (symbol-name mmode)))))) 490 | (if as-string 491 | (symbol-name bname) 492 | bname))) 493 | 494 | (defun outorg-get-mode-name (babel-name &optional as-strg-p) 495 | "Return the major-mode name associated with BABEL-NAME. 496 | 497 | Uses `outorg-language-name-assocs' as association list between 498 | the symbol returned by `major-mode' in the associated source-code 499 | buffer and the symbol used for that language in 500 | `org-babel-load-languages'. If AS-STRG-P is non-nil, a string 501 | is returned." 502 | (let* ((bname 503 | (cond 504 | ((stringp babel-name) (intern babel-name)) 505 | ((symbolp babel-name) babel-name) 506 | (t (error "Babel-Name neither String nor Symbol")))) 507 | (mmode 508 | (car 509 | (rassoc bname outorg-language-name-assocs)))) 510 | (if as-strg-p (symbol-name mmode) mmode))) 511 | 512 | (defun outorg-get-language-name (&optional mode-name as-sym-p) 513 | "Extract car of splitted and normalized MODE-NAME. 514 | 515 | If AS-SYM-P is non-nil, a symbol instead of a string is 516 | returned." 517 | (let* ((mmode (or 518 | (and mode-name 519 | (cond 520 | ((stringp mode-name) mode-name) 521 | ((symbolp mode-name) (symbol-name mode-name)) 522 | (t (error 523 | "Mode-Name neither String nor Symbol")))) 524 | (symbol-name major-mode))) 525 | (splitted-mmode 526 | (split-string mmode "-mode")) 527 | (language-name 528 | (if (> (length splitted-mmode) 1) 529 | (car splitted-mmode) 530 | (car (split-string mmode "\\."))))) 531 | (if as-sym-p (intern language-name) language-name))) 532 | 533 | (defun outorg-in-babel-load-languages-p (&optional mode-name) 534 | "Non-nil if MODE-NAME is in Org-Babel load languages. 535 | 536 | If MODE-NAME is nil, check if Org-Babel identifier of major-mode of current buffer is in Org-Babel load languages." 537 | (let* ((mmode (or 538 | (and mode-name 539 | (cond 540 | ((stringp mode-name) (intern mode-name)) 541 | ((symbolp mode-name) mode-name) 542 | (t (error 543 | "Mode-Name neither String nor Symbol")))) 544 | major-mode))) 545 | (assoc 546 | ;; Note that babel's cpp (for C++) is packaged in ob-C with the C 547 | ;; language 548 | (let ((bname (outorg-get-babel-name mmode))) 549 | (if (eq bname (intern "cpp")) (intern "C") bname)) 550 | org-babel-load-languages))) 551 | 552 | 553 | ;;;;; Configure Edit Buffer 554 | 555 | ;; copied and adapted from org-src.el 556 | (defun outorg-edit-configure-buffer () 557 | "Configure edit buffer" 558 | (let ((msg 559 | (concat "[ " 560 | (buffer-name 561 | (marker-buffer outorg-code-buffer-point-marker)) 562 | " ] " 563 | (substitute-command-keys "Exit with \\[outorg-copy-edits-and-exit]")))) 564 | 565 | ;; Only run the kill-buffer-hooks when the outorg edit buffer is 566 | ;; being killed. This is because temporary buffers may be created 567 | ;; by various org commands, and when those buffers are killed, we 568 | ;; do not want the outorg kill hooks to run. 569 | (org-add-hook 'kill-buffer-hook 570 | (lambda () 571 | (when (string= (buffer-name) outorg-edit-buffer-name) 572 | (outorg-save-edits-to-tmp-file))) 573 | nil 'local) 574 | 575 | (org-add-hook 'kill-buffer-hook 576 | (lambda () 577 | (when (string= (buffer-name) outorg-edit-buffer-name) 578 | (outorg-reset-global-vars)) nil 'local)) 579 | 580 | 581 | ;; (setq buffer-offer-save t) 582 | (and outorg-edit-buffer-persistent-message 583 | (setq-local header-line-format msg)) 584 | ;; (setq buffer-file-name 585 | ;; (concat (buffer-file-name 586 | ;; (marker-buffer outorg-code-buffer-point-marker)) 587 | ;; "[" (buffer-name) "]")) 588 | (if (featurep 'xemacs) 589 | (progn 590 | (make-variable-buffer-local 591 | 'write-contents-hooks) ; needed only for 21.4 592 | (setq write-contents-hooks 593 | '(outorg-save-edits-to-tmp-file))) 594 | (setq write-contents-functions 595 | '(outorg-save-edits-to-tmp-file))) 596 | ;; (setq buffer-read-only t) ; why? 597 | )) 598 | 599 | 600 | ;; (org-add-hook 'outorg-edit-minor-mode-hook 'outorg-edit-minor-mode) 601 | (org-add-hook 'outorg-edit-minor-mode-hook 602 | 'outorg-edit-configure-buffer) 603 | 604 | ;;;;; Backup Edit Buffer 605 | 606 | ;; copied and adapted from ob-core.el 607 | (defun outorg-temp-file (prefix &optional suffix) 608 | "Create a temporary file in the `outorg-temporary-directory'. 609 | Passes PREFIX and SUFFIX directly to `make-temp-file' with the 610 | value of `temporary-file-directory' temporarily set to the value 611 | of `outorg-temporary-directory'." 612 | (let ((temporary-file-directory 613 | (if (file-remote-p default-directory) 614 | (concat (file-remote-p default-directory) "/tmp") 615 | (or (and (boundp 'outorg-temporary-directory) 616 | (file-exists-p outorg-temporary-directory) 617 | outorg-temporary-directory) 618 | temporary-file-directory)))) 619 | (make-temp-file prefix nil suffix))) 620 | 621 | (defun outorg-save-edits-to-tmp-file () 622 | "Save edit-buffer in temporary file" 623 | (interactive) 624 | (let* ((code-file (file-name-sans-extension 625 | (file-name-nondirectory 626 | (buffer-name 627 | (marker-buffer 628 | outorg-code-buffer-point-marker))))) 629 | (tmp-file (outorg-temp-file code-file)) 630 | (tmp-dir (file-name-directory tmp-file))) 631 | (setq outorg-last-temp-file tmp-file) 632 | (setq buffer-file-name (concat tmp-dir "outorg-edit-" code-file)) 633 | (write-region nil nil tmp-file nil 'VISIT))) 634 | 635 | ;; copied and adapted from ob-core.el 636 | (defun outorg-remove-temporary-directory () 637 | "Remove `outorg-temporary-directory' on Emacs shutdown." 638 | (when (and (boundp 'outorg-temporary-directory) 639 | (file-exists-p outorg-temporary-directory)) 640 | ;; taken from `delete-directory' in files.el 641 | (condition-case nil 642 | (progn 643 | (mapc (lambda (file) 644 | ;; This test is equivalent to 645 | ;; (and (file-directory-p fn) (not (file-symlink-p fn))) 646 | ;; but more efficient 647 | (if (eq t (car (file-attributes file))) 648 | (delete-directory file) 649 | (delete-file file))) 650 | ;; We do not want to delete "." and "..". 651 | (directory-files outorg-temporary-directory 'full 652 | "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")) 653 | (delete-directory outorg-temporary-directory)) 654 | (error 655 | (message "Failed to remove temporary outorg directory %s" 656 | (if (boundp 'outorg-temporary-directory) 657 | outorg-temporary-directory 658 | "[directory not defined]")))))) 659 | 660 | (add-hook 'kill-emacs-hook 'outorg-remove-temporary-directory) 661 | 662 | ;;;;; Reset Global Vars 663 | 664 | ;; TODO better use buffer-local variables instead? 665 | (defun outorg-reset-global-vars () 666 | "Reset some global vars defined by outorg to initial values." 667 | (ignore-errors 668 | (set-marker outorg-code-buffer-point-marker nil) 669 | (set-marker outorg-code-buffer-beg-of-subtree-marker nil) 670 | (set-marker outorg-edit-buffer-point-marker nil) 671 | (set-marker outorg-edit-buffer-beg-of-subtree-marker nil) 672 | (setq outorg-edit-whole-buffer-p nil) 673 | (setq outorg-initial-window-config nil) 674 | (setq outorg-code-buffer-read-only-p nil) 675 | (setq outorg-oldschool-elisp-headers-p nil) 676 | (setq outorg-insert-default-export-template-p nil) 677 | (setq outorg-ask-user-for-export-template-file-p nil) 678 | (setq outorg-keep-export-template-p nil) 679 | (setq outorg-propagate-changes-p nil) 680 | (setq outorg-called-via-outshine-use-outorg-p nil) 681 | (when outorg-markers-to-move 682 | (mapc (lambda (m) 683 | (when (markerp m) 684 | (move-marker m nil))) 685 | outorg-markers-to-move) 686 | (setq outorg-markers-to-move nil)) 687 | (setq outorg-org-finish-function-called-p nil))) 688 | 689 | ;;;;; Remove Trailing Blank Lines 690 | 691 | ;; inspired by `article-remove-trailing-blank-lines' in `gnus-art.el' 692 | (defun outorg-remove-trailing-blank-lines () 693 | "Remove all trailing blank lines from buffer. 694 | Finally add one newline." 695 | (save-excursion 696 | (let ((inhibit-read-only t)) 697 | (goto-char (point-max)) 698 | (delete-region 699 | (point) 700 | (progn 701 | (while (and (not (bobp)) 702 | (looking-at "^[ \t]*$")) 703 | (forward-line -1)) 704 | (forward-line 1) 705 | (point)))))) 706 | 707 | ;;;;; Save and Restore Markers 708 | 709 | ;; 1. Deal with position markers in code and edit buffer, to get the 710 | ;; least possible surprise about point position after switching 711 | ;; buffers 712 | 713 | ;; 2. Deal with org markers set in the edit buffer and needed in 714 | ;; after command hooks when edit buffer is already closed 715 | 716 | (defun outorg-save-markers (markers) 717 | "Save MARKERS in `outorg-markers-to-move'." 718 | (save-restriction 719 | (widen) 720 | (let* ((beg (if (or outorg-edit-whole-buffer-p 721 | (equal (buffer-name) outorg-edit-buffer-name)) 722 | (point-min) 723 | (if (outline-on-heading-p) 724 | (point) 725 | (save-excursion 726 | (outline-previous-heading) 727 | (point))))) 728 | (end (if (or outorg-edit-whole-buffer-p 729 | (equal (buffer-name) outorg-edit-buffer-name)) 730 | (point-max) 731 | (save-excursion 732 | (outline-end-of-subtree) 733 | (point)))) 734 | (prefix (cond ((eq (current-buffer) (marker-buffer outorg-code-buffer-point-marker)) 735 | "outorg-code-buffer-") 736 | ((eq (current-buffer) (marker-buffer outorg-edit-buffer-point-marker)) 737 | "outorg-edit-buffer-") 738 | (t (error "This should not happen")))) 739 | (markers (mapcar (lambda (marker) 740 | (intern (format "%s%s" 741 | (if (string-match "\\(org\\|mark\\)" 742 | (car (split-string (symbol-name marker) "-" t))) 743 | "" 744 | prefix) 745 | marker))) 746 | markers))) 747 | (mapc (lambda (marker) 748 | (outorg-check-and-save-marker marker beg end)) 749 | markers)))) 750 | 751 | ;; adapted from org.el 752 | (defun outorg-check-and-save-marker (marker-or-var beg end) 753 | "Check if MARKER-OR-VAR is between BEG and END. 754 | If yes, remember the marker and the distance to BEG." 755 | (let ((marker (cond 756 | ((markerp marker-or-var) marker-or-var) 757 | ((boundp marker-or-var) (eval marker-or-var)) 758 | (t nil)))) 759 | (when (and (markerp marker) 760 | (marker-buffer marker) 761 | (equal (marker-buffer marker) (current-buffer))) 762 | (when (and (>= marker beg) (< marker end)) 763 | (let* ((splitted-marker-name 764 | (split-string 765 | (symbol-name marker-or-var) 766 | "\\(outorg-\\|-buffer-\\)" t)) 767 | (split-gt-1-p (> (length splitted-marker-name) 1)) 768 | (marker-buf 769 | (ignore-errors 770 | (when split-gt-1-p 771 | (intern (car splitted-marker-name))))) 772 | (marker-typ 773 | (ignore-errors 774 | (if split-gt-1-p 775 | (intern (cadr splitted-marker-name)) 776 | (intern (car splitted-marker-name)))))) 777 | (push (list marker-buf marker-typ (- marker beg)) 778 | outorg-markers-to-move)))))) 779 | 780 | (defun outorg-reinstall-markers-in-region (beg) 781 | "Move all remembered markers to their position relative to BEG." 782 | (mapc (lambda (--marker-lst) 783 | (move-marker 784 | (eval 785 | (intern 786 | (format "%s%s" 787 | (cond 788 | ((eq (car --marker-lst) 'code) 789 | "outorg-edit-buffer-") 790 | ((eq (car --marker-lst) 'edit) 791 | "outorg-code-buffer-") 792 | ((and (booleanp (car --marker-lst)) 793 | (null (car --marker-lst))) 794 | "") 795 | (t (error "This should not happen."))) 796 | (cadr --marker-lst)))) 797 | (+ beg (caddr --marker-lst)))) 798 | outorg-markers-to-move) 799 | (setq outorg-markers-to-move nil)) 800 | 801 | ;;;;; Copy and Convert 802 | 803 | (defun outorg-convert-org-to-outshine 804 | (&optional mode infile outfile BATCH) 805 | "Convert an existing Org-mode file into an Outshine buffer. 806 | 807 | If MODE is non-nil, the Outshine buffer will be put in this 808 | major-mode, otherwise the major-mode of the language of the first 809 | source-code block in the Org-mode buffer will be used. 810 | 811 | If INFILE is non-nil, the specified Org-mode file will be 812 | visited, otherwise the current buffer will be used (i.e. the 813 | buffer content will be copied to a temporary *outorg-edit-buffer* 814 | for further processing). 815 | 816 | If OUTFILE is non-nil, the converted Outshine buffer will be 817 | saved in this file. Its the user's responsability to make sure 818 | that OUTFILE's file-extension is suited for the major-mode of the 819 | Outshine buffer to be saved. When in doubt, consult variable 820 | `auto-mode-alist' for associations between file-extensions and 821 | major-modes. 822 | 823 | If BATCH is non-nil (and OUTFILE is non-nil, otherwise it makes 824 | no sense), the new Outshine file is saved and its buffer 825 | deleted." 826 | (let* ((org-buffer (if infile 827 | (if (and (file-exists-p infile) 828 | (string-equal 829 | (file-name-extension infile) "org")) 830 | (find-file (expand-file-name infile)) 831 | (error 832 | "Infile doesn't exist or is not an Org file")) 833 | (current-buffer))) 834 | (maj-mode (or mode 835 | (with-current-buffer org-buffer 836 | (save-excursion 837 | (goto-char (point-min)) 838 | (or 839 | ;; major-mode of first src-block 840 | (ignore-errors 841 | (org-next-block 842 | nil nil org-babel-src-block-regexp) 843 | (format 844 | "%s-mode" 845 | (car (org-babel-get-src-block-info 'LIGHT)))) 846 | ;; default case emacs-lisp-mode 847 | "emacs-lisp-mode")))))) 848 | (with-current-buffer (get-buffer-create 849 | (generate-new-buffer-name "tmp")) 850 | (setq outorg-code-buffer-point-marker (point-marker)) 851 | (funcall (intern maj-mode)) 852 | (and outfile 853 | ;; ;; FIXME does not really avoid confirmation prompts 854 | ;; (add-to-list 'revert-without-query (expand-file-name outfile)) 855 | (if BATCH 856 | (write-file (expand-file-name outfile)) 857 | (write-file (expand-file-name outfile) 'CONFIRM)))) 858 | (setq outorg-edit-whole-buffer-p t) 859 | (setq outorg-initial-window-config 860 | (current-window-configuration)) 861 | (with-current-buffer (get-buffer-create outorg-edit-buffer-name) 862 | (erase-buffer) 863 | (insert-buffer-substring org-buffer) 864 | (org-mode) 865 | (outorg-transform-active-source-block-headers) 866 | (outorg-copy-edits-and-exit)) 867 | ;; ;; FIXME ugly hack 868 | ;; (funcall major-mode) 869 | ;; (funcall major-mode) 870 | ;; (fontify-keywords) 871 | (when outfile 872 | (save-buffer) 873 | ;; (revert-buffer t t) 874 | ;; (remove 875 | ;; (expand-file-name outfile) 876 | ;; revert-without-query) 877 | (and BATCH (kill-buffer))))) 878 | 879 | (defun outorg-transform-active-source-block-headers () 880 | "Move switches and arguments on top of block. 881 | 882 | This functions transforms all active source-blocks, i.e. those 883 | with the associated source-code buffer's major-mode as 884 | language. If there are switches and header arguments after the 885 | language specification on the #+BEGIN_SRC line, they are moved on 886 | top of the block. 887 | 888 | The idea behind this function is that it should be possible to 889 | specify permanent switches and arguments even for source-code 890 | blocks that are transformed back to code after 891 | `outorg-copy-and-switch' is called. They will remain as comment 892 | lines directly over their code section in the source-code buffer, 893 | and thus be transformed to text - and thereby activated - 894 | everytime `outorg-edit-as-org' is called." 895 | (save-excursion 896 | (let* ((mode (outorg-get-buffer-mode 897 | (marker-buffer outorg-code-buffer-point-marker))) 898 | (active-lang 899 | (outorg-get-babel-name mode 'as-strg-p))) 900 | (org-babel-map-src-blocks nil 901 | (when (string-equal active-lang lang) 902 | (let ((sw switches) 903 | (args header-args)) 904 | (goto-char end-lang) 905 | (delete-region (point) (line-end-position)) 906 | (goto-char beg-block) 907 | (forward-line -1) 908 | (when (org-string-nw-p sw) 909 | (newline) 910 | (insert (format "#+header: %s" sw))) 911 | (when (org-string-nw-p args) 912 | (let ((params 913 | (ignore-errors 914 | (org-split-string args))) 915 | headers) 916 | (while params 917 | (setq headers 918 | (cons 919 | (format "#+header: %s %s" 920 | (org-no-properties (pop params)) 921 | (org-no-properties (pop params))) 922 | headers))) 923 | (newline) 924 | (insert (mapconcat 'identity headers "\n")))))))))) 925 | ;; (insert (format "#+header: %s" args))))))))) 926 | 927 | ;; Thx to Eric Abrahamsen for the tip about `mail-header-separator' 928 | (defun outorg-prepare-message-mode-buffer-for-editing () 929 | "Prepare an unsent-mail in a message-mode buffer for outorg. 930 | 931 | This function assumes that '--text follows this line--' (or 932 | whatever is found inside variable `mail-header-separator') is the 933 | first line below the message header, is always present, and never 934 | modified by the user. It turns this line into an `outshine' 935 | headline and out-comments all text below this line - if any." 936 | (goto-char (point-min)) 937 | ;; (re-search-forward "--text follows this line--" nil 'NOERROR) 938 | (re-search-forward mail-header-separator nil 'NOERROR) 939 | (let ((inhibit-read-only t)) 940 | (replace-match "* \\&")) 941 | ;; (replace-match "* \\&") 942 | (beginning-of-line) 943 | (let ((start-body (point))) 944 | (comment-region start-body (point-max)) 945 | (narrow-to-region start-body (point-max)) 946 | (forward-line))) 947 | 948 | (defun outorg-prepare-message-mode-buffer-for-sending () 949 | "Prepare an unsent-mail edited via `outorg-edit' for sending. 950 | 951 | This function assumes that '* --text follows this line--' is the 952 | first line below the message header and is, like all lines below 953 | it, out-commented with `comment-region'. It deletes the leading 954 | star and uncomments the line and all text below it - if any." 955 | (save-excursion 956 | (goto-char (point-min)) 957 | (re-search-forward 958 | (concat 959 | "\\(" (regexp-quote "* ") "\\)" 960 | "--text follows this line--") 961 | nil 'NOERROR) 962 | (replace-match "" nil nil nil 1) 963 | (beginning-of-line) 964 | (let ((start-body (point))) 965 | (uncomment-region start-body (point-max)) 966 | (widen)))) 967 | 968 | (defun outorg-prepare-iorg-edit-buffer-for-editing () 969 | "Prepare a buffer opened with `edit' from iorg-scrape for outorg. 970 | 971 | This function assumes that a PicoLisp symbol that contains the 972 | text of an Org-mode file (fetched from an iOrg application) has 973 | been loaded into a PicoLisp `edit' buffer. It transforms the 974 | buffer content to a `outshine' compatible format, such that 975 | `outorg-edit-as-org' can be applied on it. 976 | 977 | In particular, this function assumes that the original `edit' 978 | buffer has the following format 979 | 980 | ;; #+begin_quote 981 | txt \"\" 982 | 983 | \(********\) 984 | ;; #+end_quote 985 | 986 | and that the text must be transformed to a format that looks 987 | somehow like this 988 | 989 | ;; #+begin_quote 990 | ## #+DESCRIPTION txt 991 | 992 | \[## #+\] 993 | 994 | ## * Org-file 995 | ## Content 996 | 997 | \(********\) 998 | ;; #+end_quote 999 | 1000 | i.e. the symbol-name 'txt' is converted to a #+DESCRIPTION keyword 1001 | and is followed by the (expanded and unquoted) content of the Org 1002 | file. This whole section of the buffer is outcommented with 1003 | picolisp-mode comment syntax. Finally, at the end of the buffer 1004 | the '\(********\)' line is left as-is." 1005 | (goto-char (point-min)) 1006 | (insert "#+DESCRIPTION: ") 1007 | (re-search-forward "\\(\"\\|NIL\\)" nil 'NOERROR) 1008 | (if (string-equal (match-string-no-properties 0) "NIL") 1009 | (progn 1010 | (backward-word) 1011 | (newline 2) 1012 | (looking-at "NIL") 1013 | (replace-match "*
" 'FIXEDCASE 'LITERAL)) 1014 | (replace-match "") 1015 | (newline 2)) 1016 | (goto-char (point-max)) 1017 | (re-search-backward "[^*)(\n\t\s]" nil 'NOERROR) 1018 | (if (string-equal (match-string-no-properties 0) "\"") 1019 | (replace-match "") 1020 | (forward-char)) 1021 | (newline) 1022 | (let ((end-body (point)) 1023 | (start-body (point-min))) 1024 | (save-excursion 1025 | (goto-char start-body) 1026 | (while (search-forward "^J" end-body t) 1027 | (replace-match "\n" nil t))) 1028 | ;; (replace-string "^J" "\n" nil start-body end-body) 1029 | (goto-char (point-min)) 1030 | (re-search-forward 1031 | (concat "(" (regexp-quote "********") ")") nil 'NOERROR) 1032 | (forward-line -1) 1033 | (setq end-body (point)) 1034 | (comment-region start-body end-body))) 1035 | 1036 | (defun outorg-prepare-iorg-edit-buffer-for-posting () 1037 | "Prepare an `edit' buffer for posting via iorg-scrape. 1038 | 1039 | This function assumes that a PicoLisp symbol that contains the 1040 | text of an Org-mode file (fetched from an iOrg application) has 1041 | been edited with outorg and converted back to PicoLisp. It 1042 | transforms the `edit' buffer content back to its original format, 1043 | such that it can be posted back to the PicoLisp system by closing 1044 | the emacsclient (via the protocol defined in `eedit.l'). 1045 | 1046 | In particular, this function assumes that the original `edit' 1047 | buffer had the following format 1048 | 1049 | ;; #+begin_quote 1050 | txt \"\" 1051 | 1052 | \(********\) 1053 | ;; #+end_quote 1054 | 1055 | and that the actual text that has to be transformed back to this 1056 | format looks somehow like this 1057 | 1058 | ;; #+begin_quote 1059 | ## #+DESCRIPTION txt 1060 | 1061 | \[## #+\] 1062 | 1063 | ## * Org-file 1064 | ## Content 1065 | 1066 | \(********\) 1067 | ;; #+end_quote 1068 | 1069 | i.e. the symbol-name 'txt' has been converted to a #+DESCRIPTION 1070 | keyword and is followed by the (expanded and unquoted) content of 1071 | the Org file. This whole section of the buffer is outcommented 1072 | with picolisp-mode comment syntax. Finally, at the end of the 1073 | buffer the '\(********\)' line is found again." 1074 | (let ((final-line 1075 | (concat "(" (regexp-quote "********") ")"))) 1076 | (uncomment-region (point-min) (point-max)) 1077 | (goto-char (point-min)) 1078 | (re-search-forward (regexp-quote "#+DESCRIPTION: ") nil 'NOERROR) 1079 | (replace-match "") 1080 | (end-of-line) 1081 | (let ((show-trailing-whitespace nil)) 1082 | (kill-line 2)) 1083 | (insert "\"") 1084 | (re-search-forward final-line nil 'NOERROR) 1085 | (beginning-of-line) 1086 | (re-search-backward "[[:alnum:][:punct:]]" nil 'NOERROR) 1087 | (forward-char) 1088 | (insert "\"") 1089 | (kill-line) 1090 | (save-excursion 1091 | (let ((pt (point))) 1092 | (goto-char (point-min)) 1093 | (while (search-forward "^J" pt t) 1094 | (replace-match "\n" nil t)))) 1095 | ;; (replace-string "\n" "^J" nil (point-min) (point)) 1096 | (goto-char (point-min)) 1097 | (when (looking-at 1098 | (concat "\\(^.*\\)" 1099 | "\\(\"\\*
\"\\)" 1100 | "\\([\s\t\n]+" final-line "\\)")) 1101 | (replace-match (format "%s" "NIL") nil nil nil 2) 1102 | ;; (kill-line) 1103 | ))) 1104 | 1105 | (defun outorg-convert-oldschool-elisp-buffer-to-outshine () 1106 | "Transform oldschool elisp buffer to outshine. 1107 | In `emacs-lisp-mode', transform an oldschool buffer (only 1108 | semicolons as outline-regexp) into an outshine buffer (with 1109 | outcommented org-mode headers)." 1110 | (save-excursion 1111 | (goto-char (point-min)) 1112 | (when (outline-on-heading-p) 1113 | (outorg-convert-oldschool-elisp-headline-to-outshine)) 1114 | (while (not (eobp)) 1115 | (outline-next-heading) 1116 | (outorg-convert-oldschool-elisp-headline-to-outshine))) 1117 | (funcall 'outshine-hook-function)) 1118 | 1119 | (defun outorg-convert-oldschool-elisp-headline-to-outshine () 1120 | "Transform oldschool headline to outshine. 1121 | In `emacs-lisp-mode', transform one oldschool header (only semicolons) into an outshine header (outcommented org-mode header)." 1122 | (unless (bolp) (beginning-of-line)) 1123 | (when (looking-at "^;;[;]+ ") 1124 | (let* ((header-level 1125 | (- (length (match-string-no-properties 0)) 3)) 1126 | (replacement-string 1127 | (concat 1128 | ";; " 1129 | (let ((strg "*")) 1130 | (dotimes (i (1- header-level) strg) 1131 | (setq strg (concat strg "*")))) 1132 | " "))) 1133 | (replace-match replacement-string)))) 1134 | 1135 | (defun outorg-copy-and-convert () 1136 | "Copy code buffer content to temp buffer and convert it to Org syntax. 1137 | If `outorg-edit-whole-buffer' is non-nil, copy the whole buffer, 1138 | otherwise the current subtree." 1139 | 1140 | (when (buffer-live-p (get-buffer outorg-edit-buffer-name)) 1141 | (if (y-or-n-p (format "%s exists - save and overwrite contents " outorg-edit-buffer-name)) 1142 | (with-current-buffer outorg-edit-buffer-name 1143 | (outorg-save-edits-to-tmp-file)) 1144 | (user-error "Edit as Org cancelled."))) 1145 | 1146 | (let* ((edit-buffer (get-buffer-create outorg-edit-buffer-name))) 1147 | (save-restriction 1148 | 1149 | ;; Erase edit-buffer 1150 | (with-current-buffer edit-buffer 1151 | (erase-buffer)) 1152 | 1153 | ;; Copy code buffer content 1154 | (copy-to-buffer edit-buffer 1155 | (if outorg-edit-whole-buffer-p 1156 | (point-min) 1157 | (save-excursion 1158 | (outline-back-to-heading 'INVISIBLE-OK) 1159 | (point))) 1160 | (if outorg-edit-whole-buffer-p 1161 | (point-max) 1162 | (save-excursion 1163 | (outline-end-of-subtree) 1164 | (point))))) 1165 | 1166 | ;; Switch to edit buffer 1167 | (when (one-window-p) 1168 | (split-window-sensibly (get-buffer-window))) 1169 | (switch-to-buffer-other-window edit-buffer) 1170 | 1171 | ;; Reinstall outorg-markers 1172 | (outorg-reinstall-markers-in-region (point-min)) 1173 | 1174 | ;; Set point 1175 | (goto-char outorg-edit-buffer-point-marker) 1176 | 1177 | ;; Activate programming language major mode and convert to org 1178 | (let ((mode (outorg-get-buffer-mode (marker-buffer outorg-code-buffer-point-marker)))) 1179 | ;; Special case R-mode 1180 | (if (eq mode 'ess-mode) 1181 | (funcall 'R-mode) 1182 | (funcall mode))) 1183 | 1184 | ;; Convert oldschool elisp headers to outshine headers 1185 | (when outorg-oldschool-elisp-headers-p 1186 | (outorg-convert-oldschool-elisp-buffer-to-outshine) 1187 | ;; Reset var to original state after conversion 1188 | (setq outorg-oldschool-elisp-headers-p t)) 1189 | 1190 | ;; Call conversion function 1191 | (outorg-convert-to-org) 1192 | 1193 | ;; Change major mode to org-mode 1194 | (org-mode) 1195 | 1196 | ;; Activate minor mode outorg-edit-minor-mode 1197 | (outorg-edit-minor-mode) 1198 | 1199 | ;; Set outline visibility 1200 | (if (not outorg-edit-whole-buffer-p) 1201 | (show-all) 1202 | (hide-sublevels 3) 1203 | (ignore-errors (show-subtree)) 1204 | 1205 | ;; Insert export template 1206 | (cond (outorg-ask-user-for-export-template-file-p 1207 | (call-interactively 'outorg-insert-export-template-file)) 1208 | (outorg-insert-default-export-template-p 1209 | (outorg-insert-default-export-template)))) 1210 | 1211 | ;; Update md5 for watchdoc 1212 | (when (and outorg-propagate-changes-p 1213 | (require 'org-watchdoc nil t)) 1214 | (org-watchdoc-set-md5)) 1215 | 1216 | ;; Reset buffer-undo-list 1217 | (setq buffer-undo-list nil))) 1218 | 1219 | (defun outorg-wrap-source-in-block (lang &optional example-block-p) 1220 | "Wrap code between in src-block of LANG. 1221 | If EXAMPLE-BLOCK-P is non-nil, use an example-block instead of a 1222 | source-block. Use `outorg-beginning-of-code' and 1223 | `outorg-end-of-code' to find start and end position of block." 1224 | (save-excursion 1225 | ;; Begin of block 1226 | (goto-char outorg-beginning-of-code) 1227 | 1228 | ;; Display blank line between text and block 1229 | (overlay-put (make-overlay (1- (point)) (1- (point))) 1230 | 'before-string "\n") 1231 | 1232 | (newline) 1233 | (forward-line -1) 1234 | (insert (if example-block-p 1235 | "#+begin_example" 1236 | (format "#+begin_src %s" lang))) 1237 | (move-marker outorg-beginning-of-code (point-at-bol)) 1238 | ;; End of block 1239 | (goto-char outorg-end-of-code) 1240 | (newline) 1241 | (insert (if example-block-p 1242 | "#+end_example" 1243 | "#+end_src")))) 1244 | 1245 | ;; We treat nestable comments as code. This is the fourth field of the 1246 | ;; parser state vector: it is `t' if in a non-nestable comment, or the 1247 | ;; comment nesting level if inside a comment that can be nested. 1248 | 1249 | (defun skip-line-comment-or-ws () 1250 | "If the current line is a comment or whitespace, move to the 1251 | next line and return `t'. Otherwise, leaves point alone and 1252 | returns `nil'." 1253 | (cond 1254 | ((looking-at "[[:space:]]*$") (forward-line)) 1255 | ((outorg-comment-on-line-p) (forward-line)) 1256 | (t nil))) 1257 | 1258 | ;; Note: this behavior is slightly different than `forward-comment': 1259 | ;; it leaves point at the beginning of the line that is not a line 1260 | ;; comment or white space, not at the actual first character of code 1261 | ;; on the line. 1262 | (defun forward-line-comments () 1263 | "Move forward across comments. Stop scanning if we find 1264 | something other than a comment or white space. Set point to where 1265 | scanning stops." 1266 | (while (and (not (eobp)) (skip-line-comment-or-ws)))) 1267 | 1268 | (defun backward-line-comments () 1269 | "Move backward across comments. Stop scanning if we find 1270 | something other than a comment or white space. Point is left at 1271 | the end of the first line found to not be a line comment or white 1272 | space." 1273 | (while (and (not (bobp)) (save-excursion (skip-line-comment-or-ws)) (forward-line -1))) 1274 | (end-of-line)) 1275 | 1276 | (defun outorg-convert-to-org () 1277 | "Convert buffer content to Org Syntax" 1278 | (let* ((buffer-mode (outorg-get-buffer-mode (marker-buffer outorg-code-buffer-point-marker))) 1279 | (babel-lang (outorg-get-babel-name buffer-mode)) 1280 | (example-block-p (and (not (outorg-in-babel-load-languages-p buffer-mode)) 1281 | (not babel-lang)))) 1282 | 1283 | (outorg-remove-trailing-blank-lines) 1284 | 1285 | ;; Reset (left-over) markers 1286 | (move-marker outorg-beginning-of-comment nil) 1287 | (move-marker outorg-beginning-of-code nil) 1288 | (move-marker outorg-end-of-code nil) 1289 | 1290 | (save-excursion 1291 | (goto-char (point-min)) 1292 | (unless (outorg-comment-on-line-p) 1293 | ;; Special case beginning of buffer 1294 | ;; Buffer begins with code 1295 | ;; Mark beginning of code 1296 | (move-marker outorg-beginning-of-code (progn 1297 | (forward-line-comments) 1298 | (point)))) 1299 | (while (and (< (point) (point-max)) 1300 | (marker-position (move-marker outorg-beginning-of-comment (outorg-comment-search-forward)))) ; Mark beginning of comment 1301 | ;; Loop over rest of buffer 1302 | (goto-char outorg-beginning-of-comment) 1303 | (if (or (not 1304 | ;; Comment does not start at BOL -> skip 1305 | (eq (marker-position outorg-beginning-of-comment) 1306 | (point-at-bol))) 1307 | ;; Looking at src-block delimiter -> skip 1308 | (looking-at "^#\\+begin_") 1309 | (looking-at "^#\\+end_")) 1310 | (forward-line) 1311 | 1312 | ;; Comments starts at BOL -> convert 1313 | (if (marker-position outorg-beginning-of-code) 1314 | ;; Special case buffer begins with code 1315 | (move-marker outorg-end-of-code (progn 1316 | (beginning-of-line) 1317 | (backward-line-comments) 1318 | (point))) 1319 | ;; Default case buffer begins with comments 1320 | ;; Mark beginning of code 1321 | (move-marker outorg-beginning-of-code (progn 1322 | ;; Skip forward comments and whitespace 1323 | (forward-line-comments) 1324 | (point))) 1325 | ;; Mark end of code 1326 | (move-marker outorg-end-of-code (progn 1327 | ;; Search next comment (starting at bol) 1328 | (forward-line) 1329 | (outorg-comment-search-forward) 1330 | ;; Move point to beg of comment 1331 | (beginning-of-line) 1332 | (unless (bobp) 1333 | ;; Skip backward comments and whitespace 1334 | (backward-line-comments) 1335 | (unless (bobp) 1336 | ;; Deal with trailing comment on line 1337 | (end-of-line))) 1338 | (point)))) 1339 | ;; Wrap code between B and C in block 1340 | (when (< outorg-beginning-of-code outorg-end-of-code) 1341 | (outorg-wrap-source-in-block babel-lang example-block-p)) 1342 | 1343 | ;; Remember marker positions 1344 | (let ((pt-A-pos (marker-position outorg-beginning-of-comment)) ; beg-of-comment 1345 | (pt-B-pos (marker-position outorg-beginning-of-code)) ; beg-of-code 1346 | (pt-C-pos (marker-position outorg-end-of-code))) ; end-of-code 1347 | 1348 | (when (and (eq pt-A-pos 1) 1349 | (eq pt-B-pos 1)) 1350 | ;; Special case only comments and whitespace in buffer 1351 | ;; Mark whole buffer 1352 | (move-marker outorg-beginning-of-code (point-max))) 1353 | 1354 | (when (< outorg-beginning-of-comment outorg-beginning-of-code) 1355 | ;; Uncomment region between A and B 1356 | (uncomment-region outorg-beginning-of-comment outorg-beginning-of-code) 1357 | ;; Move point to end of src 1358 | (and pt-B-pos pt-C-pos 1359 | (cond ((eq (marker-position outorg-beginning-of-code) 1360 | (point-max)) 1361 | ;; Special case only comments and whitespace in buffer -> finish loop 1362 | (goto-char outorg-beginning-of-code)) 1363 | ((< pt-B-pos pt-C-pos) 1364 | ;; Loop until C is at EOB 1365 | (goto-char outorg-end-of-code)) 1366 | (t "This should not happen")))) 1367 | (when (< pt-C-pos pt-B-pos) 1368 | (goto-char (point-max)))) 1369 | 1370 | ;; Reset markers 1371 | (move-marker outorg-beginning-of-code nil) 1372 | (move-marker outorg-end-of-code nil) 1373 | (move-marker outorg-beginning-of-comment nil)))))) 1374 | 1375 | (defun outorg-indent-active-source-blocks (mode-name) 1376 | "Indent active source-blocks after conversion to Org. 1377 | 1378 | This function calls `org-indent-block' on source-blocks in the 1379 | major-mode language of the associated source-file." 1380 | (let ((language (outorg-get-babel-name mode-name))) 1381 | (save-excursion 1382 | (org-babel-map-src-blocks nil 1383 | ;; language given as argument equal to lang of processed 1384 | ;; block? 1385 | (and (string-equal language lang) 1386 | (org-babel-mark-block) 1387 | (org-indent-region 1388 | (car (outorg-region-or-buffer-limits)) 1389 | (cadr (outorg-region-or-buffer-limits)))))))) 1390 | 1391 | (defun outorg-unindent-active-source-blocks (mode-name) 1392 | "Remove common indentation from active source-blocks. 1393 | 1394 | While editing in the *outorg-edit-buffer*, the source-code of the 1395 | source-blocks with language LANG (which should be the major-mode 1396 | language of the associated source-code buffer) might be indented 1397 | consciously or by accident. The latter happens e.g. when the 1398 | source-blocks are edited with `org-edit-special' (C-c '), and 1399 | variable `org-edit-src-content-indentation' has a value > 0. 1400 | 1401 | This function removes the introduced common indentation (e.g. 2 1402 | spaces) in these source-blocks (and only in them) before 1403 | converting back from Org to source-code if customizable variable 1404 | `outorg-unindent-active-source-blocks-p' is non-nil." 1405 | (let ((language (outorg-get-babel-name mode-name))) 1406 | (save-excursion 1407 | (org-babel-map-src-blocks nil 1408 | ;; language given as argument equal to lang of processed 1409 | ;; block? 1410 | (and (string-equal language lang) 1411 | (org-babel-mark-block) 1412 | (save-restriction 1413 | (narrow-to-region 1414 | (car (outorg-region-or-buffer-limits)) 1415 | (cadr (outorg-region-or-buffer-limits))) 1416 | (org-do-remove-indentation))))))) 1417 | 1418 | 1419 | (defun outorg-convert-back-to-code () 1420 | "Convert edit-buffer content back to programming language syntax. 1421 | Assume that edit-buffer major-mode has been set back to the 1422 | programming-language major-mode of the associated code-buffer 1423 | before this function is called." 1424 | (let* ((comment-style "plain") ; "multi-line"? 1425 | (buffer-mode (outorg-get-buffer-mode)) 1426 | (babel-lang (outorg-get-babel-name buffer-mode)) 1427 | (example-block-p (and (not (outorg-in-babel-load-languages-p buffer-mode)) 1428 | (not babel-lang))) 1429 | (regexp (if example-block-p 1430 | (concat "\\(?:#\\+begin_example" "[^\000]*?\n#\\+end_example\\)") ; NUL char 1431 | (format "%s%s%s" 1432 | "\\(?:^#\\+begin_src[[:space:]]+" 1433 | (regexp-quote (outorg-get-babel-name buffer-mode 'AS-STRG-P)) 1434 | "[^\000]*?\n#\\+end_src\\)"))) 1435 | (first-block-p t)) 1436 | 1437 | ;; 1st run: outcomment text, delete (active) block delimiters 1438 | ;; reset (left-over) marker 1439 | (move-marker outorg-beginning-of-code nil) 1440 | (move-marker outorg-end-of-code nil) 1441 | 1442 | ;; 1st run: outcomment text 1443 | (goto-char (point-min)) 1444 | (while (re-search-forward regexp nil 'NOERROR) 1445 | ;; special case 1st block 1446 | (if first-block-p 1447 | (progn 1448 | ;; Handle first block 1449 | (move-marker outorg-beginning-of-code (match-beginning 0)) 1450 | (move-marker outorg-end-of-code (match-end 0)) 1451 | (if (eq (point-min) (match-beginning 0)) 1452 | (goto-char (match-end 0)) 1453 | (save-match-data 1454 | (ignore-errors 1455 | (comment-region (point-min) (marker-position outorg-beginning-of-code))))) 1456 | (setq first-block-p nil)) 1457 | ;; default case 1458 | (let ((previous-beg-src (marker-position outorg-beginning-of-code)) 1459 | (previous-end-src (marker-position outorg-end-of-code))) 1460 | (move-marker outorg-beginning-of-code (match-beginning 0)) 1461 | (move-marker outorg-end-of-code (match-end 0)) 1462 | (save-match-data 1463 | (ignore-errors 1464 | (comment-region previous-end-src (marker-position outorg-beginning-of-code)))) 1465 | (save-excursion 1466 | (goto-char previous-end-src) 1467 | (delete-region (1- (point-at-bol)) (point-at-eol)) 1468 | (goto-char previous-beg-src) 1469 | (if (eq (point-at-bol) (point-min)) 1470 | (delete-region 1 (1+ (point-at-eol))) 1471 | (delete-region (1- (point-at-bol)) (point-at-eol))))))) 1472 | ;; special case last block 1473 | (ignore-errors 1474 | (comment-region (if first-block-p 1475 | (point-min) 1476 | outorg-end-of-code) 1477 | (point-max))) 1478 | (unless first-block-p ; no src-block so far 1479 | (save-excursion 1480 | (goto-char outorg-end-of-code) 1481 | (delete-region (1- (point-at-bol)) (point-at-eol)) 1482 | (goto-char outorg-beginning-of-code) 1483 | (delete-region (1- (point-at-bol)) (point-at-eol))))) 1484 | (move-marker outorg-beginning-of-code nil) 1485 | (move-marker outorg-end-of-code nil) 1486 | ;; 2nd (optional) run: convert elisp headers to oldschool 1487 | (when outorg-oldschool-elisp-headers-p 1488 | (save-excursion 1489 | (goto-char (point-min)) 1490 | (while (re-search-forward "\\(^;;\\)\\( [*]+\\)\\( \\)" nil 'NOERROR) 1491 | (let* ((org-header-level (- (length (match-string-no-properties 0)) 4)) 1492 | (replacement-string (let ((strg ";")) 1493 | (dotimes (i (1- org-header-level) strg) 1494 | (setq strg (concat strg ";")))))) 1495 | (replace-match replacement-string nil nil nil 2)))))) 1496 | ;; ;; finally remove trailing empty lines REALLY? 1497 | ;; (outorg-remove-trailing-blank-lines)) 1498 | 1499 | (defun outorg-replace-code-with-edits () 1500 | "Replace code-buffer contents with edits." 1501 | (let* ((edit-buf (marker-buffer outorg-edit-buffer-point-marker)) 1502 | (code-buf (marker-buffer outorg-code-buffer-point-marker)) 1503 | (edit-buf-point-min 1504 | (with-current-buffer edit-buf 1505 | (point-min))) 1506 | (edit-buf-point-max 1507 | (with-current-buffer edit-buf 1508 | (save-excursion 1509 | (goto-char (point-max)) 1510 | (unless (and (bolp) (looking-at "^[ \t]*$")) 1511 | (newline)) 1512 | (point))))) 1513 | (with-current-buffer code-buf 1514 | (if outorg-edit-whole-buffer-p 1515 | (progn 1516 | (if (buffer-narrowed-p) 1517 | (delete-region (point-min) (point-max)) 1518 | (erase-buffer)) 1519 | (insert-buffer-substring-no-properties 1520 | edit-buf edit-buf-point-min edit-buf-point-max) 1521 | (outorg-reinstall-markers-in-region (point-min))) 1522 | (goto-char 1523 | (marker-position outorg-code-buffer-point-marker)) 1524 | (save-restriction 1525 | (narrow-to-region 1526 | (save-excursion 1527 | (outline-back-to-heading 'INVISIBLE-OK) 1528 | (point)) 1529 | (save-excursion 1530 | (outline-end-of-subtree) 1531 | (point))) 1532 | (delete-region (point-min) (point-max)) 1533 | (insert-buffer-substring-no-properties 1534 | edit-buf edit-buf-point-min edit-buf-point-max) 1535 | (outorg-reinstall-markers-in-region (point-min))) 1536 | ;; (save-buffer) 1537 | )))) 1538 | 1539 | ;;;; Commands 1540 | ;;;;; Edit and Exit 1541 | 1542 | ;;;###autoload 1543 | (defun outorg-edit-as-org (&optional arg) 1544 | "Convert and copy to temporary Org buffer 1545 | 1546 | With ARG, act conditional on the raw value of ARG: 1547 | 1548 | | prefix | raw | action 1 | action 2 | 1549 | |--------+-----+-------------------+--------------------------------| 1550 | | C-u | (4) | edit-whole-buffer | --- | 1551 | | C-1 | 1 | edit-whole-buffer | insert default export-template | 1552 | | C-2 | 2 | edit-whole-buffer | prompt user for template-file | 1553 | | C-3 | 3 | edit-whole-buffer | insert & keep default template | 1554 | | C-4 | 4 | edit-whole-buffer | insert & keep template-file | 1555 | | C-5 | 5 | propagate changes | --- | 1556 | 1557 | " 1558 | (interactive "P") 1559 | (unless outline-minor-mode 1560 | (error "Activate `outline-minor-mode' to use `outorg'")) 1561 | (ignore-errors 1562 | (outorg-reset-global-vars)) 1563 | (and buffer-file-read-only 1564 | (error "Cannot edit read-only buffer-file")) 1565 | (and buffer-read-only 1566 | (if (not (y-or-n-p "Buffer is read-only - make writable ")) 1567 | (error "Cannot edit read-only buffer") 1568 | (setq inhibit-read-only t) 1569 | (setq outorg-code-buffer-read-only-p t))) 1570 | (and (derived-mode-p 'message-mode) 1571 | (outorg-prepare-message-mode-buffer-for-editing)) 1572 | (and (eq major-mode 'picolisp-mode) 1573 | (save-excursion 1574 | (save-match-data 1575 | (goto-char (point-max)) 1576 | (re-search-backward 1577 | (concat "(" (regexp-quote "********") ")") 1578 | nil 'NOERROR))) 1579 | (outorg-prepare-iorg-edit-buffer-for-editing)) 1580 | (move-marker outorg-code-buffer-point-marker (point)) 1581 | (save-excursion 1582 | (or 1583 | (outline-on-heading-p 'INVISIBLE-OK) 1584 | (ignore-errors 1585 | (outline-back-to-heading 'INVISIBLE-OK)) 1586 | (ignore-errors 1587 | (outline-next-heading))) 1588 | (move-marker 1589 | outorg-code-buffer-beg-of-subtree-marker (point))) 1590 | (and arg 1591 | (cond 1592 | ((equal arg '(4)) 1593 | (setq outorg-edit-whole-buffer-p t)) 1594 | ((equal arg 1) 1595 | (setq outorg-edit-whole-buffer-p t) 1596 | (setq outorg-insert-default-export-template-p t)) 1597 | ((equal arg 2) 1598 | (setq outorg-edit-whole-buffer-p t) 1599 | (setq outorg-ask-user-for-export-template-file-p t)) 1600 | ((equal arg 3) 1601 | (setq outorg-edit-whole-buffer-p t) 1602 | (setq outorg-insert-default-export-template-p t) 1603 | (setq outorg-keep-export-template-p t)) 1604 | ((equal arg 4) 1605 | (setq outorg-edit-whole-buffer-p t) 1606 | (setq outorg-ask-user-for-export-template-file-p t) 1607 | (setq outorg-keep-export-template-p t)) 1608 | ((equal arg 5) 1609 | (setq outorg-propagate-changes-p t)))) 1610 | (and (bound-and-true-p outshine-enforce-no-comment-padding-p) 1611 | (setq outorg-oldschool-elisp-headers-p t)) 1612 | (setq outorg-initial-window-config 1613 | (current-window-configuration)) 1614 | (outorg-save-markers (append outorg-tracked-markers 1615 | outorg-tracked-org-markers)) 1616 | (outorg-copy-and-convert)) 1617 | 1618 | ;; (defun outorg-gather-src-block-data () 1619 | ;; "Gather beg/end data of active src-blocks in curr-buf. 1620 | ;; Store the data as alist with form 1621 | 1622 | ;; #+begin_src emacs-lisp 1623 | ;; ((beg-block end-block) ... (beg-block end-block)) 1624 | ;; #+end_src 1625 | 1626 | ;; in global variable `outorg-src-block-data'." 1627 | 1628 | (defun outorg-copy-edits-and-exit () 1629 | "Replace code-buffer content with (converted) edit-buffer content and 1630 | kill edit-buffer" 1631 | (interactive) 1632 | (if (not buffer-undo-list) 1633 | ;; edit-buffer not modified at all 1634 | (progn 1635 | (move-marker outorg-edit-buffer-point-marker (point)) 1636 | ;; restore window configuration 1637 | (set-window-configuration 1638 | outorg-initial-window-config) 1639 | ;; avoid confirmation prompt when killing the edit buffer 1640 | (with-current-buffer 1641 | (marker-buffer outorg-edit-buffer-point-marker) 1642 | (set-buffer-modified-p nil)) 1643 | (kill-buffer 1644 | (marker-buffer outorg-edit-buffer-point-marker)) 1645 | (and outorg-code-buffer-read-only-p 1646 | (setq inhibit-read-only nil)) 1647 | ;; (and (eq major-mode 'message-mode) 1648 | (and (derived-mode-p 'message-mode) 1649 | (outorg-prepare-message-mode-buffer-for-sending)) 1650 | (and (eq major-mode 'picolisp-mode) 1651 | (save-excursion 1652 | (save-match-data 1653 | (goto-char (point-max)) 1654 | (re-search-backward 1655 | (concat "(" (regexp-quote "********") ")") 1656 | nil 'NOERROR)))) 1657 | ;; clean up global vars 1658 | (outorg-reset-global-vars)) 1659 | ;; edit-buffer modified 1660 | (widen) 1661 | ;; propagate changes to associated doc files 1662 | (when (and outorg-propagate-changes-p 1663 | (require 'org-watchdoc nil t)) 1664 | (save-excursion 1665 | (goto-char (point-min)) 1666 | (org-watchdoc-propagate-changes))) 1667 | (let ((mode (outorg-get-buffer-mode 1668 | (marker-buffer outorg-code-buffer-point-marker)))) 1669 | (and outorg-unindent-active-source-blocks-p 1670 | (outorg-unindent-active-source-blocks mode)) 1671 | (move-marker outorg-edit-buffer-point-marker (point)) 1672 | (move-marker outorg-edit-buffer-beg-of-subtree-marker 1673 | (or (ignore-errors 1674 | (save-excursion 1675 | (outline-previous-heading) 1676 | (point))) 1677 | 1)) 1678 | ;; special case R-mode 1679 | (if (eq mode 'ess-mode) 1680 | (funcall 'R-mode) 1681 | (funcall mode))) 1682 | (outorg-convert-back-to-code) 1683 | (outorg-save-markers (append outorg-tracked-markers 1684 | outorg-tracked-org-markers)) 1685 | (outorg-replace-code-with-edits) 1686 | (set-window-configuration 1687 | outorg-initial-window-config) 1688 | (goto-char outorg-code-buffer-point-marker) 1689 | ;; avoid confirmation prompt when killing the edit buffer 1690 | (with-current-buffer 1691 | (marker-buffer outorg-edit-buffer-point-marker) 1692 | (set-buffer-modified-p nil)) 1693 | (kill-buffer 1694 | (marker-buffer outorg-edit-buffer-point-marker)) 1695 | (and outorg-code-buffer-read-only-p 1696 | (setq inhibit-read-only nil)) 1697 | (and (derived-mode-p 'message-mode) 1698 | (outorg-prepare-message-mode-buffer-for-sending)) 1699 | (and (eq major-mode 'picolisp-mode) 1700 | (save-excursion 1701 | (save-match-data 1702 | (goto-char (point-max)) 1703 | (re-search-backward 1704 | (concat "(" (regexp-quote "********") ")") 1705 | nil 'NOERROR))) 1706 | (outorg-prepare-iorg-edit-buffer-for-posting)) 1707 | (outorg-reset-global-vars))) 1708 | 1709 | ;;;;; Insert Export Template 1710 | 1711 | ;; (defun outorg-toggle-export-template-insertion (&optional arg) 1712 | ;; "Toggles automatic insertion of export template into *outorg-edit-buffer* 1713 | 1714 | ;; With prefix arg, unconditionally deactivates insertion if numeric 1715 | ;; alue of ARG is negative, otherwise unconditionally activates it, except value 1716 | ;; is 16 (C-u C-u) - then `outorg-ask-user-for-export-template-file-p' will be 1717 | ;; set to t and the user asked for a file to insert. 1718 | 1719 | ;; Toggles the value without prefix arg." 1720 | ;; (interactive "P") 1721 | ;; (let ((num (prefix-numeric-value arg))) 1722 | ;; (cond 1723 | ;; ((= num 1) (if outorg-insert-default-export-template-p 1724 | ;; (prog 1725 | ;; (setq outorg-insert-default-export-template-p nil) 1726 | ;; (setq outorg-ask-user-for-export-template-file-p nil)) 1727 | ;; (setq outorg-insert-default-export-template-p t) 1728 | ;; (setq outorg-ask-user-for-export-template-file-p nil))) 1729 | ;; ((= num 16) (setq outorg-ask-user-for-export-template-file-p t)) 1730 | ;; ((< num 0) (setq outorg-insert-default-export-template-p nil) 1731 | ;; (setq outorg-ask-user-for-export-template-file-p nil)) 1732 | ;; ((> num 1) (setq outorg-insert-default-export-template-p t)) 1733 | ;; (setq outorg-ask-user-for-export-template-file-p nil)))) 1734 | 1735 | 1736 | (defun outorg-insert-default-export-template (&optional arg) 1737 | "Insert a default export template in the *outorg-edit-buffer*" 1738 | (interactive "P") 1739 | (and arg 1740 | (cond 1741 | ((equal arg '(4)) 1742 | (setq outorg-keep-export-template-p t)))) 1743 | (save-excursion 1744 | (goto-char (point-min)) 1745 | (insert 1746 | (concat 1747 | (unless outorg-keep-export-template-p 1748 | (concat 1749 | "# <<<*** BEGIN EXPORT TEMPLATE " 1750 | "[edits will be lost at exit] ***>>>\n\n")) 1751 | (format "#+TITLE: %s\n" 1752 | (ignore-errors 1753 | (file-name-sans-extension 1754 | (file-name-nondirectory 1755 | (buffer-file-name 1756 | (marker-buffer 1757 | (or outorg-code-buffer-point-marker 1758 | outorg-code-buffer-beg-of-subtree-marker))))))) 1759 | (format "#+LANGUAGE: %s\n" "en") 1760 | ;; ;; many people write in English, although locale is different 1761 | ;; (ignore-errors 1762 | ;; (car (split-string (getenv "LANG") "_" 'OMIT-NULLS)))) 1763 | (format "#+AUTHOR: %s\n" 1764 | (ignore-errors 1765 | (user-full-name))) 1766 | (format "#+EMAIL: %s\n" (ignore-errors 1767 | (or user-mail-address 1768 | (getenv "MAIL")))) 1769 | (concat "#+OPTIONS: H:3 num:t toc:3 \\n:nil @:t ::t " 1770 | "|:t ^:nil -:t f:t *:t <:nil prop:t\n") 1771 | (concat "#+OPTIONS: TeX:t LaTeX:nil skip:nil d:nil " 1772 | "todo:t pri:nil tags:not-in-toc\n") 1773 | "#+OPTIONS: author:t creator:t timestamp:t email:t\n" 1774 | "# #+DESCRIPTION: <>\n" 1775 | "# #+KEYWORDS: <>\n" 1776 | "# #+SEQ_TODO: <>\n" 1777 | (concat "#+INFOJS_OPT: view:nil toc:t ltoc:t mouse:underline " 1778 | "buttons:0 path:http://orgmode.org/org-info.js\n") 1779 | "#+EXPORT_SELECT_TAGS: export\n" 1780 | "#+EXPORT_EXCLUDE_TAGS: noexport\n\n" 1781 | (unless outorg-keep-export-template-p 1782 | "# <<<*** END EXPORT TEMPLATE ***>>>\n\n"))))) 1783 | 1784 | (defun outorg-insert-export-template-file (arg template-file ) 1785 | "Insert a user export-template-file in the *outorg-edit-buffer*" 1786 | (interactive "P\nfTemplate File: ") 1787 | (and arg 1788 | (cond 1789 | ((equal arg '(4)) 1790 | (setq outorg-keep-export-template-p t)))) 1791 | (save-excursion 1792 | (goto-char (point-min)) 1793 | (unless outorg-keep-export-template-p 1794 | (insert 1795 | (concat 1796 | "# <<<*** BEGIN EXPORT TEMPLATE " 1797 | "[edits will be lost at exit] ***>>>\n\n"))) 1798 | (forward-char 1799 | (cadr (insert-file-contents template-file))) 1800 | (newline) 1801 | (unless outorg-keep-export-template-p 1802 | (insert "# <<<*** END EXPORT TEMPLATE ***>>>\n") 1803 | (newline)))) 1804 | 1805 | 1806 | ;;;;; Misc 1807 | 1808 | ;; courtesy to Trey Jackson (http://tinyurl.com/cbnlemg) 1809 | (defun outorg-edit-comments-and-propagate-changes () 1810 | "Edit first buffer tree and propagate changes. 1811 | Used to keep exported comment-sections in sync with their 1812 | source-files." 1813 | (interactive) 1814 | (goto-char (point-min)) 1815 | (unless (outline-on-heading-p 'INVISIBLE-OK) 1816 | (ignore-errors 1817 | (outline-next-heading))) 1818 | (outorg-edit-as-org 5)) 1819 | 1820 | (defun outorg-replace-source-blocks-with-results 1821 | (&optional arg &rest languages) 1822 | "Replace source-blocks with their results. 1823 | 1824 | Only source-blocks with ':export results' in their header 1825 | arguments will be mapped. 1826 | 1827 | If LANGUAGES is non-nil, only those source-blocks with a 1828 | language found in the list are mapped. 1829 | 1830 | If LANGUAGES is nil but a prefix-argument ARG is given, only the 1831 | languages read from the mini-buffer (separated by blanks) are mapped. 1832 | 1833 | Otherwise, all languages found in `org-babel-load-languages' are mapped." 1834 | (interactive "P\n") 1835 | (let ((langs (or languages 1836 | (and arg 1837 | (split-string 1838 | (read-string 1839 | (concat "Org Babel languages separated by blanks: ")) 1840 | " " 'OMIT-NULLS)) 1841 | (mapcar 1842 | (lambda (X) (symbol-name (car X))) 1843 | org-babel-load-languages)))) 1844 | (org-babel-map-src-blocks nil 1845 | (and 1846 | (string-equal 1847 | (cdr 1848 | (assoc 1849 | :exports 1850 | (org-babel-parse-header-arguments header-args))) 1851 | "results") 1852 | (member lang langs) 1853 | (org-babel-execute-src-block) 1854 | (let* ((block-start (org-babel-where-is-src-block-head)) 1855 | (results-head (org-babel-where-is-src-block-result)) 1856 | (results-body 1857 | (save-excursion 1858 | (goto-char results-head) 1859 | (forward-line) 1860 | (point)))) 1861 | (delete-region block-start results-body)))))) 1862 | 1863 | (defun outorg-which-active-modes () 1864 | "Give a message of which minor modes are enabled in the current buffer." 1865 | (interactive) 1866 | (let ((active-modes)) 1867 | (mapc 1868 | (lambda (mode) 1869 | (condition-case nil 1870 | (if (and (symbolp mode) (symbol-value mode)) 1871 | (add-to-list 'active-modes mode)) 1872 | (error nil) )) 1873 | minor-mode-list) 1874 | active-modes)) 1875 | 1876 | 1877 | ;;; Menus and Keys 1878 | ;;;; Menus 1879 | 1880 | (defvar outorg-edit-menu-map 1881 | (let ((map (make-sparse-keymap))) 1882 | (define-key map [outorg-copy-edits-and-exit] 1883 | '(menu-item "Copy and Exit" outorg-copy-edits-and-exit 1884 | :help "Copy edits to original-buffer 1885 | and exit outorg")) 1886 | (define-key map [outorg-save-edits-to-tmp-file] 1887 | '(menu-item "Save" outorg-save-edits-to-tmp-file 1888 | :help "Save edit buffer to temporary 1889 | file in the OS tmp directory")) 1890 | map)) 1891 | 1892 | ;;;; Keys 1893 | 1894 | ;;;;; Mode Keys 1895 | 1896 | (defvar outorg-edit-minor-mode-map 1897 | (let ((map (make-sparse-keymap))) 1898 | (define-key map "\M-#" 1899 | 'outorg-copy-edits-and-exit) 1900 | (define-key map "\C-x\C-s" 1901 | 'outorg-save-edits-to-tmp-file) 1902 | (define-key map [menu-bar outorg-edit] 1903 | (cons (purecopy "Outorg") outorg-edit-menu-map)) 1904 | map)) 1905 | 1906 | (add-to-list 'minor-mode-map-alist 1907 | (cons 'outorg-edit-minor-mode 1908 | outorg-edit-minor-mode-map)) 1909 | 1910 | ;;; Run hooks and provide 1911 | 1912 | (run-hooks 'outorg-hook) 1913 | 1914 | (provide 'outorg) 1915 | 1916 | ;; Local Variables: 1917 | ;; coding: utf-8 1918 | ;; ispell-local-dictionary: "en_US" 1919 | ;; End: 1920 | 1921 | ;;; outorg.el ends here 1922 | --------------------------------------------------------------------------------