From mboxrd@z Thu Jan 1 00:00:00 1970 From: Nicolas Goaziou Subject: Re: wish: provide flush_right/right_aligned text rendering directive Date: Thu, 22 May 2014 00:12:57 +0200 Message-ID: <877g5ezspi.fsf@gmail.com> References: <20140510135216.GA2041@boo.workgroup> <878upvsw1u.fsf@bzg.ath.cx> <20140521073916.GA25852@boo.workgroup> <87sio3ic8y.fsf@bzg.ath.cx> <877g5f1dso.fsf@gmail.com> <878upvw9yr.fsf@bzg.ath.cx> <8738g31cfg.fsf@gmail.com> <87egznutrb.fsf@bzg.ath.cx> <87mwebyzcr.fsf@gmail.com> <87y4xvjfjk.fsf@bzg.ath.cx> <87ioozyuuf.fsf@gmail.com> <87k39fje7m.fsf@bzg.ath.cx> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:46976) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WnEkP-000102-1m for emacs-orgmode@gnu.org; Wed, 21 May 2014 18:12:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WnEkI-0006wt-JF for emacs-orgmode@gnu.org; Wed, 21 May 2014 18:12:28 -0400 In-Reply-To: <87k39fje7m.fsf@bzg.ath.cx> (Bastien's message of "Wed, 21 May 2014 18:20:29 +0200") List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Bastien Cc: emacs-orgmode --=-=-= Content-Type: text/plain Bastien writes: > Yes -- I suggest we simply put this aside for the moment. Well, actually it required more work than I thought. Here is the patch, with some documentation. I didn't test it thoroughly, so feedback is welcome. Regards, -- Nicolas Goaziou --=-=-= Content-Type: text/x-diff; charset=utf-8 Content-Disposition: inline; filename=0001-ox-ascii-Implement-justifyright-and-justifyleft-bloc.patch Content-Transfer-Encoding: quoted-printable >From 744ee75b33ce1dea299626621558901d9ada09ef Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Wed, 21 May 2014 23:37:00 +0200 Subject: [PATCH] ox-ascii: Implement "justifyright" and "justifyleft" blocks * lisp/ox-ascii.el (org-ascii--justify-lines): New function. Renamed from `org-ascii--justify-string'. (org-ascii--justify-element, org-ascii--current-justification): New functions. (org-ascii-verse-block, org-ascii-table-cell, org-ascii-table org-ascii-src-block, org-ascii-property-drawer, org-ascii-planning, org-ascii-paragraph, org-ascii-paragraph, org-ascii-latex-environment, org-ascii-horizontal-rule, org-ascii-fixed-width, org-ascii-export-block, org-ascii-example-block, org-ascii-clock, org-ascii-center-block, org-ascii-template--document-title, org-ascii-template--document-title): Use new functions. * doc/org.texi (ASCII/Latin-1/UTF-8 export): Document new feature. This patches also fixes centering of tables. --- doc/org.texi | 19 +++++ lisp/ox-ascii.el | 227 +++++++++++++++++++++++++++++++++++----------------= ---- 2 files changed, 165 insertions(+), 81 deletions(-) diff --git a/doc/org.texi b/doc/org.texi index c685748..9cf0d7f 100644 --- a/doc/org.texi +++ b/doc/org.texi @@ -10804,6 +10804,25 @@ specified using an @code{ATTR_ASCII} line, directl= y preceding the rule. ----- @end example =20 +@subheading ASCII special blocks +@cindex special blocks, in ASCII export +@cindex #+BEGIN_JUSTIFYLEFT +@cindex #+BEGIN_JUSTIFYRIGHT + +In addition to @code{#+BEGIN_CENTER} blocks (@pxref{Paragraphs}), it is +possible to justify contents to the left or the right of the page with the +following dedicated blocks. + +@example +#+BEGIN_JUSTIFYLEFT +It's just a jump to the left +#+END_JUSTIFYLEFT + +#+BEGIN_JUSTIFYRIGHT +And then a step to the right. +#+END_JUSTIFYRIGHT +@end example + @node Beamer export @section Beamer export @cindex Beamer export diff --git a/lisp/ox-ascii.el b/lisp/ox-ascii.el index 858e3f0..b7ed268 100644 --- a/lisp/ox-ascii.el +++ b/lisp/ox-ascii.el @@ -385,14 +385,14 @@ nil to ignore the inline task." =20 ;; Internal functions fall into three categories. =20 -;; The first one is about text formatting. The core function is -;; `org-ascii--current-text-width', which determines the current -;; text width allowed to a given element. In other words, it helps -;; keeping each line width within maximum text width defined in -;; `org-ascii-text-width'. Once this information is known, -;; `org-ascii--fill-string', `org-ascii--justify-string', -;; `org-ascii--box-string' and `org-ascii--indent-string' can -;; operate on a given output string. +;; The first one is about text formatting. The core functions are +;; `org-ascii--current-text-width' and +;; `org-ascii--current-justification', which determine, respectively, +;; the current text width allowed to a given element and its expected +;; justification. Once this information is known, +;; `org-ascii--fill-string', `org-ascii--justify-lines', +;; `org-ascii--justify-element' `org-ascii--box-string' and +;; `org-ascii--indent-string' can operate on a given output string. =20 ;; The second category contains functions handling elements listings, ;; triggered by "#+TOC:" keyword. As such, `org-ascii--build-toc' @@ -421,7 +421,8 @@ a communication channel. Optional argument JUSTIFY can specify any type of justification among `left', `center', `right' or `full'. A nil value is equivalent to `left'. For a justification that doesn't also fill -string, see `org-ascii--justify-string'. +string, see `org-ascii--justify-lines' and +`org-ascii--justify-block'. =20 Return nil if S isn't a string." ;; Don't fill paragraph when break should be preserved. @@ -436,8 +437,8 @@ Return nil if S isn't a string." (fill-region (point-min) (point-max) justify)) (buffer-string)))))) =20 -(defun org-ascii--justify-string (s text-width how) - "Justify string S. +(defun org-ascii--justify-lines (s text-width how) + "Justify all lines in string S. TEXT-WIDTH is an integer specifying maximum length of a line. HOW determines the type of justification: it can be `left', `right', `full' or `center'." @@ -453,6 +454,40 @@ HOW determines the type of justification: it can be `l= eft', (forward-line))) (buffer-string))) =20 +(defun org-ascii--justify-element (contents element info) + "Justify CONTENTS of ELEMENT, as a block. +INFO is a plist used as a communication channel. Justification +is done according to the widest non blank line in CONTENTS. It +is appropriate for regular (i.e, non-greater) elements, except +paragraphs, which should be filled instead." + (if (not (org-string-nw-p contents)) contents + (let ((text-width (org-ascii--current-text-width element info)) + (how (org-ascii--current-justification element))) + (if (eq how 'left) contents + ;; Paragraphs are treated specially as they also need to be + ;; filled. + (if (eq (org-element-type element) 'paragraph) + (org-ascii--fill-string contents text-width info how) + (with-temp-buffer + (insert contents) + (goto-char (point-min)) + (let ((max-width 0)) + ;; Compute max width. + (save-excursion + (while (not (eobp)) + (unless (org-looking-at-p "[ \t]*$") + (end-of-line) + (when (> (current-column) max-width) + (setq max-width (current-column)))) + (forward-line))) + ;; Justify every line according to TEXT-WIDTH and MAX-WIDTH. + (while (not (eobp)) + (unless (org-looking-at-p "[ \t]*$") + (org-indent-to-column + (/ (- text-width max-width) (if (eq how 'right) 1 2)))) + (forward-line))) + (buffer-string))))))) + (defun org-ascii--indent-string (s width) "Indent string S by WIDTH white spaces. Empty lines are not indented." @@ -539,6 +574,21 @@ INFO is a plist used as a communication channel." (or (org-list-get-tag beg-item struct) (org-list-get-bullet beg-item struct))))))))))))) =20 +(defun org-ascii--current-justification (element) + "Return expected justification for ELEMENT's contents. +Return value is a symbol among `left', `center', `right' and +`full'." + (let (justification) + (while (and (not justification) + (setq element (org-element-property :parent element))) + (case (org-element-type element) + (center-block (setq justification 'center)) + (special-block + (let ((name (org-element-property :type element))) + (cond ((string=3D name "JUSTIFYRIGHT") (setq justification 'right)) + ((string=3D name "JUSTIFYLEFT") (setq justification 'left))))))) + (or justification 'left))) + (defun org-ascii--build-title (element info text-width &optional underline notags toc) "Format ELEMENT title and return it. @@ -879,7 +929,7 @@ INFO is a plist used as a communication channel." date "\n\n\n")) ((org-string-nw-p date) (concat - (org-ascii--justify-string date text-width 'right) + (org-ascii--justify-lines date text-width 'right) "\n\n\n")) ((and (org-string-nw-p author) (org-string-nw-p email)) (concat author "\n" email "\n\n\n")) @@ -900,7 +950,7 @@ INFO is a plist used as a communication channel." (string-width (or email ""))) 2) text-width) (if utf8p ?=E2=94=81 ?_)))) - (org-ascii--justify-string + (org-ascii--justify-lines (concat line "\n" (unless utf8p "\n") (upcase formatted-title) @@ -1021,8 +1071,7 @@ contextual information." "Transcode a CENTER-BLOCK element from Org to ASCII. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." - (org-ascii--justify-string - contents (org-ascii--current-text-width center-block info) 'center)) + contents) =20 =20 ;;;; Clock @@ -1031,16 +1080,18 @@ holding contextual information." "Transcode a CLOCK object from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." - (concat org-clock-string " " - (org-translate-time - (org-element-property :raw-value - (org-element-property :value clock))) - (let ((time (org-element-property :duration clock))) - (and time - (concat " =3D> " - (apply 'format - "%2s:%02s" - (org-split-string time ":"))))))) + (org-ascii--justify-element + (concat org-clock-string " " + (org-translate-time + (org-element-property :raw-value + (org-element-property :value clock))) + (let ((time (org-element-property :duration clock))) + (and time + (concat " =3D> " + (apply 'format + "%2s:%02s" + (org-split-string time ":")))))) + clock info)) =20 =20 ;;;; Code @@ -1088,8 +1139,10 @@ contextual information." (defun org-ascii-example-block (example-block contents info) "Transcode a EXAMPLE-BLOCK element from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." - (org-ascii--box-string - (org-export-format-code-default example-block info) info)) + (org-ascii--justify-element + (org-ascii--box-string + (org-export-format-code-default example-block info) info) + example-block info)) =20 =20 ;;;; Export Snippet @@ -1107,7 +1160,8 @@ CONTENTS is nil. INFO is a plist holding contextual = information." "Transcode a EXPORT-BLOCK element from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." (when (string=3D (org-element-property :type export-block) "ASCII") - (org-remove-indentation (org-element-property :value export-block)))) + (org-ascii--justify-element + (org-element-property :value export-block) export-block info))) =20 =20 ;;;; Fixed Width @@ -1115,9 +1169,11 @@ CONTENTS is nil. INFO is a plist holding contextual= information." (defun org-ascii-fixed-width (fixed-width contents info) "Transcode a FIXED-WIDTH element from Org to ASCII. CONTENTS is nil. INFO is a plist holding contextual information." - (org-ascii--box-string - (org-remove-indentation - (org-element-property :value fixed-width)) info)) + (org-ascii--justify-element + (org-ascii--box-string + (org-remove-indentation + (org-element-property :value fixed-width)) info) + fixed-width info)) =20 =20 ;;;; Footnote Definition @@ -1193,7 +1249,7 @@ information." (let ((text-width (org-ascii--current-text-width horizontal-rule info)) (spec-width (org-export-read-attribute :attr_ascii horizontal-rule :width))) - (org-ascii--justify-string + (org-ascii--justify-lines (make-string (if (and spec-width (string-match "^[0-9]+$" spec-width)) (string-to-number spec-width) text-width) @@ -1358,7 +1414,9 @@ information." CONTENTS is nil. INFO is a plist holding contextual information." (when (plist-get info :with-latex) - (org-remove-indentation (org-element-property :value latex-environment= )))) + (org-ascii--justify-element + (org-remove-indentation (org-element-property :value latex-environmen= t)) + latex-environment info))) =20 =20 ;;;; Latex Fragment @@ -1433,7 +1491,7 @@ information." "Transcode a PARAGRAPH element from Org to ASCII. CONTENTS is the contents of the paragraph, as a string. INFO is the plist used as a communication channel." - (org-ascii--fill-string + (org-ascii--justify-element (if (not (wholenump org-ascii-indented-line-width)) contents (concat ;; Do not indent first paragraph in a section. @@ -1442,7 +1500,7 @@ the plist used as a communication channel." 'section)) (make-string org-ascii-indented-line-width ?\s)) (replace-regexp-in-string "\\`[ \t]+" "" contents))) - (org-ascii--current-text-width paragraph info) info)) + paragraph info)) =20 =20 ;;;; Plain List @@ -1479,25 +1537,27 @@ INFO is a plist used as a communication channel." "Transcode a PLANNING element from Org to ASCII. CONTENTS is nil. INFO is a plist used as a communication channel." - (mapconcat - 'identity - (delq nil - (list (let ((closed (org-element-property :closed planning))) - (when closed - (concat org-closed-string " " - (org-translate-time - (org-element-property :raw-value closed))))) - (let ((deadline (org-element-property :deadline planning))) - (when deadline - (concat org-deadline-string " " - (org-translate-time - (org-element-property :raw-value deadline))))) - (let ((scheduled (org-element-property :scheduled planning))) - (when scheduled - (concat org-scheduled-string " " - (org-translate-time - (org-element-property :raw-value scheduled))))))) - " ")) + (org-ascii--justify-element + (mapconcat + #'identity + (delq nil + (list (let ((closed (org-element-property :closed planning))) + (when closed + (concat org-closed-string " " + (org-translate-time + (org-element-property :raw-value closed))))) + (let ((deadline (org-element-property :deadline planning))) + (when deadline + (concat org-deadline-string " " + (org-translate-time + (org-element-property :raw-value deadline))))) + (let ((scheduled (org-element-property :scheduled planning))) + (when scheduled + (concat org-scheduled-string " " + (org-translate-time + (org-element-property :raw-value scheduled))))))) + " ") + planning info)) =20 =20 ;;;; Property Drawer @@ -1506,7 +1566,8 @@ channel." "Transcode a PROPERTY-DRAWER element from Org to ASCII. CONTENTS holds the contents of the drawer. INFO is a plist holding contextual information." - (org-string-nw-p contents)) + (and (org-string-nw-p contents) + (org-ascii--justify-element contents property-drawer info))) =20 =20 ;;;; Quote Block @@ -1567,11 +1628,13 @@ contextual information." (let ((caption (org-ascii--build-caption src-block info)) (code (org-export-format-code-default src-block info))) (if (equal code "") "" - (concat - (when (and caption org-ascii-caption-above) (concat caption "\n")) - (org-ascii--box-string code info) - (when (and caption (not org-ascii-caption-above)) - (concat "\n" caption)))))) + (org-ascii--justify-element + (concat + (when (and caption org-ascii-caption-above) (concat caption "\n")) + (org-ascii--box-string code info) + (when (and caption (not org-ascii-caption-above)) + (concat "\n" caption))) + src-block info)))) =20 =20 ;;;; Statistics Cookie @@ -1620,25 +1683,27 @@ holding contextual information." CONTENTS is the contents of the table. INFO is a plist holding contextual information." (let ((caption (org-ascii--build-caption table info))) - (concat - ;; Possibly add a caption string above. - (when (and caption org-ascii-caption-above) (concat caption "\n")) - ;; Insert table. Note: "table.el" tables are left unmodified. - (cond ((eq (org-element-property :type table) 'org) contents) - ((and org-ascii-table-use-ascii-art - (eq (plist-get info :ascii-charset) 'utf-8) - (require 'ascii-art-to-unicode nil t)) - (with-temp-buffer - (insert (org-remove-indentation - (org-element-property :value table))) - (goto-char (point-min)) - (aa2u) - (goto-char (point-max)) - (skip-chars-backward " \r\t\n") - (buffer-substring (point-min) (point)))) - (t (org-remove-indentation (org-element-property :value table)))) - ;; Possible add a caption string below. - (and (not org-ascii-caption-above) caption)))) + (org-ascii--justify-element + (concat + ;; Possibly add a caption string above. + (when (and caption org-ascii-caption-above) (concat caption "\n")) + ;; Insert table. Note: "table.el" tables are left unmodified. + (cond ((eq (org-element-property :type table) 'org) contents) + ((and org-ascii-table-use-ascii-art + (eq (plist-get info :ascii-charset) 'utf-8) + (require 'ascii-art-to-unicode nil t)) + (with-temp-buffer + (insert (org-remove-indentation + (org-element-property :value table))) + (goto-char (point-min)) + (aa2u) + (goto-char (point-max)) + (skip-chars-backward " \r\t\n") + (buffer-substring (point-min) (point)))) + (t (org-remove-indentation (org-element-property :value table)))) + ;; Possible add a caption string below. + (and (not org-ascii-caption-above) caption)) + table info))) =20 =20 ;;;; Table Cell @@ -1701,7 +1766,7 @@ a communication channel." (let* ((indent-tabs-mode nil) (data (when contents - (org-ascii--justify-string + (org-ascii--justify-lines contents width (org-export-table-cell-alignment table-cell info))))) (setq contents @@ -1800,7 +1865,7 @@ CONTENTS is verse block contents. INFO is a plist ho= lding contextual information." (let ((verse-width (org-ascii--current-text-width verse-block info))) (org-ascii--indent-string - (org-ascii--justify-string contents verse-width 'left) + (org-ascii--justify-element contents verse-block info) org-ascii-quote-margin))) =20 =20 --=20 1.9.3 --=-=-=--