Bagaimana cara mencapai efek pelipatan kode di Emacs?

123

Apa cara terbaik untuk mencapai sesuatu seperti melipat kode, atau jenis bersepeda yang digunakan mode org. Apa solusi terbaik di elisp untuk menciptakan jenis perilaku ini?

EDIT: Maaf saya tidak jelas. Saya ingin memprogram sesuatu secara elisp yang melakukan hal-hal yang sangat mirip dengan pelipatan kode, atau sebenarnya paling mirip dengan mode-org dengan hierarki yang dapat diperluas. Saya bertanya-tanya cara terbaik untuk mencapai pengaruh ini. Saya rasa saya pernah mendengar emacs overlay adalah solusi yang baik, tetapi saya tidak tahu.

Untuk melipat saya hanya menggunakan builtin set-selective-display

EDIT NOMOR 2:

Terima kasih atas jawabannya tetapi saya pikir saya mengajukan pertanyaan yang salah, jadi izinkan saya mencoba lebih jelas tentang apa yang saya coba lakukan. Saya ingin membuat yang berikut ini

Ketika Anda meletakkan poin Anda pada suatu fungsi dan memanggil fungsi elisp ini, itu akan menempatkan definisi fungsi dari mana pun itu (saya berpikir untuk hanya menggunakan find-tag untuk ini) dan membuka lipatannya di buffer saat ini. Idenya adalah jika Anda harus melompat ke buffer yang berbeda untuk membaca definisi fungsi, saya merasa ini adalah konteks yang beralih ke file lain. Jadi saya ingin berperilaku seperti kode lipat hanya itu menarik kode eksternal dari buffer. Hal ini menimbulkan beberapa masalah karena tidak dapat menempelkan kode ke buffer atau jika seseorang menyimpannya akan menyimpan kode yang ditarik. Jadi saya bertanya-tanya apakah ada cara untuk membuat area di dalam buffer yang juga bukan bagian dari buffer. Saya pikir itu masuk akal.

jacob
sumber
Anda sedang mencari sesuatu yang ketika Anda memanggilnya dengan titik dalam fungsi CALL itu melompat ke definisi fungsi? seperti mendapatkan bantuan tentang fungsi elisp akan memungkinkan Anda melompat ke kode elisp? Saya tidak berpikir Anda dapat melakukan ini tanpa beberapa konsep "Proyek" Misalnya, bagaimana Anda tahu fungsi "swap" mana yang ingin Anda lompat?
Brian Postow
1
Lihat juga: stackoverflow.com/questions/382781/… di mana tampilan selektif di-tweak sedikit untuk beberapa efek seperti lipat.
Michael Paulukonis
Saya sarankan Anda menghapus Anda EDIT NB 2dan membuat pertanyaan baru untuk itu.
Stefan

Jawaban:

151

Melipat biasanya tidak diperlukan dengan emacs, karena memiliki alat yang secara eksplisit mengimplementasikan tindakan yang dilakukan orang secara manual saat melipat kode.

Kebanyakan orang sukses baik dengan pencarian tambahan sederhana. Lihat "foo" disebutkan di suatu tempat? Ketik C-sfoo, temukan definisinya, tekan enter, baca, lalu tekan C-x C-xuntuk kembali ke tempat Anda sebelumnya. Sederhana dan sangat berguna.

Kebanyakan mode mendukung imenu . M-ximenuakan membiarkan Anda melompat ke definisi fungsi (dll.) dengan nama. Anda juga dapat mengikatnya ke klik mouse untuk mendapatkan menu fungsi (atau menambahkannya ke bilah menu; lihat halaman Info untuk detail selengkapnya). Ini menyediakan data untuk mode-fungsi mana, yang akan memungkinkan Anda melihat fungsi mana yang saat ini Anda berada di dalam modeline. (Namun, mengapa fungsi Anda selama ini?)

Ada juga speedbar , yang menampilkan informasi imenu (dan hal lain) secara grafis.

