Your configuration is init.ss; your live changes are made in M-: and with C-M-x. Every change belongs to where you wrote it, so it can be taken back exactly.
init.ss and (use-plugin p …)user
Does.init.ss runs once, top to bottom. (use-plugin p) chooses plugin p: it starts at its line, or earlier if a line above or another plugin’s file needs it first. A plugin not listed never starts. For a contract with several implementations, the use-plugin line picks which one runs. (use-plugin a b c) chooses several at once when none has options; options need one plugin per line. Other lines are any Scheme: set!, verbs such as keys:bind!, redefine, advice-add, your own definitions. init.ss sees every contract by its prefix without importing.
Underneath. Before anything runs, the whole file is checked: every plugin exists, every option name and value fits, every c:x exists in its contract. Each line is an owner: what it does belongs to it. Because chosen plugins start on first need, the order of use-plugin lines does not matter for correctness; it decides only the order of entries from different plugins.
Errors. All at once, each with its line: init.ss:4: no plugin is named rop-store; init.ss:9: contract settings has no fill-colum. A line that fails while running is undone and reported; the rest still run.
Where Tuna differs. Emacs starts with its editor built in, and init.el adds to it. Tuna starts with only the core, and init.ss lists the plugins that make it an editor.
;; Emacs needs no such line: its defaults are built in,;; and a starter kit is loaded with one require.(require'my-starter-kit)
p::xuser
Does. In init.ss and M-: only, reaches plugin p’s private name x on purpose: read it, call it, set! it, redefine it. Plugin code cannot.
Errors. In a plugin: …: plugins cannot reach a private name.
Tuna · M-:
(dabbrev::helper"x")
Emacs
(dabbrev--helper "x")
Where Tuna differs. Every Emacs name is reachable by anyone; the double hyphen only asks you not to. Tuna lets the user reach in, on purpose, and no plugin.
(redefine (name arg …) body …)usercore
Does. Replaces a function, c:name or p::name, with a new body. Everyone who calls it, including stored references such as key bindings, gets the new one.
Underneath. A layer on the function, owned by where the form is written. Remove the owner and the original returns. A redefinition survives a reload of the plugin that defines the function: it is applied to the new code.
Errors. Redefining a macro: … is a macro; changing it needs a reload of its plugin.
Where Tuna differs. An Emacs defun overwrites the function until the package is loaded again, which then overwrites yours. A Tuna redefinition is a layer that outlives the plugin’s reloads and goes when you remove the line.
(advice-add target how procedure [name: 'n]), (advice-remove target [name: 'n])usercore
Does. Wraps function target without replacing it. how is one of before, after, around (your procedure gets the original as its first argument), override, filter-args, filter-return, as in Emacs. You have one advice of each kind per function unless you name more with name:.
Underneath. A layer owned by where it is written, like redefine. Several advices stack.
Errors.advice-add: unknown how ….
Tuna · init.ss
(advice-add dabbrev:expand filter-return
(lambda(s)(string-append s "+i")))
Emacs
(advice-add 'dabbrev-expand:filter-return(lambda(s)(concat s "+i")))
Where Tuna differs. Emacs identifies an advice by its function, so a lambda cannot be removed without a name property. Tuna identifies it by its owner, so removing the line removes it.
M-: (evaluate an expression)user
Does. Evaluates one expression in your session. You can call any contract, reach private names (p::x), define your own names, and make changes: set!, verbs, redefine, advice-add, even define-worker.
Underneath. The session is an owner like a plugin’s run: its changes are layers and entries on its receipt. They last until you end the session or Tuna exits. A worker written here is compiled apart, as in a plugin.
Where Tuna differs. Emacs’s eval-expression changes things for good. Ending a Tuna session undoes everything done in it.
C-M-x (evaluate the definition at point, in a plugin’s file)user
Does. In a plugin’s plugin.ss, evaluates the definition around the cursor inside that plugin, at once. It lasts until the plugin is next reloaded from its file.
Underneath.
A procedure’s define: becomes a layer on that function, owned by “your edits of this plugin”; every caller gets it.
commands:define, add-hook! and other verbs: replace the plugin’s entry of the same name or owner.
define-worker: recompiled apart; jobs started from now on run the new code.
define-option: changes the default.
define-saved: resets the value to its new initial value; the old one is set aside, and restore-saved! brings it back.
Any other form runs as the plugin’s current run.
Errors.… is off; evaluating in it is refused; on define-syntax or define-record-type: … cannot change live; reload …, which rebuilds the plugins that use it.
Tuna · highlight/plugin.ss, cursor in the form
(define(highlight! id)(start-job find-hello (buffers:text id)(lambda(spans)(buffers:set-faces! id spans))for: id))
Emacs
;; C-M-x on a defun: eval-defun(defun my-highlight ()(my-scan (buffer-string)))
Where Tuna differs.C-M-x on a defvar in Emacs resets the variable; on a Tuna define-saved it resets the value but sets the old one aside, because it is your data.
reload-configuser
Does. Applies only what changed in init.ss since it last ran. A removed line is undone. A new line runs. A changed line runs anew, and its old version is undone only after the new one succeeded: if the new one fails, the old stays and you are told. A changed use-plugin line restarts that plugin with its new options. Replacing one implementation’s use-plugin line with another’s is a swap.
Underneath. Lines are matched by their text. The whole file is checked first, as at start; if the check fails nothing changes.
Tuna · M-x
(commands:run!'reload-config)
Emacs
(load-file user-init-file)
Where Tuna differs. Loading init.el again runs it all again and undoes nothing you removed.
Turning off, reloading, swappinguser
Does. The core offers the operations; a plugin-management plugin offers the commands, whose names are not decided yet. The same results come from editing init.ss and reload-config: remove a line to turn a plugin off, add one to turn it on, replace one to swap. See reload, turn off and swap.
Underneath. The turn-off command first asks any question the plugin’s views would ask on closing (a running compile); the core itself never asks.
Errors. A reload whose new code drops a name another plugin uses is refused before anything changes: reload of dabbrev refused: tweaks uses dabbrev:expand at …/plugin.ss:3, which the new version does not export. A swap to a plugin that does not fill every contract the old one filled is refused.
Tuna · M-:
(commands:run!'turn-off-plugin'flymake)
Emacs
(unload-feature 'flymaket)
Ending the sessionuser
Does. Undoes everything you did in M-:, and with it your C-M-x edits. The command’s name is not decided.
Tuna · M-:
(commands:run!'end-session)
Emacs
;; No equivalent: Emacs cannot undo evaluated expressions.(restart-emacs)
(describe name)user
Does. Says what the core knows about a name: a plugin’s file, status, and the reason it is off; a function’s definer and layers (who redefined or advised it); an option’s value and layers, with their scopes; a table’s or hook’s entries and owners; saved data’s value and anything set aside. Commands that format this nicely belong to a help plugin.