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.eldan mengimplementasikan kembali beberapa yang dapat membantu, tapi saya senang dengan ini untuk saat ini, untuk tujuan saya.
set-selective-displayAnda dekat dengan yang Anda butuhkan?