Upgrade to Pro — share decks privately, control downloads, hide ads and more …

"EmacsでLisp" 礼讃

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for nfunato nfunato
October 18, 2020

"EmacsでLisp" 礼讃

Avatar for nfunato

nfunato

October 18, 2020
Tweet

More Decks by nfunato

Other Decks in Programming

Transcript

  1. Disclaimer “தߴੜʹLispͷྑ͞Λ఻͍͕͑ͨɺॳֶෛՙͷߴ͍EmacsΛಉ࣌ʹ֮͑ͤ͞Δ ͷ͸ਓݖ৵֐Ͱ͋Δ” ͱ͍͏πΟʔτ[4]ΛݟͯɺEmacs্ͰͷLispίʔυ޲͚ ฤूػೳΛࡽͯ͠ΈͨΒɺϢʔβձ੮্ͳΒͲ͏͍͏ײ૝ΛಘΒΕΔͷ͔ͱ͍͏ খωλͰ͢ɻ ຊདྷɺ͜͏͍͏ͷ͸ωλͰ͢Βͳ͍ΜͰ͕͢ɺࡶஊͷλω΍Կ͔ͷؾ෇͖ʹͭ ͳ͕Ε͹޾͍Ͱ͢ɻ (ޙ஫: ϢʔβձͰ΋ɺGNU

    EmacsϢʔβ͸൒਺ҎԼͰͨ͠) ݁Ռతʹɺ10߲໨+ЋͷτϐοΫʹͳΓ·ͨ͠ɻ ΍͸Γॳֶෛՙ͸ͦΕͳΓʹ͋Γͦ͏… ྑ͍ڭՊॻ͕ཁΔͷ͔΋ ྫࣔͷͨΊɺCommon Lisp, GNU Emacs, paredit, slime౳ͷ࢖༻Λ૝ఆ͍ͯ͠·͢ ͕ɺࢥ૝ͱͯ͠͸ଞͷLisp(e.g. Clojure)΍emacsen(e.g. lem)ʹ௨͡ΔͰ͠ΐ͏ɻ ͍͍͍ͨ͜ͱ͸ɺ຤ඌͷʮ͓ΘΓʹʯʹॻ͖·ͨ͠ɻ 4
  2. #1: ΋ͬͱυΩϡϝϯτΛʂ (C-h˘) EmacsͰ ಺ଂυΩϡϝϯτ(ӳޠ)ʹΞΫηε͢Δͷ͸ෆՄආ the extensible, customizable, self-documenting, real-time

    display editor 6 C-h?ɹ˘ʹདྷΔจࣈͱυΩϡϝϯτछผͷରԠΛදࣔ(HELPͷHELP) C-hmɹͦͷόοϑΝͷϞʔυͰ࢖͑ΔίϚϯυΛදࣔ C-hkɹଓ͍ͯλΠϓ͢ΔΩʔγʔέϯεʹରԠ͢ΔίϚϯυͷHELP C-hfɹଓ͍ͯλΠϓ͢Δelispͷؔ਺ʹରԠ͢ΔHELP C-hvɹଓ͍ͯλΠϓ͢Δelispͷม਺ʹରԠ͢ΔHELP C-hwɹଓ͍ͯλΠϓ͢ΔίϚϯυʹରԠ͢ΔΩʔόΠϯυΛදࣔ C-hlɹ௚ۙʹλΠϓ͞Εͨ300จࣈͷදࣔ C-hiɹinfoܗࣜ(hypertext)ͷ֤छυΩϡϝϯτͷΠϯσΫεΛදࣔ C-haɹଓ͍ͯλΠϓ͢ΔจࣈྻΛؚΉίϚϯυ܈Λݕࡧͯ͠දࣔ
  3. օ͞Μʂ ಺ଂυΩϡϝϯτݟͯ·͔͢ʁ ࣮͸ ࡉ͔͍ΩʔόΠϯυ͸Α͘๨ΕΔ (C-hmͰࢥ͍ग़ͤ͹͍͍) ҎԼͷΑ͏ͳײ͡ͰγεςϜΛஈ֊తʹཧղͰ͖Δ - C-hk C-l ͱଧͭͱɺC-l

    ʹׂΓ౰ͯΒΕͨ ɹ recenter-top-bottomίϚϯυͷHELP͕ग़ͯ͘Δ - ͦΕΛಡΜͰ΋෼͔Γʹ͍͘ඍົͳڍಈ͕ؾʹͳΔ৔߹͸ɺ ɹ දࣔ͞Ε͍ͯΔ "window.el" ͱ͍͏ϦϯΫ্Ͱ ɹ ϦλʔϯΩʔΛଧͬͯɺelispͷιʔείʔυ΁δϟϯϓʂ BSΩʔ(C-h)΁Ұจࣈ࡟আػೳΛׂΓ౰ͯΔํ๏Λઆ໌͍ͯ͠Δ ೖ໳هࣄͷଟ͕͘ɺ୅ସΩʔ(F1΍C-?౳)Λ࢖ͬͨ಺ଂHELP΁ͷ ΞΫηεํ๏͸આ໌͍ͯ͠ͳ͔ͬͨΓ͢Δ… 7
  4. #2: ΋ͬͱҾ਺Λ… (C-uͱ͔ M-nͱ͔) Prefix ArgumentΛαϙʔτ͢ΔίϚϯυͨͪͷྫ M-0 C-l : ΧʔιϧߦΛը໘ͷ্͔Βදࣔ

    (C-l C-lͱಉ͡) C-M-a M-0 C-l : ˢͷԠ༻ (ݱࡏͷఆٛΛը໘ͷ্͔Βදࣔ) C-[ C-a M-0 C-l : ಉ্ C-u C-v : 4ߦεΫϩʔϧ C-u C-u C-v : 16ߦεΫϩʔϧ (viͷC-dͷΑ͏ͳ΋ͷ͔…) C-u C-c C-c : (slimeͰ) ؔ਺ΛσόοάϞʔυͰcompile C-u C-c C-k : (slimeͰ) bufferΛσόοάϞʔυͰcompile ɹ˞ ͪͳΈʹ ݸਓతʹ͸ (setq scroll-step 1) ͱ͠ͳ͍೿Ͱ͢ ɹɹ (୅ΘΓʹ C-u C-u C-v ͱ͔ଟ༻ͨ͠Γ͢Δ) 8
  5. Prefix Argumentͱ͸ Numeric Prefix Argument ز͔ͭͷίϚϯυ͸ɺC-u n ΍ ESC n

    (n͸਺ࣈ) ·ͨ͸ M-n (n͸1ܻͷ਺ࣈ)Λ࣮ߦ͍ͨ͠ίϚϯυͷΩʔγʔέϯεͷલʹ ෇͚Δ͜ͱͰɺίϚϯυʹ਺ࣈͷҾ਺Λ༩͑ΔޮՌΛಘΒΕΔ Raw Prefix Argument ୯ʹ C-u ͚ͩΛΩʔγʔέϯεͷલʹ෇͚ΒΕΔίϚϯυ΋ ͋ΓɺͦͷίϚϯυʹॴఆͷҾ਺Λ༩͑ΔޮՌΛಘΒΕΔ (ෳ਺ͷC-uΛΩʔγʔέϯεͷલʹ෇͚ΒΕΔ৔߹΋͋Δ) 9
  6. #3: ΋ͬͱϦζϜΛ… (1-stroke OR 2-stroke) Α࣮͘ߦ͞ΕΔίϚϯυ͸ɺ1ετϩʔΫͷΩʔόΠϯυΛ ࣋ͭ͜ͱ͕ଟ͍͕ɺͦΕʹՃ͑ͯ 2ετϩʔΫͷΩʔόΠϯυ΋ උ͍͑ͯΔ͜ͱ͕͋Δ (e.g.

    undo ͸ C-/ Ͱ΋ C-xu Ͱ΋Α͍) ࿈ଓ͢ΔίϚϯυྻͷதͰ2ετϩʔΫγʔέϯε͕ଟ͍ͱ͖͸ 2ετϩʔΫͷΩʔͰἧ͑ΔͱϦζϜ͕ྑ͘ͳΔ͔ΒΒ͍͠ - M-˘Λ ESC ˘ ΍ C-[ ˘ Ͱ୅༻Ͱ͖Δͷ΋ಉझࢫ - numerical prefix arg ʹ M-n ͱ C-u n ͕͋Δͷ΋ಉझࢫ ྫ͑͹ɺؔ਺Λը໘Ұഋʹදࣔ͢Δ C-M-a M-0 C-l (#2)͸ɺ ؾ͕ͭ͘ͱ C-[ C-a M-0 C-l (2stroke-2stroke) ͱଧͬͯͨΓ͢Δ 10
  7. #4: όοϑΝΛφϏήʔτ͢Δ جຊతͳΧʔιϧҠಈܥͷίϚϯυͱͯ͠ɺviܥͷ h j k l (ࠨԼ্ӈ)ʹ ૬౰͢Δ C-b

    C-n C-p C-f ͕͋Δ͕ɺҎԼ΋Α͘࢖͏ C-uC-v, C-uC-uC-v #2Ͱड़΂ͨεΫϩʔϧίϚϯυ C-s, C-r ΠϯΫϦϝϯλϧαʔν ҠಈίϚϯυͷԦऀ ˠ ଟ͘ͷղઆ͕͋ΔͷͰ ͜͜Ͱ͸ׂѪ C-M-a, C-M-e ఆٛͷ๯಄·ͨ͸຤ඌ΁ͷҠಈ ɹ LispίʔυΛฤू͍ͯ͠Δ৔߹ɺC-M-a͸ؔ਺౳ͷఆٛͷઌ಄΁ɺ C-M-e͸ఆٛͷ຤ඌ΁ΧʔιϧΛҠ͢ ˠ طʹઌ಄(຤ඌ)ʹ͍Δ৔߹͸લͷ(࣍ͷ)ఆٛͷઌ಄(຤ඌ)ʹҠಈ ɹ ͢ΔͷͰɺ࿈ଧ͢Δ͜ͱͰଓ͚ͯલͷ(࣍ͷ)ఆٛʹҠಈͰ͖Δ 11
  8. #5: SࣜΛφϏήʔτ͢Δ ҎԼͷҠಈܥίϚϯυ͸Α͘࢖͏ ( 1ετϩʔΫͰ࢖͏͜ͱ͕ଟ͍ ) ɾ C-M-a, C-M-e :

    ఆٛΛߦ͏Sࣜͷઌ಄·ͨ͸຤ඌʹҠಈ (cf. #4) ɾ C-M-u : ্ͷϨϕϧͷSࣜͷઌ಄ʹҠಈ ɾ C-M-d : ԼͷϨϕϧͷSࣜͷઌ಄ʹҠಈ ɾ C-M-b, C-M-f : લޙʹҰSࣜҠಈ ɾ M-b, M-f : (ׅހΛແࢹͯ͠)લޙʹҰ୯ޠҠಈ ɾ C-b, C-f : લޙʹҰจࣈҠಈ ɾ C-p, C-n : ্ԼͷߦʹҠಈ ɾ M-m : ͦͷߦͷ࠷ॳͷඇۭനจࣈʹҠಈ ɹ˞ Լઢͷ΋ͷ͸Sࣜߏ଄ʹɺͦ͏Ͱͳ͍΋ͷ͸ݟ͔͚ʹ͕͍ͨ͠ಈ࡞͢Δ ɹɹ (యܕతͳ࢖͍ํɿ ॴ๬ͷߦʹ্ԼҠಈͷޙɺC-M-u ΍ C-M-d ΍ M-m Ͱ ɹɹ Sࣜͷ಄ग़͠Λ͔ͯ͠Βɺࠨ͔Βӈʹ M-f ΍ C-M-f ͰҠಈͨ͠Γ͢Δ) 13
  9. #6: SࣜΛߏ଄ฤू͢Δ 14 Lispϓϩάϥϛϯά͸ɺจࣈྻͱ͍͏ΑΓߏจ໦(Sࣜ)ͷ௚઀ฤू ݸਓతʹ paredit [5][6] ͰΑ͘࢖͏มߋܥίϚϯυͷྫ ɾ C-),

    C-} : ӈଆͷslurp(ವࠐΈ), ӈଆͷburf(ుग़͠) ɾ C-k : ߦ຤ํ޲΁SࣜͷσϦϛλ·Ͱ࡟আ ɾ C-M-k, C-M-t : Sࣜͷ࡟আ, ೖΕସ͑ (ΦϦδφϧͷEmacsͷ··) ɾ M-r : ݱࡏҐஔͷSࣜͷ্࣋ͪ͛ (cf. #8) ɾ M-<up> : ಉϨϕϧͷલํཁૉΛফ͔ͯ͠Β্࣋ͪ͛(cf. #9) ɾ M-? : 2ͭͷbindingߏจͷଋറ෦ͷೖସ͑ (cf. #10) ݸਓతʹɺҎԼ͸ຆͲ࢖͑ͯͳ͍ (͍͍࢖༻γʔϯ͋Γ·͢ʁ) ɾ C-(, C-{ : ࠨଆslurp, ࠨଆburf ɾ C-M-n, C-M-p : paredit-forward-up, paredit-backword-down
  10. #7: Πϯσϯτͷम෮ ҎԼͷίϚϯυΛ࢖͑Δ (ΩʔόΠϯυ͸ΦϦδφϧͷ΋ͷ) ɾ C-M-q : ݱࡏҐஔͷSࣜͷΠϯσϯτ(indent-sexp) ɾ M-q

    : ؔ਺ͷ࠶Πϯσϯτ(paredit-reindent-defun) ɾ C-c M-q : ؔ਺ͷ࠶Πϯσϯτ(slime-reindent-defun) ɹ˞ M-q ͱ C-c M-q ͷڍಈ͸ɺຆͲͷ৔߹ͨ͞͠Δҧ͍͕ͳ͍ͷͰɺ ɹɹ γʔέϯεͷ୹͍M-q Λ࢖͓͚ͬͯ͹े෼ ɹɹ(ͱ͍͍ͭͭɺࣗ෼Ͱ͸ ྆ऀͷΩʔόΠϯυΛೖΕସ͑ͯɺ ɹɹ slime-reindent-defunΛ M-qͰ࢖ͬͯ·͢) 15
  11. #8: sub sexpΛ্࣋ͪ͛Δ M-rͰ paredit-raise-sexpΛ࢖͏ (´∀ʆ∩)ˢageˢɹɹ ྫ͑͹ if ΍ cond

    ͷຊମͷઅ͕1ͭΛআ͍ͯෆཁͳ৔߹ͱ͔… (if (test1 ...) (conseq ...) | (altern ...)) ὎ M-r ὎ | (altern ...) 17
  12. ΋͏1ͭ ྫΛ͹ ɹɹผͷྫɿ if ͷtest෦͔Β not Λআڈ͢Δ ɹɹ(transpose-sexps (C-M-t) ΋࢖͍ͬͯΔ)

    (if (not |(test ...)) (conseq ...) (altern ...)) ɹɹ὎ M-r C-n C-n M-m C-M-t ὎ ɹɹ(if (test ...) (altern ...) (conseq ...)|) 18 λΠϓ਺ͷଟՉΑΓ΋ ݸʑͷૢ࡞͕গ͠ߴ࣍ͳͷ͕خ͍͠ (keyboard macroʹ΋࢖͍қ͍)
  13. #9: M-<up> Ͱ ଋറ෦Λऔͬ෷͏ M-<up>Ͱ paredit-splice-sexp-killing-backward Λ ࢖͏ (body-expr͕1͚ͭͩͳΒ M-rΛ࢖ͬͯ΋ಉ͡)

    (progn expr1 (let ((var val)) | expr2 expr3) expr4) ὎ M-<up>ͷ৔߹ ὎ (progn expr1 | expr2 expr3 expr4) ; ଋറ෦͕ফ͍͑ͯΔ ὎ M-rͷ৔߹ ὎ (progn expr1 | expr2 expr4) ; expr2্͚͕͕͍ͩ࣋ͪͬͯΔ 19
  14. #10: M-[ Ͱ labels/let eversion M-[ Ͱ paredit-convolute-sexp Λ࢖͏ ΋ͱ΋ͱͷׂ౰ઌͰ͋ΔM-?

    ͕ slime-edit-uses িಥ͓ͯ͠Γɺ ݸਓతʹ flet΍labelsͱlet Λ “ͻͬ͘Γฦ͍ͨ͠”͜ͱ͕ Α͋͘ΔͷͰɺshift-keyͷཁΒͳ͍ M-[ ʹremap͍ͯ͠Δ ɹɹ(labels (...)ɹ ɹɹ(let (...) ɹɹ| body-expr1 ...) ɹɹ὎ M-[ ὎ ɹɹ(let (...) ɹɹ| (labels (...) ɹɹbody-expr1 ...) 20 ݸਓతʹΑ͘࢖͏ʂ
  15. [1] ๺ై෉, ঁਓྱࢌ, ͋͘ͼϊΦτ(৽ைจݿ), May 1975 [2] Conrad Barski, Lisp

    Alien logo [3] @zick_minoh (et al?), Manga Guide to Lisp [4] @phasetrbot, a tweet on twitter, Sep 2020 [5] Taylor Campbell, paredit command ref. (v23), Apr 2013 [6] Daregada, ParEditνϡʔτϦΞϧ, Mar 2012 [7] Ole Arndt, slime-company, as of Apr 2020 [8] company-mode, issue #342, Apr 2016 References 22
  16. ൪֎: γϯϘϧͷೖྗิ׬ ɹ͍·΍ΤσΟλʹඞਢͷػೳ(ಛʹೖྗ࣌ิ׬ύοέʔδ)͕ͩɺ ɹଞͷฤूػೳͱੑ࣭͕ҟͳΔ͏͑ʹɺଟ਺ͷखஈ͕͋ΔͷͰɺ ɹҎԼʹ͘͝؆୯ʹ·ͱΊ͓ͯ͘ GNU Emacs্ͰͷLispϓϩάϥϛϯάͰ͸ɺҎԼͷิ׬खஈΛ࢖͑Δ ɾུশల։Ϟʔυ : abbrev-mode

    ɾM-/ : ಈతิ׬ (dabbrev-expand) ɾM-tab : γϯϘϧͷิ׬ (complete-symbol) ɾC-c M-i : γϯϘϧͷิ׬ (slime-fuzzy-complete-symbol) ɾೖྗ࣌ิ׬ػೳͷύοέʔδ (company-mode, auto-complete-mode) C-c M-i Ҏ֎͸൚༻ (LispݶఆͰ͸ͳ͍) 23
  17. abbrev-mode ۭؾͷΑ͏ͳଘࡏɿ www.emacswiki.org/emacs/AbbrevMode ลΓΛࢀর ;; ҎԼ͸චऀͷ abbrev_defs ͷlispؔ࿈෦෼ (define-abbrev-table 'lisp-mode-abbrev-table

    '( ;; 1st itemͷ࠷ޙͷz͸ແͯ͘Α͍͕ɺ͋Γ͕ͪͳ໊લͱඃΓʹ͘͘͢ΔͨΊ ;; 4th itemͷ੔਺͸ݱࡏ͸ obsoletedͰݱࡏ͸࢖ΘΕ͍ͯͳ͍Β͍͠ ("dbz" "destructuring-bind" nil 16) ; dbz SPC ͱଧͭͱల։͞ΕΔ ("mvbz" "multiple-value-bind" nil 15) ("smlz" "symbol-macrolet" nil 2) ("waz" "with-accessors" nil 11) ("wofz" "with-open-file" nil 1) : : ("wotsz" "with-output-to-string" nil 0) ("wsz" "with-slots" nil 4))) 24
  18. dabbrevίϚϯυ (M-/) ݱࡏҐஔͷsymbolΛ όοϑΝ্ํͷsymbolͰิ׬͢Δ M-/ Λԡͨ͢ͼʹ ͦͷ࣍ͷީิ͕ೖྗදࣔ͞ΕΔ ݟ͔ͭΒͳ͍৔߹ɺόοϑΝԼํ΍ଞͷ৘ใιʔε΋ࢀর͢Δ abbrev-modeͱҧͬͯɺಛʹઃఆ͠ͳ͍Ͱ΋࢖͑Δ LispͰ͸ɺ௨ྫ

    ςετͭͭ͠bottom-upతʹίʔσΟϯά͍ͯ͘͠ͱ͍͏ ಛੑ্ɺ͠͹͠͹ಉҰϑΝΠϧͷ্ํۙ๣ʹิ׬͍ͨ͠symbol͕͋Γɺ dabbrev͚ͩͰࢫ͘ػೳͯ͠͠·͏͜ͱ΋ଟ͍ ɹ˞ ͱ͸͍͑ɺcompanyͷΑ͏ͳଶ༷Ͱone stopͷิ׬UI͕͋Δͱྑ͍Ͱ͢Ͷ ɹɹ (େ͖͍ϥΠϒϥϦͱ͔ॳΊͯ࢖͏৔߹ʹɺෳ਺ͷิ׬UIΛ࢖͍෼͚ͯΒΕͳ͍) 25 Α͘࢖͏ʂ
  19. ͦͷଞͷೖྗิ׬खஈ complete-symbolίϚϯυ (M-tab, ESC tab ͋Δ͍͸ ୯ʹtabͳͲ) ɹ- ݹདྷEmacsʹ͋ΓɺݴޠϞʔυʹΑΒͣڞ௨ૢ࡞Ͱpop-up bufferʹީิΛදࣔ͢Δ

    slime-fuzzy-completions-mode (C-c M-i) ɹ- prefix͕׬શҰக͠ͳ͍ީิ΋நग़͢ΔͷͰɺ͏ΖԱ͑ͷͱ͖΋࢖͑Δ ɹ- pop-up bufferʹग़ྗ͞ΕΔީิΛ pulldown list ͷΑ͏ʹC-p,C-n౳Ͱૢ࡞Ͱ͖Δ ೖྗ࣌ิ׬ػೳͷύοέʔδ (company-mode, ac-complete-mode) ɹ- ҰจࣈೖΕΔͨͼʹิ׬ީิΛin-place pulldown listʹߋ৽දࣔ͢Δ(˞) ɹ- ac-complete-mode͸Α͘஌Βͳ͍ͷ͕ͩɺcompany-mode͸ɺഎޙͰར༻͢Δ ɹ dabbrev ΍ slime-fuzzy-…-mode ͷީิ΋listʹՃ͑Δ͜ͱ͕Ͱ͖ΔΑ͏ͩ [7][8] ˞ ࠷ۙͷIDEͷΤσΟλͰ͸ɺީิநग़΍දࣔॱҐʹݴޠґଘͷߏจಛੑ(e.g. ϝιου ɹ ໊͕ޙஔͰ͋Δ͜ͱ)΍໊લۭؒ΍੩తܕ෇͚౳ͷจ຺৘ใΛར༻͍ͯ͠Δɻ ɹ Lispͷ৔߹ɺੲ͔ΒඞཁʹԠͯ͡backendͷLispϓϩηεʹ΋໰͍߹ΘͤΔελΠϧ͕ ɹ ཱ͍֬ͯ͠Δ͕ɺؔ਺໊͸લஔͩ͠ɺܕ৘ใ͸͋ͬͯ΋ॲཧܥґଘͷ৔߹͕͋Δɻ 26