Простая команда «копировать форму»

Мне нужна команда, которая копирует форму в кольцо уничтожения. В emacs-live самое близкое, что я смог найти, это эта команда/привязка клавиш

(global-set-key (kbd "M-]") 'kill-ring-save)

Однако kill-ring-save ведет себя несколько шатко. II копирует более 1 формы после курсора. В конечном счете, мне нужна простая функция, похожая на то, что ниже (это не совсем работает).

(defun copy-form () 
  (kill-ring-save (line-beginning-position) (live-paredit-forward))) 

(global-set-key (kbd "M-]") 'copy-form)

Я искал сверху и снизу ( SO question и Поиск в Google), но не может найти простую работающую команду для копирования сбалансированного выражения. Кто-то уже сделал это?

Спасибо

Тим


person Nutritioustim    schedule 26.08.2013    source источник


Ответы (4)


Функция sexp-at-point дает вам sexp ("форму") в курсоре. Просто скопируйте это в kill-ring, используя kill-ring-save. Например.:

(defun copy-sexp-at-point ()
  (interactive)
  (let ((bnds  (bounds-of-thing-at-point 'sexp)))
    (kill-ring-save (car bnds) (cdr bnds))))

В качестве альтернативы просто используйте kill-new:

(defun copy-sexp-at-point ()
  (interactive)
  (kill-new (thing-at-point 'sexp)))
person Drew    schedule 26.08.2013
comment
Это выглядит действительно хорошо. За исключением того, что kill-ring-save ожидает этот формат (kill-ring-save BEG END). Поэтому мне нужно либо i) использовать это, либо ii) использовать другую функцию, которая может сохранять результаты sexp-at-point в список уничтожений. Любые идеи? - person Nutritioustim; 26.08.2013
comment
Поэтому используйте (bounds-of-thing-at-point 'sexp), чтобы получить нужные вам BEG и END -- он возвращает (BEG . END), поэтому передайте car и cdr в kill-ring-save. - person Drew; 26.08.2013
comment
Когда я пробую этот подход, emacs выдает ошибку Wrong type argument: symbolp, (one (two)). Мой код онлайн здесь. Я должен упомянуть, что я новичок в Emacs Lisp. Поэтому мне нужны очень подробные объяснения. Не стесняйтесь редактировать этот блок кода или делать то, что проще всего. Спасибо. - person Nutritioustim; 26.08.2013
comment
Используйте символ sexp, а не (sexp-at-point), в качестве аргумента для bounds-of-thing-at-point. - person Drew; 26.08.2013
comment
Или просто используйте kill-new. Я отредактировал ответ, чтобы сделать его явным для вас. - person Drew; 26.08.2013
comment
Ааааа, благослови твое сердце. Это помогло. Большое спасибо :) - person Nutritioustim; 26.08.2013

Причина, по которой ваш copy-form не может быть привязан к клавише, заключается в том, что это функция, а не команда — в ней отсутствует interactive.

Однако в вашем случае вам даже не нужно писать новую функцию.

Попробуйте комбинацию из

mark-sexp - это интерактивная скомпилированная функция Лиспа в `lisp.el'.

Он связан с C-M-@, C-M-SPC.

а также

M-w запускает команду kill-ring-save, которая представляет собой интерактивную скомпилированную функцию Lisp в `simple.el'.

Он связан с ‹C-insertchar›, M-w, ‹строка меню› ‹редактировать› ‹копировать›.

person sds    schedule 26.08.2013
comment
Когда я использую команду, emacs все равно выдает ошибку: Wrong type argument: integer-or-marker-p, nil. Я думаю, это просто связано с тем, что kill-ring-save не возвращает целые числа в формате (kill-ring-save BEG END). - person Nutritioustim; 26.08.2013

Я не уверен, что понимаю вопрос, но когда мне нужно сделать то, что я считаю «копированием сбалансированной формы», я делаю: M-C-SPC M-w. Если я хочу его вырезать, я делаю M-C-SPC C-w.

person Stefan    schedule 26.08.2013

Вот что я обычно использую. Почему-то мне удобнее убить сбалансированное выражение, чем копировать. Если вместо этого мне нужна копия, я сначала убиваю, а потом отменяю.

Эта функция уничтожает строку, если точка находится внутри строки, в противном случае используется сбалансированное выражение, т.е. (),[],{},<> или что-то другое, определенное синтаксисом.

(defun kill-at-point ()
  "Kill the quoted string or the list that includes the point"
  (interactive)
  (let ((p (nth 8 (syntax-ppss))))
    (cond
      ;; string
      ((eq (char-after p) ?\")
       (goto-char p)
       (kill-sexp))
      ;; list
      ((ignore-errors (when (eq (char-after) ?\()
                        (forward-char))
                      (up-list)
                      t)
       (let ((beg (point)))
         (backward-list)
         (kill-region beg (point)))))))

Я также попытался добавить особый случай, когда точка находится внутри комментария, но я не смог найти общий способ определить границы комментария в точке. Если кто-нибудь знает, пожалуйста, скажите мне.

Эта другая функция также может иметь значение. Он метит, а не убивает, как предыдущий. Приятно то, что он расширяет регион каждый раз, когда он вызывается. Я связываю первый с C-,, а второй с C-M-,.

(defun mark-at-point ()
  "Mark the quoted string or the list that includes the point"
  (interactive)
  (let ((p (nth 8 (syntax-ppss))))
    (if (eq (char-after p) ?\")
    (progn
      (goto-char p)
          (set-mark (point))
      (forward-sexp))
      (progn
        (when (eq (char-after) 40)
          (forward-char))
        (condition-case nil
            (progn
              (up-list)
              (set-mark (point))
              (let ((beg (point)))
                (backward-list)
                (exchange-point-and-mark)))
          (error
           (when (looking-back "}")
             (exchange-point-and-mark)
             ;; assumes functions are separated by one empty line
             (re-search-backward "^[^A-Z-a-z]" nil t)
             (forward-char))))))))
person abo-abo    schedule 26.08.2013
comment
Хейя, спасибо за ответ. Убить сбалансированное выражение, а затем отменить его — вот что я сейчас делаю. Поэтому я хотел чего-то сверх этого. Ответ @Drew выше помог мне. Я удивлен, что это не стандартная вещь в emacs/lisp. В любом случае, еще раз спасибо. - person Nutritioustim; 26.08.2013
comment
Моя функция работает не так, как у @Drews. Его подход дает ошибку, когда точка находится на пробеле, или копирует символ, когда он находится на символе. Моя функция убивает выражение плюс скобки. Очень полезно для lisp/C++. - person abo-abo; 26.08.2013