Emacs Extensions for
GE Smallworld Magik Development

Screen-casts, tutorials, and productivity tools for Magik programmers who use Emacs. From tab-mode and code folding to the Magik Debugger and object inspector — explore features built by a developer, for developers.

Learn More
HydePark Consulting Screen-casts on YouTube RSS via FeedBurner

Nine screen-casts published between November 2010 and January 2011 — covering everything from ECB mode to the Tree Item GUI control. Read the story behind the project →

Get in Touch

Magik method navigation: building a minor mode

Emacs already gives Magik programmers a capable editing environment through magik-mode. A minor mode adds focused functionality without taking over the buffer’s major mode. That distinction makes minor modes ideal for navigation, inspection, folding, or debugging helpers that should feel like optional extensions to an existing Magik workflow.

Writing a minor mode for Magik in Emacs starts with an Emacs Lisp entry point, a small command set, and a clear promise about what changes. You do not need to rebuild syntax highlighting or indentation to deliver something useful. A method browser or a safer navigation command can sit comfortably beside the established editing tools.

The examples below build a method-navigation mode for Magik source files. It finds method definitions, exposes them through Imenu, and provides commands for moving between definitions. The implementation deliberately avoids production database connections and file writes, allowing it to be developed and tested with ordinary source files.

For developers in Melbourne and Sydney maintaining Smallworld systems, a compact extension can travel comfortably between workstations. It can be enabled locally, shared as an ELisp file, or packaged for a team. Australian engineering consultancies and banks often value maintainable tooling, especially when new functionality must coexist with established in-house development standards.

Choose a focused purpose

Begin with one useful behaviour rather than an ambitious framework. A good first target is moving between Magik method definitions and listing them in Imenu. Keep database debugging, compilation, production object inspection, and source folding out of the initial version. Those features involve environment-specific configuration and usually deserve separate minor modes with their own lifecycle and error handling.

Define the mode’s contract before writing its commands. Enabling it should install only the promised navigation behaviour; disabling it should restore any settings it changed. The implementation must tolerate non-Magik buffers, missing definitions, and repeated activation without modifying unrelated parts of the user’s configuration.

Build the mode and keymap

A sparse keymap keeps the extension’s commands separate from the major mode’s bindings. Emacs provides define-minor-mode for the mode itself, while the :keymap option associates the commands with that mode.

