Como definir marca no elisp e ter seleção de turno?


9

O comportamento normal do Emacs quando o modo de marca transitória está ativo é que, quando você faz uma seleção de turno, se o próximo comando for um movimento sem turno, a marca será desativada. Por exemplo, após os comandos M-l(para marcar a linha atual com a função abaixo) e C-f, a marca é desativada. Como emular esse comportamento do elisp depois (set-mark-command nil)?

Por exemplo:

(defun my-mark-current-line ()
  (interactive)
  (beginning-of-line)
  (set-mark-command nil)
  (end-of-line)
  (forward-char))

(global-set-key (kbd "M-l") 'my-mark-current-line)

Agora Ml Cf e a região crescerão, mas, em vez disso, quero que o comportamento padrão, ou seja, a região desative quando Cf e cresça com CSf.

EDIT : deve usar uma função diferente para set-mark-command que permite isso? Não consegui encontrar nenhum.


Eu acredito que isso não é possível (e posso estar errado). Enquanto uma região estiver ativa, os comandos de navegação mudarão a seleção. O uso da seleção de turnos C-S-fé análogo a C-SPC(ativar uma região) + C-f(navegação). Provavelmente, você pode obter o que deseja vinculando-se C-f a uma função de wrapper que primeiro desativa uma região, se ativa, e depois faz o que C-fdoes ( forward-char); e vincular C-S-fdiretamente a forward-char. Note que se você nunca usar emacs no modo terminal, C-fe C-S-fserão ambos se comportam como C-fcomo o terminal não pode distinguir entre os dois.
Kaushal Modi

Além disso, o wrapper e a ligação para os quais você C-faplicou também se aplicariam a todos os outros comandos de navegação usados.
Kaushal Modi

btw C-fafter M-lnão estende a região porque não existe uma região ativa no final de M-l(que é vinculada downcase-wordpor padrão).
Kaushal Modi

11
@KaushalModi Eu acho que o M-lreferido pelo OP não é a ligação (default downcase-word), mas a ligação do costumemy-mark-current-line
nispio

de fato @nispio.
Mikl # 10/16

Respostas:


8

Como a conversão de turnos e a ativação temporária da marca são manipuladas pelo loop de comando, você precisará chamar as versões interativas das funções de movimento para obter o comportamento apropriado da seleção de turnos:

;; (source: http://emacs.stackexchange.com/a/22166/93)
(defun my-mark-current-line ()
  (interactive)
  (beginning-of-line)
  (setq this-command-keys-shift-translated t)
  (call-interactively 'end-of-line)
  (call-interactively 'forward-char))

(global-set-key (kbd "M-l") 'my-mark-current-line)

Atualizar:

Desde que escrevi a resposta acima, dediquei um tempo para aprender um pouco mais sobre como a seleção de turnos realmente funciona sob o capô. Ele define o valor do símbolo transient-mark-modecomo uma célula de contras do formulário (only . OLDVAL), onde OLDVALé o valor anterior à seleção de turno.

A solução abaixo evita o uso de call-interactively, ativando a marca conforme necessário e definindo o valor apropriado de transient-mark-mode. Basicamente, considero esta solução menos invasiva que a primeira.

Como bônus, agora ele possui uma contagem de repetição opcional e estenderá a seleção atual em qualquer direção, se a marca já estiver ativa.

;; (source: http://emacs.stackexchange.com/a/22166/93)
(defun my-mark-current-line (&optional arg)
  "Uses shift selection to select the current line.
When there is an existing shift selection, extends the selection
in the appropriate direction to include current line."
  (interactive "p")
  (let ((oldval (or (cdr-safe transient-mark-mode) transient-mark-mode))
        (backwards (and mark-active (> (mark) (point))))
        (beg (and mark-active (mark-marker))))
    (unless beg
      (if backwards (end-of-line) (beginning-of-line))
      (setq beg (point-marker)))
    (if backwards (end-of-line (- 1 arg)) (beginning-of-line (+ 1 arg)))
    (unless mark-active
      (push-mark beg nil t))
    (setq transient-mark-mode (cons 'only oldval))))

11
Ambos funcionam perfeitamente e a coisa oldval é muito útil! Muito obrigado!
Mikl
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.