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

"EmacsでLisp" 礼讃

nfunato
October 18, 2020

"EmacsでLisp" 礼讃

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