(require 'imenu)

(defvar magik-method-navigation-mode-map
  (make-sparse-keymap)
  "Keymap for `magik-method-navigation-mode'.")

(define-key magik-method-navigation-mode-map
  (kbd "C-c M-n") #'magik-method-navigation--next)
(define-key magik-method-navigation-mode-map
  (kbd "C-c M-p") #'magik-method-navigation--previous)
(define-key magik-method-navigation-mode-map
  (kbd "C-c M-i") #'imenu)

(define-minor-mode magik-method-navigation-mode
  "Navigate Magik method definitions without replacing `magik-mode'."
  :lighter " MagikNav"
  :keymap magik-method-navigation-mode-map
  (if magik-method-navigation-mode
      (magik-method-navigation--setup)
    (magik-method-navigation--teardown)))

The mode delegates installation and removal to helper functions, which are defined later in the file. Emacs resolves those function names when the mode is enabled or a key is pressed, so their order in the source file does not affect operation. The MagikNav lighter makes the mode’s state visible in the mode line without replacing Magik’s own indicator.

Add navigation and inspection

The navigation functions use regular expressions to locate common Magik method declarations. A small helper checks the syntax state so that commented definitions do not appear as executable methods. The index function returns the structure expected by Imenu: an association list of names and buffer positions.

(defconst magik-method-navigation--method-regexp
  "^[ \t]*\\(?:private[ \t]+\\)?_?method[ \t]+\\([^ \t\n()]+\\)"
  "Regexp matching a Magik method definition and its name.")

(defun magik-method-navigation--code-position-p (position)
  "Return non-nil when POSITION is outside a string or comment."
  (let ((state (syntax-ppss position)))
    (not (or (nth 3 state) (nth 4 state)))))

(defun magik-method-navigation--imenu-index ()
  "Return an Imenu index of Magik method definitions."
  (let ((index '()))
    (save-excursion
      (goto-char (point-min))
      (while (re-search-forward
              magik-method-navigation--method-regexp nil t)
        (when (magik-method-navigation--code-position-p
                (match-beginning 0))
          (push (cons (match-string 1) (match-beginning 1))
                index))))
    (nreverse index)))

(defun magik-method-navigation--next ()
  "Move to the next Magik method definition."
  (interactive)
  (let ((found nil))
    (save-excursion
      (while (and (not found)
                  (re-search-forward
                   magik-method-navigation--method-regexp nil t))
        (when (magik-method-navigation--code-position-p
                (match-beginning 0))
          (setq found (match-beginning 1)))))
    (if found
        (goto-char found)
      (message "No later Magik method found."))))

(defun magik-method-navigation--previous ()
  "Move to the previous Magik method definition."
  (interactive)
  (let ((origin (point))
        (previous nil))
    (save-excursion
      (goto-char (point-min))
      (while (re-search-forward
              magik-method-navigation--method-regexp nil t)
        (let ((start (match-beginning 0))
              (end (match-end 0)))
          (when (and (< end origin)
                     (magik-method-navigation--code-position-p start))
            (setq previous start)))
        (goto-char (match-end 0))))
    (if previous
        (goto-char previous)
      (message "No earlier Magik method found."))))

Running M-x imenu now presents an index of the discovered methods. The regular expressions cover ordinary and private method declarations, but they remain a lightweight scanner rather than a complete Magik parser. Test them against representative source before treating the index as exhaustive. Teams can compare this focused Emacs extension with Norton for Magik when deciding whether functionality should live inside Emacs or in a broader development environment.

Protect buffer-local settings

A Magik buffer may already contain a custom Imenu index or other local configuration. The setup function therefore saves the existing imenu-create-index-function before replacing it. An installation flag prevents repeated activation from overwriting the original value, and the teardown function restores it when the minor mode is disabled.

(defvar-local magik-method-navigation--saved-imenu nil)
(defvar-local magik-method-navigation--installed nil)

(defun magik-method-navigation--setup ()
  "Install Magik method navigation in the current buffer."
  (when (derived-mode-p 'magik-mode)
    (unless magik-method-navigation--installed
      (setq-local magik-method-navigation--saved-imenu
                  imenu-create-index-function)
      (setq-local magik-method-navigation--installed t))
    (setq-local imenu-create-index-function
                #'magik-method-navigation--imenu-index)))

(defun magik-method-navigation--teardown ()
  "Restore the Imenu setting replaced by the navigation mode."
  (when magik-method-navigation--installed
    (setq-local imenu-create-index-function
                magik-method-navigation--saved-imenu)
    (setq-local magik-method-navigation--installed nil)))

Automatic activation belongs in magik-mode-hook, where it affects Magik buffers rather than every buffer opened in Emacs. The minor mode remains buffer-local by default even when its enabling variable is globalised.

(add-hook 'magik-mode-hook #'magik-method-navigation-mode)

Avoid replacing the major mode’s keymap with use-local-map, since that would interfere with existing Magik commands. Keep this mode free of live debugger processes and database sessions. If a future extension handles customer or employee records, Australian teams must also consider the Privacy Act 1988, along with contractual and workplace controls. Source code and object contents should not leave the workstation merely because a convenient helper is available.

Test the behaviour

Use Emacs’ built-in test framework, ERT, to check the scanner against small fixtures. The first test confirms that an Imenu index contains both regular and private methods. The second checks that the next-method command reaches the expected definition.

(ert-deftest magik-method-navigation-indexes-methods ()
  (with-temp-buffer
    (magik-mode)
    (insert "method worker.run()\n")
    (insert "private method worker.reset()\n")
    (should (equal
             (mapcar #'car
                     (magik-method-navigation--imenu-index))
             '("worker.run" "worker.reset")))))

(ert-deftest magik-method-navigation-moves-forward ()
  (with-temp-buffer
    (magik-mode)
    (insert "method worker.run()\n")
    (insert "method worker.stop()\n")
    (goto-char (point-min))
    (magik-method-navigation--next)
    (should (looking-at "worker\\.run"))))

Run M-x ert, then add cases for comments, absent methods, repeated activation, and restoration of the original Imenu function. A developer in Melbourne can perform these checks on a train using a local checkout, because the tests require neither a VPN connection nor a live Smallworld session. For file edits made while refining the extension, the Undo Tree workflow provides a visual way to revisit earlier changes without abandoning the current session.

Package and use the extension

Save the implementation as magik-method-navigation.el. End the file with a provide form and the usual Emacs Lisp footer, then place the file on your load-path. During early development, loading the file directly is sufficient; a stable installation can require it from your initialisation file.

(add-to-list 'load-path "/path/to/your/elisp")
(require 'magik-method-navigation)

Enable the extension with M-x magik-method-navigation-mode, or let the magik-mode-hook activate it automatically. Use C-c M-n and C-c M-p to move between definitions, and C-c M-i to open the method index. Existing Magik highlighting, indentation, compilation, and debugging facilities remain available.

Install this example in a scratch Magik buffer, run the ERT checks, and then publish the finished package for the Magik Emacs community or your organisation’s internal tooling group.

Core Features

Tab Mode & ECB

Quick tab switching and Emacs Code Browsing mode for navigating Magik codebases efficiently.

Magik Smeller

Code analysis tool that helps identify potential issues in Magik source files.

Code Folding

Hide/Show mode for collapsing and expanding Magik code blocks to focus on what matters.

Visual Bookmarks

Quick visual bookmarks for jumping between key locations in your Smallworld session buffers.

Object Inspector

Inspect Magik objects and display them in an Emacs Deep Print buffer for detailed examination.

Magik Debugger

Set breakpoints and monitor slots and variables directly from within Emacs.

Development Tools

Direct links between Emacs and the Smallworld Development Tools application, including Click Monitor.

Screen-casts & Tutorials

Dark code editor window with syntax-highlighted Magik source code in muted blues and greys, conveying a focused development environment

Screen-cast 1: Tab Mode, ECB & More

Covers tab-mode, ECB, Magik Smeller, code folding, visual bookmarks, pragma toggling, moving code, external editor, and MS Explorer.

November 7, 2010
Split-pane Emacs interface with multiple buffers open, warm amber and navy tones against a dark background

Screen-cast 5: Object Inspection & Deep Print

Inspect a Magik object, prompt for an expression evaluated within a Smallworld session, and display results in a Deep Print buffer.

January 16, 2011
Debugging interface with breakpoint markers and variable watch panels in subdued teal and charcoal tones

Screen-cast 7: Magik Debugger

Useful tools for application developers: Object Inspector and Magik Debugger with breakpoints and slot/variable monitoring.

January 2011
Tree control GUI element with expandable branches rendered in clean greys and muted blues on a light background

Screen-cast 9: Tree Item GUI Control

Tree Item is a GUI control providing extensive facilities for displaying lists with rows, columns, trees, and in-place editing.

January 20, 2011