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