Emakso kaj Paroj

Esperanto | English
Laste ĝisdatigita: la 7-an de marto 2021

La blanka bruo kiu batas ene la blanka mallumo estas la ritmo de la vivo; estas la pulso kiu neniam vere foriris la podion.
—Ergo PROXY, Ergo Proxy

wallhaven-578010

Enhavotabelo

Enkonduko

En ĉi tiu artikolo, mi eksklusive parolas pri smartparens—tiu pako, kiun oni esperis, ke oni jam uzis antaŭe, supozante oni ne jam uzis ĝin . Se oni estas komencanto pri ĝi, laŭlegu; se ne, ĉi tio eble estas bona memorigilo.

smartparens estas unu el tiuj pakoj kiu draste plibonigas, kaj ŝanĝas kiel oni uzas emakson . Similas al kibernetikaj membroj—igas onin por pli alte salti kaj pli forte pugnobati.

Memoru, ke la nomo malpravas tial, ke ne nur rondajn krampojn ĝi traktas. Ĝi ankaŭ traktas iujn ajn kiuj pariĝas, kaj ĝi traktas ilin stele.

Instalo

Instali smartparens estas facila:

M-x package-install EN smartparens EN

Agordaĵo

Sekve, oni ŝaltu smartparens en la startigo, kaj oni kroĉu ĝin al egaj kroĉiloj:

(use-package smartparens-config
  :ensure smartparens
  :config (progn (show-smartparens-global-mode t)))

(add-hook 'prog-mode-hook 'turn-on-smartparens-strict-mode)
(add-hook 'markdown-mode-hook 'turn-on-smartparens-strict-mode)

Uzado

Administri parigitajn signojn kiel rondaj krampoj, kurbaj krampoj, kvadrataj krampoj, citiloj, angulaj krampoj, kaj aliaj koncepteblaj parigeblaj signoj jam ĉiam doloras sin. Aliaj pakoj solvas tiun problemon parte. Bedaŭrinde, mankas al ili kelkaj punktoj.

En la kodetoj ĉi-sube, la ĉapelo () simbolo estos uzita por reprezenti la punkton.

Bazaferoj

Per smartparens, kiam oni enigas parigeblajn signojn:


(defn foo )
          ^

ankaŭ eniĝas la kongrua paro, kaj la punkto estas poziciita ene la paro:


(defn foo [])
           ^

Navigado

Komencoj kaj finoj

Sa oni havas le jenan esprimon:


(let [x "foo bar baz ... blah"])
                         ^

kaj oni volas movi la punkton al la komenco de la signovico:


(let [x "foo bar baz ... blah"])
         ^

Rulu sp-beginning-of-sexp. Mi bindis ĝin al C-M-a.

Male, por movi la punkton al la fino de la esprimo:


(let [x "foo bar baz ... blah"])
                             ^

Rulu sp-end-of-sexp. Mi bindis ĝin al C-M-e.

Listojn trairi

Se oni havas la jenan esprimon:


(defun format-date (format)
  "La daton enmetu laŭ specio FORMAT kun specifa lokaĵaro."
  (let ((system-time-locale "en_US.UTF-8"))
    (insert (format-time-string format)))) ^

kaj oni volas movi la punkton al insert:


(defun format-date (format)
  "La daton enmetu laŭ specio FORMAT kun specifa lokaĵaro."
  (let ((system-time-locale "en_US.UTF-8"))
    (insert (format-time-string format))))
     ^

Rulu sp-down-sexp. Mi bindis ĝin al C-down.

Sa oni havas la jenan esprimon:


(str "foo" "bar baz qux")
    ^

kaj oni volas movi la punkton post ):


(str "foo" "bar baz qux")
                         ^

Rulu sp-up-sexp. Mi bindis ĝin al C-up.

Se oni havas la jenan esprimon:


(defn foo [bar] (let [x 0] x))
                ^

kaj oni volas movi la punkton al la apuda ]:


(defn foo [bar] (let [x 0] x))
              ^

Rulu sp-backward-down-sexp. Mi bindis ĝin al M-down.

Sa oni havas la jenan esprimon:


(insert (format-time-string format))
                           ^

kaj la punkton oni volas movi al (format:


(insert (format-time-string format))
        ^

Rulu sp-backward-up-sexp. Mi bindis ĝin al M-up.

Blokaj movadoj

Sa oni havas la jenan esprimon:


(:require [clojure.string :as s])
          ^

kaj la punkton oni volas movi post ]:


(:require [clojure.string :as s])
                                ^

Rulu sp-forward-sexp. Mi bindis ĝin al C-M-f.

