show-marks.el の拡張

# Emacs 29.0.50 対応
動かなくなっていたので更新しました(Nov 26 2022).

- [github.com/s-fubuki/show-marks-ex.el](https://github.com/s-fubuki/show-marks-ex.el) 

# show-marks の拡張
`mark-ring` のマーカーをメニューから選んでジャンプできる Greg Roweさん作の [show-marks](https://github.com/vapniks/show-marks) を自分で使いやすいように少しいじったので公開します。

# 主な変更点
- 必要分だけウィンドウを開き確定/キャンセルすれば閉じる
- SPACE, BS や n, p, TAB, q 等にもポイント移動やキャンセルをバインド
- マーカーを可視化し同一行のマーカーは1行にまとめる
- 開いてすぐ RET を叩けば往年の C-x C-x のように 2箇所のポイントを行き来できる
- global-mark-ring 等も見れる
- マーカーが narrow 箇所なら除外
- 他

![show-marks-ex-cap11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239081/597c7087-359b-b108-c461-4e8979d0a50b.png)

# インストール
  list-package 等で [show-marks](https://github.com/vapniks/show-marks) (0.4) をインストールした場合、  show-marks.el が [fm.el](https://github.com/tavisrudd/emacs.d/blob/master/vendor/fm.el) を使うので一緒にインストールされるが、  個別にインストールするときはそちらもインストールしてください。list-package はお手軽な分いろいろ勝手をされるので個人的にはこの方が好み。

  その上で [show-marks-ex.el](https://github.com/s-fubuki/show-marks-ex.el) を `load-path` の通ったディレクトリに置き `init.el` 等で

```emacs-lisp:init.el
(require 'show-marks-ex) 
```


等とし好みでキーバインドする

```emacs-lisp:init.el
(global-set-key (kbd "C-c SPC") 'show-marks)
```
あるいは

```emacs-lisp:init.el
(global-set-key (kbd "M-s SPC") 'show-marks)
```

上記バインドでたまに他のモードと衝突するので、現在個人設定ではこのふたつ共をバインドしていて、実際どちらがいいかもしくは両方駄目なのか試し中だが `M-s SPC` を使うことの方が多いように思える.

ちなみに上は org-mode 下は mew とかぶっているが、こうするとどちらかで逃げられる。

# 使い方
開いて `SPACE` 等で選んで `C-j` や `RET` で確定しジャンプするだけですが、  肝心のマークの仕方を念のため...

今はたいていの人はデフォルトであるリージョンをハイライトするモードでそのまま使っていると思います。
それだと `C-SPC` でマークをするとハイライトがアクティブになってしまうのですが、 `C-SPC` を2連打することによって、  往年の Emacs のようにハイライトさせずにマークだけすることができます。
`C-SPC` は勿論 `C-@` でも OK です。

```EMACS-LISP:Cosole
C-SPC C-SPC
```

ちなみに `exchange-point-and-mark` も `C-u C-x C-x` で
昔のようにハイライトさせずに実行できます。

- see [Transient Mark Mode の無効化](https://www.gnu.org/software/emacs/manual/html_node/emacs/Disabled-Transient-Mark.html#Disabled-Transient-Mark)

# カスタマイズ
## グローバルリングをリストに加えない
デフォルトでは `mark-ring` の次に `global-mark-ring` を追加して表示しますが、それをやめたい場合 変数 `show-marks-global` を `nil` にします。実はこの方がシンプルで使いやすいかもしれません。

```emacs-lisp:init.el
(setq show-marks-global nil)
```

ここが数値ならグローバルマークも対象になり、指定した長さに切り詰めたバッファ名も表示します。
`t` なら切り詰めませんが表示が崩れます。

## 逆に bm や register のマークも追加する
   先の変数 `show-marks-global`  も設定した上で、 変数 `show-marks-add-mark-ring` に、   マークリングの入ったリストかそれを返す関数を設定します。

   レジスタのマーカーをリストで返す関数 `show-marks-register-mark-ring` と、 bm ブックマークをマーカリストにして返す関数 `show-marks-bm-mark-ring` を附属しています。

```emacs-lisp:init.el
(setq show-marks-add-mark-ring 
      '(global-mark-ring
        show-marks-register-mark-ring
        show-marks-bm-mark-ring))
```

bm やレジスタは個人的にはほぼ使っていないので、この機能が有用かどうかは不明ですが、 `global-mark-ring` を追加できるようにしたときついでなので追加しました。

## exchange-point-and-mark 的な挙動
オリジナル show-marks では確定したものを `mark-ring` トップに移動するのですが、起動時に更に現在のマークをその `mark-ring` トップに乗せてリストを作っているので、2行目が前回確定された箇所に変更された状態で起動します。
1行目であるカレントマークのものを使うと、次回起動時の全体の順列はかわりません。

ちょっと何を言っているのかよく判りませんが、実際の挙動がはじめよく判らなくて使っていて混乱したので、現在のポイントをマークしてから、カーソルをマークバッファの2行目に合わせて起動するようにしてあります。
これによって起動時にカレントマークが常にポイント位置に更新され、ひとつ前のマークは `mark-ring` にプッシュされていくので、起動して `RET` を叩くだけで2ポイント間を行き来できるようになります[^1]。

[^1]: 同一バッファに限ります。

これをやめ、1行目にカーソルのある状態で起動するには、変数 `show-marks-exchange` を `nil` にします。
但しマークがないときに起動するとエラーになるので、起動時にポイントをマークをするのはそのままです。

```emacs-lisp:init.el
(setq show-marks-exchange nil)
```

## キーバインドの変更や追加
元のバインドをマイナーモードでオーバーライドして拡張しているので、`mark-mode-map` ではなく  `show-marks-ex-minor-mode-map` に対してして行なってください。

```emacs-lisp:init.el
(require 'show-marks-ex)
(define-key show-marks-ex-minor-mode-map (kbd "C-.") 'mark-mode-next-mark-ex)
(define-key show-marks-ex-minor-mode-map (kbd "C-,") 'mark-mode-prev-mark-ex)
```

# テスト的機能
`j` 押しで ace-jump 的なショートカットが使えます。
マーカーのあるポイントに文字が出るのでそのキーを押せばダイレクトに飛べます。
`q` でこのモードから抜けます。

![show-marks-ex-cap22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239081/7fee5fd8-e49e-a876-a239-b01f6d2df193.png)

数値～英小文字～英大文字の順でポイントにキーを割り当てていきますが、割り当て文字が尽きると単純に割り当てられません。
`q` だけ特別でジャンプの割り当てがされず、このモードからの脱出になります。
   
基本のマイナーモードの上に更にマイナーモードを張ってこのモードのキーをかぶせるので、かぶらなかった場合元のキーの機能はそのまま使えます。 `d` 等がそうなる可能性が高いです。

はなからこのモードで起動したい場合 `show-marks` ではなく `show-marks-jp` でキーバインドしてください。

```emacs-lisp:source.el
(global-set-key (kbd "M-s SPC") 'show-marks-jp)
(define-key show-marks-ex-jump-mode-map "q" 'mark-mode-quit)
```

overlay をかぶせたとき行末のマークで何故だか起こる色漏れ対策を、フェイスを一時的に変更するギミックで対処しているので、バージョンに依存している可能性があります(:extend 等でも回避できなかった)。
テストは 27.1, 28.0 でしかしていません。

# 既知の問題点
## org-mode の link 上でマークした箇所がハイライトされない場合がある
org-link は text-property を使って文字列の一部を隠しているのですが、org-link 上でマークをすると隠す前の位置がマークされてしまうことがあります。
つまりマークされた箇所が隠されてハイライトが見えなくなってしまいます。
結果的にジャンプに問題は出ないのですが、発生するときとそうでないときがあってトリガーが判らず対処できていません。

おそらく text property と maker の処理のタイミングの関係だと思うのですが、対策するにしてもマークをする側に仕掛をしないといけないと思いますが、 `org-toggle-link-display` で隠されていた部分を見ることができるので、消極的措置としてこれを `C-c C-o` にバインドしてあります。