Jika Anda ingin mendapatkan gambaran umum tentang file Anda, coba M-xoccur". Diberikan regex, ini akan membuat buffer baru dengan setiap kecocokan di buffer saat ini. Anda dapat mencari" (defun "untuk mendapatkan gambaran umum tentang fungsi file saat ini mengimplementasikan. Mengklik pada hasil akan memindahkan Anda ke posisi itu dalam file.

Jadi, pikirkan tentang apa yang sebenarnya ingin Anda capai, dan Emacs mungkin mengimplementasikannya. Jangan berkelahi dengan alat yang tidak sempurna yang membuat Anda terus melipat dan membuka barang.

jrockway
sumber
13
Vim juga menyediakan semua fitur ini dalam satu bentuk atau lainnya tetapi saya masih merasa fasilitas kode lipatnya sangat berharga.
Intuisi
115
Saya tidak menyukai kalimat pertama ("Melipat biasanya tidak diperlukan dengan emacs, karena ..."). Saya menggunakan pelipatan sederhana (berdasarkan level indentasi) terus-menerus untuk memindai struktur kode yang tidak dikenal.
Simon Michael
4
Ms o adalah jalan pintas untuk Mx terjadi
Joshua Olson
3
Saya memilih karena banyak jalan pintas yang berguna dalam jawaban tetapi juga komentar @SimonMichael yang dipilih secara maksimal karena terkadang lipat / terungkap masih bisa berguna!
Adrien Coquio
56
Jawabannya dipikirkan dengan matang dan sangat informatif. Namun, OP menanyakan bagaimana melakukan pelipatan kode. OP tidak menanyakan cara favorit semua orang untuk menghindari pelipatan kode. Turun memilih.
wkschwartz
104

sembunyikan-tampilkan mode ( hs-minor-mode) dengan keybinding default C-c @ C-M-huntuk memicu pelipatan ( hs-hide-all)

dmckee --- kucing mantan moderator
sumber
12
Ini bekerja dengan baik. Dan dengan kejahatan-mode, ini dipicu oleh perintah vim biasa: zR, zM, zo, zc.
Justin M. Keyes
39

Cara lain untuk menguliti kucing:

Saat itu terjadi, Anda tidak memerlukan paket atau konfigurasi tambahan untuk itu. Buka saja file sumber apa saja, ketik

M-1 Cx $ dan keajaiban terjadi!

Seperti biasa, ini ajaib: Cx $ akan mengembalikan kode Anda.

Kita dapat menggunakan sistem bantuan Emacs untuk mengetahui apa yang terjadi: Ch k Cx $ memberitahu kita bahwa kombinasi tombol di atas memanggil set-selektif-tampilan , sebuah fungsi yang mengambil satu argumen numerik (awalan M-1 melewati 1 sebagai nilainya argumen itu) dan, tidak mengherankan, menetapkan variabel selektif-tampilan ke nilai argumen itu.

dari blog sihir emacs minor

Hanya untuk kelengkapan: M-3 Cx $ akan menampilkan kode bersarang yang lebih dalam dan seterusnya.

FWIW Saya membuat pembantu kecil hari ini berdasarkan smth. ditemukan di sini sehingga F5 mengaktifkan pelipatan kode berdasarkan posisi kursor saat ini:

(global-set-key (kbd "<f5>") 'set-selective-display-dlw)

(defun set-selective-display-dlw (&optional level)
"Fold text indented same of more than the cursor.
If level is set, set the indent level to LEVEL.
If 'selective-display' is already set to LEVEL, clicking
F5 again will unset 'selective-display' by setting it to 0."
  (interactive "P")
  (if (eq selective-display (1+ (current-column)))
      (set-selective-display 0)
    (set-selective-display (or level (1+ (current-column))))))
einSelbst
sumber
22

Saya menggunakan mode minor outline untuk melipat kode python saya. Alih-alih perlu menempatkan {{{and}}} seperti dalam mode lipat, mode ini menggunakan tempat blok ditentukan.

http://www.gnu.org/software/emacs/manual/html_node/emacs/Outline-Mode.html http://www.emacswiki.org/emacs/OutlineMinorMode

Saya cukup yakin bahwa itu datang dengan emacs. Saya kemudian menambahkan ini ke .emacs saya

;;======= Code folding =======
(add-hook 'python-mode-hook 'my-python-outline-hook)
; this gets called by outline to deteremine the level. Just use the length of the whitespace
(defun py-outline-level ()
  (let (buffer-invisibility-spec)
    (save-excursion
      (skip-chars-forward "    ")
      (current-column))))
; this get called after python mode is enabled
(defun my-python-outline-hook ()
  ; outline uses this regexp to find headers. I match lines with no indent and indented "class"
  ; and "def" lines.
  (setq outline-regexp "[^ \t]\\|[ \t]*\\(def\\|class\\) ")
  ; enable our level computation
  (setq outline-level 'py-outline-level)
  ; do not use their \C-c@ prefix, too hard to type. Note this overides some bindings.
  (setq outline-minor-mode-prefix "\C-t")
  ; turn on outline mode
  (outline-minor-mode t)
  ; initially hide all but the headers
  ;(hide-body)
  ; make paren matches visible
  (show-paren-mode 1)
)
Nikwin
sumber
8
Sepertinya sudah outline-modemendukung python out-of-the-box di emacs 24 - tidak perlu outline-levelfungsi khusus . Ini semua yang perlu saya tambahkan ke user.el:(add-hook 'python-mode-hook 'outline-minor-mode)
scytale
1
oh dan Anda pasti ingin menggantinya outline-minor-mode-prefix- keybindings default buruk - saya gunakan(setq outline-minor-mode-prefix (kbd "C-;"))
scytale
13

Anda juga bisa mendapatkan kode lipat dengan menggunakan CEDET dengan kode berikut di file init:

(global-semantic-folding-mode t)

Setelah evaluasi kode ini, segitiga kecil akan muncul di area pinggiran, sehingga Anda dapat melipat & membuka kode dengan menggunakannya. Metode ini lebih tepat, karena menggunakan informasi sintaksis, yang diekstrak dari kode sumber

Alex Ott
sumber
1
jika menghadapi beberapa bug, lihat pertanyaan ini: stackoverflow.com/questions/15307113/…
AdrieanKhisbe
9

hs-minor-mode bekerja dengan baik.

Ia bekerja lebih indah saat dipasangkan dengan fold-dwim (lakukan apa yang saya maksud). Lalu ada lipat-dwim-org, yang menyediakan mode-org seperti pengikatan kunci untuk pelipatan kode! Keduanya dapat diinstal melalui selai jeruk (dan menurut saya elpa).

Jones
sumber
5

vimish-fold juga merupakan solusi yang bagus dan mudah.

https://github.com/mrkkrp/vimish-fold .

Dari beranda:

Ini adalah paket untuk melakukan pelipatan teks seperti di Vim. Ini memiliki beberapa fitur berikut:

  • melipat daerah aktif;
  • umpan balik visual yang baik: jelas bagian teks mana yang terlipat;
  • kegigihan secara default: ketika Anda menutup file lipatan Anda tidak menghilang;
  • ketekunan berskala dengan baik, Anda dapat mengerjakan ratusan file dengan banyak lipatan tanpa efek buruk;
  • itu tidak merusak lekukan atau sesuatu;
  • lipatan dapat diubah dari keadaan terlipat menjadi tidak terlipat dan kembali dengan sangat mudah;
  • navigasi cepat antara lipatan yang ada;
  • Anda dapat menggunakan mouse untuk membuka lipatan (baik untuk pemula dan tidak hanya untuk mereka);
  • untuk penggemar paket avy: Anda dapat menggunakan avy untuk melipat teks dengan sedikit penekanan tombol!

Menggunakan sangat baik use-packagesaya menginstal dan mengaktifkannya menggunakan potongan ini di konfigurasi saya:

(use-package vimish-fold
  :ensure t
  :config (vimish-fold-global-mode t))
Horus
sumber
3

Saya heran tidak ada yang menyebutkan penyempitan-pelebaran. Ini sangat luar biasa, dibundel dengan emacs juga. Cukup pilih kode yang ingin Anda fokuskan dan tekan C-x n n, untuk kembali ke mode tampilan penuh, lakukan saja C-x n w. Saya selalu lebih suka menggunakan fungsionalitas emacs bawaan daripada mengacaukan ruang pengguna saya dengan paket lain. Jika emacs dapat melakukannya dengan fungsionalitas built-in maka saya akan lebih memilihnya daripada beberapa paket pihak ketiga, tapi itu hanya saya, tidak berarti atau menyiratkan hal lain selain itu saya suka hal-hal sederhana daripada konfigurasi panjang yang rumit.

Kirk Walla
sumber
2

Saya percaya bahwa perbandingan "proyek" Anda dengan melipat tidak cukup baik, karena melipat adalah tentang mengubah tampilan sambil menjaga konten penyangga tetap utuh (teks). Proyek Anda akan melibatkan menampilkan teks tambahan sambil menjaga konten buffer tetap utuh, AFAIU. Begitu. itu tidak dapat diimplementasikan sebagai komposisi penyisipan dan pelipatan teks (kemudian, konten buffer akan diubah).

Tapi mungkin, itu memang mungkin dengan mekanisme yang sama seperti melipat dilakukan dengan - "overlay" ... Pertimbangkan properti overlay "before-string" dan "after-string" ; mungkin, Anda bisa meletakkan definisi fungsi Anda ke dalam string yang termasuk dalam hamparan kosong pada intinya. Lihat fungsi outline-flag-region untuk melihat bagaimana overlay digunakan dalam mode outline.

imz - Ivan Zakharyaschev
sumber
2

Jika Anda menggunakan hs-minor-mode, mungkin ada baiknya juga menyetel pintasan yang lebih nyaman, misalnya:

(eval-after-load 'hideshow
 '(progn
   (global-set-key (kbd "C-+") 'hs-toggle-hiding)))
quazgar
sumber
0

Dengan inspirasi dari jawaban einSelbst :

(saran-tambahkan 'set-selektif-tampilan
            : filter-args (lambda (args)
                           (if (atau (car args) selective-display)
                               args
                             (daftar (1+ (kolom saat ini)))))
            '((nama. set-selektif-tampilan-dari-kursor-kolom)))

Voila, C-x $tiba-tiba menjadi berguna bahkan tanpa bisnis C-uatau apapun M-4.

DomQ
sumber
0

Jika Anda melakukan beberapa JavaScript dan menggunakan js2-mode.el, Anda dapat:

C-c C-f: beralih sembunyikan / tampilkan semua

C-c C-e: sembunyikan elemen

C-c C-s: elemen acara

roboli
sumber