Meneliti empat jawaban yang tersedia saat ini ( dua di Super User dan dua di pertanyaan ini), saya melihat masalah berikut:
- Yang di SuperUser oleh Stefan dan Peng Bai (bergerak baris demi baris, melihat lekukan saat ini) tidak menerapkan mempertahankan posisi kolom saat ini dan naik ke orangtua,
- The jawaban oleh Dan (menggunakan kembali pencarian maju untuk menemukan baris berikutnya dengan lekukan yang sama) melompati garis dengan kurang lekukan: tidak tahu kapan ada saudara berikutnya, dan karena itu dapat pindah ke sesuatu yang tidak saudara kandung tapi anak dari orang tua lain ... "sepupu" selanjutnya mungkin.
- The jawaban dengan Gilles (menggunakan garis-mode) tidak mempertahankan posisi kolom dan itu tidak bekerja dengan garis-garis dengan nol lekukan ( "top-level" garis). Juga, dengan melihat kodenya
outline.el
, pada dasarnya juga akan berjalan baris demi baris (menggunakan outline-next-visible-heading
) dalam kasus kami, karena (hampir) semua baris akan cocok dengan regexp garis besar dan dihitung sebagai "heading".
Jadi, mengumpulkan beberapa ide dari masing-masing, saya memiliki yang berikut: maju selangkah demi selangkah, melompati garis-garis kosong dan lebih indentasi. Jika Anda berada pada indentasi yang sama maka itu adalah saudara kandung berikutnya. Ide dasarnya terlihat seperti ini:
(defun indentation-get-next-sibling-line ()
"The line number of the next sibling, or nil if there isn't any."
(let ((wanted-indentation (current-indentation)))
(save-excursion
(while (and (zerop (forward-line)) ; forward-line returns 0 on success
(or (eolp) ; Skip past blank lines and more-indented lines
(> (current-indentation) wanted-indentation))))
;; Now we can't go further. Which case is it?
(if (and (not (eobp)) (= (current-indentation) wanted-indentation))
(line-number-at-pos)
nil))))
(defun indentation-forward-to-next-sibling ()
(interactive)
(let ((saved-column (current-column)))
(forward-line (- (indentation-get-next-sibling-line) (line-number-at-pos)))
(move-to-column saved-column)))
Secara umum sesuai (maju / mundur / naik / turun), apa yang saya gunakan tampak seperti berikut ini saat ini:
(defun indentation-get-next-good-line (direction skip good)
"Moving in direction `direction', and skipping over blank lines and lines that
satisfy relation `skip' between their indentation and the original indentation,
finds the first line whose indentation satisfies predicate `good'."
(let ((starting-indentation (current-indentation))
(lines-moved direction))
(save-excursion
(while (and (zerop (forward-line direction))
(or (eolp) ; Skip past blank lines and other skip lines
(funcall skip (current-indentation) starting-indentation)))
(setq lines-moved (+ lines-moved direction)))
;; Now we can't go further. Which case is it?
(if (and
(not (eobp))
(not (bobp))
(funcall good (current-indentation) starting-indentation))
lines-moved
nil))))
(defun indentation-get-next-sibling-line ()
"The line number of the next sibling, if any."
(indentation-get-next-good-line 1 '> '=))
(defun indentation-get-previous-sibling-line ()
"The line number of the previous sibling, if any"
(indentation-get-next-good-line -1 '> '=))
(defun indentation-get-parent-line ()
"The line number of the parent, if any."
(indentation-get-next-good-line -1 '>= '<))
(defun indentation-get-child-line ()
"The line number of the first child, if any."
(indentation-get-next-good-line +1 'ignore '>))
(defun indentation-move-to-line (func preserve-column name)
"Move the number of lines given by func. If not possible, use `name' to say so."
(let ((saved-column (current-column))
(lines-to-move-by (funcall func)))
(if lines-to-move-by
(progn
(forward-line lines-to-move-by)
(move-to-column (if preserve-column
saved-column
(current-indentation))))
(message "No %s to move to." name))))
(defun indentation-forward-to-next-sibling ()
"Move to the next sibling if any, retaining column position."
(interactive "@")
(indentation-move-to-line 'indentation-get-next-sibling-line t "next sibling"))
(defun indentation-backward-to-previous-sibling ()
"Move to the previous sibling if any, retaining column position."
(interactive "@")
(indentation-move-to-line 'indentation-get-previous-sibling-line t "previous sibling"))
(defun indentation-up-to-parent ()
"Move to the parent line if any."
(interactive "@")
(indentation-move-to-line 'indentation-get-parent-line nil "parent"))
(defun indentation-down-to-child ()
"Move to the first child line if any."
(interactive "@")
(indentation-move-to-line 'indentation-get-child-line nil "child"))
Masih ada beberapa fungsi yang diinginkan, dan melihat outline.el
dan mengimplementasikan kembali beberapa yang dapat membantu, tapi saya senang dengan ini untuk saat ini, untuk tujuan saya.
set-selective-display
Anda dekat dengan yang Anda butuhkan?