Male, por movi ĝin reen al [:


(:require [clojure.string :as s])
          ^

Rulu sp-backward-sexp. Mi bindis ĝin al C-M-b.

Supra niveleca trairado

Se oni havas la jenan esprimon:


(defn blah
  "Returns blah of foo."
  [foo]                 ^
  )

kaj oni volas movi la punkton al [:


(defn blah
  "Returns blah of foo."
  [foo]
  ^)

Rulu sp-next-sexp . Mi bindis ĝin al C-M-n.

Male, por movi ĝin reen:


(defn blah
    "Returns blah of foo."
  [foo]                 ^
  )

Rulu sp-previous-sexp. Mi bindis ĝin al C-M-p.

Libermanaj movadoj

Se oni havas la jenan esprimon:


(defn blah [] (let [x 0 y 1] (+ x 1)))
               ^

kaj oni volas movi la punkton al blah:


(defn blah [] (let [x 0 y 1] (+ x 1)))
      ^

Rulu sp-backward-symbol. Mi bindis ĝin al C-S-b.

Male, se oni havas la jenan esprimon:


(defn blah [] (let [x 0 y 1] (+ x 1)))
            ^

kaj oni volas movi la punkton tuj post (let:


(defn blah [] (let [x 0 y 1] (+ x 1)))
                  ^

Rulu sp-forward-symbol. Mi bindis ĝin al C-S-f.

Kion ili faras, estas ke, ili ĉirkaŭnavigas kvazaŭ ne ekzistas la limiligoj kiel rondaj krampoj, kvadrataj krampoj, kaj kurbaj krampoj.

Manipulado

Faldado

Se oni havas la jenan esprimon:


var mods = "vars";
           ^

kaj oni volas ĉirkaŭi "vars" per [ kaj ]:


var mods = ["vars"];
            ^

Preminte C-M-Space kaj [ la tuta regiono fariĝas ĉirkaŭitaj per kongruaj [ kaj ]. Tio ankaŭ estas aplikeblaj al klavoj kiel (, {, ", ', *, _, ktp, dependas per la regimo kiun oni uzas.

Oni povas difini faldadajn funkciojn alterne:

(defmacro def-pairs (pairs)
  "Funkciojn por parigado difinu. PAIRS estas asocialisto de (NAME . STRING) conses, en kiu, NAME estas la nomo de la funkcio kiu estos kreita kaj STRING estas sole signa signovico kiu la komencan signon markas.

La alvoko

  (def-pairs ((paren . \"(\")
              (bracket . \"[\"))

difinas la funkciojn WRAP-WITH-PAREN kaj WRAP-WITH-BRACKET, respektive."
  `(progn
     ,@(loop for (key . val) in pairs
             collect
             `(defun ,(read (concat
                             "wrap-with-"
                             (prin1-to-string key)
                             "s"))
                  (&optional arg)
                (interactive "p")
                (sp-wrap-with-pair ,val)))))

(def-pairs ((paren . "(")
            (bracket . "[")
            (brace . "{")
            (single-quote . "'")
            (double-quote . "\"")
            (back-quote . "`")))

Ĉi tiuj havas la avantaĝon de ne postuli regionojn por esti operaciotaj. Mi bindis la unuajn tri funkciojn al C-c (, C-c [, kaj C-c {, respektive. Do, se oni havas la jenan esprimon:


(defn foo args (let [x 0] (inc x)))
          ^

kaj oni volas ĉirkaŭi args per [ kaj ]:


(defn foo [args] (let [x 0] (inc x)))
           ^

Premu C-c [.

Fojfoje, oni malatentence forviŝas unu el la paraj paroj—ĉi tio rezultas al malekvilibrigita esprimo. Smartparens malpermesas onin por fari tion. Se oni premasBackspace en la jena esprimo:


var mods = ["vars"];
            ^

Nenio okazas. smartparens savas onin el multe da ĝeno, ĉi tie.

Malfaldado

Se oni havas la jenan esprimon:


(foo (bar x y z))
     ^

kaj oni volas malfaldi la bar esprimon, forigante la rondajn krampojn ĉirkaŭ foo:


foo (bar x y z)
    ^

Rulu sp-backward-unwrap-sexp. Mi bindis ĝin al M-[.

Male, se oni volas malfaldi la esprimon bar, forigante la rondajn krampojn ĉirkaŭ bar:


(foo bar x y z)
     ^

Rulu sp-unwrap-sexp. Mi bindis ĝin al M-].

Glutado kaj vomado

Sa oni havas la jenan esprimon:


[foo bar] baz
        ^

kaj oni volas igi baz parto de foo kaj bar:


[foo bar baz]
        ^

Rulu sp-forward-slurp-sexp. Mi bindis ĝin al C-right.

Male, se oni volas forigi baz:


[foo bar] baz
        ^

Rulu sp-forward-barf-sexp. Mi bindis ĝin al M-right.

Se oni havas la jenan esprimon:


blah [foo bar]
             ^

kaj oni volas igi blah parto de foo kaj bar:


[blah foo bar]
             ^

Rulu sp-backward-slurp-sexp. Mi bindis ĝin al C-left.

Male, se oni volas forigi blah:


blah [foo bar]
             ^

Rulu sp-backward-barf-sexp. Mi bindis ĝin al M-left.

Interŝanĝado

Se oni havas la jenan esprimon:


"foo" "bar"
      ^

kaj oni volas interŝanĝi "foo" kaj "bar":


"bar" "foo"
      ^

Rulu sp-transpose-sexp. Mi bindis ĝin al C-M-t.

Mortigado

Se oni havas la jenan esprimon:


(let [x "xxx" y "y yy yyy" z 0])
               ^

kaj oni volas mortigi nur "y yy yyy":


(let [x "xxx" y z 0])
               ^

Rulu sp-kill-sexp. Mi bindis ĝin al C-M-k.

Se oni volas mortigi "y yy yyy" z 0:


(let [x "xxx" y])
               ^

Rulu sp-kill-hybrid-sexp. Mi bindis ĝin al C-k.

Se oni havas la jenan esprimon:


(:require [clojure.string :as s])
                                ^

kaj oni volas mortigi [clojure.string :as s]:


(:require )
          ^

Rulu sp-backward-kill-sexp. Mi bindis ĝin al M-k.

Klavoj

La jena kodeto resumas la uzatajn klavkombinojn en ĉi tiu artikolo. Mi uzas bind-keys por mapi miajn klavojn oportune. Mi pridiskutis ĝin en antaŭa artikolo.

(defmacro def-pairs (pairs)
  "Funkciojn por parigado difinu. PAIRS estas asocialisto de (NAME . STRING) conses, en kiu, NAME estas la nomo de la funkcio kiu estos kreita kaj STRING estas sole signa signovico kiu la komencan signon markas.

La alvoko

  (def-pairs ((paren . \"(\")
              (bracket . \"[\"))

difinas la funkciojn WRAP-WITH-PAREN kaj WRAP-WITH-BRACKET, respektive."
  `(progn
     ,@(loop for (key . val) in pairs
             collect
             `(defun ,(read (concat
                             "wrap-with-"
                             (prin1-to-string key)
                             "s"))
                  (&optional arg)
                (interactive "p")
                (sp-wrap-with-pair ,val)))))

(def-pairs ((paren . "(")
            (bracket . "[")
            (brace . "{")
            (single-quote . "'")
            (double-quote . "\"")
            (back-quote . "`")))

(bind-keys
 :map smartparens-mode-map
 ("C-M-a" . sp-beginning-of-sexp)
 ("C-M-e" . sp-end-of-sexp)

 ("C-<down>" . sp-down-sexp)
 ("C-<up>"   . sp-up-sexp)
 ("M-<down>" . sp-backward-down-sexp)
 ("M-<up>"   . sp-backward-up-sexp)

 ("C-M-f" . sp-forward-sexp)
 ("C-M-b" . sp-backward-sexp)

 ("C-M-n" . sp-next-sexp)
 ("C-M-p" . sp-previous-sexp)

 ("C-S-f" . sp-forward-symbol)
 ("C-S-b" . sp-backward-symbol)

 ("C-<right>" . sp-forward-slurp-sexp)
 ("M-<right>" . sp-forward-barf-sexp)
 ("C-<left>"  . sp-backward-slurp-sexp)
 ("M-<left>"  . sp-backward-barf-sexp)

 ("C-M-t" . sp-transpose-sexp)
 ("C-M-k" . sp-kill-sexp)
 ("C-k"   . sp-kill-hybrid-sexp)
 ("M-k"   . sp-backward-kill-sexp)
 ("C-M-w" . sp-copy-sexp)
 ("C-M-d" . delete-sexp)

 ("M-<backspace>" . backward-kill-word)
 ("C-<backspace>" . sp-backward-kill-word)
 ([remap sp-backward-kill-word] . backward-kill-word)

 ("M-[" . sp-backward-unwrap-sexp)
 ("M-]" . sp-unwrap-sexp)

 ("C-x C-t" . sp-transpose-hybrid-sexp)

 ("C-c ("  . wrap-with-parens)
 ("C-c ["  . wrap-with-brackets)
 ("C-c {"  . wrap-with-braces)
 ("C-c '"  . wrap-with-single-quotes)
 ("C-c \"" . wrap-with-double-quotes)
 ("C-c _"  . wrap-with-underscores)
 ("C-c `"  . wrap-with-back-quotes))

Finrimaroj

La pletoro de la komandoj en smartparens eble povas senkuraĝigas en la komenco, tamen la investo per tempo en lerni ilin, estas minimuma kontraste al la gajnojn oni povas rikolti.

smartparens estas la elpensintaĵo de Matus GOLJER. Por vidi pli da informo pri smartparens, iru ĉi tien. Se oni ŝatas ĉi tiun projekton, oni povas donaci ĉi tie.