Gancho que indica cuándo se ha movido el cursor desplazándose

7

Inspirado por esta pregunta: deje que Emacs mueva el cursor fuera de la pantalla , estoy considerando escribir un modo menor que mantendrá el cursor en una posición fija que no se vea afectada por las operaciones de desplazamiento. Tengo algunas ideas sobre cómo podría implementar esto, pero requeriría un gancho para avisarme cuando el cursor se está "empujando" fuera de la pantalla.

En algún lugar dentro de las entrañas de Emacs, existe un código que se llama cuando la ubicación de pointse mueve fuera de la pantalla. Si bien se ha dicho que el código que controla este comportamiento vive en profundidad con el código fuente C, me gustaría saber si hay alguna manera de que pueda recibir una notificación cuando esté a punto de suceder.

¿Hay alguna manera de que pueda ser notificado cuando un comando de desplazamiento está a punto de mover el cursor? O al menos, ¿hay alguna manera de que pueda ser notificado cuando la pantalla está a punto de desplazarse?


Actualización: ¡Ya no planeo escribir un modo menor para lograr esto porque se acaba de lanzar un nuevo paquete en GNU ELPA llamado scroll-restoreque proporciona exactamente las características que estaba pensando implementar yo mismo!

nispio
fuente

Respuestas:

5

.

Las funciones en window-scroll-functionsse llaman justo antes de una nueva visualización que provocaría el desplazamiento. Cada función devuelve dos argumentos, la ventana windowy la posición de inicio de la nueva ventana new-start. Puede llamar para obtener la posición inicial de la ventana actual, para obtener la posición final de la ventana actual y para obtener la nueva posición final de la ventana. Si el punto no está entre y , está a punto de moverse. Por lo que puedo decir, estas funciones se llaman en todos los casos que cambian la extensión de una ventana, incluido el desplazamiento y el cambio de tamaño. También se les llama cuando una ventana comienza a mostrar un búfer (porque se acaba de crear o porque ahora muestra un nuevo búfer).(window-start window)(window-end window)(window-end window t)new-start(window-end window t)

Para que los comandos de desplazamiento parezcan no mover el punto, es probable que desee guardar el punto actual en este gancho y hacer algo post-command-hook. Dado que el punto tendrá que moverse debido al desplazamiento, presumiblemente lo guardará y lo restaurará pre-command-hook.

Gilles 'SO- deja de ser malvado'
fuente
1
¡Excelente! Debo admitir que no esperaba que la respuesta fuera "sí".
nispio
¿Hay algo así como (window-start)para el desplazamiento horizontal? (tenga en cuenta que window-hscrollno hace el trabajo cuando la fuente en el búfer difiere de la predeterminada).
Siempre aprendiendo
1

La respuesta de @Gilles es el camino correcto. Mantendré este aquí para la información y los hacks.

Creo que el pointmovimiento lo realizan las funciones C window_scroll_line_basedy window_scroll_pixel_based(dependiendo de los parámetros de su marco). Estas funciones no están expuestas a la máquina de lisp, por lo que no puede aconsejarlas. Tendría que aconsejar las funciones que los llaman.

Dos de las funciones (accesibles para lisp) que pueden hacer esto son scroll-upy scroll-down. Así es como me enteré de ellos:

  1. Ve a un búfer largo.
  2. Selecciona una pequeña región.
  3. Llamar, M-x (put-text-property (region-beginning) (region-end) 'point-left (lambda (&rest _) (error "Point leaving"))). Esto arrojará un error cuando el punto abandone la región.
  4. Activar M-x toggle-debug-on-error.
  5. Asegúrese de que el punto esté dentro de esta región.
  6. Desplácese con la rueda del mouse hasta que el punto sea arrastrado fuera de la región.

Se le proporcionará un búfer de traza inversa como este, que señala claramente la scroll-downfunción.

Debugger entered--Lisp error: (error "Point leaving")
  signal(error ("Point leaving"))
  error("Point leaving")
  (lambda (&rest _) (error "Point leaving"))(1508 1192)
  scroll-down(10)
  funcall(scroll-down 10)
  mwheel-scroll((double-mouse-4 (#<window 50 on *Backtrace*> 1299 (578 . 545) 77086296 nil 1299 (57 . 25) nil (398 . 20) (10 . 21)) 2))
  funcall-interactively(mwheel-scroll (double-mouse-4 (#<window 50 on *Backtrace*> 1299 (578 . 545) 77086296 nil 1299 (57 . 25) nil (398 . 20) (10 . 21)) 2))
  call-interactively(mwheel-scroll nil nil)
  command-execute(mwheel-scroll)

Seguí scroll-downsu definición en C, que me llevó a window_scroll, que me llevó a esas dos funciones anteriores.

Lo que puedes hacer

Puede asesorar scroll-down/upcon un aroundconsejo (así como cualquier otra función que también pueda resultar en el movimiento del punto). Use este consejo para verificar si la posición de pointha cambiado y registre la posición anterior. Y luego haz lo que quieras con él.

Tenga en cuenta que los consejos son muy poco confiables cuando se trata de funciones C. Algunas funciones importantes tienen direcciones especiales en el código compilado por bytes, lo que significa que no se les avisa cuando se compila el código. No creo que ese sea el caso aquí, pero pensé que no deberías.

Malabarba
fuente
No creo aconsejar scroll-downy scroll-upsería útil aquí. Hay muchas otras formas en que puede ocurrir el desplazamiento. Al menos todos los comandos que tienen la isearch-scrollpropiedad deben considerarse comandos de desplazamiento.
Gilles 'SO- deja de ser malvado'
@Gilles por eso dije "así como cualquier otra función que también pueda resultar en movimiento de puntos" . ¡Pero tu respuesta definitivamente se ve mejor!
Malabarba
¡Esa es una depuración bastante inteligente!
nispio