如何格式化字符串列表

时间:2012-10-24 02:00:28

标签: lisp elisp

我有一个字符串列表,我需要使用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的新手,我可能会遗漏一些明显的东西。

2 个答案:

答案 0 :(得分:4)

使用apply

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

apply函数将一个函数(或符号)作为其第一个参数,然后是一些单独的参数,以一个参数列表结束。

答案 1 :(得分:2)

我决定通过添加更多功能,修复一些错误并添加更多错误来使其成为独立项目!是啊:)

您可以在此处找到该项目: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类似的打印行为。