diff options
author | Andre A. Gomes <andremegafone@gmail.com> | 2024-09-26 14:32:26 +0300 |
---|---|---|
committer | Andre A. Gomes <andremegafone@gmail.com> | 2024-09-27 14:11:42 +0300 |
commit | f726ddaa1c7374ab1a4f3abb6a030a0149a7659d (patch) | |
tree | b8f48bc5587f3f873f37b0fa80279f66801fc806 | |
parent | cdbdfc309231342b53eb6dc57be73eb20b3d2b2d (diff) |
Rewrite developer's manual.
-rw-r--r-- | README.org | 4 | ||||
-rw-r--r-- | assets/nyxt.metainfo.xml | 2 | ||||
-rw-r--r-- | developer-manual.org | 320 | ||||
-rw-r--r-- | documents/README.org | 426 | ||||
-rw-r--r-- | guix.scm | 2 |
5 files changed, 324 insertions, 430 deletions
diff --git a/README.org b/README.org index b31a32fcc..c4794572c 100644 --- a/README.org +++ b/README.org @@ -10,7 +10,7 @@ instabilities or feature wishes. ----- -#+html: <div align="center"> <a href="https://nyxt-browser.com/">Homepage</a> | <a href="https://nyxt-browser.com/purchase">Download</a> | <a href="https://nyxt-browser.com/articles">Articles</a> | <a href="https://github.com/atlas-engineer/nyxt/blob/master/documents/README.org">Developer's Manual</a> | <a href="https://discourse.atlas.engineer/">Forum</a> | <a href="https://kiwiirc.com/nextclient/irc.libera.chat/nyxt">Chat</a> </div> +#+html: <div align="center"> <a href="https://nyxt-browser.com/">Homepage</a> | <a href="https://nyxt-browser.com/purchase">Download</a> | <a href="https://nyxt-browser.com/articles">Articles</a> | <a href="https://github.com/atlas-engineer/nyxt/blob/master/developer-manual.org">Developer's Manual</a> | <a href="https://discourse.atlas.engineer/">Forum</a> | <a href="https://kiwiirc.com/nextclient/irc.libera.chat/nyxt">Chat</a> </div> ----- @@ -78,4 +78,4 @@ maintainers of those packaging efforts. * Contributing -Please refer to the developer's documentation at [[file:documents/README.org][documents/README.org]]. +Please refer to the [[file:developer-manual.org][developer's documentation]]. diff --git a/assets/nyxt.metainfo.xml b/assets/nyxt.metainfo.xml index 0368f6dcc..8e988bb17 100644 --- a/assets/nyxt.metainfo.xml +++ b/assets/nyxt.metainfo.xml @@ -23,7 +23,7 @@ <url type="donation">https://nyxt-browser.com/purchase</url> <!-- <url type="translate"></url> --> <url type="contact">https://atlas.engineer/contact</url> - <url type="contribute">https://github.com/atlas-engineer/nyxt/blob/master/documents/README.org</url> + <url type="contribute">https://github.com/atlas-engineer/nyxt/blob/master/developer-manual.org</url> <launchable type="desktop-id">nyxt.desktop</launchable> <provides> <binary>nyxt</binary> diff --git a/developer-manual.org b/developer-manual.org new file mode 100644 index 000000000..c4de372df --- /dev/null +++ b/developer-manual.org @@ -0,0 +1,320 @@ +#+TITLE: Nyxt Developer's Manual + +# Install org-make-toc so the TOC below will be automatically generated. +# https://github.com/alphapapa/org-make-toc +* Table of contents :TOC: +:PROPERTIES: +:TOC: :include all :ignore this +:END: +:CONTENTS: +- [[#bill-of-materials][Bill of Materials]] + - [[#source][Source]] + - [[#common-lisp][Common Lisp]] + - [[#web-renderers][Web renderers]] + - [[#webkitgtk][WebKitGTK]] + - [[#electron][Electron]] + - [[#other][Other]] +- [[#development-environment][Development environment]] + - [[#tests][Tests]] + - [[#functional-package-managers][Functional package managers]] + - [[#guix][Guix]] + - [[#nix][Nix]] +- [[#installation][Installation]] +- [[#interact-with-a-running-nyxt-binary][Interact with a running Nyxt binary]] +- [[#contributing][Contributing]] + - [[#help][Help]] + - [[#commit-style][Commit style]] + - [[#branch-management][Branch management]] + - [[#programming-conventions][Programming conventions]] +:END: + +* Bill of Materials +** Source + +Either get a tarball (=nyxt-<version>-source-with-submodules.tar.xz=) from a +[[https://github.com/atlas-engineer/nyxt/releases][tagged release]], or clone as a git repository: + +#+begin_src sh +mkdir -p ~/common-lisp +git clone --recurse-submodules https://github.com/atlas-engineer/nyxt ~/common-lisp/nyxt +#+end_src + +** Common Lisp + +Nyxt is written in Common Lisp. Currently, we only target one of its +implementations - [[http://www.sbcl.org/][SBCL]]. + +Nyxt also depends on Common Lisp libraries. These are bundled in the tarball +mentioned above or fetched as git submodules (under =./_build=). + +Note for advanced users: the single source of truth for CL libraries is dictated +by the git submodules. Any Nyxt build that deviates from it is considered +unofficial. See environment variable =NYXT_SUBMODULES= defined in the makefile +to override the default behavior. + +** Web renderers + +Nyxt is designed to be web engine agnostic so its dependencies vary. + +*** WebKitGTK + +Using the latest [[https://webkitgtk.org][WebKitGTK]] version is advised for security concerns. The oldest +version that supports all features is 2.36. + +The packages that provide the following shared objects are required: + +- libwebkit2gtk-4.1.so +- libgobject-2.0.so +- libgirepository-1.0.so +- libglib-2.0.so +- libgthread-2.0.so +- libgio-2.0.so +- libcairo.so +- libpango-1.0.so +- libpangocairo-1.0.so +- libgdk_pixbuf-2.0.so +- libgdk-3.so +- libgtk-3.so + +To improve media stream it is recommended to install =gst-libav= and the +following plugins: + +- gst-plugins-bad +- gst-plugins-base +- gst-plugins-good +- gst-plugins-ugly + +*** Electron + +Experimental support for [[https://www.electronjs.org/][Electron]]. Further documentation soon. + +** Other + +The packages that provide the following shared objects are required: + +- libssl.so.3 +- libcrypto.so.3 +- libfixposix.so.3 +- libsqlite3.so + +Additionally, the following packages: + +- xclip :: when using X system; +- wl-clipboard :: when using Wayland; +- enchant :: spellchecking (optional). + +* Development environment + +Lisp favors incremental program development meaning that you make some changes +and compile them. In other words, there's no need to compile the whole codebase +or even restart the program. + +The typical Common Lisp IDE is [[https://github.com/slime/slime][SLIME]] (or its fork [[https://github.com/joaotavora/sly][SLY]]), which requires being +comfortable with Emacs. Add the snippet below to Emacs' init file. + +#+begin_src emacs-lisp +(setq slime-lisp-implementations + '((nyxt ("sbcl" "--dynamic-space-size 3072") + :env ("CL_SOURCE_REGISTRY=~/common-lisp//:~/common-lisp/nyxt/_build//")))) +#+end_src + +Start the REPL by issuing =M-- M-x sly RET nyxt RET= and evaluate: + +#+begin_src lisp +(asdf:load-system :nyxt/gi-gtk) +(nyxt:start) +#+end_src + +Note that: + +- [[https://asdf.common-lisp.dev/asdf/Configuring-ASDF-to-find-your-systems.html][ASDF must be configured to find the required systems]]; +- =cffi= must be configured to find the required shared objects by setting env + var =LD_LIBRARY_PATH= or =cffi:*foreign-library-directories*=. + +** Tests + +It is recommended to restart the Lisp image before and after running the tests +since some of them are stateful: + +#+begin_src lisp +(asdf:test-system :nyxt/gi-gtk) +#+end_src + +** Functional package managers + +If you're a user of the Guix or Nix package managers, see the sections below. + +*** Guix + +See [[file:~/common-lisp/nyxt/guix.scm][guix.scm]]. + +#+begin_src emacs-lisp +(setq slime-lisp-implementations + '((nyxt-guix + ("guix" "shell" "-D" "-f" "guix.scm" + "--" "bash" "-c" "env LD_LIBRARY_PATH=\"$GUIX_ENVIRONMENT/lib\" sbcl") + :env ("CL_SOURCE_REGISTRY=~/common-lisp//:~/common-lisp/nyxt/_build//") + :directory "~/common-lisp/nyxt/"))) +#+end_src + +*** Nix + +See [[file:~/common-lisp/nyxt/shell.nix][shell.nix]]. + +#+begin_src emacs-lisp +(setq slime-lisp-implementations + '((nyxt-nix + ("nix-shell" "shell.nix" "--run" "sbcl --dynamic-space-size 3072") + :env ("CL_SOURCE_REGISTRY=~/common-lisp//:~/common-lisp/nyxt/_build//") + :directory "~/common-lisp/nyxt/"))) +#+end_src + +* Installation + +Nyxt uses the =Make= build system. Run =make= to display the documentation or +see the [[../makefile][Makefile]] for more details. + +* Interact with a running Nyxt binary + +At Nyxt's runtime, it is possible to attach a REPL via SLIME (resp. SLY). + +1. From Nyxt, run the command =start-swank= (resp. =start-slynk=). Note the + port number in the message buffer (by default, 4006). +2. From Emacs, run =M-x slime-connect RET 127.0.0.1 RET 4006= + (resp. =sly-connect=). + +* Contributing + +Nyxt is a joint effort and we welcome contributors! You can find tasks [[https://github.com/atlas-engineer/nyxt/issues?q=is%3Aissue+is%3Aopen+label%3Agood-first-issue][on our +issue tracker]] to suit your interests and skills. Please fork the project and +open a pull request (PR) on GitHub to undergo the reviewing process. Refer to +the [[*Branch management][branch management section]] for more detailed information. + +Please resist the temptation of discussing changes without drafting its +implementation. Currently, we value pragmatism over creativity. + +** Help + +Feel free to contact us at any point if you need guidance. + +- To learn Common Lisp, see [[https://nyxt-browser.com/learn-lisp]]; +- [[https://github.com/atlas-engineer/nyxt/issues][Open up an issue on GitHub]]; +- Find Nyxt on Libera IRC: [[https://kiwiirc.com/nextclient/irc.libera.chat/nyxt][#nyxt]]; +- [[https://discord.com/channels/1178074327309099069/1178074327309099072][Nyxt's discord]]; +- [[https://discourse.atlas.engineer/][Nyxt's discourse]]. + +** Commit style + +Ensure to isolate commits containing whitespace changes (including indentation) +or code movements as to avoid noise in the diffs. + +Regarding commit messages, we follow the convention of prefixing the title with +the basename when there's a single modified file. For instance, for changes in +=source/mode/blocker.lisp= the commit message would look as per below: + +#+begin_example +mode/blocker: Short description of the change. + +Further explanation. +#+end_example + +** Branch management + +Nyxt uses the following branches: + +- =master= for development; +- =<feature-branches>= for working on particular features; +- =<integer>-series= to backport commits corresponding to specific major + versions. + +Branch off from the target branch and rebase onto it right before merging as to +avoid merge conflicts. + +A commit is said to be atomic when it builds and starts Nyxt successfully. At +times, for the sake of readability, it is wise to break the changes down to +smaller non-atomic commits. In that case, a merge commit is required (use merge +option =no-ff=). This guarantees that running =git bisect= with option +=--first-parent= only picks atomic commits, which streamlines the process. + +Those with commit access may push trivial changes directly to the target branch. + +** Programming conventions + +The usual style guides by [[https://www.cs.umd.edu/~nau/cmsc421/norvig-lisp-style.pdf][Norvig & Pitman's Tutorial on Good Lisp Programming +Style]] and [[https://google.github.io/styleguide/lispguide.xml][Google Common Lisp Style Guide]] are advised. + +For symbol naming conventions, see https://www.cliki.net/Naming+conventions. + +Some of our conventions include: + +- Prefer =first= and =rest= over =car= and =cdr=, respectively. +- Use =define-class= instead of =defclass=. +- Use =nyxt:define-package= for Nyxt-related pacakges. Notice that it features + default imports (e.g. =export-always=) and package nicknames (e.g. =alex=, + =sera=, etc.). Prefer =uiop:define-package= for general purpose packages. +- Export using =export-always= next to the symbol definition. This helps + prevent exports to go out-of-sync, or catch typos. Unlike =export=, + =export-always= saves you from surprises upon recompilation. +- When sensible, declaim the function types using =->=. Note that there is then + no need to mention the type of the arguments and the return value in the + docstring. +- Use the =maybe= and =maybe*= types instead of =(or null ...)= and =(or null + (array * (0)) ...)=, respectively. +- Use the =list-of= type for typed lists. +- Use =funcall*= to not error when function does not exist. +- Prefer classes over structs. +- Classes should be usable with just a =make-instance=. +- Slots classes should be formatted in the following way: +#+begin_src lisp +(slot-name + slot-value + ... + :documentation "Foo.") +#+end_src + +When =slot-value= is the only parameter specified then: +#+begin_src lisp +(slot-name slot-value) +#+end_src +- =customize-instance= is reserved for end users. Use + =initialize-instance :after= or =slot-unbound= to initialize the slots. + Set up the rest of the class in =customize-instance :after=. Bear in mind + that anything in this last method won't be customizable for the end user. +- Almost all files should be handled via the =nfiles= library. +- =(setf SLOT-WRITER) :after= is reserved for "watchers", + i.e. handlers that are run whenever the slot is set. The =:around= method is + not used by watchers, and thus the watcher may be overridden. +- We use the =%foo%= naming convention for special local variables. +- We suffix predicates with =-p=. Unlike the usual convention, we always use a + dash (i.e. =foo-p= over =foop=). +- Prefer the term =url= over =uri=. +- URLs should be of type =quri:uri=. If you need to manipulate a URL string, call + it =url-string=. In case the value contains a URL, but is not =quri:url=, use + =url-designator= and its =url= method to normalize into =quri:uri=. +- Paths should be of type =cl:pathname=. + Use =uiop:native-namestring= to "send" to OS-facing functions, + =uiop:ensure-pathname= to "receive" from OS-facing functions or to "trunamize". +- Prefer =handler-bind= over =handler-case=: when running from the REPL, this + triggers the debugger with a full stacktrace; when running the Nyxt binary, + all conditions are caught anyway. +- Do not handle the =T= condition, this may break everything. Handle =error=, + =serious-condition=, or exceptionally =condition= (for instance if you do not + control the called code, and some libraries subclass =condition= instead of + =error=). +- Dummy variables are called =_=. +- Prefer American spelling. +- Construct =define-command= requires a short one-line docstring without newlines. + +# - Conversion functions =FROM->TO= or =->TO= for generic functions. The +# only one that comes to mind is =url= which does not follow this convention... + +# - Blocking function should be prefixed with =wait-on-=. + +# Local Variables: +# eval: (add-hook 'before-save-hook +# (lambda nil (if (fboundp 'org-make-toc) +# (org-make-toc) +# (message-box "Please install org-make-toc."))) +# nil +# t) +# End: diff --git a/documents/README.org b/documents/README.org deleted file mode 100644 index a0a8085ac..000000000 --- a/documents/README.org +++ /dev/null @@ -1,426 +0,0 @@ -#+TITLE: Nyxt Developer's Manual - -# Please install org-make-toc so the TOC below will be automatically -# generated. -# https://github.com/alphapapa/org-make-toc -* Table of contents :TOC: -:PROPERTIES: -:TOC: :include all :ignore this -:END: -:CONTENTS: -- [[#development-environment-guide][Development environment guide]] -- [[#developers-installation-guide][Developer's installation guide]] - - [[#installing-sbcl][Installing SBCL]] - - [[#lisp-dependencies][Lisp dependencies]] - - [[#gtk-dependencies][GTK dependencies]] - - [[#gnulinux-freebsd-gtk-dependencies][GNU/Linux, FreeBSD GTK dependencies]] - - [[#fetch-the-source-code][Fetch the source code]] - - [[#compile][Compile]] - - [[#using-the-makefile][Using the Makefile]] - - [[#interacting-with-a-compiled-version-of-nyxt][Interacting with a compiled version of Nyxt]] - - [[#slime][SLIME]] - - [[#sly][SLY]] -- [[#contributing][Contributing]] - - [[#asking-for-help][Asking for help]] - - [[#issue-tracker][Issue tracker]] - - [[#learning-common-lisp][Learning Common Lisp]] - - [[#irc-channel][IRC Channel]] - - [[#commit-style][Commit style]] - - [[#branch-management][Branch management]] - - [[#adding-a-new-lisp-dependency][Adding a new Lisp dependency]] - - [[#programming-conventions][Programming conventions]] -:END: - -* Development environment guide - -If you are new to hacking on Nyxt, you may be looking for a straightforward way -to set up the development environment. While there are several ways to go about -it, we describe the approach the Nyxt team uses. - -Firstly, install: -1. [[https://guix.gnu.org][The GUIX package manager]] -2. [[https://www.sbcl.org/][SBCL]] -3. [[https://www.gnu.org/software/emacs/][Emacs]] -4. [[https://github.com/joaotavora/sly][SLY]] - -With these working on your system, clone the Nyxt repository at -=~/common-lisp=. Then add the snippet below to your Emacs configuration file and -reload it. - -#+begin_src emacs-lisp -(load "~/common-lisp/nyxt/build-scripts/nyxt-guix.el" :noerror) - -(setq sly-lisp-implementations - '((nyxt-sbcl - (lambda () (nyxt-make-guix-cl-for-nyxt - "~/common-lisp/nyxt" - ;; You may set it to t, if you experience odd behavior. - :force nil - :cl-implementation "sbcl" - :cl-system "nyxt/gi-gtk" - :no-grafts t - :ad-hoc '("emacs" "xdg-utils" "git")))))) -#+end_src - -Then, to start the SLY REPL, ~M-- M-x sly RET nyxt-sbcl RET~. Wait for it to -finish and the REPL will open. At this point you are almost ready to start -hacking. In the SLY REPL, evaluate as follows: - -#+begin_src lisp -(asdf:load-system :nyxt/gi-gtk) -(nyxt:start) -#+end_src - -With Nyxt started in this way, you can hack on Nyxt without recompiling the -whole codebase or even restarting the browser. You can make your changes, -recompile only the relevant file/expression with SLY and it's done. - -You can also run the full test suite locally with: - -#+begin_src lisp -(asdf:test-system :nyxt/gi-gtk) -#+end_src - -It is recommended to restart the SLY session before and after running the tests. - -* Developer's installation guide - -There are several ways to install Nyxt on your system. For example, to install -with Guix, follow the instructions in the [[../build-scripts/nyxt.scm]] file of the -Nyxt repository. In this section, we will provide a more tool-agnostic way. - -Nyxt is written in Common Lisp. It should build with any standard Common Lisp -implementation but currently, only [[http://www.sbcl.org/][SBCL]] support is tested. It is designed to be -cross-platform, cross-engine compatible. Nyxt is available in both WebKit and -WebEngine (experimental) flavors. - -** Installing SBCL - -You'll need SBCL ≥ 2.0.0 to compile Nyxt. - -You can obtain SBCL from your package manager or by downloading it directly from -the SBCL repository. - -To install SBCL from source, download SBCL: -[[http://www.sbcl.org/platform-table.html]]. Full installation instructions can be -found here: [[http://www.sbcl.org/getting.html]]. - -** Lisp dependencies - -All Lisp dependencies are included as Git submodules of this repository, so -there's no extra setup. - -In case you'd like to manage them manually, set the environment variable -~NYXT_SUBMODULES=false~ and place them at a location that [[https://www.common-lisp.net/project/asdf/asdf.html#Configuring-ASDF-to-find-your-systems][ASDF honors]]. Note the -Nyxt requires some Lisp libraries and, since some are pinned at specific -versions, relying on Quicklisp is discouraged. - -** GTK dependencies - -*** GNU/Linux, FreeBSD GTK dependencies - -- WebKitGTK+ also known as webkit2gtk (make sure to use the most recent version - for security reasons) -- gobject-introspection (for WebKitGTK+ bindings) -- glib-networking (for WebKitGTK+) -- gsettings-desktop-schemas (for WebKitGTK+) -- libfixposix -- xclip (if on X) or wl-clipboard (if on Wayland) (for clipboard support) -- enchant (for spellchecking) - -- Debian-based distributions: - #+begin_src sh - sudo apt install sbcl libwebkit2gtk-4.0-dev gobject-introspection glib-networking gsettings-desktop-schemas libfixposix-dev pkg-config xclip enchant-2 libssl-dev - #+end_src - -- Arch Linux: - #+begin_src sh - sudo pacman -S git sbcl cl-asdf webkit2gtk gobject-introspection glib-networking gsettings-desktop-schemas enchant libfixposix - #+end_src - -- Fedora: - #+begin_src sh - sudo dnf install sbcl webkit2gtk4.0-devel glib-networking gsettings-desktop-schemas libfixposix-devel xclip wl-clipboard enchant pkgconf - #+end_src - -- FreeBSD and derivatives - #+begin_src sh - pkg install sbcl webkit2-gtk3 glib-networking libfixposix xclip enchant rubygem-pkg-config - #+end_src - -If your distribution does not install libraries in an [[https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard][FHS]]-expected location, you -have to let your Lisp compiler know where to find them. To do so, add the -library directories to ~cffi:*foreign-library-directories*~ list. For instance, -if you are running Guix you may want to expose =~/.guix-profile/lib= to the -compiler by adding the following snippet to =~/.sbclrc=: - -#+begin_src lisp -(require "asdf") - -(let ((guix-profile (format nil "~a/.guix-profile/lib/" (uiop:getenv "HOME")))) - (when (and (probe-file guix-profile) - (ignore-errors (asdf:load-system "cffi"))) - (push guix-profile - (symbol-value (find-symbol (string '*foreign-library-directories*) - (find-package 'cffi)))))) -#+end_src - -#+begin_quote -A note of caution about installing WebKit via your package manager: Your -distribution supplied version of WebKit may not provide up-to-date versions of -WebKit including the latest security patches. WebKitGTK+ tries to do the best -job possible with maintaining security patches upstream, but it is also up to -the distribution provider to update their packages to take advantage of -these fixes. -#+end_quote - -** Fetch the source code - -Clone the Nyxt repository into =~/common-lisp= (or [[https://www.common-lisp.net/project/asdf/asdf.html#Configuring-ASDF-to-find-your-systems][another directory where ASDF -will find it]]): - -#+begin_src sh -mkdir -p ~/common-lisp -git clone --recurse-submodules https://github.com/atlas-engineer/nyxt ~/common-lisp/nyxt -#+end_src - -** Compile -*** Using the Makefile - -The following command will build the Lisp core. - -- GNU/Linux: - #+begin_src sh - make all - #+end_src - -- FreeBSD - #+begin_src sh - gmake all - #+end_src - -Inside the Makefile you'll find many options you can specify. Run ~make~ -to display some documentation or see the [[../makefile][Makefile]] for more details. - -** Interacting with a compiled version of Nyxt - -After compiling Nyxt or installing it in some other way, you can use SLIME or -SLY to interact with it in a REPL. This is accomplished by starting a ~swank~ -or ~slynk~ server (for SLIME and SLY respectively) from Nyxt and connecting -to it through Emacs. - -*** SLIME - -1. Run the command =start-swank= in Nyxt. Note the port number in the message - buffer. The default is 4006. -2. Connect to the ~swank~ server in Emacs with - ~M-x slime-connect RET 127.0.0.1 RET 4006~. - -*** SLY - -1. Run the command =start-slynk= in Nyxt. Note the port number in the message - buffer. The default is 4006. -2. Connect to the ~slynk~ server in Emacs with - ~M-x sly-connect RET 127.0.0.1 RET 4006~. - -* Contributing - -Nyxt is a joint effort and we need you to make it succeed! You can find ideas -[[https://github.com/atlas-engineer/nyxt/issues?q=is%3Aissue+is%3Aopen+label%3Agood-first-issue][on our issue tracker]] to suit your interests and skills. When ready to start -working please fork the repository, add your changes and open a pull request on -GitHub to pass the review process. Refer to the [[*Branch management][branch management section]] for -more detailed information. - -You can contribute to Nyxt without commit access. However, if you're a frequent -contributor, you may request it. Remember that with great power comes great -responsibility. - -** Asking for help - -Feel free to contact us at any point if you need guidance. There are several -ways to ask for help from the community. - -*** Issue tracker - -The first and easiest one is to simply [[https://github.com/atlas-engineer/nyxt/issues][open up an issue]] with whatever problem or -suggestion you wish to discuss. - -*** Learning Common Lisp - -See [[https://nyxt-browser.com/learn-lisp]] for a few recommendations. - -*** IRC Channel - -You can find Nyxt on Libera IRC: [[https://kiwiirc.com/nextclient/irc.libera.chat/nyxt][#nyxt]]. - -** Commit style - -We follow the general Git guidelines, namely we try to commit atomic changes -that are "clean", that is, on which Nyxt builds and starts. - -Make sure to make seperate commits in these cases to avoid distracting noise in -commits with actual changes: - -- Indentation and whitespace trimming; - -- Code movements (within a file or to a different file). In this case, it's - crucial that the commit contains nothing else, otherwise "diffs" may fail to - highlight the changes. - -For commit messages, we follow (somewhat flexibly) the convention of prefixing -the title with the basename of the file that was modified. For instance, for -changes in =source/mode/blocker.lisp= the commit message would look like this: - -#+begin_example -mode/blocker: What and why this change. - -Rest of the message here. -#+end_example - -Your commit should clarify _what_ it does and _why_ (in case it's not already -obvious). - -** Branch management - -Nyxt uses the following branches: - -- =master= for development; -- =<feature-branches>= for working on particular features; -- =<2,3,...>-series= to backport commits corresponding to specific major - versions. - -It's recommended to branch off from the target branch and to rebase onto it -right before merging. This keeps the history as clear as possible and reduces -the complexity of the diff. - -Unless the changes are trivial and each commit is atomic (that is, leaving Nyxt -fully functional), they should be followed by a merge commit. That is -guaranteed by using the merge option =no-ff= (no fast-forward). If required, -the merge commit can be reworded. - -The names of the branches really matter since the merge commit references them, -so please take that into account! - -After the changes are merged, please do not forget to delete obsolete or -dangling branches. If you merge the remote branch instead of the local one, then -GitHub deletes the remote branch automatically. - -Note to core contributors: since you have commit access, you can push trivial -changes directly to the target branch (skipping the review process). The merge -commit is required when at least one commit isn't atomic. - -** Adding a new Lisp dependency -- Add and shallow clone upstream source as a Git submodule in [[../_build/]] - directory. -- Add dependency name to [[../nyxt.asd]] and [[SOURCES.org][documents/SOURCES.org]]. -- Add dependency to [[../build-scripts/nyxt.scm]], [[https://guix.gnu.org/en/packages/][checking]] to make sure Guix - already has it packaged. - -** Programming conventions - -We try to follow the usual Common Lisp conventions as recommended by -[[https://www.cs.umd.edu/~nau/cmsc421/norvig-lisp-style.pdf][Norvig & Pitman's Tutorial on Good Lisp Programming Style]] and [[https://google.github.io/styleguide/lispguide.xml][Google Common Lisp -Style Guide]]. - -For symbol naming conventions, see https://www.cliki.net/Naming+conventions. - -We've also developed some of our own: - -- Prefer =first= and =rest= over =car= and =cdr= respectively. -- Use =define-class= instead of =defclass=. -- Use =nyxt:define-package= for Nyxt-related pacakges. Notice that it features - default imports (e.g. =export-always=) and package nicknames (e.g. =alex=, - =sera=, etc.). Prefer =uiop:define-package= for general purpose packages. -- Export using =export-always= (from Serapeum) next to the symbol definition. - This helps prevent exports to go out-of-sync, or catch typos. - Unlike =export=, =export-always= saves you from surprises upon recompilation. -- When sensible, declaim the function types using =->= (from Serapeum). Note - that there is then no need to mention the type of the arguments and the return - value in the docstring. -- Use the =maybe= and =maybe*= types instead of =(or null ...)= and =(or null - (array * (0)) ...)= respectively. -- Use the =list-of= type for typed lists. -- We make heavy use of Alexandria and Serapeum, remember to use them instead of - writing the same boilerplate over and over. In particular, note these - systematic uses of Serapeum: - - =sera:eval-always=; - - =export-always=; - - =sera:and-let*=; - - =sera:lret=; - - =sera:single= - - =->= (declaimed types). -- Use =funcall*= to not error when function does not exist. -- Prefer classes over structs. Rationale: - - Class slots have documentation. - - Class allow for full-fledged CLOS use (metaclasses, etc.). - - Structs have read-only slots but it's easy enough to implement them for - classes. - - Structs have better performance, but this is usually micro-optimization, and - even then class implementations can be made more efficient via MOP. -- Classes should be usable with just a =make-instance=. -- Slots classes should be formatted in the following way: -#+begin_src lisp -(slot-name - slot-value - ... - :documentation "Foo.") -#+end_src - -When =slot-value= is the only parameter specified then: -#+begin_src lisp -(slot-name slot-value) -#+end_src -- Prefer =defmethod= over =defun= if one of the arguments is a user-class. This - allows the user to write specializations of subclasses. -- =customize-instance= is reserved for end users. Use - =initialize-instance :after= or =slot-unbound= to initialize the slots. - Set up the rest of the class in =customize-instance :after=. Bear in mind - that anything in this last method won't be customizable for the end user. -- Almost all files should be handled via the =nfiles= library. -- Specialize =print-object= for recurring class instances. -- =(setf SLOT-WRITER) :after= is reserved for "watchers", - i.e. handlers that are run whenever the slot is set. The =:around= method is - not used by watchers, and thus the watcher may be overridden. -- A function as a slot value is often a sign that it should be a method instead. - Methods give more flexibility to the end user. - Example: Avoid adding a =constructor= slot, make it a method instead. -- Define generic functions (in particular if they are heavily used) using an - explicit call to =defgeneric=, not with just calls to =defmethod=. This - enables proper source location of the generic function (otherwise it cannot be - found), plus it lets you write different documentation for the generic and the - specialized methods. -- We use the =%foo%= naming convention for special local variables. But special - variables are rare and ideally they should be avoided. -- We suffix predicates with =-p=. Unlike the usual convention, we always use a - hyphen even for single word predicates. -- Prefer the term =url= over =uri=. -- URLs should be of type =quri:uri=. If you need to manipulate a URL string, call - it =url-string=. In case the value contains a URL, but is not =quri:url=, use - =url-designator= and its =url= method to normalize into =quri:uri=. -- Paths should be of type =cl:pathname=. - Use =uiop:native-namestring= to "send" to OS-facing functions, - =uiop:ensure-pathname= to "receive" from OS-facing functions or to "trunamize". -- Prefer =handler-bind= over =handler-case=: when running from the REPL, this - triggers the debugger with a full stacktrace; when running the Nyxt binary, - all conditions are caught anyway. -- Do not handle the =T= condition, this may break everything. Handle =error=, - =serious-condition=, or exceptionally =condition= (for instance if you do not - control the called code, and some libraries subclass =condition= instead of - =error=). -- Dummy variables are called =_=. -- Prefer American spelling. -- Construct =define-command= requires a short one-line docstring without newlines. - -# - Conversion functions =FROM->TO= or =->TO= for generic functions. The -# only one that comes to mind is =url= which does not follow this convention... - -# - Blocking function should be prefixed with =wait-on-=. - -# Local Variables: -# eval: (add-hook 'before-save-hook -# (lambda nil (if (fboundp 'org-make-toc) -# (org-make-toc) -# (message-box "Please install org-make-toc."))) -# nil -# t) -# End: @@ -17,7 +17,7 @@ ;; ;; guix shell -D -f guix.scm -- bash -c 'env LD_LIBRARY_PATH="$GUIX_ENVIRONMENT/lib" sbcl' ;; -;; See documents/README.org on how to setup the development environment. +;; See developer-manual.org on how to setup the development environment. ;; ;;; Code: |