Commit | Line | Data |
---|---|---|
c8d0cf5c CD |
1 | ;;; org-ascii.el --- ASCII export for Org-mode |
2 | ||
cbd20947 | 3 | ;; Copyright (C) 2004-2011 Free Software Foundation, Inc. |
c8d0cf5c CD |
4 | |
5 | ;; Author: Carsten Dominik <carsten at orgmode dot org> | |
6 | ;; Keywords: outlines, hypermedia, calendar, wp | |
7 | ;; Homepage: http://orgmode.org | |
3ab2c837 | 8 | ;; Version: 7.7 |
c8d0cf5c CD |
9 | ;; |
10 | ;; This file is part of GNU Emacs. | |
11 | ;; | |
12 | ;; GNU Emacs is free software: you can redistribute it and/or modify | |
13 | ;; it under the terms of the GNU General Public License as published by | |
14 | ;; the Free Software Foundation, either version 3 of the License, or | |
15 | ;; (at your option) any later version. | |
16 | ||
17 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | ;; GNU General Public License for more details. | |
21 | ||
22 | ;; You should have received a copy of the GNU General Public License | |
23 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
24 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
25 | ;; | |
26 | ;;; Commentary: | |
27 | ||
86fbb8ca CD |
28 | ;;; Code: |
29 | ||
c8d0cf5c | 30 | (require 'org-exp) |
86fbb8ca | 31 | |
8d642074 CD |
32 | (eval-when-compile |
33 | (require 'cl)) | |
c8d0cf5c CD |
34 | |
35 | (defgroup org-export-ascii nil | |
36 | "Options specific for ASCII export of Org-mode files." | |
37 | :tag "Org Export ASCII" | |
38 | :group 'org-export) | |
39 | ||
3ab2c837 | 40 | (defcustom org-export-ascii-underline '(?\- ?\= ?\~ ?^ ?\# ?\$) |
c8d0cf5c CD |
41 | "Characters for underlining headings in ASCII export. |
42 | In the given sequence, these characters will be used for level 1, 2, ..." | |
43 | :group 'org-export-ascii | |
44 | :type '(repeat character)) | |
45 | ||
46 | (defcustom org-export-ascii-bullets '(?* ?+ ?-) | |
47 | "Bullet characters for headlines converted to lists in ASCII export. | |
48 | The first character is used for the first lest level generated in this | |
49 | way, and so on. If there are more levels than characters given here, | |
50 | the list will be repeated. | |
51 | Note that plain lists will keep the same bullets as the have in the | |
52 | Org-mode file." | |
53 | :group 'org-export-ascii | |
54 | :type '(repeat character)) | |
55 | ||
56 | (defcustom org-export-ascii-links-to-notes t | |
ed21c5c8 | 57 | "Non-nil means convert links to notes before the next headline. |
c8d0cf5c CD |
58 | When nil, the link will be exported in place. If the line becomes long |
59 | in this way, it will be wrapped." | |
60 | :group 'org-export-ascii | |
61 | :type 'boolean) | |
62 | ||
8bfe682a | 63 | (defcustom org-export-ascii-table-keep-all-vertical-lines nil |
ed21c5c8 | 64 | "Non-nil means keep all vertical lines in ASCII tables. |
8bfe682a CD |
65 | When nil, vertical lines will be removed except for those needed |
66 | for column grouping." | |
67 | :group 'org-export-ascii | |
68 | :type 'boolean) | |
69 | ||
ed21c5c8 CD |
70 | (defcustom org-export-ascii-table-widen-columns t |
71 | "Non-nil means widen narrowed columns for export. | |
72 | When nil, narrowed columns will look in ASCII export just like in org-mode, | |
73 | i.e. with \"=>\" as ellipsis." | |
74 | :group 'org-export-ascii | |
75 | :type 'boolean) | |
76 | ||
77 | (defvar org-export-ascii-entities 'ascii | |
78 | "The ascii representation to be used during ascii export. | |
79 | Possible values are: | |
80 | ||
81 | ascii Only use plain ASCII characters | |
82 | latin1 Include Latin-1 character | |
83 | utf8 Use all UTF-8 characters") | |
84 | ||
8d642074 CD |
85 | ;;; Hooks |
86 | ||
87 | (defvar org-export-ascii-final-hook nil | |
88 | "Hook run at the end of ASCII export, in the new buffer.") | |
89 | ||
c8d0cf5c CD |
90 | ;;; ASCII export |
91 | ||
92 | (defvar org-ascii-current-indentation nil) ; For communication | |
93 | ||
ed21c5c8 CD |
94 | ;;;###autoload |
95 | (defun org-export-as-latin1 (&rest args) | |
96 | "Like `org-export-as-ascii', use latin1 encoding for special symbols." | |
97 | (interactive) | |
3ab2c837 | 98 | (org-export-as-encoding 'org-export-as-ascii (org-called-interactively-p 'any) |
ed21c5c8 CD |
99 | 'latin1 args)) |
100 | ||
101 | ;;;###autoload | |
102 | (defun org-export-as-latin1-to-buffer (&rest args) | |
103 | "Like `org-export-as-ascii-to-buffer', use latin1 encoding for symbols." | |
104 | (interactive) | |
3ab2c837 BG |
105 | (org-export-as-encoding 'org-export-as-ascii-to-buffer |
106 | (org-called-interactively-p 'any) 'latin1 args)) | |
ed21c5c8 CD |
107 | |
108 | ;;;###autoload | |
109 | (defun org-export-as-utf8 (&rest args) | |
3ab2c837 | 110 | "Like `org-export-as-ascii', use encoding for special symbols." |
ed21c5c8 | 111 | (interactive) |
3ab2c837 BG |
112 | (org-export-as-encoding 'org-export-as-ascii |
113 | (org-called-interactively-p 'any) | |
ed21c5c8 CD |
114 | 'utf8 args)) |
115 | ||
116 | ;;;###autoload | |
117 | (defun org-export-as-utf8-to-buffer (&rest args) | |
118 | "Like `org-export-as-ascii-to-buffer', use utf8 encoding for symbols." | |
119 | (interactive) | |
3ab2c837 BG |
120 | (org-export-as-encoding 'org-export-as-ascii-to-buffer |
121 | (org-called-interactively-p 'any) 'utf8 args)) | |
ed21c5c8 CD |
122 | |
123 | (defun org-export-as-encoding (command interactivep encoding &rest args) | |
124 | (let ((org-export-ascii-entities encoding)) | |
125 | (if interactivep | |
126 | (call-interactively command) | |
127 | (apply command args)))) | |
128 | ||
129 | ||
c8d0cf5c CD |
130 | ;;;###autoload |
131 | (defun org-export-as-ascii-to-buffer (arg) | |
132 | "Call `org-export-as-ascii` with output to a temporary buffer. | |
133 | No file is created. The prefix ARG is passed through to `org-export-as-ascii'." | |
134 | (interactive "P") | |
135 | (org-export-as-ascii arg nil nil "*Org ASCII Export*") | |
136 | (when org-export-show-temporary-export-buffer | |
137 | (switch-to-buffer-other-window "*Org ASCII Export*"))) | |
138 | ||
139 | ;;;###autoload | |
140 | (defun org-replace-region-by-ascii (beg end) | |
141 | "Assume the current region has org-mode syntax, and convert it to plain ASCII. | |
142 | This can be used in any buffer. For example, you could write an | |
143 | itemized list in org-mode syntax in a Mail buffer and then use this | |
144 | command to convert it." | |
145 | (interactive "r") | |
146 | (let (reg ascii buf pop-up-frames) | |
147 | (save-window-excursion | |
148 | (if (org-mode-p) | |
149 | (setq ascii (org-export-region-as-ascii | |
150 | beg end t 'string)) | |
151 | (setq reg (buffer-substring beg end) | |
152 | buf (get-buffer-create "*Org tmp*")) | |
153 | (with-current-buffer buf | |
154 | (erase-buffer) | |
155 | (insert reg) | |
156 | (org-mode) | |
157 | (setq ascii (org-export-region-as-ascii | |
158 | (point-min) (point-max) t 'string))) | |
159 | (kill-buffer buf))) | |
160 | (delete-region beg end) | |
161 | (insert ascii))) | |
162 | ||
163 | ;;;###autoload | |
164 | (defun org-export-region-as-ascii (beg end &optional body-only buffer) | |
165 | "Convert region from BEG to END in org-mode buffer to plain ASCII. | |
166 | If prefix arg BODY-ONLY is set, omit file header, footer, and table of | |
167 | contents, and only produce the region of converted text, useful for | |
168 | cut-and-paste operations. | |
169 | If BUFFER is a buffer or a string, use/create that buffer as a target | |
170 | of the converted ASCII. If BUFFER is the symbol `string', return the | |
171 | produced ASCII as a string and leave not buffer behind. For example, | |
172 | a Lisp program could call this function in the following way: | |
173 | ||
174 | (setq ascii (org-export-region-as-ascii beg end t 'string)) | |
175 | ||
176 | When called interactively, the output buffer is selected, and shown | |
177 | in a window. A non-interactive call will only return the buffer." | |
178 | (interactive "r\nP") | |
3ab2c837 | 179 | (when (org-called-interactively-p 'any) |
c8d0cf5c CD |
180 | (setq buffer "*Org ASCII Export*")) |
181 | (let ((transient-mark-mode t) (zmacs-regions t) | |
182 | ext-plist rtn) | |
8bfe682a | 183 | (setq ext-plist (plist-put ext-plist :ignore-subtree-p t)) |
c8d0cf5c CD |
184 | (goto-char end) |
185 | (set-mark (point)) ;; to activate the region | |
186 | (goto-char beg) | |
187 | (setq rtn (org-export-as-ascii | |
188 | nil nil ext-plist | |
189 | buffer body-only)) | |
190 | (if (fboundp 'deactivate-mark) (deactivate-mark)) | |
3ab2c837 | 191 | (if (and (org-called-interactively-p 'any) (bufferp rtn)) |
c8d0cf5c CD |
192 | (switch-to-buffer-other-window rtn) |
193 | rtn))) | |
194 | ||
195 | ;;;###autoload | |
196 | (defun org-export-as-ascii (arg &optional hidden ext-plist | |
197 | to-buffer body-only pub-dir) | |
198 | "Export the outline as a pretty ASCII file. | |
199 | If there is an active region, export only the region. | |
200 | The prefix ARG specifies how many levels of the outline should become | |
201 | underlined headlines, default is 3. Lower levels will become bulleted | |
202 | lists. When HIDDEN is non-nil, don't display the ASCII buffer. | |
203 | EXT-PLIST is a property list with external parameters overriding | |
204 | org-mode's default settings, but still inferior to file-local | |
205 | settings. When TO-BUFFER is non-nil, create a buffer with that | |
206 | name and export to that buffer. If TO-BUFFER is the symbol | |
207 | `string', don't leave any buffer behind but just return the | |
208 | resulting ASCII as a string. When BODY-ONLY is set, don't produce | |
209 | the file header and footer. When PUB-DIR is set, use this as the | |
210 | publishing directory." | |
211 | (interactive "P") | |
ed21c5c8 | 212 | (run-hooks 'org-export-first-hook) |
c8d0cf5c CD |
213 | (setq-default org-todo-line-regexp org-todo-line-regexp) |
214 | (let* ((opt-plist (org-combine-plists (org-default-export-plist) | |
215 | ext-plist | |
216 | (org-infile-export-plist))) | |
217 | (region-p (org-region-active-p)) | |
218 | (rbeg (and region-p (region-beginning))) | |
219 | (rend (and region-p (region-end))) | |
220 | (subtree-p | |
8bfe682a | 221 | (if (plist-get opt-plist :ignore-subtree-p) |
c8d0cf5c CD |
222 | nil |
223 | (when region-p | |
224 | (save-excursion | |
225 | (goto-char rbeg) | |
226 | (and (org-at-heading-p) | |
227 | (>= (org-end-of-subtree t t) rend)))))) | |
228 | (level-offset (if subtree-p | |
229 | (save-excursion | |
230 | (goto-char rbeg) | |
231 | (+ (funcall outline-level) | |
232 | (if org-odd-levels-only 1 0))) | |
233 | 0)) | |
234 | (opt-plist (setq org-export-opt-plist | |
235 | (if subtree-p | |
236 | (org-export-add-subtree-options opt-plist rbeg) | |
237 | opt-plist))) | |
ed21c5c8 CD |
238 | ;; The following two are dynamically scoped into other |
239 | ;; routines below. | |
240 | (org-current-export-dir | |
241 | (or pub-dir (org-export-directory :html opt-plist))) | |
242 | (org-current-export-file buffer-file-name) | |
c8d0cf5c CD |
243 | (custom-times org-display-custom-times) |
244 | (org-ascii-current-indentation '(0 . 0)) | |
245 | (level 0) line txt | |
246 | (umax nil) | |
247 | (umax-toc nil) | |
248 | (case-fold-search nil) | |
249 | (bfname (buffer-file-name (or (buffer-base-buffer) (current-buffer)))) | |
250 | (filename (if to-buffer | |
251 | nil | |
252 | (concat (file-name-as-directory | |
253 | (or pub-dir | |
254 | (org-export-directory :ascii opt-plist))) | |
255 | (file-name-sans-extension | |
256 | (or (and subtree-p | |
257 | (org-entry-get (region-beginning) | |
258 | "EXPORT_FILE_NAME" t)) | |
259 | (file-name-nondirectory bfname))) | |
260 | ".txt"))) | |
261 | (filename (and filename | |
262 | (if (equal (file-truename filename) | |
263 | (file-truename bfname)) | |
264 | (concat filename ".txt") | |
265 | filename))) | |
266 | (buffer (if to-buffer | |
267 | (cond | |
268 | ((eq to-buffer 'string) | |
269 | (get-buffer-create "*Org ASCII Export*")) | |
270 | (t (get-buffer-create to-buffer))) | |
271 | (find-file-noselect filename))) | |
272 | (org-levels-open (make-vector org-level-max nil)) | |
273 | (odd org-odd-levels-only) | |
274 | (date (plist-get opt-plist :date)) | |
275 | (author (plist-get opt-plist :author)) | |
276 | (title (or (and subtree-p (org-export-get-title-from-subtree)) | |
277 | (plist-get opt-plist :title) | |
278 | (and (not | |
279 | (plist-get opt-plist :skip-before-1st-heading)) | |
280 | (org-export-grab-title-from-buffer)) | |
ed21c5c8 CD |
281 | (and (buffer-file-name) |
282 | (file-name-sans-extension | |
283 | (file-name-nondirectory bfname))) | |
284 | "UNTITLED")) | |
c8d0cf5c CD |
285 | (email (plist-get opt-plist :email)) |
286 | (language (plist-get opt-plist :language)) | |
287 | (quote-re0 (concat "^[ \t]*" org-quote-string "\\>")) | |
288 | (todo nil) | |
289 | (lang-words nil) | |
290 | (region | |
291 | (buffer-substring | |
292 | (if (org-region-active-p) (region-beginning) (point-min)) | |
293 | (if (org-region-active-p) (region-end) (point-max)))) | |
3ab2c837 BG |
294 | (org-export-footnotes-seen nil) |
295 | (org-export-footnotes-data (org-footnote-all-labels 'with-defs)) | |
c8d0cf5c CD |
296 | (lines (org-split-string |
297 | (org-export-preprocess-string | |
298 | region | |
3ab2c837 | 299 | :for-backend 'ascii |
c8d0cf5c CD |
300 | :skip-before-1st-heading |
301 | (plist-get opt-plist :skip-before-1st-heading) | |
302 | :drawers (plist-get opt-plist :drawers) | |
303 | :tags (plist-get opt-plist :tags) | |
304 | :priority (plist-get opt-plist :priority) | |
305 | :footnotes (plist-get opt-plist :footnotes) | |
306 | :timestamps (plist-get opt-plist :timestamps) | |
307 | :todo-keywords (plist-get opt-plist :todo-keywords) | |
3ab2c837 | 308 | :tasks (plist-get opt-plist :tasks) |
c8d0cf5c CD |
309 | :verbatim-multiline t |
310 | :select-tags (plist-get opt-plist :select-tags) | |
311 | :exclude-tags (plist-get opt-plist :exclude-tags) | |
312 | :archived-trees | |
313 | (plist-get opt-plist :archived-trees) | |
314 | :add-text (plist-get opt-plist :text)) | |
315 | "\n")) | |
316 | thetoc have-headings first-heading-pos | |
afe98dfa | 317 | table-open table-buffer link-buffer link type path desc desc0 rpl wrap fnc) |
c8d0cf5c CD |
318 | (let ((inhibit-read-only t)) |
319 | (org-unmodified | |
320 | (remove-text-properties (point-min) (point-max) | |
321 | '(:org-license-to-kill t)))) | |
322 | ||
323 | (setq org-min-level (org-get-min-level lines level-offset)) | |
324 | (setq org-last-level org-min-level) | |
325 | (org-init-section-numbers) | |
326 | (setq lang-words (or (assoc language org-export-language-setup) | |
327 | (assoc "en" org-export-language-setup))) | |
328 | (set-buffer buffer) | |
329 | (erase-buffer) | |
330 | (fundamental-mode) | |
331 | (org-install-letbind) | |
332 | ;; create local variables for all options, to make sure all called | |
333 | ;; functions get the correct information | |
334 | (mapc (lambda (x) | |
335 | (set (make-local-variable (nth 2 x)) | |
336 | (plist-get opt-plist (car x)))) | |
337 | org-export-plist-vars) | |
338 | (org-set-local 'org-odd-levels-only odd) | |
339 | (setq umax (if arg (prefix-numeric-value arg) | |
340 | org-export-headline-levels)) | |
341 | (setq umax-toc (if (integerp org-export-with-toc) | |
342 | (min org-export-with-toc umax) | |
343 | umax)) | |
344 | ||
345 | ;; File header | |
346 | (unless body-only | |
54a0dee5 CD |
347 | (when (and title (not (string= "" title))) |
348 | (org-insert-centered title ?=) | |
349 | (insert "\n")) | |
350 | ||
c8d0cf5c CD |
351 | (if (and (or author email) |
352 | org-export-author-info) | |
afe98dfa | 353 | (insert (concat (nth 1 lang-words) ": " (or author "") |
ed21c5c8 CD |
354 | (if (and org-export-email-info |
355 | email (string-match "\\S-" email)) | |
356 | (concat " <" email ">") "") | |
c8d0cf5c CD |
357 | "\n"))) |
358 | ||
359 | (cond | |
360 | ((and date (string-match "%" date)) | |
361 | (setq date (format-time-string date))) | |
362 | (date) | |
363 | (t (setq date (format-time-string "%Y-%m-%d %T %Z")))) | |
364 | ||
365 | (if (and date org-export-time-stamp-file) | |
366 | (insert (concat (nth 2 lang-words) ": " date"\n"))) | |
367 | ||
54a0dee5 CD |
368 | (unless (= (point) (point-min)) |
369 | (insert "\n\n"))) | |
c8d0cf5c CD |
370 | |
371 | (if (and org-export-with-toc (not body-only)) | |
372 | (progn | |
373 | (push (concat (nth 3 lang-words) "\n") thetoc) | |
374 | (push (concat (make-string (string-width (nth 3 lang-words)) ?=) | |
375 | "\n") thetoc) | |
3ab2c837 BG |
376 | (mapc #'(lambda (line) |
377 | (if (string-match org-todo-line-regexp | |
378 | line) | |
379 | ;; This is a headline | |
380 | (progn | |
381 | (setq have-headings t) | |
382 | (setq level (- (match-end 1) (match-beginning 1) | |
383 | level-offset) | |
384 | level (org-tr-level level) | |
385 | txt (match-string 3 line) | |
386 | todo | |
387 | (or (and org-export-mark-todo-in-toc | |
388 | (match-beginning 2) | |
389 | (not (member (match-string 2 line) | |
390 | org-done-keywords))) | |
c8d0cf5c | 391 | ; TODO, not DONE |
3ab2c837 BG |
392 | (and org-export-mark-todo-in-toc |
393 | (= level umax-toc) | |
394 | (org-search-todo-below | |
395 | line lines level)))) | |
396 | (setq txt (org-html-expand-for-ascii txt)) | |
397 | ||
398 | (while (string-match org-bracket-link-regexp txt) | |
399 | (setq txt | |
400 | (replace-match | |
401 | (match-string (if (match-end 2) 3 1) txt) | |
402 | t t txt))) | |
403 | ||
404 | (if (and (memq org-export-with-tags '(not-in-toc nil)) | |
405 | (string-match | |
406 | (org-re "[ \t]+:[[:alnum:]_@#%:]+:[ \t]*$") | |
407 | txt)) | |
408 | (setq txt (replace-match "" t t txt))) | |
409 | (if (string-match quote-re0 txt) | |
410 | (setq txt (replace-match "" t t txt))) | |
411 | ||
412 | (if org-export-with-section-numbers | |
413 | (setq txt (concat (org-section-number level) | |
414 | " " txt))) | |
415 | (if (<= level umax-toc) | |
416 | (progn | |
417 | (push | |
418 | (concat | |
419 | (make-string | |
420 | (* (max 0 (- level org-min-level)) 4) ?\ ) | |
421 | (format (if todo "%s (*)\n" "%s\n") txt)) | |
422 | thetoc) | |
423 | (setq org-last-level level)) | |
424 | )))) | |
c8d0cf5c CD |
425 | lines) |
426 | (setq thetoc (if have-headings (nreverse thetoc) nil)))) | |
427 | ||
428 | (org-init-section-numbers) | |
429 | (while (setq line (pop lines)) | |
3ab2c837 | 430 | (when (and link-buffer (string-match org-outline-regexp-bol line)) |
c8d0cf5c CD |
431 | (org-export-ascii-push-links (nreverse link-buffer)) |
432 | (setq link-buffer nil)) | |
433 | (setq wrap nil) | |
434 | ;; Remove the quoted HTML tags. | |
435 | (setq line (org-html-expand-for-ascii line)) | |
436 | ;; Replace links with the description when possible | |
afe98dfa CD |
437 | (while (string-match org-bracket-link-analytic-regexp++ line) |
438 | (setq path (match-string 3 line) | |
439 | link (concat (match-string 1 line) path) | |
440 | type (match-string 2 line) | |
441 | desc0 (match-string 5 line) | |
442 | desc (or desc0 link)) | |
c8d0cf5c CD |
443 | (if (and (> (length link) 8) |
444 | (equal (substring link 0 8) "coderef:")) | |
445 | (setq line (replace-match | |
446 | (format (org-export-get-coderef-format (substring link 8) desc) | |
447 | (cdr (assoc | |
448 | (substring link 8) | |
449 | org-export-code-refs))) | |
450 | t t line)) | |
afe98dfa CD |
451 | (setq rpl (concat "[" desc "]")) |
452 | (if (functionp (setq fnc (nth 2 (assoc type org-link-protocols)))) | |
453 | (setq rpl (or (save-match-data | |
454 | (funcall fnc (org-link-unescape path) | |
455 | desc0 'ascii)) | |
456 | rpl)) | |
457 | (when (and desc0 (not (equal desc0 link))) | |
458 | (if org-export-ascii-links-to-notes | |
459 | (push (cons desc0 link) link-buffer) | |
460 | (setq rpl (concat rpl " (" link ")") | |
461 | wrap (+ (length line) (- (length (match-string 0 line))) | |
462 | (length desc)))))) | |
c8d0cf5c CD |
463 | (setq line (replace-match rpl t t line)))) |
464 | (when custom-times | |
465 | (setq line (org-translate-time line))) | |
466 | (cond | |
467 | ((string-match "^\\(\\*+\\)[ \t]+\\(.*\\)" line) | |
468 | ;; a Headline | |
469 | (setq first-heading-pos (or first-heading-pos (point))) | |
470 | (setq level (org-tr-level (- (match-end 1) (match-beginning 1) | |
471 | level-offset)) | |
472 | txt (match-string 2 line)) | |
473 | (org-ascii-level-start level txt umax lines)) | |
474 | ||
475 | ((and org-export-with-tables | |
476 | (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line)) | |
477 | (if (not table-open) | |
478 | ;; New table starts | |
479 | (setq table-open t table-buffer nil)) | |
480 | ;; Accumulate lines | |
481 | (setq table-buffer (cons line table-buffer)) | |
482 | (when (or (not lines) | |
483 | (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" | |
484 | (car lines)))) | |
485 | (setq table-open nil | |
486 | table-buffer (nreverse table-buffer)) | |
487 | (insert (mapconcat | |
488 | (lambda (x) | |
489 | (org-fix-indentation x org-ascii-current-indentation)) | |
490 | (org-format-table-ascii table-buffer) | |
491 | "\n") "\n"))) | |
492 | (t | |
afe98dfa CD |
493 | (if (string-match "^\\([ \t]*\\)\\([-+*][ \t]+\\)\\(.*?\\)\\( ::\\)" |
494 | line) | |
c8d0cf5c CD |
495 | (setq line (replace-match "\\1\\3:" t nil line))) |
496 | (setq line (org-fix-indentation line org-ascii-current-indentation)) | |
497 | ;; Remove forced line breaks | |
498 | (if (string-match "\\\\\\\\[ \t]*$" line) | |
499 | (setq line (replace-match "" t t line))) | |
500 | (if (and org-export-with-fixed-width | |
501 | (string-match "^\\([ \t]*\\)\\(:\\( \\|$\\)\\)" line)) | |
502 | (setq line (replace-match "\\1" nil nil line)) | |
503 | (if wrap (setq line (org-export-ascii-wrap line wrap)))) | |
504 | (insert line "\n")))) | |
505 | ||
506 | (org-export-ascii-push-links (nreverse link-buffer)) | |
507 | ||
508 | (normal-mode) | |
509 | ||
510 | ;; insert the table of contents | |
511 | (when thetoc | |
512 | (goto-char (point-min)) | |
513 | (if (re-search-forward "^[ \t]*\\[TABLE-OF-CONTENTS\\][ \t]*$" nil t) | |
514 | (progn | |
515 | (goto-char (match-beginning 0)) | |
516 | (replace-match "")) | |
517 | (goto-char first-heading-pos)) | |
518 | (mapc 'insert thetoc) | |
519 | (or (looking-at "[ \t]*\n[ \t]*\n") | |
520 | (insert "\n\n"))) | |
521 | ||
522 | ;; Convert whitespace place holders | |
523 | (goto-char (point-min)) | |
524 | (let (beg end) | |
525 | (while (setq beg (next-single-property-change (point) 'org-whitespace)) | |
526 | (setq end (next-single-property-change beg 'org-whitespace)) | |
527 | (goto-char beg) | |
528 | (delete-region beg end) | |
529 | (insert (make-string (- end beg) ?\ )))) | |
530 | ||
531 | ;; remove display and invisible chars | |
532 | (let (beg end) | |
533 | (goto-char (point-min)) | |
534 | (while (setq beg (next-single-property-change (point) 'display)) | |
535 | (setq end (next-single-property-change beg 'display)) | |
536 | (delete-region beg end) | |
537 | (goto-char beg) | |
538 | (insert "=>")) | |
539 | (goto-char (point-min)) | |
540 | (while (setq beg (next-single-property-change (point) 'org-cwidth)) | |
541 | (setq end (next-single-property-change beg 'org-cwidth)) | |
542 | (delete-region beg end) | |
543 | (goto-char beg))) | |
8d642074 | 544 | (run-hooks 'org-export-ascii-final-hook) |
c8d0cf5c CD |
545 | (or to-buffer (save-buffer)) |
546 | (goto-char (point-min)) | |
547 | (or (org-export-push-to-kill-ring "ASCII") | |
548 | (message "Exporting... done")) | |
549 | ;; Return the buffer or a string, according to how this function was called | |
550 | (if (eq to-buffer 'string) | |
551 | (prog1 (buffer-substring (point-min) (point-max)) | |
552 | (kill-buffer (current-buffer))) | |
553 | (current-buffer)))) | |
554 | ||
555 | (defun org-export-ascii-preprocess (parameters) | |
86fbb8ca | 556 | "Do extra work for ASCII export." |
ed21c5c8 CD |
557 | ;; |
558 | ;; Realign tables to get rid of narrowing | |
559 | (when org-export-ascii-table-widen-columns | |
560 | (let ((org-table-do-narrow nil)) | |
561 | (goto-char (point-min)) | |
562 | (org-ascii-replace-entities) | |
563 | (goto-char (point-min)) | |
564 | (org-table-map-tables | |
86fbb8ca CD |
565 | (lambda () (org-if-unprotected (org-table-align))) |
566 | 'quietly))) | |
c8d0cf5c CD |
567 | ;; Put quotes around verbatim text |
568 | (goto-char (point-min)) | |
569 | (while (re-search-forward org-verbatim-re nil t) | |
ed21c5c8 CD |
570 | (org-if-unprotected-at (match-beginning 4) |
571 | (goto-char (match-end 2)) | |
572 | (backward-delete-char 1) (insert "'") | |
573 | (goto-char (match-beginning 2)) | |
574 | (delete-char 1) (insert "`") | |
575 | (goto-char (match-end 2)))) | |
c8d0cf5c CD |
576 | ;; Remove target markers |
577 | (goto-char (point-min)) | |
578 | (while (re-search-forward "<<<?\\([^<>]*\\)>>>?\\([ \t]*\\)" nil t) | |
ed21c5c8 | 579 | (org-if-unprotected-at (match-beginning 1) |
86fbb8ca CD |
580 | (replace-match "\\1\\2"))) |
581 | ;; Remove list start counters | |
582 | (goto-char (point-min)) | |
3ab2c837 BG |
583 | (while (org-list-search-forward |
584 | "\\[@\\(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\][ \t]*" nil t) | |
afe98dfa CD |
585 | (replace-match "")) |
586 | (remove-text-properties | |
587 | (point-min) (point-max) | |
588 | '(face nil font-lock-fontified nil font-lock-multiline nil line-prefix nil wrap-prefix nil))) | |
c8d0cf5c CD |
589 | |
590 | (defun org-html-expand-for-ascii (line) | |
591 | "Handle quoted HTML for ASCII export." | |
592 | (if org-export-html-expand | |
593 | (while (string-match "@<[^<>\n]*>" line) | |
594 | ;; We just remove the tags for now. | |
595 | (setq line (replace-match "" nil nil line)))) | |
596 | line) | |
597 | ||
ed21c5c8 CD |
598 | (defun org-ascii-replace-entities () |
599 | "Replace entities with the ASCII representation." | |
600 | (let (e) | |
afe98dfa | 601 | (while (re-search-forward "\\\\\\([a-zA-Z]+[0-9]*\\)\\({}\\)?" nil t) |
ed21c5c8 CD |
602 | (org-if-unprotected-at (match-beginning 1) |
603 | (setq e (org-entity-get-representation (match-string 1) | |
604 | org-export-ascii-entities)) | |
605 | (and e (replace-match e t t)))))) | |
606 | ||
c8d0cf5c CD |
607 | (defun org-export-ascii-wrap (line where) |
608 | "Wrap LINE at or before WHERE." | |
609 | (let ((ind (org-get-indentation line)) | |
610 | pos) | |
611 | (catch 'found | |
612 | (loop for i from where downto (/ where 2) do | |
613 | (and (equal (aref line i) ?\ ) | |
614 | (setq pos i) | |
615 | (throw 'found t)))) | |
616 | (if pos | |
617 | (concat (substring line 0 pos) "\n" | |
618 | (make-string ind ?\ ) | |
619 | (substring line (1+ pos))) | |
620 | line))) | |
621 | ||
622 | (defun org-export-ascii-push-links (link-buffer) | |
623 | "Push out links in the buffer." | |
624 | (when link-buffer | |
625 | ;; We still have links to push out. | |
626 | (insert "\n") | |
627 | (let ((ind "")) | |
628 | (save-match-data | |
629 | (if (save-excursion | |
630 | (re-search-backward | |
3ab2c837 BG |
631 | (concat "^\\(\\([ \t]*\\)\\|\\(" |
632 | org-outline-regexp | |
633 | "\\)\\)[^ \t\n]") nil t)) | |
c8d0cf5c CD |
634 | (setq ind (or (match-string 2) |
635 | (make-string (length (match-string 3)) ?\ ))))) | |
636 | (mapc (lambda (x) (insert ind "[" (car x) "]: " (cdr x) "\n")) | |
637 | link-buffer)) | |
638 | (insert "\n"))) | |
639 | ||
640 | (defun org-ascii-level-start (level title umax &optional lines) | |
641 | "Insert a new level in ASCII export." | |
642 | (let (char (n (- level umax 1)) (ind 0)) | |
643 | (if (> level umax) | |
644 | (progn | |
645 | (insert (make-string (* 2 n) ?\ ) | |
646 | (char-to-string (nth (% n (length org-export-ascii-bullets)) | |
647 | org-export-ascii-bullets)) | |
648 | " " title "\n") | |
649 | ;; find the indentation of the next non-empty line | |
650 | (catch 'stop | |
651 | (while lines | |
652 | (if (string-match "^\\* " (car lines)) (throw 'stop nil)) | |
653 | (if (string-match "^\\([ \t]*\\)\\S-" (car lines)) | |
654 | (throw 'stop (setq ind (org-get-indentation (car lines))))) | |
655 | (pop lines))) | |
656 | (setq org-ascii-current-indentation (cons (* 2 (1+ n)) ind))) | |
657 | (if (or (not (equal (char-before) ?\n)) | |
658 | (not (equal (char-before (1- (point))) ?\n))) | |
659 | (insert "\n")) | |
3ab2c837 BG |
660 | (setq char (or (nth (1- level) org-export-ascii-underline) |
661 | (car (last org-export-ascii-underline)))) | |
c8d0cf5c | 662 | (unless org-export-with-tags |
afe98dfa | 663 | (if (string-match (org-re "[ \t]+\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$") title) |
c8d0cf5c CD |
664 | (setq title (replace-match "" t t title)))) |
665 | (if org-export-with-section-numbers | |
666 | (setq title (concat (org-section-number level) " " title))) | |
667 | (insert title "\n" (make-string (string-width title) char) "\n") | |
668 | (setq org-ascii-current-indentation '(0 . 0))))) | |
669 | ||
670 | (defun org-insert-centered (s &optional underline) | |
671 | "Insert the string S centered and underline it with character UNDERLINE." | |
672 | (let ((ind (max (/ (- fill-column (string-width s)) 2) 0))) | |
673 | (insert (make-string ind ?\ ) s "\n") | |
674 | (if underline | |
675 | (insert (make-string ind ?\ ) | |
676 | (make-string (string-width s) underline) | |
677 | "\n")))) | |
678 | ||
679 | (defvar org-table-colgroup-info nil) | |
680 | (defun org-format-table-ascii (lines) | |
681 | "Format a table for ascii export." | |
682 | (if (stringp lines) | |
683 | (setq lines (org-split-string lines "\n"))) | |
684 | (if (not (string-match "^[ \t]*|" (car lines))) | |
685 | ;; Table made by table.el - test for spanning | |
686 | lines | |
687 | ||
688 | ;; A normal org table | |
689 | ;; Get rid of hlines at beginning and end | |
690 | (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines))) | |
691 | (setq lines (nreverse lines)) | |
692 | (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines))) | |
693 | (setq lines (nreverse lines)) | |
694 | (when org-export-table-remove-special-lines | |
695 | ;; Check if the table has a marking column. If yes remove the | |
696 | ;; column and the special lines | |
697 | (setq lines (org-table-clean-before-export lines))) | |
698 | ;; Get rid of the vertical lines except for grouping | |
8bfe682a CD |
699 | (if org-export-ascii-table-keep-all-vertical-lines |
700 | lines | |
701 | (let ((vl (org-colgroup-info-to-vline-list org-table-colgroup-info)) | |
702 | rtn line vl1 start) | |
703 | (while (setq line (pop lines)) | |
704 | (if (string-match org-table-hline-regexp line) | |
705 | (and (string-match "|\\(.*\\)|" line) | |
706 | (setq line (replace-match " \\1" t nil line))) | |
707 | (setq start 0 vl1 vl) | |
708 | (while (string-match "|" line start) | |
709 | (setq start (match-end 0)) | |
710 | (or (pop vl1) (setq line (replace-match " " t t line))))) | |
711 | (push line rtn)) | |
712 | (nreverse rtn))))) | |
c8d0cf5c CD |
713 | |
714 | (defun org-colgroup-info-to-vline-list (info) | |
715 | (let (vl new last) | |
716 | (while info | |
717 | (setq last new new (pop info)) | |
718 | (if (or (memq last '(:end :startend)) | |
719 | (memq new '(:start :startend))) | |
720 | (push t vl) | |
721 | (push nil vl))) | |
722 | (setq vl (nreverse vl)) | |
723 | (and vl (setcar vl nil)) | |
724 | vl)) | |
725 | ||
726 | (provide 'org-ascii) | |
727 | ||
5b409b39 | 728 | |
c8d0cf5c | 729 | ;;; org-ascii.el ends here |