- Introduction
- Install
- Tutorial
- Preparing an org file
- A quick references to useful commands
- import source codes of some packages
- compile a code block
- format code block
- show suggestions
- delete current class or method
- update source code block from Pharo
- eval code (REPL)
- browse class or implementors in Pharo
- compile all source code blocks inside a section
- release current package to local file system
- References
literate-smalltalk is an Emacs lisp library and a Smalltalk library to provide an easy way to use literal programming in Smalltalk.
Pharo is a pure object-oriented programming language and a powerful environment, focused on simplicity and immediate feedback. It also provides a markdown syntax MicroDown for its class comment.
From the point of my view, Pharo is a wonderful IDE for development, except its native editor.
So here is a new literate programming environment for Pharo in Emacs org mode.
It setup a HTTP server in Pharo, so Emacs can interact with Pharo to
- fetch packages, classes, method source
- compile class/methods
- format code block
- show suggestions, etc.
In Emacs, we use an org file as both documentation and codes, and Emacs lisp library polymode to enable native source code block in org mode. In each code block, you can compile, format code, ask for suggestions, show compiling critiques instantly, just like it is inside Pharo.
This library contains the following files:
- ./literate-smalltalk.org
The implementation and documentation of both Emacs side and Pharo side. - BaselineOfLiterateSmalltalk.class.st
The tangled codes of Base line for Pharo side package. - LiterateServer.class.st
The tangled codes of Pharo side package. - ./readme.org
This file contains introduction about how to do literate Smalltalk in an org file.
Currently it only tests in Pharo but other Smalltalk dialects should be easy to adopt.
You can add this package via metacello by adding a file named as literate-server.st
in Pharo’s configuration directory,
For Pharo 9.0 it is in ~/.config/Pharo/9.0
in Linux, or ~/Library/Preferences/pharo
in Mac OS.
To know the Pharo’s configuration directory, please print the result of code StartupPreferencesLoader preferencesGeneralFolder
in Pharo.
the file content can be like this:
StartupPreferencesLoader default executeAtomicItems: { (StartupAction
name: 'Start Literate Server'
code: [
| class |
class := Smalltalk at: #LiterateServer ifAbsent: [
Metacello new
baseline: 'LiterateSmalltalk';
repository: 'github://jingtaozf/literate-smalltalk';
onConflict: [ :ex | ex allow ];
load.
Smalltalk at: #LiterateServer ].
class ifNotNil: [ LiterateServer start ] ]
runOnce: false) }
So each time Pharo starts, it will start a HTTP server listening in local port 9092
, which Emacs can interact with.
Of course, you can also add it via Iceberg manually.
In Emacs side, you should install Emacs library literate-elisp firstly, then load this library in Emacs like this:
(load "~/projects/literate-elisp/literate-elisp.el")
(literate-elisp-load "~/projects/literate-smalltalk/literate-smalltalk.org")
(add-to-list 'org-src-lang-modes '("smalltalk" . "literate-smalltalk-code"))
(use-package poly-org :ensure t)
literate-smalltalk
provides a new major mode literate-smalltalk-code for Smalltalk source file, we also ensure polymode mode
use it.
I’ll show the general workflow and features of literate-smalltalk
in this tutorial.
Let’s assume that you or your team have already created a git repository and imported the codes into Pharo,
then you setup literate-smalltalk
correctly so Pharo listens on port 9092
to wait for request from Emacs side.
let’s create an org file, that’s all for this step but I suggest the following lines in the beginning of an org file. You can check the raw content of ./literate-smalltalk.org to have a quick view.
- enable poly-org mode
# -*- encoding:utf-8 Mode: POLY-ORG; tab-width: 2; org-src-preserve-indentation: t; -*- ---
- remove the result part of all code block
#+PROPERTY: header-args :results silent
- some default org properties for literate-smalltalk
#+PROPERTY: literate-load yes #+PROPERTY: literate-lang smalltalk
'(
("package of class" literate-smalltalk-namespace-of-current-symbol)
("bindings of evaluation" literate-smalltalk-eval-bindings)
("c open definition of class" literate-smalltalk-browse-class)
("Compile codes in current header" literate-smalltalk-execute-current-header)
("execute codes" literate-smalltalk-execute-current-code-block)
("delete current class method" literate-smalltalk-delete-current-class-or-method)
("format code for current code block" literate-smalltalk-code-format-current-code-block)
("Format code for current file" literate-smalltalk-code-format-current-file)
("i open definition of implementors" literate-smalltalk-browse-implementors)
("run current line or selected region" literate-smalltalk-eval-current-line-or-selected-region)
("update codes" literate-smalltalk-update-source))
Generally speaking, the first step is importing some Smalltalk packages into our org file.
We provide two Emacs command for this purpose:
- literate-smalltalk-namespace-to-org-section
It will import the packages specified in each class’s category slot. This kind of packages are very large as it’s a one level mapping between packages and classes.
- literate-smalltalk-package-to-org-section It will import the packages organized by RPackage, which is the top-level packages listed in Pharo System Browser. It is more clean way I suggest to use.
Now you have some source codes inside your org file.
A code block can contain either a class definition or a method code,
you can execute each source code block by Emacs command literate-smalltalk-execute-current-code-block,
or execute in org mode by org-babel-execute-src-block-maybe
.
After compiling, it will show critiques by adding them as Overlays.
Please note that we use the following codes for a class definition in a code block
Object subclass: #LiterateServer
instanceVariableNames: ''
classVariableNames: 'Server Started interactionModel transcriptLogStream'
package: 'LiterateSmalltalk'.
LiterateServer class
instanceVariableNames: ''.
LiterateServer comment: 'The REST Server for LiterateSmalltalk.'
It is better to format code before compiling, you can do so by Emacs command literate-smalltalk-code-format-current-code-block.
We use company mode to show suggestions, via Emacs command company-literate-smalltalk-code.
You can press shortcut key Alt-/
or Tab
to show a suggestion menu.
You can delete it in current code block by Emacs command literate-smalltalk-delete-current-class-or-method.
Sometimes you change some code inside Pharo, to get the latest code, you can update current code block by Emacs command literate-smalltalk-update-source.
You can create a code block with additional header argument :type code
, in this case when you compile this code block,
it is evaluated, and if you created a variable in it, you can use this variable in another code block with header argument :type code
.
For me, I will create an individual org file for one project as an REPL for it.
# -*- Mode: POLY-ORG; encoding: utf-8; tab-width: 2; -*- --- #+Title: The REPL of literate-smalltalk #+OPTIONS: tex:t toc:2 \n:nil @:t ::t |:t ^:nil -:t f:t *:t <:t #+STARTUP: noindent #+STARTUP: inlineimages #+PROPERTY: literate-header-arguments :type code #+PROPERTY: literate-lang smalltalk #+PROPERTY: literate-load yes
To just eval current line or selected region, you can run command literate-smalltalk-eval-current-line-or-selected-region
.
The Emacs command To browse class in Pharo Window is literate-smalltalk-browse-class
.
The Emacs command To browse implementors in Pharo Window is literate-smalltalk-browse-implementors
.
To compile all source code blocks inside a section, please invoke the Emacs command literate-smalltalk-execute-current-header. It will compiling all code blocks from current point to the end of current section.
If you execute this command with command prefix C-u
, it will execute all code blocks from current point to the end of current buffer.
I release codes of this project to local file system by method releaseIcebergPackage
in class LiterateServer
.
LiterateServer releaseIcebergPackage: #LiterateSmalltalk.
I find it useful because Iceberg
will have detached working copy sometimes.
- Shampoo mode for Emacs
- Literate Programming a site of literate programming
- Literate Programming in the Large a talk video from Timothy Daly, one of the original authors of Axiom.
- literate programming in org babel
- A collection of literate programming examples using Emacs Org mode