Saya memodifikasi beberapa kode elisp dari linum.el:
(custom-set-variables '(linum-format 'dynamic))
(defadvice linum-update-window (around linum-dynamic activate)
(let* ((w (length (number-to-string
(+ (count-lines (point-min) (point-max)) 1))))
(linum-format (concat " %" (number-to-string w) "d ")))
ad-do-it))
Saya bisa memperbaiki bug di mana lekukan itu off-per-satu dengan memodifikasi (count-lines (point-min) (point-max))
untuk (+ (count-lines (point-min) (point-max)) 1)
. Itu mudah.
Tapi sekarang saya ingin memodifikasinya sehingga lebar minimum adalah 2 dengan menambahkan if-conditional di mana (concat " %" (number-to-string w) "2d ")
jika jumlah barisnya <10.
Ini seharusnya mudah! Tambahkan satu syarat dan salin / tempelkan concat. Sepotong kue, kan? Maksud saya, saya tahu apa yang seharusnya saya lakukan tetapi saya jarang menyentuh elisp dan saya selalu gentar ketika saya harus memodifikasi apa pun dengan banyak tanda kurung.
Gaya "benar", dari apa yang saya mengerti, adalah untuk menyusun kode berdasarkan indentasi dan membungkus tanda kurung di akhir baris daripada pada sendiri. Berasal dari bahasa gaya 'C' lainnya, saya berjuang dengan baik membaca dan menulis kode dengan cara ini. Jadi pertanyaan saya adalah: apa yang saya lakukan salah? Bagaimana saya bisa mengedit elisp dan menavigasi kode sehingga saya tidak harus duduk di sana dan menghitung setiap tanda kurung?
Ketika saya bekerja dengan sesuatu di elisp yang menjadi terlalu dalam, saya harus menutup pintu, menarik tirai, dan mulai memposisikan tanda kurung K&R sehingga saya tidak hanya bisa membaca tetapi memodifikasi benda sialan itu tanpa panik.
Jelas saya melakukan ini semua salah. Bagaimana saya bisa menyentuh elisp seperti ini tanpa rasa takut?
Harap dicatat bahwa pertanyaan saya adalah bagaimana menavigasi dan mengedit elisp bukan sebagai pertanyaan tentang gaya. Saya menggunakan yang berikut ini sebagai panduan gaya: https://github.com/bbatsov/emacs-lisp-style-guide
Pembaruan:
Cara memformat elisp dengan benar sebelum mempermalukan diri Anda di emacs.stackexchange:
Tandai elisp Anda dan lakukan M-x indent-region
.
Solusi Masalah:
Bagi mereka yang ingin tahu bagaimana melakukan pembenaran yang tepat untuk linum dengan lebar minimum dua, berikut adalah solusinya:
(defadvice linum-update-window (around linum-dynamic activate)
(let* ((w (length (number-to-string
(+ (count-lines (point-min) (point-max)) 1))))
(linum-format (if (> w 1)
(concat " %" (number-to-string w) "d ")
" %2d ")))
ad-do-it))
sumber
%2d
karena sekali lebarnya bergeser ke 3 atau lebih karakter maka itu bergerak dari membawa kanan-dibenarkan ke kiri-dibenarkan.highlight-parentheses
,;rainbow-delimiters
; dll. Ini adalah versi sederhana saya sendirihighlight-parentheses
yang memungkinkan pengguliran tanpa menghapus tanda kurung yang terakhir diwarnai: stackoverflow.com/a/23998965/2112489 Di masa depan, ini adalah satu pertanyaan per pelanggan / utas.Jawaban:
Ada sejumlah paket tambahan yang mungkin membantu, seperti paredit, smartparens, dan lispy. Paket-paket ini memudahkan navigasi dan memanipulasi kode lisp sehingga Anda dapat berpikir dalam ekspresi s dan membiarkan editor khawatir tentang menyeimbangkan parens.
Emacs juga memiliki banyak perintah bawaan untuk menangani sexps dan daftar yang layak dipelajari dan dapat membantu Anda lebih terbiasa dengan struktur kode lisp. Ini umumnya terikat dengan
C-M-
awalan, seperti:C-M-f
/C-M-b
untuk bergerak maju / mundur dengan sexpC-M-n
/C-M-p
untuk bergerak maju / mundur berdasarkan daftarC-M-u
/C-M-d
untuk naik / turun satu tingkatC-M-t
untuk menukar dua sexps di sekitar titikC-M-k
untuk membunuh sexpC-M-SPC
untuk menandai sexpC-M-q
untuk indentasi ulang sexpContoh kode yang Anda berikan mungkin lebih jelas jika Anda memperbaiki lekukan: beri titik di awal
(defadvice...
dan tekanC-M-q
untuk indentasi ulang seluruh ekspresi. Untuk mengganti(concat...
saya akan mulai dengan menempatkan titik di awal sexp dan memukulC-M-o
untuk membagi garis sambil menjaga lekukan. Kemudian tambahkan Anda(if...
, dan gunakan perintah di atas untuk melompat ke akhir daftar untuk menambahkan paren penutup lain, kembali ke awal untuk indentasi ulang, dll.Anda mungkin juga ingin menghidupkan
show-paren-mode
, yang akan menyoroti paren yang sesuai ketika titik berada di awal atau akhir daftar. Anda mungkin lebih suka menyorot seluruh ekspresi daripada paren yang cocok, jadi coba ubahsuaikanshow-paren-style
.Seperti @Tyler disebutkan dalam komentar pada jawaban lain, Anda harus melihat manual untuk mempelajari lebih lanjut tentang ini dan perintah terkait.
sumber
C-M-q
bisa dipanggil dengan argumen awalan (C-u C-M-q
) untuk mencetak ekspresi di titik. Ini akan memecah semuanya pada baris dan indentasi yang terpisah sehingga sarangnya sangat jelas. Anda biasanya tidak ingin kode pelat Anda terlihat seperti itu, tetapi mungkin membantu untuk memahami sedikit kode tanpa secara manual menjalankan K&R penuh di atasnya. (Dan Anda selaluC-x u
dapat membatalkan).Cara yang baik untuk mengedit LISP adalah dengan memanipulasi AST, alih-alih karakter atau garis individual. Saya sudah melakukan itu dengan paket saya lispy yang saya mulai 2 tahun yang lalu. Saya pikir sebenarnya perlu sedikit latihan untuk mempelajari bagaimana melakukan ini dengan baik, tetapi bahkan hanya dengan dasar-dasarnya saja sudah dapat membantu Anda.
Saya bisa menjelaskan bagaimana saya akan melakukan perubahan ini:
Langkah 1
Posisi awal biasanya memiliki titik sebelum sexp tingkat atas. Inilah
|
intinya.Anda ingin memiliki indentasi kode yang benar, jadi tekan isekali. Ini akan memperbaikinya dengan baik.
Langkah 2
Anda ingin menandai
"d "
dengan suatu wilayah, karena objek yang dapat memanipulasilispy
adalah daftar, yang tidak perlu ditandai, atau urutan simbol atau / dan daftar yang perlu ditandai dengan suatu wilayah.Tekan atuntuk melakukannya. The aperintah memungkinkan untuk menandai simbol tunggal dalam daftar orang tua, dan tadalah indeks simbol tertentu.
Langkah 3
()
, tekan (.if
.()
.> w 10
.Langkah 4
Untuk mengkloning string:
Jika Anda ingin menonaktifkan wilayah dengan cara yang mewah dan meletakkan titik di bagian paling awal dari string, Anda dapat menekan idm:
Atau Anda bisa melakukannya m C-b C-b C-bdalam kasus ini, atau C-g C-b C-b C-b. Saya pikir idmlebih baik, karena itu sama terlepas dari panjang tali. Saya pikir C-x C-x C-f C-g juga akan bekerja terlepas dari panjang string.
Akhirnya, masukkan
2
untuk mendapatkan kode akhir:Ringkasan
Urutan penuh adalah: at( C-f,
if
, (,> w 10
, C-f C-m M-m cidm,2
.Perhatikan bahwa jika Anda menghitung penyisipan kode, satu-satunya kunci yang tidak terkait dengan manipulasi AST adalah dua C-fdan satu C-m.
sumber
Anda akan terbiasa dengannya seiring waktu, tetapi tentu saja ada banyak hal yang dapat Anda lakukan untuk mempercepatnya:
Lekukan
Ada metode untuk kegilaan ini. Anda dapat melakukan ini:
Misalkan itu
1
benar-benar ekspresi yang besar, dan Anda ingin membukanya sendiri.Ini menyesatkan.
1
Diindentasi hanya satu slot, meskipun seluruh tiga tingkat bersarang lebih tinggi! Lebih baik letakkan di samping orang tuanya.Jika kami menggunakan skema ini pada kode Anda sendiri, kami mendapatkannya:
Perhatikan korelasi kuat antara lekukan dan tingkat sarang. Garis dengan tingkat yang lebih besar dari sarang selalu diindentasi lebih dari garis dengan lebih sedikit.
Ini saja akan banyak membantu. Anda dapat dengan mudah melihat "bentuk" kode, dan sebagian besar bahasa lain telah melatih Anda untuk mengaitkan indentasi dengan blok dan blok dengan beberapa bentuk sarang (baik tersurat maupun tersirat).
Sebagai latihan, saya telah menghapus tanda kurung yang tidak penting dari kode. Anda harus dapat membaca kode dan menyediakan tanda kurung yang hilang, mengingat pengetahuan dasar tentang Elisp (yaitu, hal-hal apa saja fungsi dan nilai, dan struktur
let*
).sumber
newline-and-indent
untuk emacs-lisp-mode dan lisp-interaksi-mode memecahkan contoh pertama Anda, PythonNut. Dan TAB akan melakukan pekerjaan itu sepanjang waktu.Saya memasukkan ini sebagai jawaban yang berbeda.
Terkadang, lekukan akan mengecewakan Anda. Jalan lain Anda adalah menggunakan sesuatu seperti
rainbow-delimiters
:Ini membuat level bersarang paren apa pun menjadi eksplisit dan mudah dipindai.
Namun ada satu masalah yang cukup besar: orangtua itu menggelikan. Ada keseimbangan penekanan di sini.
rainbow-delimiters
biasanya akan memberikan banyak penekanan pada parens dengan mengorbankan sisa kode Anda! Tetapi jika Anda menekan pelangi ke bawah, mereka akan semakin sulit untuk dipindai.Jika Anda dapat menemukan satu set wajah yang menyeimbangkan ini dengan baik, maka tentu saja gunakan itu.
Yang mengatakan, satu solusi (salah satu yang membuat saya berkotek dengan gembira), adalah memiliki dua pasang wajah, dan beralih di antara mereka dengan cepat. Saat Anda melakukan hal-hal lain, wajah menjadi encer dan menghilang ke latar belakang:
Tetapi ketika Anda meletakkan titik pada paren, itu meninju paren sehingga Anda dapat melihat tingkat bersarang:
Dan di sini adalah kode untuk melakukan itu:
sumber
Jika Anda membuat indentasi kode Anda, maka Anda benar-benar perlu indentasi dengan benar. Pengembang Lisp memiliki harapan seperti apa lekukan yang seharusnya. Ini tidak berarti bahwa kode tersebut terlihat sama. Masih ada berbagai cara untuk memformat kode.
Saya berharap bahwa lekukan menunjukkan penahanan dalam beberapa cara. Tetapi tidak dalam kode Anda.
Secara default kode Anda mungkin indentasi seperti ini. Jawaban lain menjelaskan bagaimana Anda dapat melakukannya dengan bantuan Emacs:
Saya berharap bahwa
let
variabel terikat mulai pada kolom vertikal yang sama. Saya juga berharap bahwa tubuh yanglet
kurang lekuk. Kita belajar bagaimana sebuahlet
indentasi. Setelah Anda melatihnya sedikit, itu adalah pola visual yang mudah dikenali.Blok pembangun visual utama dalam kode adalah
defadvice
,let*
dan banyak panggilan fungsi. Dalamdef
nama memberitahu saya bahwa itu adalah definisi yang diikuti oleh nama, daftar argumen dan badan.Jadi saya suka melihat
Yang
let*
akan menjadilet*
:, daftar ikatan dan tubuh.Jadi saya suka melihat:
Lebih detail:
Untuk panggilan fungsi, saya ingin melihat:
atau
atau
Yang digunakan tergantung pada berapa lama argumen itu. Kami tidak ingin membuat garis terlalu panjang dan setiap argumen pada barisnya sendiri memungkinkan kami untuk memiliki lebih banyak struktur.
Jadi, Anda perlu menulis kode menggunakan pola-pola itu dan Anda perlu memastikan bahwa pembaca dapat dengan mudah mengidentifikasi pola-pola itu dalam kode Anda.
Kurung harus secara langsung melampirkan konstruksi mereka.
Hindari contoh spasi putih:
atau
atau
Dalam Lisp, tanda kurung tidak memiliki fungsi sintaksis bahasa, mereka adalah bagian dari sintaksis dari struktur data daftar (s-ekspresi). Jadi kami menulis daftar dan memformat daftar. Untuk memformat isi daftar kami menggunakan pengetahuan tentang bahasa pemrograman Lisp. Sebuah
let
ekspresi harus diformat berbeda dari panggilan fungsi. Masih keduanya adalah daftar dan tanda kurung harus langsung melampirkan daftar. Ada beberapa contoh di mana masuk akal untuk memiliki tanda kurung tunggal pada sebuah baris, tetapi jarang menggunakannya.Gunakan tanda kurung untuk mendukung Anda menemukan batas ekspresi. Biarkan mereka membantu Anda untuk berpindah dari daftar ke daftar, untuk mengedit daftar, untuk memotong & menyalin daftar, untuk mengganti daftar, untuk indent / format daftar, pilih daftar, ...
sumber
Untuk bantuan dasar dengan indentasi, gunakan TAB dan "CMq" (
indent-pp-sexp
); mengikat "Cm" untuknewline-and-indent
akan menghemat Anda harus menekan TAB setelah baris baru.Anda dapat menavigasi dengan sexp dengan "CM-kiri / kanan / atas / bawah / home / end", yang sangat berguna.
Jika Anda khawatir tentang menjaga keseimbangan kurung, gunakan sesuatu seperti smartparens (itu sedikit lebih memaafkan paredit itu , yang awalnya bisa terasa seperti mengenakan jaket pendek). Itu juga dilengkapi dengan banyak binding untuk menavigasi dan mengedit di tingkat sexp.
Terakhir, untuk menyoroti parens, mulailah dengan mengaktifkan opsi (Menu menu-> Tanda kurung yang cocok, atau
show-paren-mode
.) Anda juga dapat menggunakan salah satu paket yang disebutkan oleh daftar hukum dalam komentarnya, seperti "highlight-parenthesis" atau "rainbow-delimiters ".sumber
Sebagai tambahan dari apa yang orang lain berikan sebagai jawaban, berikut adalah 2 sen saya:
emacs-lisp-mode
sangat penting.blink-matching-paren
aktif (non-nil
) secara default. Biarkan begitu.show-paren-mode
, untuk menyorot paren kiri yang sesuai dengan paren kanan sebelum kursor.Saya tidak menggunakan pasangan listrik atau pelangi apa pun atau "bantuan" semacam itu. Bagi saya itu adalah masalah, bukan bantuan.
Secara khusus,
electric-pair-mode
bagi saya, merupakan gangguan yang tidak nyaman. Tetapi beberapa orang menyukainya. Dan saya membayangkan bahwa mungkin bermanfaat dalam beberapa konteks pemasangan lain selain tanda kurung Lisp (saya bayangkan juga begitu, tetapi saya juga tidak yakin untuk kasus penggunaan semacam itu).Anda akan menemukan yang terbaik untuk Anda. Hal utama yang ingin saya katakan adalah: (1) lekukan otomatis adalah teman Anda, seperti beberapa cara untuk menemukan paren kiri yang cocok dengan paren kanan sebelum titik.
Khususnya, melihat apa yang dilakukan lekukan otomatis untuk Anda segera mengajari Anda bahwa Anda tidak akan pernah lagi ingin menempatkan orangtua yang benar di telepon. Gaya pengkodean, yang ada di mana-mana dalam bahasa lain, hanya berisik.
Selain lekukan otomatis yang Anda dapatkan
RET
danTAB
, dapatkan nyaman menggunakanC-M-q
. (GunakanC-h k
diemacs-lisp-mode
untuk mencari tahu apa kunci ini lakukan.)sumber
Saya perhatikan beberapa orang telah menyebutkan pelangi-pembatas, itu juga mode favorit saya saat mengedit kode lisp.
Sebenarnya saya suka tanda kurung, hal terbaik tentang Lisp adalah tanda kurung itu, menyenangkan untuk berurusan dengan mereka jika Anda tahu caranya:
instal evil-mode dan pluginnya evil-surround, sehingga Anda dapat mengedit tanda kurung dengan mudah, misalnya, tekan
ci(
akan menghapus semua yang ada di dalamnya()
,va(
akan memilih benda yang dibungkus oleh "()" dan "()" itu sendiri. dan Anda dapat menekan%
untuk melompat di antara tanda kurung yang cocokgunakan flycheck atau flymake, tanda kurung yang tidak cocok akan digarisbawahi secara real time
sumber
Kesulitannya di sini adalah Anda ingin menambahkan beberapa kode sebelum dan sesudah tertentu
sexp
. Dalam situasi ini sexp adalah(concat " %" (number-to-string w) "d ")
. Anda ingin menyisipkan pernyataan if(if (> w 1)
sebelum dan pernyataan lain" %2d ")
sesudahnya.Bagian utama dari kesulitan adalah untuk mengisolasi ini
sexp
, secara pribadi saya menggunakan perintah di bawah ini untuk mengisolasi asexp
Cukup letakkan kursor di awal
(concat " %" (number-to-string w) "d ")
, yaitu, di yang pertama(
, lalu terapkan di atasisolate-sexp
. Anda memperolehKemudian tambahkan kode yang sesuai sebelum dan sesudah ini
sexp
, yaituDan voila. Kode yang diperoleh dengan cara ini mungkin tidak indah tetapi kemungkinan tersesat lebih kecil.
sumber