Как правильно разобрать буфер в elisp? - PullRequest
4 голосов
/ 26 марта 2012

Как правильно проанализировать буфер, чтобы сохранить его содержимое и повторно использовать его?

Скажем, я получил этот буфер:

always|five|words|by|line
not|always|the|same|words
sometimes|no|lines|at|all
but|only|five|no|more/less

Каков наилучший подход кпостроить список из символов, найденных в строках (и приятно, если ничего не найдено)?

Буфер есть, я могу его посетить, получить его содержимое примерно так:

(message "Buffer content : %s" (buffer-substring (point-min) (point-max)))

после того, как я убил его чисто, но каким-то образом я не смог построить объект (список «строк» ​​списков «слов»), который позволил бы мне сделать это:

(list-length lines)
    ==> 4

(car (nthcdr 3 lines))
    ==> sometimes

Может ли родственная душа указать мне насвет?Спасибо за ваше терпение, Лисп старейшины.

Ответы [ 3 ]

7 голосов
/ 26 марта 2012

Вы также можете использовать встроенную функцию split-string, аналогичную split в Perl и других языках:

(defun buffer-to-list-of-lists (buf)
  (with-current-buffer buf
    (save-excursion
      (goto-char (point-min))
      (let ((lines '()))
        (while (not (eobp))
          (push (split-string
                 (buffer-substring (point) (point-at-eol)) "|")
                lines)
          (beginning-of-line 2))
        (nreverse lines)))))

Затем с вашим примером текста в буфере с именем temp, (buffer-to-list-of-lists "temp") возвращает значение

(("always" "five" "words" "by" "line") 
 ("not" "always" "the" "same" "words")
 ("sometimes" "no" "lines" "at" "all")
 ("but" "only" "five" "no" "more/less"))

Это будет работать в строках с любым количеством слов, разделенных |, что может или не может быть лучше для вашего приложения. Измените buffer-substring на buffer-substring-no-properties, если вы не хотите, чтобы строки в вашем списке списков включали информацию о шрифте и другие свойства, которые они имели в исходном буфере.

После того, как вы все заработаете, вам также нужно изменить пример использования (list-length '(lines)) на (list-length lines). В его текущей форме вы запрашиваете длину постоянного одноэлементного списка, содержащего только символ lines.

3 голосов
/ 18 марта 2014

Предположим, что переменная text содержит содержимое вашего буфера в виде строки, за Jon O answer .Затем используйте dash.el список API и s.el API функции:

(--map (s-split "|" it) (s-lines text))

--map является анафорическимверсия из -map предоставляет временную переменную it, поэтому вам не нужно передавать анонимную функцию.s-split - это простая оболочка вокруг split-string, s-lines, делит строку на новые строки.

2 голосов
/ 26 марта 2012

Вот простой синтаксический анализатор на основе регулярных выражений, который может быть полезен в качестве начала для достижения того, что вы хотите:

(let (lines)
  (beginning-of-line)  
  (while (not (eobp))
    (push
     (if (looking-at "\\([^|\n]+\\)|\\([^|\n]+\\)|\\([^|\n]+\\)|\\([^|\n]+\\)|\\([^|\n]+\\)")
         (list (match-string-no-properties 1)
               (match-string-no-properties 2)
               (match-string-no-properties 3)
               (match-string-no-properties 4)
               (match-string-no-properties 5))    
       'no-match)
     lines)
    (forward-line 1))

  (setq lines (nreverse lines))

  (print lines))
...