dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

CONTRIBUTING.md (12182B)


      1 # The SLY Hacker's Handbook
      2 
      3 ## Reporting bugs
      4 
      5 The most important thing when reporting bugs is making sure that the
      6 developer has a way to reproduce it. To do this, he needs to rule out
      7 interference from external factors like other Emacs extensions or
      8 other Lisp-side code. Here's a great example of a bug report
      9 
     10 ```
     11 $ emacs --version
     12 Emacs 24.3
     13 $ sbcl --version
     14 SBCL 1.2.1
     15 $ cd sly
     16 sly $ emacs -Q -L . -l sly-autoloads --eval '(setq inferior-lisp-program "sbcl")' -f sly
     17 
     18 I get the REPL but when I try to X, I get Y
     19 OR
     20 I don't get the REPL at all because frankinbogen!
     21 ```
     22 
     23 
     24 ## Coding style
     25 
     26 This section is very empty, in the meantime try to be sensible and
     27 emulate or improve on SLY's existing style.
     28 
     29 ### Commit messages
     30 
     31 ChangeLog files are gone! However, the syntax of ChangeLogs is very
     32 useful to everybody and Emacs supports it perfectly:
     33 
     34 * in Emacs, for every snippet that you've changed, type `C-x 4 a` (or
     35   `add-change-log-entry-other-window`)
     36 
     37 * Emacs will open up a ChangeLog buffer, but this is just a dummy
     38   buffer that you can ignore. However, the content inside it should be
     39   pasted (sans indentation) to the commit message.
     40 
     41 * As an added bonus, if you are using Emacs >= 24.4 and `vc-dir` to
     42   prepare your commits, Emacs does that for you automatically.
     43 
     44 The benefits of this format are great. One can still use `M-x
     45 vc-print-log` in a source file and browse through its ChangeLog
     46 without the hassle of ChangeLog conflicts.
     47 
     48 ### General philosophy
     49 
     50 I keep a sentence of the previous Coding Guide that I like very much.
     51 
     52 > Remember that to rewrite a program better is the sincerest form of
     53 > code appreciation. When you can see a way to rewrite a part of SLY
     54 > better, please do so!
     55 
     56 
     57 ## Lisp code file structure
     58 
     59 The code is organized into these files:
     60 
     61 * `slynk/slynk-backend.lisp`: Definition of the interface to non-portable
     62 features.  Stand-alone.
     63 
     64 * `slynk/backend/slynk-<cmucl|...>.lisp`: Back-end implementation
     65 for a specific Common Lisp system.  Uses slynk-backend.lisp.
     66 
     67 * `slynk/slynk.lisp`: The top-level server program, built from the other
     68 components.  Uses `slynk-backend.lisp` as an interface to the actual
     69 backends.
     70 
     71 * `sly.el`: The Emacs front-end that the user actually interacts
     72 with and that connects to the Slynk server to send expressions to, and
     73 retrieve information from the running Common Lisp system.
     74 
     75 * `contrib/sly-<extension>.el`: Elisp code for SLY extensions.
     76 
     77 * `contrib/slynk-<extension>.lisp`: Supporting Common Lisp related
     78 code for a particular extension.
     79 
     80 
     81 ## SLY-Slynk RPC protocol
     82 
     83 The info in this section would be something for a future "Slynk
     84 Programmer's Guide" to be included in the regular manual or a separate
     85 one.
     86 
     87 Follows a brief description of the SLY-Slynk protocol. The protocol is
     88 *s-exp messages* over *s-exp primitives* over *UTF-8* over *TCP*.
     89 Let's start top-down:
     90 
     91 ### S-exp messages
     92 
     93 Most messages in the top group look like Lisp function calls. The
     94 functions are known as "Slyfuns" and are defined with a `DEFSLYFUN`
     95 operator in the `slynk-*.lisp` side. These are the "remote procedures"
     96 of the RPC protocol. There must be about 100 or so of them, maybe
     97 more, I haven't counted. Slyfuns appear in both Slynk's core and in
     98 supporting contrib's Slynk code.
     99 
    100 For a future reference manual, I think there has to be a way to
    101 automatically harvest the `DEFSLYFUN` definitions and their
    102 docstrings.
    103 
    104 Another type of message contains calls to "channel methods". These are
    105 slightly different from Slyfuns. Their return value is ignored, but
    106 otherwise they also work like function calls. They're good for
    107 expressing a reply-free evaluation in the context of a "channel".
    108 
    109 These are defined with `sly-define-channel-method` and
    110 `DEFINE-CHANNEL-METHOD` and on the SLY and Slynk sides, respectively.
    111 
    112 The only use right now is in `sly-mrepl.el`,
    113 
    114 ### S-exp primitives
    115 
    116 This is a much smaller set of primitives, the most common is
    117 `:EMACS-REX`, "rex" is for "Remote EXecution".
    118 
    119 Informally it's saying: "here is Slyfun X's call number 3487 with
    120 argumentss Y, for evaluation in thread Z" ). The asynchronous reply
    121 `:RETURN`, if it ever arrives, will be "your call 3487 returned the
    122 following sexp".
    123 
    124 ```lisp
    125 (:emacs-rex
    126  (slynk:connection-info)
    127  nil t 1)
    128 (:return
    129  (:ok
    130   (:pid 16576 :style :spawn :encoding
    131         :lisp-implementation
    132         (:type "International Allegro CL Enterprise Edition" :name "allegro" :version "8.1 [Windows] (Sep 3, 2008 19:38)" :program nil)
    133         :package
    134         (:name "COMMON-LISP-USER" :prompt "CL-USER")
    135         :version "1.0.0-alpha"))
    136  1)
    137  ```
    138 
    139 The return value, read into Elisp sexps is what is passed to the
    140 callback argument to the Elisp function `sly-eval-async`. Here's the
    141 way to get the PID of the underlying Slynk process.
    142 
    143 ```elisp
    144 (sly-eval-async '(slynk:connection-info)
    145    (lambda (info) (plist-get info :pid)))
    146 ```
    147 
    148 The primitives `:CHANNEL-SEND` and `:EMACS-CHANNEL-SEND` implement
    149 channel methods. Channels are named by number, and normally have a
    150 special serving thread in the Common Lisp implementation of
    151 Slynk. Here is an extract showing the `:PROCESS`, `:WRITE-VALUES` and
    152 `:PROMPT` channel methods for the REPL.
    153 
    154 ```lisp
    155 (:emacs-channel-send 1
    156                      (:process "(list 1 2 3)"))
    157 (:channel-send 1
    158                (:write-values
    159                 (("(1 2 3)" 2))))
    160 (:channel-send 1
    161                (:prompt "COMMON-LISP-USER" "CL-USER" 0))
    162 ```
    163 
    164 There are also debugger-specific primitives, like `:DEBUG-ACTIVATE`
    165 and `:DEBUG-RETURN`. Then there are indentation-specific primitives
    166 like `:INDENTATION-UPDATE`. These could/should become
    167 `:EMACS-CHANNEL-SEND`s in the future (but that would probably finally
    168 break Swank compatibility).
    169 
    170 ### UTF-8 and TCP
    171 
    172 UTF-8 is relevant because the information in the wire are text-encoded
    173 sexp's that sometimes carry strings with chunks of code, for example,
    174 and these can have funky characters.
    175 
    176 TCP is well TCP, a host and a port and reliable transfer make SLY work
    177 well over any IP network.
    178 
    179 ### Common Lisp bias
    180 
    181 *Note: This section is very incomplete*
    182 
    183 SLY has is primarily a Common-Lisp IDE and the supporting Slynk have
    184 strong Common-lisp bias. There have been many attempts, some quite
    185 successful at creating Slynk backends for other languages.
    186 
    187 I believe that some of the Slyfuns will always be Common-Lisp specific
    188 and should be marked as such. Others can perhaps be more naturally
    189 adapted to other languages.
    190 
    191 It's very important that a future reference manual have this in
    192 consideration: remove the CL bias from the protocol's description, at
    193 least from some of its layers, so that things like
    194 [swank-js](https://github.com/swank-js/swank-js) can one day be more
    195 easily implemented.
    196 
    197 
    198 ## Architecture changes from SLIME to SLY
    199 
    200 As of time of writing (SLY 1.0, SLIME 2.9) the following list
    201 summarizes the main architecture differences between SLY and SLIME. If
    202 it's not mentioned here, it's a safe bet that some particular
    203 mechanism you're interested in stayed the same and any SLIME
    204 documentation is applicable to SLY.
    205 
    206 ### Swank is now called Slynk
    207 
    208 SLY can be loaded alongside SLIME both in the same Emacs or Lisp
    209 image. This interoperability meant that SLY's Lisp server had to be
    210 renamed to "Slynk".
    211 
    212 SLY can still speak the Swank protocol, and should be able to connect
    213 to any other non-Lisp backends such as Christopher Rhodes' [swankr][4]
    214 or have non-SLIME clients connect to it such as Robert Brown's
    215 [swank-client][5].
    216 
    217 This is done via a contrib called `sly-retro` and its `slynk-retro`
    218 counterpart. The contrib's code is loaded by `M-x sly` or `M-x
    219 sly-connect` *on demand*, meaning that it is possible to start the
    220 Slynk server without the contrib's Lisp counterpart. See the section
    221 called "Slynk-loading method"" for how this works in SLY.
    222 
    223 *If* it is loaded, `sly-retro` ensures that messages leaving SLY still
    224 look like
    225 
    226      (:emacs-rex (swank:connection-info) nil t 1)
    227 
    228 It also ensures that incoming messages are directed to the `SLYNK` and
    229 `SLYNK-BACKEND` packages. This particular redirection is done via
    230 package nicknames and a trick in `lib/lisp/slynk-rpc.lisp`. The trick
    231 is necessary only for the first bootstrapping messages, because on
    232 startup the `sly-retro` contrib hasn't kicked in and nicknames are not
    233 immediately setup.
    234 
    235 The nicknames pose a compatibility hazard if the user tries to load
    236 SLIME's Swank server into the Lisp image where Slynk is already
    237 setup. Therefore, users wishing to run both servers alongside in the
    238 same Lisp image must ensure that the `sly-retro` contrib is not in
    239 `sly-contribs`.
    240 
    241      (setq sly-contribs (delq 'sly-retro sly-contribs))
    242 
    243 [4]: https://github.com/gigamonkey/swankr
    244 [5]: https://github.com/brown/swank-client
    245 
    246 ### Slynk-loading method
    247 
    248 In SLIME, `M-x slime` immediately tells the Lisp process started by
    249 Emacs to use SLIME's own `swank-loader.lisp` program to compile and
    250 load all possibly available lisp under its directory (including
    251 contrib's) before the Swank server is created with
    252 `SWANK:CREATE-SERVER`.
    253 
    254 In SLY, the elisp variable `sly-init-function` is set to
    255 `sly-init-using-asdf` by default, meaning that `M-x sly` will try to
    256 load Slynk (the SLY equivalent to Swank) via `ASDF:LOAD-SYSTEM`. But 
    257 this will load only Slynk and no contribs.
    258 
    259 Slynk contribs are also represented as ASDF systems. Internally the
    260 function `sly-contrib--load-slynk-dependencies` will ask Slynk to put
    261 the contrib's path to the ASDF load path. The `SLYNK:REQUIRE-MODULE`
    262 abstraction will then call `ASDF:LOAD-SYSTEM`.
    263 
    264 In SLY, a contrib's associated Slynk modules is loaded on demand, not
    265 forced on the user's Lisp run-time.
    266 
    267 This also allows the developer to write completely independent
    268 third-party extensions to SLY, with both Emacs and Lisp parts. See the
    269 URL http://github.com/joaotavora/sly-hello-world for an example
    270 extension.
    271 
    272 Additionally, if SLY detects that ASDF is not available in the Lisp
    273 run-time, it will fallback to the old `slynk-loader.lisp` mechanism,
    274 which has also been revised to support the previous two use cases. Any
    275 of the two methods is transparent from Emacs's perspective.
    276 
    277 ### mREPL
    278 
    279 `slime-mrepl` is an experimental SLIME contrib that inspired
    280 `sly-mrepl`, which is a much enhanced version of it and the default
    281 REPL for SLY. The main difference to the popular `slime-repl` contrib
    282 is that `sly-mrepl` is based on Emacs's own `comint.el` so that that
    283 SLY does not need to worry about functionality like history navigation
    284 and persistent history, which are consistent with other Emacs modes
    285 based on `comint.el`.
    286 
    287 `sly-mrepl` allows multiple REPLs through the use of channels, which
    288 are abstraction pioneered in SLIME. Channels are like separate
    289 mailboxes in the Lisp run-time, and it's slightly different from the
    290 regular `:emacs-rex` RPC calls in that they directly invoke a remote
    291 method but expect no reply.
    292 
    293 In `slynk-mrepl.lisp`, the `mrepl` class multiple inherits from
    294 `slynk:channel` and `slynk:listener`. The first takes care of
    295 channel-based communication and the second has the REPL-specific
    296 context.
    297 
    298 See the section on the "RPC protocl" and switch to the `*sly-events*`
    299 buffer to see what's going on. 
    300 
    301 ### Display-related code
    302 
    303 SLIME's age and historical compatibility with XEmacs means it
    304 reinvented (and possibly invented) many buffer/window/display managing
    305 techniques that are available today in GNU Emacs's core. Interactive
    306 buttons, display-related and completion-code have all been pruned as
    307 much as possible and now reuse Emacs' own libraries.
    308 
    309 Hopefully this will make SLY's code focus on SLY's "business logic"
    310 and easier to read.
    311 
    312 ### Channels
    313 
    314 TODO
    315 
    316 ### Listeners
    317 
    318 TODO
    319 
    320 
    321 ## Pull requests
    322 
    323 * Read [how to properly contribute to open source projects on Github][1].
    324 * Use a topic branch to easily amend a pull request later, if necessary.
    325 * Commit messages should use the syntax of GNU ChangeLog entries.
    326 * Open a [pull request][2] that relates to *only* one subject with a
    327   clear title and description in grammatically correct, complete
    328   sentences.
    329 
    330 [1]: http://gun.io/blog/how-to-github-fork-branch-and-pull-request
    331 [2]: https://help.github.com/articles/using-pull-requests
    332 [3]: http://www.gnu.org/prep/standards/html_node/Style-of-Change-Logs.html#Style-of-Change-Logs