emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [O] [RFC] ox-ascii.el: fixing variable width character handling


From: Yasushi SHOJI
Subject: Re: [O] [RFC] ox-ascii.el: fixing variable width character handling
Date: Sat, 04 Jan 2014 20:18:17 +0900
User-agent: Wanderlust/2.15.9

Hi,

At Fri, 03 Jan 2014 10:34:08 +0100,
Nicolas Goaziou wrote:
> 
> Thank you. It looks mostly good, but I cannot apply it on top of master
> branch. Could you rebase and send an updated version?

Opps.  Rebased version attached.

> The usual format is
> 
>   (org-ascii--build-title, org-ascii--build-toc, ...): Likewise.
> 
> IOW, you don't need a new line for each function.

Thanks.  I've now checked Emacs' Changelog.  It seems like each line
have open and close parentheses.  Am I right?

> > -            (let ((struct (org-element-property :structure parent-item))
> > -                  (beg-item (org-element-property :begin parent-item)))
> > +            (let* ((struct (org-element-property :structure parent-item))
> > +                   (beg-item (org-element-property :begin parent-item))
> > +                   (tag (org-list-get-tag beg-item struct))
> > +                   (bullet (org-list-get-bullet beg-item struct)))
> 
> Since you don't use these variables below, you can skip both tag and
> bullet binding.

My bad.  Deleted.  New patch attached.

----- >8 ----- >8 ----- >8 -----
Subject: [PATCH] ox-ascii: Convert `length' to `string-width' where
 appropriate

* lisp/ox-ascii.el (org-ascii--current-text-width): Convert `length'
  to `string-width'.
  (org-ascii--build-title, org-ascii--build-toc)
  (org-ascii--list-listings, org-ascii--list-tables)
  (org-ascii-template--document-title)
  (org-ascii-inner-template, org-ascii-format-inlinetask-default)
  (org-ascii-format-inlinetask-default, org-ascii-item
  (org-ascii--table-cell-width, org-ascii-table-cell)
  (org-ascii--current-text-width): Likewise.

I've checked all occurrences of the function `length' in ox-ascii.el.
It turns out that the most of them are calculating the width of given
string. To support fullwidth characters, we better use `string-width'
instead of `length'.

Some characters in UCS are categorized as "East Asian Ambiguous"[1].
The return value of `string-width' with those characters depends on
how Emacs is setup.  We leave those ambiguous character handling to
Emacs.

Two usages of `length' in `ox-ascii.el' were left as-is, because those
were used for:

 - bullet depth calculation in `org-ascii-headline', and
 - cell position calculation in `org-ascii--table-cell-width'.

[1]: http://www.unicode.org/reports/tr11/#Ambiguous
---
 lisp/ox-ascii.el | 71 +++++++++++++++++++++++++++++++-------------------------
 1 file changed, 40 insertions(+), 31 deletions(-)

diff --git a/lisp/ox-ascii.el b/lisp/ox-ascii.el
index b278ab6..4b20afd 100644
--- a/lisp/ox-ascii.el
+++ b/lisp/ox-ascii.el
@@ -527,15 +527,16 @@ INFO is a plist used as a communication channel."
                 ;; the list and current item bullet's length.  Also
                 ;; remove checkbox length, and tag length (for
                 ;; description lists) or bullet length.
-                (let ((struct (org-element-property :structure parent-item))
-                      (beg-item (org-element-property :begin parent-item)))
+                (let* ((struct (org-element-property :structure parent-item))
+                       (beg-item (org-element-property :begin parent-item)))
                   (+ (- (org-list-get-ind beg-item struct)
                         (org-list-get-ind
                          (org-list-get-top-point struct) struct))
-                     (length (org-ascii--checkbox parent-item info))
-                     (length
+                     (string-width (or (org-ascii--checkbox parent-item info) 
""))
+                     (string-width
                       (or (org-list-get-tag beg-item struct)
-                          (org-list-get-bullet beg-item struct)))))))))))))
+                          (org-list-get-bullet beg-item struct)
+                          ""))))))))))))
 
 (defun org-ascii--build-title
   (element info text-width &optional underline notags toc)
@@ -591,7 +592,8 @@ possible.  It doesn't apply to `inlinetask' elements."
      (when tags
        (format
        (format " %%%ds"
-               (max (- text-width  (1+ (length first-part))) (length tags)))
+               (max (- text-width (1+ (string-width first-part)))
+                    (string-width tags)))
        tags))
      ;; Maybe underline text, if ELEMENT type is `headline' and an
      ;; underline character has been defined.
@@ -602,7 +604,9 @@ possible.  It doesn't apply to `inlinetask' elements."
                              org-ascii-underline)))))
         (and under-char
              (concat "\n"
-                     (make-string (length first-part) under-char))))))))
+                     (make-string (/ (string-width first-part)
+                                     (char-width under-char))
+                                  under-char))))))))
 
 (defun org-ascii--has-caption-p (element info)
   "Non-nil when ELEMENT has a caption affiliated keyword.
@@ -649,7 +653,7 @@ which the table of contents generation has been initiated."
   (let ((title (org-ascii--translate "Table of Contents" info)))
     (concat
      title "\n"
-     (make-string (length title)
+     (make-string (string-width title)
                  (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_))
      "\n\n"
      (let ((text-width
@@ -676,7 +680,7 @@ generation.  INFO is a plist used as a communication 
channel."
   (let ((title (org-ascii--translate "List of Listings" info)))
     (concat
      title "\n"
-     (make-string (length title)
+     (make-string (string-width title)
                  (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_))
      "\n\n"
      (let ((text-width
@@ -690,9 +694,10 @@ generation.  INFO is a plist used as a communication 
channel."
          ;; Store initial text so its length can be computed.  This is
          ;; used to properly align caption right to it in case of
          ;; filling (like contents of a description list item).
-         (let ((initial-text
-                (format (org-ascii--translate "Listing %d:" info)
-                        (incf count))))
+         (let* ((initial-text
+                 (format (org-ascii--translate "Listing %d:" info)
+                         (incf count)))
+                (width (string-width initial-text)))
            (concat
             initial-text " "
             (org-trim
@@ -702,8 +707,8 @@ generation.  INFO is a plist used as a communication 
channel."
                (let ((caption (or (org-export-get-caption src-block t)
                                   (org-export-get-caption src-block))))
                  (org-export-data caption info))
-               (- text-width (length initial-text)) info)
-              (length initial-text))))))
+               (- text-width width) info)
+              width)))))
        (org-export-collect-listings info) "\n")))))
 
 (defun org-ascii--list-tables (keyword info)
@@ -714,7 +719,7 @@ generation.  INFO is a plist used as a communication 
channel."
   (let ((title (org-ascii--translate "List of Tables" info)))
     (concat
      title "\n"
-     (make-string (length title)
+     (make-string (string-width title)
                  (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_))
      "\n\n"
      (let ((text-width
@@ -728,9 +733,10 @@ generation.  INFO is a plist used as a communication 
channel."
          ;; Store initial text so its length can be computed.  This is
          ;; used to properly align caption right to it in case of
          ;; filling (like contents of a description list item).
-         (let ((initial-text
-                (format (org-ascii--translate "Table %d:" info)
-                        (incf count))))
+         (let* ((initial-text
+                 (format (org-ascii--translate "Table %d:" info)
+                         (incf count)))
+                (width (string-width initial-text)))
            (concat
             initial-text " "
             (org-trim
@@ -740,8 +746,8 @@ generation.  INFO is a plist used as a communication 
channel."
                (let ((caption (or (org-export-get-caption table t)
                                   (org-export-get-caption table))))
                  (org-export-data caption info))
-               (- text-width (length initial-text)) info)
-              (length initial-text))))))
+               (- text-width width) info)
+              width)))))
        (org-export-collect-tables info) "\n")))))
 
 (defun org-ascii--unique-links (element info)
@@ -854,14 +860,14 @@ INFO is a plist used as a communication channel."
         ((and (org-string-nw-p date) (org-string-nw-p author))
          (concat
           author
-          (make-string (- text-width (length date) (length author)) ? )
+          (make-string (- text-width (string-width date) (string-width 
author)) ? )
           date
           (when (org-string-nw-p email) (concat "\n" email))
           "\n\n\n"))
         ((and (org-string-nw-p date) (org-string-nw-p email))
          (concat
           email
-          (make-string (- text-width (length date) (length email)) ? )
+          (make-string (- text-width (string-width date) (string-width email)) 
? )
           date "\n\n\n"))
         ((org-string-nw-p date)
          (concat
@@ -877,11 +883,13 @@ INFO is a plist used as a communication channel."
       (let* ((utf8p (eq (plist-get info :ascii-charset) 'utf-8))
             ;; Format TITLE.  It may be filled if it is too wide,
             ;; that is wider than the two thirds of the total width.
-            (title-len (min (length title) (/ (* 2 text-width) 3)))
+            (title-len (min (string-width title) (/ (* 2 text-width) 3)))
             (formatted-title (org-ascii--fill-string title title-len info))
             (line
              (make-string
-              (min (+ (max title-len (length author) (length email)) 2)
+              (min (+ (max title-len
+                           (string-width (or author ""))
+                           (string-width (or email ""))) 2)
                    text-width) (if utf8p ?━ ?_))))
        (org-ascii--justify-string
         (concat line "\n"
@@ -920,7 +928,7 @@ holding export options."
            (concat
             title "\n"
             (make-string
-             (length title)
+             (string-width title)
              (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_))))
          "\n\n"
          (let ((text-width (- org-ascii-text-width org-ascii-global-margin)))
@@ -1197,7 +1205,7 @@ contextual information."
 ;;;; Inlinetask
 
 (defun org-ascii-format-inlinetask-default
-    (todo type priority name tags contents width inlinetask info)
+  (todo type priority name tags contents width inlinetask info)
   "Format an inline task element for ASCII export.
 See `org-ascii-format-inlinetask-function' for a description
 of the paramaters."
@@ -1210,7 +1218,7 @@ of the paramaters."
       (unless utf8p (concat (make-string width ? ) "\n"))
       ;; Add title.  Fill it if wider than inlinetask.
       (let ((title (org-ascii--build-title inlinetask info width)))
-       (if (<= (length title) width) title
+       (if (<= (string-width title) width) title
          (org-ascii--fill-string title width info)))
       "\n"
       ;; If CONTENTS is not empty, insert it along with
@@ -1303,7 +1311,7 @@ contextual information."
      ;; Contents: Pay attention to indentation.  Note: check-boxes are
      ;; already taken care of at the paragraph level so they don't
      ;; interfere with indentation.
-     (let ((contents (org-ascii--indent-string contents (length bullet))))
+     (let ((contents (org-ascii--indent-string contents (string-width 
bullet))))
        (if (eq (org-element-type (car (org-element-contents item))) 'paragraph)
           (org-trim contents)
         (concat "\n" contents))))))
@@ -1675,7 +1683,7 @@ are ignored."
               (org-element-map table 'table-row
                 (lambda (row)
                   (setq max-width
-                        (max (length
+                        (max (string-width
                               (org-export-data
                                (org-element-contents
                                 (elt (org-element-contents row) col))
@@ -1695,7 +1703,8 @@ a communication channel."
   ;; each cell in the column.
   (let ((width (org-ascii--table-cell-width table-cell info)))
     ;; When contents are too large, truncate them.
-    (unless (or org-ascii-table-widen-columns (<= (length contents) width))
+    (unless (or org-ascii-table-widen-columns
+               (<= (string-width (or contents "")) width))
       (setq contents (concat (substring contents 0 (- width 2)) "=>")))
     ;; Align contents correctly within the cell.
     (let* ((indent-tabs-mode nil)
@@ -1704,7 +1713,7 @@ a communication channel."
              (org-ascii--justify-string
               contents width
               (org-export-table-cell-alignment table-cell info)))))
-      (setq contents (concat data (make-string (- width (length data)) ? ))))
+      (setq contents (concat data (make-string (- width (string-width (or data 
""))) ? ))))
     ;; Return cell.
     (concat (format " %s " contents)
            (when (memq 'right (org-export-table-cell-borders table-cell info))
-- 
1.8.5.2

-- 
             yashi



reply via email to

[Prev in Thread] Current Thread [Next in Thread]