Combinando dos operadores en Emacs en modo malvado

7

En vim he reasignado >y <cuando estoy en modo visual a >gvy <gvrespectivamente, así:

vnoremap > >gv
vnoremap < <gv

Dado que mi objetivo para esta pregunta son personas con experiencia en emacs y no vim, qué >y <qué es sangrar / sangrar texto seleccionado visualmente. Lo que gvhace es volver a seleccionar el texto previamente seleccionado. Estos mapas causan >y <para sangrar / dedent y luego vuelva a seleccionar el texto previamente seleccionado.

Estoy probando emacs con modo malvado y me gustaría hacer lo mismo, pero tengo dificultades para descubrir cómo, exactamente, lograr la reselección automática.

Parece que necesito llamar de alguna manera evil-shift-righty evil-visual-restoresecuencialmente, pero no sé cómo crear un mapa que haga ambas cosas, así que intenté crear mi propia función que llamaría tanto secuencialmente como mapa, pero no funcionó. , posiblemente debido al hecho de que ambos están definidos, no como funciones con defunsino como operadores con evil-define-operator.

Intenté crear mis propios operadores:

(evil-define-operator shift-left-reselect (beg end)
    (evil-shift-left beg end)
    (evil-visual-restore))

(evil-define-operator shift-right-reselect (beg end)
    (evil-shift-right beg end)
    (evil-visual-restore))

pero eso no restaura visual como se esperaba. Una puñalada en la oscuridad me dio esto:

(evil-define-operator shift-left-reselect (beg end)
    (evil-shift-left beg end)
    ('evil-visual-restore))

(evil-define-operator shift-right-reselect (beg end)
    (evil-shift-right beg end)
    ('evil-visual-restore))

pero eso selecciona una línea adicional cuando se supone que debe volver a seleccionar.

Por ahora he estado usando lo siguiente, que solo tiene el problema de que vuelve a seleccionar una línea adicional en el <operador.

(evil-define-operator shift-right-reselect (beg end)
  (evil-shift-right beg end)
  (evil-visual-make-selection beg end))

(evil-define-operator shift-left-reselect (beg end)
  (evil-shift-left beg end)
  (evil-visual-make-selection beg end))

y los he mapeado:

(define-key evil-visual-state-map ">" 'shift-right-reselect)
(define-key evil-visual-state-map "<" 'shift-left-reselect)

Cualquier ayuda / punteros / consejos serían muy apreciados.

Gracias por adelantado.

editar:

Me gustaría poder hacer esto esencialmente:

(define-key evil-visual-state-map ">" (kbd ">gv"))
(define-key evil-visual-state-map "<" (kbd "<gv"))

Pero dado que no existe el concepto de un mapeo predeterminado> o <la idea de un mapeo recursivo no tiene ningún sentido, y esto tiene todos los problemas que esperaría de dicho mapa. Sin embargo, lo siguiente funciona, pero es feo ya que requiere la adición de dos mapas descartables. ¿Hay alguna forma de evitar hacer esto?

(define-key evil-visual-state-map "g>" 'evil-shift-right)
(define-key evil-visual-state-map "g<" 'evil-shift-left)
(define-key evil-visual-state-map ">" (kbd "g>gv"))
(define-key evil-visual-state-map "<" (kbd "g<gv"))

Si pasa el tiempo suficiente, tomaré esto, crearé una respuesta y la aceptaré para que otros que encuentren esta pregunta puedan encontrarla / usarla fácilmente.

mkomitee
fuente
¿Sería una transgresión horrible para mí publicar esto en unix.stackexchange.com, con la esperanza de tener más ojos en él?
mkomitee
1
No estoy seguro acerca de Unix, pero ¿qué hay de Stack Overflow? Además, ¿se ha acercado al autor del mal y / o algún grupo de discusión que pueda existir para ello?
echristopherson
Prefiero hablar con las personas en el proyecto: la lista de correo y el IRC se encuentran en emacswiki.org/emacs/Evil
Johan Lindstrom
Estoy tratando de entender lo que quieres hacer. ¿Hace indent-according-to-mode(sangrar / desangrar) y C-x C-x(volver a seleccionar) hacer (incluso más o menos) lo que quieres? Porque si es así, podemos trabajar una función y luego una combinación de teclas alrededor de eso.
yPhil
Esto no es realmente una respuesta a su pregunta, pero ¿por qué reasignó '>' en Vim? ¿Es solo para que pueda continuar sangrando presionando la tecla> nuevamente (mientras ve realmente lo que sucede)? En ese caso, podría usar el operador de punto (.) Para repetir la sangría para que no necesite la asignación. En lugar de hacer 'V3j >>>' (con su mapeo) puede hacer 'V3j> ..' con las combinaciones de teclas vim predeterminadas. ¿Quizás esto también funciona en modo malvado?
jeroen

Respuestas:

4

El evil-shift-rightcomando necesita un argumento inicial y final, con el requisito de que el argumento inicial sea menor que el argumento final. Una forma de lograr esto es la siguiente:

(define-key evil-visual-state-map ">" (lambda ()
    (interactive)
    ; ensure mark is less than point
    (when (> (mark) (point)) 
        (exchange-point-and-mark)
    )
    (evil-normal-state)
    (evil-shift-right (mark) (point))
    (evil-visual-restore) ; re-select last visual-mode selection
))

(define-key evil-visual-state-map "<" (lambda ()
    (interactive)
    ; ensure mark is less than point
    (when (> (mark) (point)) 
        (exchange-point-and-mark)
    )
    (evil-normal-state)
    (evil-shift-left (mark) (point))
    (evil-visual-restore) ; re-select last visual-mode selection
))
marca
fuente
2

Terminé usando lo siguiente:

(define-key evil-visual-state-map (kbd "<") (lambda ()
  (interactive)
  (evil-shift-left (region-beginning) (region-end))
  (evil-normal-state)
  (evil-visual-restore)))
(define-key evil-visual-state-map (kbd ">") (lambda ()
  (interactive)
  (evil-shift-right (region-beginning) (region-end))
  (evil-normal-state)
  (evil-visual-restore)))
rápido
fuente