スクロールによってカーソルが移動したことを示すフック


7

この質問に触発されました:Emacsにカーソルを画面外に移動させます。スクロール操作の影響を受けない固定位置にカーソルを維持するマイナーモードを書くことを検討しています。私はこれをどのように実装するかについていくつかのアイデアを持っていますが、カーソルが画面から「押し出された」ときに通知するためのフックが必要になります。

Emacsの腸のどこかに、の位置がpointディスプレイから移動されたときに呼び出されるコードが存在します。一方で言われているコントロールのこの動作は、深いCのソースコードと一緒に住んでいることのコードは、私はそれが起こるとしているときに、私は通知できることをどのような方法があるかどうかを知りたいということ。

スクロールコマンドがカーソルを移動しようとしているときに通知を受ける方法はありますか? または、少なくとも、ディスプレイがスクロールされようとしているときに通知を受ける方法はありますか?


アップデート:私は、新しいパッケージがばかりにリリースされましたので、これは達成するために、マイナーモードを書くことにもはや計画を午前GNU ELPAと呼ばれるscroll-restoreそれは、私は自分自身を実装することを考えていたことが正確に機能を提供します!

回答:


5

はい

の関数window-scroll-functionsは、スクロールを引き起こす再表示の直前に呼び出されます。各関数は、ウィンドウwindowと新しいウィンドウの開始位置という2つの引数を返しますnew-start。を呼び出して、現在のウィンドウの開始位置、現在のウィンドウの終了位置、および新しいウィンドウの終了位置を取得できます。ポイントの間ではない場合や、それが移動することです。私の知る限り、これらの関数は、スクロールやサイズ変更など、ウィンドウの範囲を変更するすべての場合に呼び出されます。これらは、ウィンドウがバッファを表示し始めたときにも呼び出されます(作成されたばかりか、新しいバッファが表示されているため)。(window-start window)(window-end window)(window-end window t)new-start(window-end window t)

ポイントを移動しないようにスクロールコマンドを表示するには、現在のポイントをこのフックに保存し、で何かを実行する必要がありpost-command-hookます。スクロールのためにポイントが移動する必要があるため、おそらくそれを保存し、で復元しpre-command-hookます。


1
優秀な!認めざるを得ない。答えが「イエス」であるとは思っていなかった。
nispio 2014年

(window-start)横スクロールのようなものはありますか?(window-hscrollバッファー内のフォントがデフォルトのフォントと異なる場合、ジョブは実行されないことに注意してください)。
AlwaysLearning

1

@ギレスの答えは正しい方法です。情報とハックのためにこれをここに保管します。

私は信じているpoint動きがC関数によって実行される window_scroll_line_basedwindow_scroll_pixel_based(自分のフレームパラメータのdependinyg)。これらの関数はlispマシンに公開されていないため、アドバイスすることはできません。それらを呼び出す関数にアドバイスする必要があります。

これを行うことができます(lispのアクセス)機能の二つがある scroll-upscroll-down。ここに私がそれらについて知った方法があります:

  1. 長いバッファに移動します。
  2. 小さな領域を選択します。
  3. コール、M-x (put-text-property (region-beginning) (region-end) 'point-left (lambda (&rest _) (error "Point leaving")))。これは、ポイントが領域を離れるとエラーをスローします。
  4. をアクティブにしM-x toggle-debug-on-errorます。
  5. ポイントがこの領域内にあることを確認してください。
  6. ポイントが領域の外にドラッグされるまで、マウスホイールでスクロールします。

このようなバックトレースバッファーが与えられ、scroll-down関数を明確に示します。

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)

私はscroll-downCの定義に従いました。その結果、になり window_scroll、上記の2つの関数につながりました。

あなたができること

あなたは助言できるscroll-down/uparoundアドバイス(だけでなく、また点移動につながる可能性のある他の機能)。このアドバイスを使用して、ポジションpointが変更されたかどうかを確認し、古いポジションを記録します。そして、それであなたがやりたいことを何でもしてください。

C関数に関しては、アドバイスは非常に信頼できません。一部の重要な関数は、バイトコンパイルされたコードで特別なアドレスを持っています。つまり、コードがコンパイルされるときに、関数に関するアドバイスは呼び出されません。ここではそうはならないと思いますが、そうすべきではないと考えました。


私は助言するscroll-downscroll-upは思わず、ここで役に立ちます。スクロールが発生する可能性がある他の多くの方法があります。isearch-scrollプロパティを持つ少なくともすべてのコマンドは、スクロールコマンドと見なされます。
Gilles「SO-邪悪なことをやめなさい」2014

@Gillesだから、「ポイントの移動につながる可能性のある他の関数も」と私は言った。しかし、あなたの答えは間違いなく良く見えます!
Malabarba 2014年

それはかなり賢いデバッグです!
nispio 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.