2016-03-20 1 views
1

Я начинаю новичок (но не программирую) и задаю несколько вопросов о наилучшей практике для реализации функции. Я написал функцию elisp, которая переформатирует исходный код ассемблера в соответствии с определенными правилами; эта функция работает в течение одной строки. В основном он использует навигацию по линиям, поиск и замещение вызовов по подвыражениям для достижения цели.Как эффективно перемещаться по линиям модификации буфера emacs

Теперь я хотел бы применить его к отмеченной области, обрабатывая область по строкам. Поведение будет аналогично положению функции отступа.

Каков рекомендуемый (и эффективный) способ его реализации? Я считаю, что (line-number-at-pos ...) применяется к (region-beginning) и (region-end) для подсчета номеров строк, а затем перемещения сверху вниз, работая через буфер по строкам, изменяя их.

Кроме того, что мне нужно для сохранения этой операции? Я, однако, о (save-match-data ...) и не уверен, как обращаться с меткой и точкой. Я думаю, они будут бесполезны, поскольку объем текста изменился.

+0

Вы хотели бы принять посмотрите на http://emacs.stackexchange.com/questions/19518 – Stefan

ответ

3

Используйте save-excursion для сохранения и восстановления точки и отметки и save-restriction, чтобы сузить область.

Шаблон будет что-то вроде этого:

(defun my-process-region (beg end) 
    "Apply `my-process-line` to every line in region." 
    (interactive "r") 
    (save-restriction 
    (widen) 
    (save-excursion 
     (narrow-to-region beg end) 
     (goto-char (point-min)) 
     (while (not (eobp)) 
     (my-process-line))))) 
+0

Спасибо, но я понимаю, что 'save-excursion' также возвращает модификации буфера, чего я не хочу (код переформатирует строки). Что касается вышеприведенного кода: если обработка изменяет длину строк, конец больше не будет указывать на нужное место? – user52366

+0

Ваше понимание ошибочно по всем пунктам. – sds

+0

Справка говорит: «Сохранить точку,d текущий буфер; выполнить BODY; восстановить эти вещи. Выполняет BODY так же, как 'progn '. Значения точечного и текущего буфера восстанавливаются даже в случае ненормального выхода (выброс или ошибка). » – user52366

-1

Я принимаю ответ ДДС. В конце я использовал код ниже. Причина в том, что я хотел, чтобы целые строки были доступны для переформатирования, а не только для отмеченной области. Так что только (narrow-to-region) не выполнил бы эту работу. Я счастлив, чтобы узнать больше, и ценим комментарии о плюсах/минусах или пропавшие вещи:

(defun x-mode-reformat-region (beg end) 
    "..." 
    (interactive "r") 
    (save-excursion 
    (let ((nlines (+ 1 (apply '- (mapcar 'line-number-at-pos `(,end ,beg))))) 
      bol 
      ...) 
     (goto-char beg) 
     (dotimes (i nlines) 
     (setq bol (line-beginning-position)) 
     (goto-char bol) 
     ;; do reformatting for this line -- uses bol for calculations 
     (forward-line))))) 

Следующая попытка - измененными на основе комментариев. Я не нашел более простой способ расширить выбор, чтобы включить всю линию ... любую идею, может ли комбинация setq/narrow-to-region быть упрощена дополнительно (за исключением использования (progn ...) непосредственно в качестве аргумента?

(defun x-mode-reformat-region (beg end) 
    "..." 
    (interactive "r") 
    (save-restriction 
    (widen) 
    (save-excursion 
     (setq beg (progn (goto-char beg) (line-beginning-position)) 
      end (progn (goto-char end) (line-end-position))) 
     (narrow-to-region beg end) 
     (goto-char (point-min)) 
     (while (not (eobp)) 
     (insert "*") ;; placeholder for fancy reformatting 
     (forward-line))))) 
+0

способ, которым вы вычисляете 'nlines', является более уродливым. вам не нужно 'bol', просто сделайте' (goto-char (строка-начало-позиция)) '.если вы боитесь, что ваша метка и точка не находятся в начале строки, вы должны отрегулировать числа, которые вы переходите в «узкий к региону». Короче говоря, вы должны оставаться рядом с идиомами Emacs, как и в моем ответе. – sds

+0

Хорошо, попытался адаптировать код, см. Отредактированную версию выше. Я вижу точку с идиомами, но это вопрос изучения того, что это такое ... – user52366

+1

В любое время, когда вы можете думать о существующей функции, которая делает что-то похожее на то, что вы хотите сделать, вы можете взглянуть на исходный код для этого и посмотреть, как это работает. Конечно, это может оказаться гораздо более сложным примером, чем вы на самом деле хотели, в зависимости от того, насколько сложна процедура, на которую вы смотрите, но вы часто сможете подобрать разумные подходы к общему эллипсу задачи таким образом. 'M-x find-function' - ваш друг. Я нахожу 'C-h C-f' удобным для него привязку. – phils

Смежные вопросы