現在のカーソル以外のバッファーでカーソルを永続的に移動するにはどうすればよいですか?


8

注意:`with-current-buffer`と` goto-char`を使用して、ポイントを別のバッファーの末尾に移動する方法は?おそらくこれと同じ質問をしますが、それに与えられた答えは、ここでの私のケースにはすぐには当てはまりません。たとえば、他のバッファにテキストを挿入するなどの答えがあります。ここで私が尋ねる質問はかなり単純で、それに対応する答えも単純であるべきだと思います。


仮定

  • Emacsフレームは2つのウィンドウに分割され、一方のウィンドウは呼び出されたバッファーを保持し*whatever*、もう一方のウィンドウは標準*scratch*バッファーを保持します。
  • *whatever*バッファは、数行のテキストが含まれています。
  • *whatever*バッファ内のカーソルは、そのバッファの先頭(つまり、その(point-min))にあります。
  • *scratch*バッファが現在のものです。

*scratch*バッファーで次のいずれかを評価した場合、*whatever*バッファー内のカーソルの位置は変更されません。

 (with-current-buffer "*whatever*"
   (goto-char (point-max)))
 (with-current-buffer "*whatever*"
   (end-of-buffer))
 (save-excursion
   (set-buffer "*whatever*")
   (goto-char (point-max)))
 (save-excursion
   (set-buffer "*whatever*")
   (end-of-buffer))

私は何でも、それを理解(goto-char (point-max))たり(end-of-buffer)しない*whatever*のカーソルの位置が、その後破棄されます。

  1. 上記のスニペットを変更して、*whatever*バッファーのカーソルがそのバッファーの末尾に(永続的に)配置されるようにする方法を教えてください。

  2. Emacsのドキュメントを使用してこの質問に自分で回答するにはどうすればよいですか?思いつく限りのことを試しました。


ジュール・タマグナンの明快な答えを読んだ後、私はさらに明確に規定する必要があることに気づきました:

問題のバッファがウィンドウに表示されているかどうかに関係なく機能する解決策を探しています。

I緩衝表示する場合、すべての後、BをウィンドウにW、特定の位置にカーソルを移動Lは、いくつかの他の緩衝視聴C同じウィンドウにWを、そして最終的に指し示すWバッファへ戻るBを、Iは、でカーソルを見ることを期待します私が去ったのと同じ場所L IOW、バッファがウィンドウに関連付けられているかどうかに関係なく、バッファのポイントがどこにあるかを覚えておく方法が必要です。

ターゲットバッファーが現在2つ以上のウィンドウ(W1W2W3、...)に表示されている場合はどうですか?このケースには多くの合理的な可能性があります。提案された解決策は、たとえば、カーソルの位置を変更することができます

  • W1W2W3、...の間で最近アクティブなウィンドウ
  • のすべてのウィンドウW1W2W3、...; または
  • などなど

(実際には非常にまれであることを期待しているので、私はこのコーナーケースについて強い意見はありません。)


1
これに関するマニュアルの主要なセクションは、PointWindow Pointです。
cjm

回答:


9

これはかなりクールな質問でした。私はこれを理解しようとして、知らなかったことをたくさん学びました。私が学んだことは、各ウィンドウにはの独自の値があるということですpoint。これは、ポイントがバッファーに関連付けられているのではなく、実際のウィンドウに関連付けられていることを意味するため、重要です。これまで見てきたように、これは大きな違いを生みます。

次に行う必要があるのは、ウィンドウ内のポイントの値を設定することです。そのための関数set-window-pointは次のとおりです(Googleでこれを見つけたのですが、emacs-docsでビルドのどこから探し始めるかわからない場合は、グーグルで見ることはいくつかの光を放つかもしれません)。次にset-window-point、選択するウィンドウを指定する必要があります。それをするために私は使用しましたget-buffer-window(もう一度私はこれを見つけるためにグーグルを使用しました)。

このコードは、バッファがウィンドウで開いている場合にのみ機能します。ウィンドウでバッファを開き、ポイントを設定して、元のウィンドウ構成に戻る別のバージョンを作成できるはずです。ただし、以下のコードははるかに単純です。

(set-window-point (get-buffer-window "*whatever*") (point-max))

他にご不明な点がある場合や、ご希望どおりに機能しない場合は、お知らせください。


意味あり; 2つのウィンドウでバッファを開いた場合(分割ウィンドウなど)、2つの独立したポイントがあります。
Juancho 2016

@Juanchoええ、私はそれがどのように機能するかを知っていましたが、今まで本当に沈没したことはありませんでした
Jules

6

Jules Tamagnanの回答が問題を特定しているので、詳しく説明します。)

あなたの解決策は、実際にsave-excursionまたはsave-excursion実際に機能します!(point)後でそのバッファーの値を確認することで確認できます。例:

(progn
  (with-current-buffer "*whatever*"
    (goto-char 42))
  (with-current-buffer "*whatever*"
    (point)))

常に42を返します(ただし、それがバッファー内の有効な位置である場合に限ります。これは、ドキュメントでの落とし穴としても言及されています。save-excursion元のバッファー内の位置のみが復元され、他のバッファー内の位置は復元されません。

バッファの位置が設定したものと異なる場合、それは何か他のものがそれを変更しているためであり、それはおそらくウィンドウ(またはどこかのフックですが、ほとんどのフックはポイントを混乱させることはありません)です。たとえば、プロセス出力フックの場合があります)。ポイントについてのドキュメント、メモがあります:

各バッファには独自のポイント値があり、他のバッファのポイント値とは無関係です。各ウィンドウにはポイントの値もあり、これは同じバッファー上の他のウィンドウのポイントの値とは無関係です。これが、同じバッファーを表示するさまざまなウィンドウでポイントの値が異なる可能性がある理由です。バッファーが1つのウィンドウのみに表示される場合、バッファーのポイントとウィンドウのポイントは通常同じ値であるため、区別が重要になることはほとんどありません。詳細については、ウィンドウポイントを参照してください。

バッファがウィンドウに表示されている場合、ポイントが変更されるか、ウィンドウが再表示されるたびに、バッファのポイントがウィンドウのポイントに更新されます。結果として、ポイントの設定は、基本的にはLispコードが続く限り持続します。トップレベルのコマンドループが制御を得るとすぐに、ウィンドウは再表示されます(私が知る限り、表示されていなくても)。バッファの位置は上書きされます。実際には、ユーザーが選択した位置は、プログラムが選択した位置より優先されます。

バッファを表示するウィンドウのポイントも更新する場合は、を呼び出しget-buffer-window-listてウィンドウを列挙できます。

(with-current-buffer "*whatever*"
  (goto-char …)
  (cl-dolist (window (get-buffer-window-list nil nil t))
    (set-window-point window (point))))

しかし、ユーザーがバッファを訪問している場合、彼らは彼らの鼻の下でポイントが変更されたことを感謝しないかもしれないことを考慮してください。

私が知る限り、Emacsはウィンドウが選択されたときに追跡しません(これはEmacsの用語では「アクティブ」です)、現在選択されているかどうかしか知ることができません。選択されたウィンドウに注意を払い始める場合は、各フレームに選択されたウィンドウがあり、Emacsはいつフレームが選択されたかを常に認識しているわけではないことに注意してください((selected-frame)特にEmacsには方法がないため、ターミナルエミュレーター内のフレームとは完全に一致しません)ユーザーがターミナルエミュレーターウィンドウをアクティブにしたときを知る)。

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