2012-10-24 153 views
5

我有一個字符串列表,我需要使用emacs lisp進行格式化。這是我能想到的唯一方法:如何格式化字符串列表

(setq slist '("is there" "any" "way" "directed iteration"))  
(format "%s _%s_ %s to do %S in elisp?" 
     (elt slist 0) 
     (elt slist 1) 
     (elt slist 2) 
     (elt slist 3) 
     (elt slist 4)) 

給我我想要的東西。

is there _any_ way to do "directed iteration" in elisp? 

必須有一個更優雅的方式,但經過很多想法,我沒有看到它。我對emacs lisp很陌生,可能會漏掉一些明顯的東西。

回答

4

使用apply

(apply 'format "%s _%s_ %s to do %S in elisp?" slist) 

apply函數採用一個函數(或符號)作爲第一個參數,然後多個單獨參數,與參數列表精加工。

+0

是的,這就是謝謝。很明顯,我確實錯過了申請的性質。哇,真是一個很棒的功能! –

2

我決定通過添加一些更多的功能,修復一些錯誤並添加更多的錯誤,使其成爲一個獨立的項目! yey :)

您可以在這裏找到的項目:http://code.google.com/p/formatting-el/source/browse/trunk/formatting.el

不知道有多少車是這樣的,但在第一眼看到它似乎工作:

(defun directive-end (c) 
    (member c "csdoxXeg%")) 

(defun pp-if-nil (spec) 
    (position ?\% spec)) 

(defun pp-list (spec args) 
    (let ((pos 0) (last 0) (fstring "% ") current seen-^) 
    (catch 't 
     (while t 
     (setq pos (1+ (or (position ?% spec :start pos) -1)) 
       current (aref spec pos)) 
     (unless (and seen-^ (char-equal current ?\}) (null args)) 
      (princ (substring spec last (1- pos)))) 
     (setq last pos pos (1+ pos)) 
     (cond 
     ((char-equal current ?^) 
      (incf last) 
      (setq seen-^ t)) 
     ((char-equal current ?\{) 
      (setq pos (+ pos (pp-list (substring spec pos) (car args))) 
       args (cdr args) 
       last pos 
       seen-^ nil)) 
     ((char-equal current ?\}) 
      (if args (setq pos 0 last 0) 
      (throw 't nil))) 
     ((char-equal current ?%) 
      (setq seen-^ nil last (1+ last)) 
      (write-char ?%)) 
     (t (unless args (error "Not enough argumens for list iteration")) 
      (setf (aref fstring 1) current) 
      (princ (format fstring (car args))) 
      (setq args (cdr args) 
        seen-^ nil 
        last 
        (or (position-if #'directive-end spec :start pos) 
         pos)))))) pos)) 

(defun cl-format (spec &rest args) 
    (with-output-to-string 
    (let ((pos 0) (last 0) (fstring "% ") current) 
     (catch 't 
     (while t 
      (setq pos (1+ (or (position ?\% spec :start pos) -1)) 
       current (aref spec pos)) 
      (when (= pos 0) (throw 't nil)) 
      (princ (substring spec last (1- pos))) 
      (setq last pos pos (1+ pos)) 
      (cond 
      ((char-equal current ?^) 
      (unless args 
       (setq last (pp-if-nil spec) 
        pos last))) 
      ((char-equal current ?\{) 
      (setq pos (+ pos (pp-list (substring spec pos) (car args))) 
        args (cdr args) 
        last pos)) 
      ((char-equal current ?\}) 
      (error "Unmatched list iteration termination directive")) 
      ((char-equal current ?%) 
      (write-char ?%) 
      (incf last)) 
      (t (unless args (error "Not enough argumens")) 
       (setf (aref fstring 1) current) 
       (princ (format fstring (car args))) 
       (setq args (cdr args) 
        last 
        (or (position-if #'directive-end spec :start pos) 
         pos)))) 
      (incf pos)))))) 

(cl-format "begin: %{%s = %d%^,%}; %% %c %% %{%{%s -> %d%^.%},%}" 
      '(a 1 b 2 c 3) ?\X '((a 2 b 4 c 6) (a 1 b 3 c 5))) 
"begin: a = 1,b = 2,c = 3; % X % a -> 2.b -> 4.c -> 6,a -> 1.b -> 3.c -> 5," 

這試圖複製一些(非常簡單化)~{ ... ~}指令的Common Lisp-like打印行爲。