* DOODLE-TIPS: Add desctiptions about byte-compile warnings.
[elisp/flim.git] / ew-line.el
index c23132c..831d508 100644 (file)
@@ -7,6 +7,22 @@
 (put 'ew-lf-line-generic 'lisp-indent-function 1)
 (put 'ew-lf-line-convert 'lisp-indent-function 1)
 
+(defun ew-tab-to-space (str)
+  (let ((i 0) (j 0) (l (length str)) result)
+    (while (< j l)
+      (when (equal (aref str j) ?\t)
+        (setq result (ew-rcons*
+                      result
+                      (substring str i j)
+                      " ")
+              i j))
+      (setq j (1+ j)))
+    (when (< i l)
+      (setq result (ew-rcons*
+                    result
+                    (substring str i))))
+    (apply 'concat (nreverse result))))
+
 (defun ew-lf-to-crlf (str)
   (let ((i 0) (j 0) (l (length str)) result)
     (while (< j l)
 (defun ew-cut-cr (str) (ew-cut-generic str '(?\r)))
 (defun ew-cut-lf (str) (ew-cut-generic str '(?\n)))
 
-(defmacro ew-crlf-line-generic-define ()
+(defmacro ew-crlf-generic-define ()
   (let ((str (make-symbol "str"))
        (others-fun (make-symbol "others-fun"))
        (fold-fun (make-symbol "fold-fun"))
-       (crlf-fun (make-symbol "crlf-fun"))
-       (bare-cr-fun (make-symbol "bare-cr-fun"))
-       (bare-lf-fun (make-symbol "bare-lf-fun"))
+       (nl-fun (make-symbol "nl-fun"))
+       (cr-fun (make-symbol "cr-fun"))
+       (lf-fun (make-symbol "lf-fun"))
        (p (make-symbol "p"))
        (q (make-symbol "q"))
        (r (make-symbol "r")))
-    `(defun ew-crlf-line-generic
-       (,str ,others-fun ,fold-fun ,crlf-fun ,bare-cr-fun ,bare-lf-fun)
+    `(defun ew-crlf-generic
+       (,str ,others-fun ,fold-fun ,nl-fun ,cr-fun ,lf-fun)
        (let ((,p 0) (,q (length ,str)) ,r)
         (while (< ,p ,q)
           (setq ,r ,p)
           (lex-scan-unibyte ,str ,p ,q
             ((+ [^ "\r\n"]) (when ,others-fun (funcall ,others-fun ,r ,p)))
             ((?\r ?\n [" \t"]) (when ,fold-fun (funcall ,fold-fun ,r ,p)))
-            ((?\r ?\n) (when ,crlf-fun (funcall ,crlf-fun ,r ,p)))
-            ((?\r) (when ,bare-cr-fun (funcall ,bare-cr-fun ,r ,p)))
-            ((?\n) (when ,bare-lf-fun (funcall ,bare-lf-fun ,r ,p)))
+            ((?\r ?\n) (when ,nl-fun (funcall ,nl-fun ,r ,p)))
+            ((?\r) (when ,cr-fun (funcall ,cr-fun ,r ,p)))
+            ((?\n) (when ,lf-fun (funcall ,lf-fun ,r ,p)))
             (() (error "something wrong"))))
         ,q))))
+(ew-crlf-generic-define)
 
+(defmacro ew-crlf-line-generic-define ()
+  (let ((str (make-symbol "str"))
+       (others-fun (make-symbol "others-fun"))
+       (fold-fun (make-symbol "fold-fun"))
+       (nl-fun (make-symbol "nl-fun"))
+       (p (make-symbol "p"))
+       (q (make-symbol "q"))
+       (r (make-symbol "r")))
+    `(defun ew-crlf-line-generic
+       (,str ,others-fun ,fold-fun ,nl-fun)
+       (let ((,p 0) (,q (length ,str)) ,r)
+        (while (< ,p ,q)
+          (setq ,r ,p)
+          (lex-scan-unibyte ,str ,p ,q
+            (() (error "something wrong"))
+            (((* [^ "\r\n"])
+              (* (+ ?\r) [^ "\r\n"] (* [^ "\r"]))
+              (* ?\r)
+              (?\r ?\n [" \t"]))
+             (when (and ,others-fun (< ,r (- ,p 3))) (funcall ,others-fun ,r (- ,p 3)))
+             (when ,fold-fun (funcall ,fold-fun (- ,p 3) ,p)))
+            (((* [^ "\r\n"])
+              (* (+ ?\r) [^ "\r\n"] (* [^ "\r"]))
+              (* ?\r)
+              (?\r ?\n))
+             (when (and ,others-fun (< ,r (- ,p 2))) (funcall ,others-fun ,r (- ,p 2)))
+             (when ,nl-fun (funcall ,nl-fun (- ,p 2) ,p)))
+            (((* [^ "\r\n"])
+              (* (+ ?\r) [^ "\r\n"] (* [^ "\r"]))
+              (* ?\r))
+             (when ,others-fun (funcall ,others-fun ,r ,p)))))
+        ,q))))
 (ew-crlf-line-generic-define)
 
-(defmacro ew-crlf-line-convert-define ()
+(defmacro ew-lf-generic-define ()
   (let ((str (make-symbol "str"))
        (others-fun (make-symbol "others-fun"))
        (fold-fun (make-symbol "fold-fun"))
-       (crlf-fun (make-symbol "crlf-fun"))
-       (bare-cr-fun (make-symbol "bare-cr-fun"))
-       (bare-lf-fun (make-symbol "bare-lf-fun"))
-       (index (make-symbol "index"))
-       (result (make-symbol "result"))
-       (start (make-symbol "starx"))
-       (end (make-symbol "end")))
-    `(defun ew-crlf-line-convert
-       (,str ,others-fun ,fold-fun ,crlf-fun ,bare-cr-fun ,bare-lf-fun)
-       (let ((,index 0) ,result)
-        (when (> (ew-crlf-line-generic
-                     ,str
-                   ,@(mapcar
-                      (lambda (fun)
-                        `(when ,fun
-                           (lambda (,start ,end)
-                             (when (< ,index ,start)
-                               (setq ,result
-                                     (ew-rcons* ,result
-                                                (substring ,str ,index ,start))))
-                             (setq ,result
-                                   (ew-rcons* ,result
-                                              (funcall ,fun
-                                                       (substring ,str ,start ,end)))
-                                   ,index ,end))))
-                      (list others-fun fold-fun crlf-fun bare-cr-fun bare-lf-fun)))
-                 ,index)
-          (setq ,result
-                (ew-rcons* ,result
-                           (substring ,str ,index))))
-        (apply 'concat (nreverse ,result))))))
-
-(ew-crlf-line-convert-define)
+       (nl-fun (make-symbol "nl-fun"))
+       (cr-fun (make-symbol "cr-fun"))
+       (p (make-symbol "p"))
+       (q (make-symbol "q"))
+       (r (make-symbol "r")))
+    `(defun ew-lf-generic
+       (,str ,others-fun ,fold-fun ,nl-fun ,cr-fun)
+       (let ((,p 0) (,q (length ,str)) ,r)
+        (while (< ,p ,q)
+          (setq ,r ,p)
+          (lex-scan-unibyte ,str ,p ,q
+            ((+ [^ "\r\n"]) (when ,others-fun (funcall ,others-fun ,r ,p)))
+            ((?\n [" \t"]) (when ,fold-fun (funcall ,fold-fun ,r ,p)))
+            ((?\n) (when ,nl-fun (funcall ,nl-fun ,r ,p)))
+            ((?\r) (when ,cr-fun (funcall ,cr-fun ,r ,p)))
+            (() (error "something wrong"))))
+        ,q))))
+(ew-lf-generic-define)
 
 (defmacro ew-lf-line-generic-define ()
   (let ((str (make-symbol "str"))
        (others-fun (make-symbol "others-fun"))
        (fold-fun (make-symbol "fold-fun"))
-       (lf-fun (make-symbol "lf-fun"))
+       (nl-fun (make-symbol "nl-fun"))
        (p (make-symbol "p"))
        (q (make-symbol "q"))
        (r (make-symbol "r")))
     `(defun ew-lf-line-generic
-       (,str ,others-fun ,fold-fun ,lf-fun)
+       (,str ,others-fun ,fold-fun ,nl-fun)
        (let ((,p 0) (,q (length ,str)) ,r)
         (while (< ,p ,q)
           (setq ,r ,p)
           (lex-scan-unibyte ,str ,p ,q
-            ((+ [^ "\n"]) (when ,others-fun (funcall ,others-fun ,r ,p)))
-            ((?\n [" \t"]) (when ,fold-fun (funcall ,fold-fun ,r ,p)))
-            ((?\n) (when ,lf-fun (funcall ,lf-fun ,r ,p)))
-            (() (error "something wrong"))))
+            (() (error "something wrong"))
+            ((+ [^ "\n"])
+             (when ,others-fun (funcall ,others-fun ,r ,p)))
+            ((?\n [" \t"])
+             (when ,fold-fun (funcall ,fold-fun ,r ,p)))
+            (?\n
+             (when ,nl-fun (funcall ,nl-fun ,r ,p)))))
         ,q))))
-
 (ew-lf-line-generic-define)
 
-(defmacro ew-lf-line-convert-define ()
+(defmacro ew-generic-convert-define (name generic &rest funcs)
   (let ((str (make-symbol "str"))
-       (others-fun (make-symbol "others-fun"))
-       (fold-fun (make-symbol "fold-fun"))
-       (lf-fun (make-symbol "lf-fun"))
+       (funcs-vars (mapcar (lambda (func) (make-symbol (symbol-name func))) funcs))
        (index (make-symbol "index"))
        (result (make-symbol "result"))
+       (tmp (make-symbol "tmp"))
        (start (make-symbol "starx"))
        (end (make-symbol "end")))
-    `(defun ew-lf-line-convert
-       (,str ,others-fun ,fold-fun ,lf-fun)
-       (let ((,index 0) ,result)
-        (when (> (ew-lf-line-generic
-                     ,str
-                   ,@(mapcar
-                      (lambda (fun)
-                        `(when ,fun
-                           (lambda (,start ,end)
-                             (when (< ,index ,start)
-                               (setq ,result
-                                     (ew-rcons* ,result
-                                                (substring ,str ,index ,start))))
-                             (setq ,result
-                                   (ew-rcons* ,result
-                                              (funcall ,fun
-                                                       (substring ,str ,start ,end)))
-                                   ,index ,end))))
-                      (list others-fun fold-fun lf-fun)))
+    `(defun ,name
+       (,str ,@funcs-vars)
+       (let ((,index 0) ,result ,tmp)
+        (when (> (,generic
+                  ,str
+                  ,@(mapcar
+                     (lambda (fun)
+                       `(when ,fun
+                          (lambda (,start ,end)
+                            (setq ,tmp (funcall ,fun (substring ,str ,start ,end)))
+                            (when ,tmp
+                              (when (< ,index ,start)
+                                (setq ,result
+                                      (ew-rcons* ,result
+                                                 (substring ,str ,index ,start))))
+                              (setq ,result (ew-rcons* ,result ,tmp)
+                                    ,index ,end)))))
+                     funcs-vars))
                  ,index)
           (setq ,result
                 (ew-rcons* ,result
                            (substring ,str ,index))))
         (apply 'concat (nreverse ,result))))))
+(ew-generic-convert-define ew-crlf-convert ew-crlf-generic others-fun fold-fun nl-fun cr-fun lf-fun)
+(ew-generic-convert-define ew-crlf-line-convert ew-crlf-line-generic others-fun fold-fun nl-fun)
+(ew-generic-convert-define ew-lf-convert ew-lf-generic others-fun fold-fun nl-fun cr-fun)
+(ew-generic-convert-define ew-lf-line-convert ew-lf-line-generic others-fun fold-fun nl-fun)
+
+(defmacro ew-fold-define (name convert nl)
+  `(defun ,name (str start-column line-length)
+     (let ((column start-column))
+       (,convert str
+         (lambda (line)
+          (let ((start 0)
+                (end (length line))
+                result tmp fold width)
+            (while (and (< start end)
+                        (progn
+                          (when (<= column 1)
+                            (setq tmp (sref line start)
+                                  result (ew-rcons* result (char-to-string tmp))
+                                  column (+ column (char-width tmp))
+                                  start (char-next-index tmp start)))
+                          (string-match "[ \t]" line start)))
+              (setq tmp (substring line start (match-beginning 0))
+                    width (string-width tmp)
+                    result (ew-rcons* result tmp)
+                    column (+ column width)
+                    start (match-beginning 0))
+              (if (<= line-length column)
+                  (progn
+                    (when (and fold (not (= line-length column)))
+                      (setcdr fold (cons (car fold) (cdr fold)))
+                      (setcar fold ,nl)
+                      (setq column (+ width
+                                      (if (eq (cdr result) fold)
+                                          0
+                                        (string-width (cadr result))))))
+                    (if (<= line-length column)
+                        (setq result (ew-rcons* result ,nl)
+                              column 0
+                              fold nil)
+                      (setq fold result)))
+                (setq fold result))
+              (setq tmp (sref line (match-beginning 0))
+                    result (ew-rcons* result (char-to-string tmp))
+                    column (+ column (char-width tmp))
+                    start (match-end 0)))
+            (when (< start end)
+              (setq tmp (substring line start)
+                    result (ew-rcons* result tmp)
+                    column (+ column (string-width tmp))))
+            (when (and (< line-length column) fold)
+              (setcdr fold (cons (car fold) (cdr fold)))
+              (setcar fold ,nl))
+            (apply 'concat (nreverse result))))
+        (lambda (fold) (setq column 1) nil)
+        (lambda (nl) (setq column 0) nil)))))
+
+(ew-fold-define ew-crlf-fold ew-crlf-line-convert "\r\n")
+(ew-fold-define ew-lf-fold ew-crlf-line-convert "\n")
+
+(defun ew-crlf-refold (string start-column line-length)
+  (ew-crlf-fold (ew-crlf-unfold string) start-column line-length))
 
-(ew-lf-line-convert-define)
+(defun ew-lf-refold (string start-column line-length)
+  (ew-lf-fold (ew-lf-unfold string) start-column line-length))