[main]Notes on TeXmacs

An overview of TeXmacs from altitude

A rapid overview/executive summary of the TeXmacs system.

Main features

Gallery

The legacy X11 backend

The Qt backend, high quality typesetting

Structured editing, high quality math typesetting

Presentation mode

Graphics editor

Microtypography, synthetic math fonts

Interfaces to external packages (here DraTeX)

Interfaces to external packages (here Mathemagix and Maxima)

Support for oriental scripts

Development

TeXmacs' content model

All TeXmacs documents or document fragments can be thought of as trees.

For instance, the tree

typically represents the formula

External representations

Serialization of TeXmacs documents without loss of informations

Typesetting

Typesetting process converts TeXmacs trees into boxes:

The typesetting primitives are designed to be very fast and they are built-in into the editor:

e.g. typesetting primitives for horizontal concatenations (concat), page breaks (page-break), mathematical fractions (frac), hyperlinks (hlink), and so on.

The rendering of many of the primitives may be customized through the built-in environment variables.

e.g. the environment variable color specifies the current color of objects, par-left the current left margin of paragraphs, etc.

The stylesheet language allows the user to write new primitives (macros) on top of the built-in primitives.

Contains primitives for defining macros, conditional statements, computations, delayed execution, etc. and a special extern tag to inject Scheme expressions in order to write macros.

Macros

Evaluation of TeXmacs trees proceeds by reduction of the primitives, essentialy by evaluation of macro applications.

<assign|hello|<macro|name|Hello name, how are you today?>>

Macros have editable input fields. Examples here below (activate the macros):

<assign|hello|>

<assign|seq|>

Guile as extension language

TeXmacs is extendable and customizable in various ways:

Guile is easy to embed and provides a reasonably fast implementation of Scheme.

Why Scheme?

  1. Allows to mix programs and data in a common framework.

  2. Allows to customize the language itself, by adding new programming constructs.

  3. Allows to write programs on a very abstract level.

Menus

(menu-bind file-menu
  ("New" (new-buffer))
  ("Load" (choose-file load-buffer "Load file" ""))
  ("Save" (save-buffer))
  …)

can be easily extended from user code:

(menu-bind insert-menu
  (former)
  –––
  (-> "Opening"
      ("Dear Sir" (insert "Dear Sir,"))
      ("Dear Madam" (insert "Dear Madam,")))
  (-> "Closing"
      ("Yours sincerely" (insert "Yours sincerely,"))
      ("Greetings" (insert "Greetings,"))))

Some more GUI

Keybindings

(kbd-map
  ("D e f ." (make 'definition))
  ("L e m ." (make 'lemma))
  ("P r o p ." (make 'proposition))
  ("T h ." (make 'theorem)))

The file my-init-buffer.scm is executed every time a buffer is loaded, it allows some specific customizations. For example:

(if (not (buffer-has-name? (current-buffer)))
    (begin
      (init-style "article")
      (buffer-pretend-saved (current-buffer))))

(if (not (buffer-has-name? (current-buffer)))
    (make-session "maxima" (url->string (current-buffer))))

Scheme invocation

Scheme commands can be invoked interactively (like in Emacs) using the ⌘⌃X shortcut.

A Scheme session is started using the InsertSessionScheme menu item:

scheme] 
(define (square x) (* x x))
scheme] 
(square 1111111)
scheme] 
(kbd-map ("h i ." (insert "Hi there!")))
scheme] 
;; try typing ‘‘hi.''

Scheme commands can be invoked from the command line:

texmacs text.tm -x "(print)" -q

Or scheme statement executed from inside TeXmacs macros:

<extern|(lambda (x) ‘(concat "Hallo " ,x))|Piet>

The tm-define macro

Contextual overloading

Function definition can depend on several run-time conditions (e.g. editor mode). This allows to develop modular user interfaces.

(tm-define (hello) (insert "Hello"))
(tm-define (hello) (:require (in-math?)) (insert-go-to "hello()" '(6)))
(tm-define (hello)
  (if (in-math?) (insert-go-to "hello()" '(6)) (former)))
(tm-define (my-replace what by)
  default-implementation)

(tm-define (my-replace what by)
  (:require (== what by))
  (noop))

Meta informations

(tm-define (square x)
  (:synopsis "Compute the square of @x")
  (:argument x "A number")
  (:returns "The square of @x")
  (* x x))

Used via e.g. (help square). Allows for interactive input of parameters: typing ⌘⌃⇧X followed by square and and you will be prompted for “A number” on the footer (or in a dialog). Tab-completion.

(tm-property (choose-file fun text type)
  (:interactive #t))

to indicate interactive commands in menu items like:

("Load" (choose-file load-buffer "Load file" ""))

Check-marks for menu items:

(tm-define (toggle-session-math-input)
  (:check-mark "v" session-math-input?)
  (session-use-math-input (not (session-math-input?))))

(tm-define mouse-unfold
  (:secure #t)
  (with-action t
    (tree-go-to t :start)
    (fold)))

This is a fold/unfold environment

It allows to toggle the display of its content by switching the tag from fold to unfold and back.

Scheme representation TeXmacs content

A full example

(tm-define (swap-numerator-denominator t)
  (:require (tree-is? t 'frac))
  (with p (tree-cursor-path t)
    (tree-set! t ‘(frac ,(tree-ref t 1) ,(tree-ref t 0)))
    (tree-go-to t (cons (- 1 (car p)) (cdr p)))
    (tree-focus t)))

To be called as (swap-numerator-denominator (focus-tree)), or just add it as a structured variant to frac

(tm-define (variant-circulate t forward?)
  (:require (tree-is? t 'frac))
  (swap-numerator-denominator t))

Regular expressions

TeXmacs implements the routines match? and select for matching regular expressions and selecting subexpressions along a “path”. For instance: in the current buffer search all expressions of the form

where and are general expressions:

Scheme]
(select (buffer-tree) '(:* (:match (frac :%1 (concat "1+" (sqrt :%1))))))

More scheme

User preferences

(define-preferences
  ("Gnu's hair color" "brown" notify-gnu-hair-change)
  ("Snail's cruising speed" "1mm/sec" notify-Achilles))

New data formats and converters

(define-format blablah
  (:name "Blablah")
  (:suffix "bla"))

(converter blablah-file latex-file
  (:require (url-exists-in-path? "bla2tex"))
  (:shell "bla2tex" from ">" to))

When a format can be converted from or into TeXmacs, then it will automatically appear into the FileExport and FileImport menus. Similarly, when a format can be converted to Postscript, then it also becomes a valid format for images. TeXmacs also attempts to combine explicitly declared converters into new ones.

Dialogues & Widgets

Dialogues

Scheme]
(user-ask "First number:"
  (lambda (a)
    (user-ask "Second number:"
      (lambda (b)
        (set-message (number->string (* (string->number a)
                                        (string->number b)))
                     "product")))))

Widgets

Scheme]
(tm-widget (example3)
  (hlist 
    (bold (text "Hello"))
    >>>
    (inert (explicit-buttons ("world" (display "!\n"))))))
Scheme]
(top-window example3 "Some text")
Scheme]

tree-view

Scheme]
(define t
  (stree->tree
   '(root
     (library "Library" "$TEXMACS_PIXMAP_PATH/tm_german.xpm" 01
              (collection "Cool stuff" 001)
              (collection "Things to read" 002)
              (collection "Current work" 003
                          (collection "Forever current" 004)
                          (collection "Read me" 005))))))
Scheme]
(define dd
  (stree->tree
   '(list (library DisplayRole DecorationRole UserRole:1)
          (collection DisplayRole UserRole:1))))
Scheme]
(define (action clicked cmd-role . user-roles)
  (display* "clicked= " clicked ", cmd-role= " cmd-role
            ", user-roles= " user-roles "\n")))
Scheme]
(tm-widget (widget-library)
  (resize ("150px" "400px" "9000px") ("300px" "600px" "9000px")
    (vertical
      (bold (text "Testing tree-view"))
      ===
      (tree-view action t dd))))
Scheme]
(top-window widget-library "Tree View")
Scheme]

Forms

Scheme]
(tm-widget (form3 cmd)
  (resize "500px" "500px"
    (padded
      (form "Test"
        (aligned
          (item (text "Input:")
            (form-input "fieldname1" "string" '("one") "1w"))
          (item === ===)
          (item (text "Enum:")
            (form-enum "fieldname2" '("one" "two" "three") "two" "2w"))
          (item === ===)
          (item (text "Choice:")
            (form-choice "fieldname3" '("one" "two" "three") "one"))
          (item === ===)
          (item (text "Choices:")
            (form-choices "fieldname4" 
                          '("one" "two" "three") 
                          '("one" "two"))))
        (bottom-buttons
          ("Cancel" (cmd "cancel")) >>
          ("Ok"
           (display* (form-fields) " -> " (form-values) "\n")
           (cmd "ok")))))))
Scheme]
(dialogue-window form3 (lambda (x) (display* x "\n")) "Test of form3")
Scheme]

Bibliography styles

New styles can be defined via Scheme modules like example.scm defined as follows:

(texmacs-module (bibtex example)
  (:use (bibtex bib-utils)))

(bib-define-style "example" "plain")

(tm-define (bib-format-date e)
  (:mode bib-example?)
  (bib-format-field e "year"))

This example style behaves in a similar way as the plain style, except that all dates are formatted according to our custom routine. Styles are stored in $TEXMACS_PATH/progs/bibtex and referred to as e.g. tm-example (for when used in a TeXmacs document.

Graphics

Graphics objects are also part of the TeXmacs format and can be manipulated programmatically from Scheme.

Actually, part of the graphics editor is written in Scheme.

Scheme] 
(stree->tree 
  '(with gr-geometry (tuple "geometry" "200px" "100px" "center") 
         color "blue" 
        (graphics (text-at "TeXmacs" (point "-2.5" "-1")) 
                  (point 0 -1) 
                  (line (point 0 0) (point 0 1) 
                        (point 1 1) (point 1 0) (point 0 0)))))

Scheme]

The future of TeXmacs

Many improvements ahead

Hacking TeXmacs

Many opportunities for contributions for all tastes