emacs

package module
v0.0.0-...-af507ad Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 25, 2024 License: Apache-2.0 Imports: 21 Imported by: 0

README

Go bindings for the Emacs module API

This package implements Go bindings for the GNU Emacs module API.

This is not an officially supported Google product.

Usage

See the package documentation.

Implementation notes

The package assumes that ptrdiff_t and intmax_t have the same domain as int64_t. It also assumes that uintptr_t has the same domain as uint64_t. The C code uses static_assert to check these assumptions. The C standard guarantees that int64_t and uint64_t have exactly 64 bits without padding bits and that they use two’s complement representation. The corresponding Go types int64 and uint64 have the same representation. This means that converting int64_t and uint64_t to and from the Go types can never lose data.

The package requires at least Emacs 27. It provides optional support for some Emacs 28 features. Such optional features always require two additional checks:

// Check that emacs-module.h has static support for Emacs 28.
#if defined EMACS_MAJOR_VERSION && EMACS_MAJOR_VERSION >= 28
// Make sure the cast below doesn’t lose information.
static_assert(SIZE_MAX >= PTRDIFF_MAX, "unsupported architecture");
// Check that the Emacs that has loaded this module supports the function.
if ((size_t)env->size > offsetof(emacs_env, function)) {
  return env->function(env, …);
}
#endif
// Some workaround in case Emacs 28 isn’t available.

CGo doesn’t support calling C function pointers. Therefore, the code wraps all function pointers in the emacs_runtime and emacs_env structures in ordinary wrapper functions. The wrapper functions use only the int64_t and uint64_t types in their interfaces.

The package uses a global registry to identify exported functions.

You can compile the examples in the test files to form an example module. In addition to the examples, this also needs the file example_test.go to initialize the examples. The Emacs Lisp file test.el runs the examples as ERT tests.

To build and run all tests, install Bazel and run

bazel test //...

Documentation

Overview

Package emacs contains infrastructure to write dynamic modules for Emacs in Go. See Emacs Dynamic Modules and Writing Dynamically-Loaded Modules for background on Emacs modules.

To build an Emacs module, you have to build your Go code as a shared C library, e.g., using go build ‑buildmode=c‑shared. If you import the emacs package, the shared library is loadable as an Emacs module.

This package contains high-level as well as lower-level functions. The high-level functions help reducing boilerplate when exporting functions to Emacs and calling Emacs functions from Go. The lower-level functions are more type-safe, support more exotic use cases, and have less overhead.

Export and Import

At the highest level, use the Export function to export Go functions to Emacs, and the Import function to import Emacs functions so that they can be called from Go. These functions automatically convert between Go and Emacs types as necessary. This export functionality is unrelated to exported Go names or the Cgo export functionality. Functions exported to Emacs don’t have to be exported in the Go or Cgo sense.

The automatic type conversion behaves as follows. Go bool values are become the Emacs symbols nil and t. When converting to Go bool, only nil becomes false, any other value becomes true. This matches the Emacs convention that all non-nil values represent a logically true value. Go integral values become Emacs integer values and vice versa. Go floating-point values become Emacs floating-point values and vice versa. Go strings become Emacs strings and vice versa. Go []byte arrays and slices become Emacs unibyte strings. Emacs unibyte strings become Go []byte slices. Other Go arrays and slices become Emacs vectors. Emacs vectors become Go slices. Go maps become Emacs hash tables and vice versa. All types that implement In can be converted to Emacs. All types that implement Out can be converted from Emacs. You can implement In or Out yourself to extend the type conversion machinery. A reflect.Value behaves like its underlying value.

Functions exported via Export don’t have a documentation string by default. To add one, pass a Doc value to Export. Since argument names aren’t available at runtime, the documentation by default lacks argument names. Use Usage to add argument names.

As an alternative to Import, you can call functions directly using Env.Invoke. Env.Invoke uses the same autoconversion rules as Import, but allows you to specify an arbitrary function value.

At a slightly lower level, you can use Env.Call and Env.CallOut to call Emacs functions. These functions use the In and Out interfaces to convert from and to Emacs values. The primary disadvantage of this approach is that you can’t use primitive types like int or string directly. Use wrapper types like Int and String instead. On the other hand, Env.Call and Env.CallOut are more type-safe than [Invoke]. If you use [Call] or [CallOut], the compiler will detect unsupported types. By contrast, when using Export, Import, or [Invoke], they will only be detected at runtime and cause runtime panics or errors.

To reduce boilerplate when using Env.Call and Env.CallOut, this package contains several convenience types that implement In or Out. Most primitive types have corresponding wrapper types, such as Int, Float, or String. Types such as List, Cons, or Hash allow you to pass common Lisp structures without much boilerplate. There are also some destructuring types such as ListOut or Uncons.

At an even lower level, you can use ExportFunc, ImportFunc, and Env.Funcall as alternatives to Export, Import, and Env.Call, respectively. They have the same behavior, but don’t do any type conversion at all.

Env and Value

The fundamental types for interacting with Emacs are Env and Value. They represent Emacs module environments and values as described in Writing Module Functions. These types are opaque, and their zero values are invalid. You can’t use Env and Value values once they are no longer live. This is described in Writing Module Functions and Conversion Between Lisp and Module Values. As a best practice, don’t let these values escape exported functions. You also can’t interact with Emacs from other threads, cf. Writing Module Functions. These rules are a bit subtle, but you are usually on the safe side if you don’t store Env and Value values in struct fields or global variables, and don’t pass them to other goroutines.

Error handling

All functions in this package translate between Go errors and Emacs nonlocal exits. See Nonlocal Exits in Modules. This package represents Emacs nonlocal exits as ordinary Go errors.

Each call to a function fetches and clears nonlocal exit information after the actual call and converts it to an error of type Signal or Throw. This means that the Go bindings don’t exhibit the saturating error behavior described at Nonlocal Exits in Modules. Instead, they behave like normal Go functions: an erroneous return doesn’t affect future function calls.

When returning from an exported function, this package converts errors back to Emacs nonlocal exits. If you return a Signal or Error, Emacs will raise a signal using the signal function. If you return a Throw, Emacs will throw to a catch using the throw function. If you return any other type of error, Emacs will signal an error of type go‑error, with the error string as signal data.

You can define your own error symbols using DefineError. There are also a couple of factory functions for builtin errors such as WrongTypeArgument and OverflowError.

Variables

You can use Var to define a dynamic variable.

User pointers and handles

This package intentionally doesn’t support wrapping pointers to arbitrary Go values in Emacs user pointer objects. Attempting to do that wouldn’t work well with Go’s garbage collection and CGo’s pointer-passing rules; see Passing pointers. Instead, prefer using handles, e.g. simple integers as map keys. See the “Handles” example.

Long-running operations

A long-running operation should periodically call Env.ProcessInput to process pending input and to check whether the user wants to quit the operation. If so, you should cancel the operation as soon as possible. See the documentation of Env.ProcessInput for a concrete example.

As an alternative, this package provides limited support for asynchronous operations. Such operations are represented using the AsyncHandle type. You can use the Async type to create and manage asynchronous operations. Async requires a way to notify Emacs about a pending asynchronous result; this package supports notification using pipes or sockets.

Initialization

If you want to run code while Emacs is loading the module, use OnInit to register initialization functions. Loading the module will call all initialization functions in order.

ERT tests

You can use ERTTest to define ERT tests backed by Go functions. This works similar to Export, but defines ERT tests instead of functions.

Example (Handles)
package main

import (
	"errors"
	"fmt"
	"math"
	"os"
	"sync"
)

func main() {
	Export(createGoFile, Doc(`Create a file with the given NAME and return a handle to it.`), Usage("NAME"))
	Export(closeGoFile, Doc(`Close the file with the given HANDLE.
HANDLE must be opened using ‘create-go-file’.`), Usage("HANDLE"))
	Export(writeGoFile, Doc(`Write CONTENTS to the file with the given HANDLE.
Return the number of bytes written.
HANDLE must be opened using ‘create-go-file’.
CONTENTS must be a unibyte string.`), Usage("HANDLE CONTENTS"))
}

type fileHandle Uint

func createGoFile(name string) (fileHandle, error) {
	fd, err := os.Create(name)
	if err != nil {
		return 0, err
	}
	h, err := registerFile(fd)
	if err != nil {
		fd.Close()
		return 0, err
	}
	return h, nil
}

func closeGoFile(h fileHandle) error {
	fd := popFile(h)
	if fd == nil {
		return fmt.Errorf("close-go-file: invalid file handle %d", h)
	}
	return fd.Close()
}

func writeGoFile(h fileHandle, b []byte) (int, error) {
	fd := getFile(h)
	if fd == nil {
		return 0, fmt.Errorf("write-go-file: invalid file handle %d", h)
	}
	return fd.Write(b)
}

var (
	fileMu   sync.Mutex
	files    = make(map[fileHandle]*os.File)
	nextFile fileHandle
)

func registerFile(fd *os.File) (fileHandle, error) {
	fileMu.Lock()
	defer fileMu.Unlock()
	h := nextFile
	if h == math.MaxUint64 {
		fd.Close()
		return 0, errors.New("too many files")
	}
	nextFile++
	files[h] = fd
	return h, nil
}

func getFile(h fileHandle) *os.File {
	fileMu.Lock()
	defer fileMu.Unlock()
	return files[h]
}

func popFile(h fileHandle) *os.File {
	fileMu.Lock()
	defer fileMu.Unlock()
	fd := files[h]
	delete(files, h)
	return fd
}

func init() {
	Example_handles()
}
Output:

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func AutoFunc

func AutoFunc(fun interface{}, opts ...Option) (Name, Func, Arity, Doc)

AutoFunc converts an arbitrary Go function to a Func. When calling the exported function from Emacs, arguments and return values are converted as described in the package documentation.

The function may accept any number of arguments. Optionally, the first argument may be of type Env. In this case, Emacs passes a live environment value that you can use to interact with Emacs. All other arguments are converted from Emacs as described in the package documentation. If not all arguments are convertible from Emacs values, AutoFunc panics.

The function must return either zero, one, or two results. If the last or only result is of type error, a non-nil value causes Emacs to trigger a non-local exit as appropriate. There may be at most one non-error result. Its value will be converted to an Emacs value as described in the package documentation. If the type of the non-error result can’t be converted to an Emacs value, AutoFunc panics. If there are invalid result patterns, AutoFunc panics.

By default, AutoFunc derives the function’s name from its Go name by Lisp-casing it. For example, MyFunc becomes my-func. To specify a different name, pass a Name option. To make the function anonymous, pass an Anonymous option. If there’s no name and the function isn’t anonymous, AutoFunc panics.

By default, the function has no documentation string. To add one, pass a Doc option.

You can call AutoFunc safely from multiple goroutines.

func ERTTest

func ERTTest(fun ERTTestFunc, opts ...Option)

ERTTest arranges for a Go function to be exported as an ERT test. Call ERTTest in an init function. Loading the dynamic module will then define the ERT test. If you want to define ERT tests after the module has been initialized, use the Env.ERTTest method instead. If the function returns an error, the ERT test fails.

By default, ERTTest derives the test’s name from the function’s Go name by Lisp-casing it. For example, MyTest becomes my-test. To specify a different name, pass a Name option. If there’s no name or the name is already registered, ERTTest panics.

By default, the ERT test has no documentation string. To add one, pass a Doc option.

You can call ERTTest safely from multiple goroutines.

Example
package main

import "log"

func main() {
	ERTTest(exampleERTTest, Name("example-ert-test"), Doc("Run an example ERT test."))
}

// Once Emacs has successfully loaded the module, ERT will see a test named
// example-ert-test that calls exampleERTTest.
func exampleERTTest(e Env) error {
	log.Print("running example test")
	return nil
}

func init() {
	// We would normally call ExampleERTTest here, but the test runner
	// already calls it for us.
}
Output:

func Export

func Export(fun interface{}, opts ...Option)

Export arranges for a Go function to be exported to Emacs. Call Export in an init function. Loading the dynamic module will then define the Emacs function. The function fun can be any Go function. When calling the exported function from Emacs, arguments and return values are converted as described in the package documentation. If you don’t want this autoconversion or need more control, use ExportFunc instead and convert arguments yourself. If you want to export functions to Emacs after the module has been initialized, use the Env.Export method instead.

The function may accept any number of arguments. Optionally, the first argument may be of type Env. In this case, Emacs passes a live environment value that you can use to interact with Emacs. All other arguments are converted from Emacs as described in the package documentation. If not all arguments are convertible from Emacs values, Export panics.

The function must return either zero, one, or two results. If the last or only result is of type error, a non-nil value causes Emacs to trigger a nonlocal exit as appropriate. There may be at most one non-error result. Its value will be converted to an Emacs value as described in the package documentation. If the type of the non-error result can’t be converted to an Emacs value, Export panics. If there are invalid result patterns, Export panics.

By default, Export derives the function’s name from its Go name by Lisp-casing it. For example, MyFunc becomes my-func. To specify a different name, pass a Name option. If there’s no name or the name is already registered, Export panics.

By default, the function has no documentation string. To add one, pass a Doc option.

You can call Export safely from multiple goroutines.

Example
package main

import (
	"fmt"
	"strings"
)

func main() {
	Export(goUppercase, Doc("Concatenate STRINGS and return the uppercase version of the result.").WithUsage("strings"))

	// Export panics when encountering an invalid type.
	defer func() { fmt.Println("panic:", recover()) }()
	Export(func(chan int) {}, Name("invalid-function"))
}

// Once Emacs has successfully loaded the module, Emacs Lisp code can call
// exampleFunc under the name go-uppercase.  For example, (go-uppercase "hi")
// will return "HI".
func goUppercase(s ...string) string {
	return strings.ToUpper(strings.Join(s, " "))
}

func init() {
	// We would normally call ExampleExport here, but the test runner
	// already calls it for us.
}
Output:

panic: function invalid-function: don’t know how to convert argument 0: Wrong type argument: go-known-type-p, "chan int"

func ExportFunc

func ExportFunc(name Name, fun Func, arity Arity, doc Doc)

ExportFunc arranges for a Go function to be exported to Emacs. Call ExportFunc in an init function. Loading the dynamic module will then define the Emacs function. Unlike Export, functions registered by ExportFunc don’t automatically convert their arguments and return values to and from Emacs. If name is empty, ExportFunc panics. If doc is empty, the function won’t have a documentation string. If you want to export functions to Emacs after the module has been initialized, use the Env.ExportFunc method instead.

You can call ExportFunc safely from multiple goroutines.

func Import

func Import(name Name, fp interface{})

Import imports an Emacs function as a Go function. name must be the Emacs symbol name of the function. fp must be a pointer to a variable of function type. Import sets *fp to a function that calls the Emacs function name.

Import must be called before Emacs loads the module. Typically you should call Import from an init function.

The dynamic type of *fp must have one of the following two forms:

func(Env, Args...) (Ret, error)
func(Env, Args...) error

Here Args is a (possibly empty) list of argument types, and Ret is the return type. If the function type has any other form, Import panics.

Calling the Go function converts all arguments to Emacs, calls the Emacs function name, and potentially converts the return value back to the Ret type. If any of the involved types can’t be represented as Emacs value, Import panics.

If you don’t want argument autoconversion, use ImportFunc instead.

You can call Import safely from multiple goroutines, provided that setting *fp is race-free.

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	Import("format-time-string", &formatTimeString)
	Export(goPrintNow)

	// Import panics when encountering nonconvertible types.
	defer func() { fmt.Println("panic:", recover()) }()
	Import("format-time-string", &invalidType)
}

var (
	formatTimeString func(Env, string, time.Time, bool) (string, error)

	// Can’t convert channel types to Emacs.
	invalidType func(Env, chan int) error
)

func goPrintNow(e Env, format string) (string, error) {
	// Functions that have access to a live environment can now call the
	// Emacs message function, like so:
	r, err := formatTimeString(e, format, time.Now(), true)
	if err != nil {
		return "", err
	}
	_, err = fmt.Println("Time from Emacs:", r)
	return r, err
}

func init() {
	// We would normally call ExampleExport here, but the test runner
	// already calls it for us.
}
Output:

panic: can’t import format-time-string: don’t know how to convert argument 1: Wrong type argument: go-known-type-p, "chan int"

func MajorVersion

func MajorVersion() int

MajorVersion returns the major version of the Emacs instance in which the module is loaded. It can only be called after the module has been loaded. Module functions and functions registered by OnInit can call MajorVersion if they have been called from Emacs. MajorVersion panics if the module isn’t yet initialized.

func NotifyListener

func NotifyListener(listener net.Listener) chan<- struct{}

NotifyListener returns a channel that causes some arbitrary content to be sent to the client of the given listener whenever something is written to the channel. NotifyListener will wait (in the background) for exactly one client to connect to the server and then close the listener. You can create the listener using net.Listen or similar. A common use case is a Unix domain socket server; the socket name should be reported to Emacs Lisp using other means. The return value of this function is useful as argument to NewAsync.

func NotifyWriter

func NotifyWriter(w io.Writer) chan<- struct{}

NotifyWriter returns a channel that causes some arbitrary content to be written to the given writer whenever something is written to the channel. The writer will typically be either a pipe created by Env.OpenPipe or a socket connection to a Unix domain socket created by net.Dial or similar. The return value of this function is useful as argument to NewAsync.

func OnInit

func OnInit(i InitFunc)

OnInit arranges for the given function to run while Emacs is loading the module. Initialization functions registered with OnInit will be called in sequence, in the same order in which they’ve been registered. You need to call OnInit before loading the module for the initializer to run. Typically, you should call OnInit in an init function. You can call OnInit safely from multiple goroutines.

Example
package main

import "fmt"

func main() {
	OnInit(func(e Env) error {
		_, err := fmt.Println("Hi from Go!")
		return err
	})
}

func init() {
	ExampleOnInit()
}
Output:

func OverflowError

func OverflowError(val string) error

OverflowError returns an error that will cause Emacs to signal an error of type overflow‑error. Use this if you notice that an integer doesn’t fit into its target type. val is the string representation of the overflowing value. val is a string instead of an In to avoid further overflows when converting it to an Emacs value.

func Provide

func Provide(feature Name)

Provide arranges for (provide feature) to be called on module initialization.

func WrongTypeArgument

func WrongTypeArgument(pred Symbol, arg In) error

WrongTypeArgument returns an error that will cause Emacs to signal an error of type wrong‑type‑argument. Use this if some argument has an unexpected type. pred should be a predicate-like symbol such as natnump. arg is the argument whose type is invalid.

Types

type Anonymous

type Anonymous struct{}

Anonymous is an Option that tells AutoFunc and friends that the new function should be anonymous. Anonymous is mutually exclusive with Name; if both are given, AutoFunc panics.

type Arity

type Arity struct{ Min, Max int }

Arity contains how many arguments an Emacs function accepts. Min must be nonnegative. Max must either be negative (indicating a variadic function) or at least Min.

func (Arity) Variadic

func (a Arity) Variadic() bool

Variadic returns whether the function is variadic, i.e., whether a.Max is negative.

type Async

type Async struct {
	// contains filtered or unexported fields
}

Async manages asynchronous operations. Create a new Async object using NewAsync; the zero Async isn’t valid, and Async objects may not be copied once created. An asynchronous operation can use Async.Start to allocate an operation handle and a channel. It can then start an operation in the background and report its result asynchronously using the channel.

Async requires a way to notify Emacs about pending asynchronous results; use NotifyWriter or NotifyListener to create notification channels. When notified about asynchronous operations, Emacs should then use Async.Flush to return the pending results.

Async doesn’t prescribe any specific programming model on the Emacs side; the example uses the “aio” package.

Example
package main

import (
	"errors"
	"log"
	"net"
	"os"
	"path/filepath"
	"sync"
)

func main() {
	Export(mersennePrimeAsyncP, Doc("Return a promise that resolves to a Boolean value indicating whether 2^N − 1 is probably prime."), Usage("N"))
	Export(asyncSocket, Doc("Return a filename of a socket to connect to"))
	Export(asyncFlush, Doc("Return a vector of asynchronous promise results"))
}

func mersennePrimeAsyncP(n uint16) AsyncHandle {
	h, ch := async.Start()
	boolCh := make(chan bool)
	go testMersennePrime(n, boolCh)
	go wrapBool(ch, boolCh)
	return h
}

func wrapBool(ch chan<- Result, boolCh <-chan bool) {
	ch <- Result{Bool(<-boolCh), nil}
}

var (
	asyncOnce sync.Once
	async     *Async
	socket    string
)

func asyncSocket() (string, error) {
	asyncOnce.Do(initAsync)
	if socket == "" {
		return "", errors.New("error initializing asynchronous socket")
	}
	return socket, nil
}

func asyncFlush() []AsyncData {
	return async.Flush()
}

func initAsync() {
	dir, err := os.MkdirTemp("", "emacs-")
	if err != nil {
		panic(err)
	}
	sock := filepath.Join(dir, "socket")
	listener, err := net.Listen("unix", sock)
	if err != nil {
		panic(err)
	}
	log.Printf("Created socket %s for asynchronous communication", sock)
	async = NewAsync(NotifyListener(listener))
	socket = sock
}

func init() {
	ExampleAsync()
}
Output:

func NewAsync

func NewAsync(notifyCh chan<- struct{}) *Async

NewAsync creates a new Async object. It will use the given notification channel to signal completion of an asynchronous operation to Emacs; use NotifyWriter or NotifyListener to create usable channels.

func (*Async) Flush

func (a *Async) Flush() []AsyncData

Flush returns and removes all pending asynchronous operation results. You should call this method from Emacs Lisp when notified about pending asynchronous results.

func (*Async) Start

func (a *Async) Start() (AsyncHandle, chan<- Result)

Start starts a new asynchronous operation. It returns a handle for the operation and a channel. Return the operation handle to Emacs so that it can associate pending operations with e.g. a promise structure. The operation can then use the channel to write exactly one result (error or value); any further writes or closes are ignored and will block. The typical usage pattern is:

func operation() AsyncHandle {
    h, ch := async.Start()
    go performOperation(ch)
    return h
}

Here, performOperation should write the result to the channel once available.

type AsyncData

type AsyncData struct {
	Handle AsyncHandle
	Result
}

AsyncData contains the result of an asynchronous operation, together with the associated operation handle. It is returned by Async.Flush.

func (AsyncData) Emacs

func (d AsyncData) Emacs(e Env) (Value, error)

Emacs implements [In.Emacs]. It returns a triple (handle value error). If Err is set, the error element will be of the form (symbol . data).

type AsyncHandle

type AsyncHandle uint64

AsyncHandle is an opaque reference to a pending asynchronous operation. Use Async.Start to create AsyncHandle objects.

func (AsyncHandle) Emacs

func (h AsyncHandle) Emacs(e Env) (Value, error)

Emacs implements In.Emacs. It returns the handle as an integer.

type BigInt

type BigInt big.Int

BigInt is a type with underlying type big.Int that knows how to convert itself to and from an Emacs value.

func (*BigInt) Emacs

func (i *BigInt) Emacs(e Env) (Value, error)

Emacs creates an Emacs value representing the given integer. It returns an error if the integer value is too big for Emacs.

func (*BigInt) FromEmacs

func (i *BigInt) FromEmacs(e Env, v Value) error

FromEmacs sets *i to the integer stored in v. It returns an error if v is not an integer.

func (*BigInt) String

func (i *BigInt) String() string

String formats the big integer as a string. It calls big.Int.String.

type Binding

type Binding struct {
	Variable Name
	Value    In
}

Binding describes a variable binding for [LetMany].

type Bool

type Bool bool

Bool is a type with underlying type bool that knows how to convert itself to and from an Emacs value.

func (Bool) Emacs

func (b Bool) Emacs(e Env) (Value, error)

Emacs returns t if v is true and nil if it’s false. It can only fail if interning nil or t fails.

func (*Bool) FromEmacs

func (b *Bool) FromEmacs(e Env, v Value) error

FromEmacs sets *b to false if v is nil and to true otherwise. It never fails.

func (Bool) Symbol

func (b Bool) Symbol() Symbol

Symbol returns Nil or T depending on the value of b.

type Bytes

type Bytes []byte

Bytes is a type with underlying type []byte that knows how to convert itself to an Emacs unibyte string.

func (Bytes) Emacs

func (b Bytes) Emacs(e Env) (Value, error)

Emacs creates an Emacs unibyte string value representing the given bytes. It always makes a copy of the byte slice.

func (*Bytes) FromEmacs

func (b *Bytes) FromEmacs(e Env, v Value) error

FromEmacs sets *b to the unibyte string stored in v. It returns an error if v is not a unibyte string.

type Car

type Car struct{ List In }

Car is an In that represents the car of List.

func (Car) Emacs

func (c Car) Emacs(e Env) (Value, error)

Emacs returns the car of c.List. It returns an error if c.List is not a list.

type Cdr

type Cdr struct{ List In }

Cdr is an In that represents the cdr of List.

func (Cdr) Emacs

func (c Cdr) Emacs(e Env) (Value, error)

Emacs returns the cdr of c.List. It returns an error if c.List is not a list.

type Cons

type Cons struct{ Car, Cdr In }

Cons represents a cons cell.

func (Cons) Emacs

func (c Cons) Emacs(e Env) (Value, error)

Emacs creates and returns a new cons cell.

type CustomHasher

type CustomHasher interface {
	// Hash returns a hash code for the given value.
	Hash(Env, Value) (int64, error)

	// Equal returns whether the given values are considered equal
	// according to this hash test.
	Equal(Env, Value, Value) (bool, error)
}

CustomHasher defines the hashing and equality functions for a custom hash test. Use RegisterHashTest to register such a custom hash test. The hashing and equality functions must be compatible, i. e., if Equal(e, a, b) is true, then Hash(e, a) = Hash(e, b) must be fulfilled.

type DeleteFunc

type DeleteFunc func()

DeleteFunc is a function returned by Env.Lambda and Env.LambdaFunc. Call this function to delete the created function. After deletion the function can’t be called any more from Emacs.

type Doc

type Doc string

Doc contains a documentation string for a function or variable. An empty doc string becomes nil. As described in Documentation Strings of Functions, a documentation string can contain usage information. Use Doc.SplitUsage to extract the usage information from a documentation string. Use Doc.WithUsage to add usage information to a documentation string. Documentation strings must be valid UTF-8 strings without embedded null bytes. You can use a Doc as an Option in Export and ERTTest to set the function or test documentation string.

func (Doc) Emacs

func (d Doc) Emacs(e Env) (Value, error)

Emacs returns nil if d is empty and an Emacs string otherwise.

func (Doc) SplitUsage

func (d Doc) SplitUsage() (actualDoc Doc, hasUsage bool, usage Usage)

SplitUsage splits d into the actual docstring and the usage information. hasUsage specifies whether a usage information is present. Absence of usage information is not the same as an empty usage.

func (Doc) WithUsage

func (d Doc) WithUsage(u Usage) Doc

WithUsage returns d with the usage string appended. If d already contains usage information, WithUsage replaces it.

type Duration

type Duration time.Duration

Duration is a type with underlying type time.Duration that knows how to convert itself from and to an Emacs time value.

func (Duration) Emacs

func (d Duration) Emacs(e Env) (Value, error)

Emacs returns an Emacs timestamp as a pair (ticks . hz) or a quadruple (high low μs ps) in the same format as the Emacs function current-time.

func (*Duration) FromEmacs

func (d *Duration) FromEmacs(e Env, v Value) error

FromEmacs sets *d to the Go equivalent of the Emacs time value in v, interpreted as a duration. v can be any time value: nil (for the current time), a number of seconds, a pair (ticks . hz), a pair (high low), a triple (high low μs), or a quadruple (high low μs ps). The picosecond value is truncated to nanosecond precision. If the Emacs time value would overflow a Go duration, FromEmacs returns an error.

func (Duration) String

func (d Duration) String() string

String formats the duration as a string. It calls time.Duration.String.

type ERTTestFunc

type ERTTestFunc func(Env) error

ERTTestFunc is a function that implements an ERT test. Use ERTTest to register ERTTestFunc functions. If the function returns an error, the ERT test fails.

type Env

type Env struct {
	// contains filtered or unexported fields
}

Env represents an Emacs module environment. The zero Env is not valid. Exported functions and module initializers will receive a valid Env value. That Env value only remains valid (or “live”) while the exported function or module initializer is active. Env values are only valid in the same goroutine as the exported function or module initializer. So don’t store them or pass them to other goroutines. See https://www.gnu.org/software/emacs/manual/html_node/elisp/Module-Functions.html for details.

func (Env) BigInt

func (e Env) BigInt(v Value, z *big.Int) error

BigInt sets z to the integer stored in v. It returns an error if v is not an integer.

func (Env) Bytes

func (e Env) Bytes(v Value) ([]byte, error)

Bytes returns the unibyte string stored in v. It returns an error if v is not a unibyte string.

func (Env) Call

func (e Env) Call(fun Name, in ...In) (Value, error)

Call calls the Emacs named fun with the given arguments.

Example
// Assumes that env is a valid Env value.
_, err := env.Call("message", String("It is %s"), Time(time.Now()))
if err != nil {
	panic(err)
}
Output:

func (Env) CallOut

func (e Env) CallOut(fun Name, out Out, in ...In) error

CallOut calls a the Emacs function named fun with the given arguments and assigns the result to out.

Example
// Assumes that env is a valid Env value.
var now Time
err := env.CallOut("current-time", &now)
if err != nil {
	panic(err)
}
Output:

func (Env) Car

func (e Env) Car(list In) (Value, error)

Car returns the car of list. It returns an error if list is not a list.

func (Env) CarOut

func (e Env) CarOut(list In, car Out) error

CarOut sets car to the car of list. It returns an error if list is not a list.

func (Env) Cdr

func (e Env) Cdr(list In) (Value, error)

Cdr returns the cdr of list. It returns an error if list is not a list.

func (Env) CdrOut

func (e Env) CdrOut(list In, cdr Out) error

CdrOut sets cdr to the cdr of list. It returns an error if list is not a list.

func (Env) Cons

func (e Env) Cons(car, cdr In) (Value, error)

Cons creates and returns a cons cell (car . cdr).

func (Env) Defalias

func (e Env) Defalias(name Name, def Value) error

Defalias calls the Emacs function defalias.

func (Env) DefineError

func (e Env) DefineError(name Name, message string, parents ...ErrorSymbol) (ErrorSymbol, error)

DefineError is like the global DefineError function, except that it requires a live environment, defines the error symbol immediately, and returns errors instead of panicking.

func (Env) Defvar

func (e Env) Defvar(name Name, init In, doc Doc) error

Defvar calls the Emacs special form defvar.

func (Env) Dolist

func (e Env) Dolist(list Value, f func(Value) error) error

Dolist calls f for each element in list. It returns an error if list is not a list. If f returns an error, the loop terminates and Dolist returns the same error. If list is a circular list, Dolist may loop forever.

Example
// Assumes that env is a valid Env value.
var sum int64
if err := env.Dolist(list, func(x Value) error {
	i, err := env.Int(x)
	if err != nil {
		return err
	}
	sum += i
	return nil
}); err != nil {
	panic(err)
}
fmt.Printf("sum is %d\n", sum)
Output:

func (Env) Duration

func (e Env) Duration(v Value) (time.Duration, error)

Duration returns the Go equivalent of the Emacs time value in v, interpreted as a duration. v can be any time value: nil (for the current time), a number of seconds, a pair (ticks . hz) a pair (high low), a triple (high low μs), or a quadruple (high low μs ps). The picosecond value is truncated to nanosecond precision. If the Emacs time value would overflow a Go duration, Duration returns an error.

func (Env) ERTDeftest

func (e Env) ERTDeftest(name Name, fun Func, doc Doc) error

ERTDeftest defines an ERT test with the given name and documentation string. The test calls the Go function fun. It succeeds if fun returns nil. This is the Go equivalent of the ert-deftest macro.

func (Env) ERTTest

func (e Env) ERTTest(fun ERTTestFunc, opts ...Option) error

ERTTest exports a Go function as an ERT test. Unlike the global ERTTest function, Env.ERTTest requires a live environment and defines the ERT test immediately. If the function returns an error, the ERT test fails.

By default, ERTTest derives the test’s name from the function’s Go name by Lisp-casing it. For example, MyTest becomes my-test. To specify a different name, pass a Name option. If there’s no name or the name is already registered, ERTTest panics.

By default, the ERT test has no documentation string. To add one, pass a Doc option.

func (Env) Emacs

func (e Env) Emacs(v interface{}) (Value, error)

Emacs converts v to an Emacs value and returns the value. See NewIn for details of the conversion process.

func (Env) Eq

func (e Env) Eq(a, b Value) bool

Eq returns true if and only if the two values represent the same Emacs object.

func (Env) Eval

func (e Env) Eval(form In) (Value, error)

Eval evaluates form using the Emacs function eval. The binding is always lexical.

func (Env) Export

func (e Env) Export(fun interface{}, opts ...Option) (Value, error)

Export exports a Go function to Emacs. Unlike the global Export function, Env.Export requires a live environment and defines the Emacs function immediately. The function fun can be any Go function. When calling the exported function from Emacs, arguments and return values are converted as described in the package documentation. If you don’t want this autoconversion or need more control, use Env.ExportFunc instead and convert arguments yourself.

The function may accept any number of arguments. Optionally, the first argument may be of type Env. In this case, Emacs passes a live environment value that you can use to interact with Emacs. All other arguments are converted from Emacs as described in the package documentation. If not all arguments are convertible from Emacs values, Export panics.

The function must return either zero, one, or two results. If the last or only result is of type error, a non-nil value causes Emacs to trigger a non-local exit as appropriate. There may be at most one non-error result. Its value will be converted to an Emacs value as described in the package documentation. If the type of the non-error result can’t be converted to an Emacs value, Export panics. If there are invalid result patterns, Export panics.

By default, Export derives the function’s name from its Go name by Lisp-casing it. For example, MyFunc becomes my-func. To specify a different name, pass a Name option. To make the function anonymous, pass an Anonymous option. If there’s no name and the function isn’t anonymous, Export panics. If the name of a non-anonymous function is already registered, Export panics.

By default, the function has no documentation string. To add one, pass a Doc option.

func (Env) ExportFunc

func (e Env) ExportFunc(name Name, fun Func, arity Arity, doc Doc) (Value, error)

ExportFunc exports a Go function to Emacs. Unlike the global ExportFunc function, Env.ExportFunc requires a live environment and defines the Emacs function immediately. Unlike Env.Export, functions defined by ExportFunc don’t automatically convert their arguments and return values to and from Emacs. ExportFunc returns the Emacs function object of the new function. If name is empty, the function is anonymous. If name is not empty, it is bound to the new function. If doc is empty, the function won’t have a documentation string.

func (Env) Float

func (e Env) Float(v Value) (float64, error)

Float returns the floating-point number stored in v. It returns an error if v is not a floating-point value.

func (Env) FormatMessage

func (e Env) FormatMessage(format string, args ...In) string

FormatMessage calls the Emacs function format-message with the given format string and arguments. If the call to format-message fails, FormatMessage returns a descriptive error string. Note that the syntax of the format string for FormatMessage is similar but not identical to the format strings for the fmt.Printf family.

func (Env) Funcall

func (e Env) Funcall(fun Value, args []Value) (Value, error)

Funcall calls the Emacs function fun with the given arguments. Both function and arguments must be Emacs values. Use Env.Call or Env.Invoke if you want them to be autoconverted.

func (Env) Gethash

func (e Env) Gethash(key In, table Value) (value Value, ok bool, err error)

Gethash returns the hash table value with the given key. ok specifies whether the key is present.

func (Env) GethashDef

func (e Env) GethashDef(key In, table Value, def Value) (Value, error)

GethashDef returns the hash table value with the given key. If the key is not present, it returns def.

func (Env) Go

func (e Env) Go(v Value, p interface{}) error

Go converts v to a Go value and stores it in p. See NewOut for details of the conversion process.

func (Env) Int

func (e Env) Int(v Value) (int64, error)

Int returns the integer stored in v. It returns an error if v is not an integer, or if it doesn’t fit into an int64.

func (Env) Intern

func (e Env) Intern(s Symbol) (Value, error)

Intern interns the given symbol name in the default obarray and returns the symbol object.

func (Env) Invoke

func (e Env) Invoke(fun interface{}, out interface{}, in ...interface{}) error

Invoke calls a named Emacs function or function value. fun may be a string, Symbol, Name, or Value. If it’s not a value, Invoke interns it first. Invoke then calls the Emacs functions with the given arguments and assigns the result to out. It converts arguments and the return value as described in the package documentation.

Example
// Assumes that env is a valid Env value.
var now time.Time
err := env.Invoke("current-time", &now)
if err != nil {
	panic(err)
}
Output:

func (Env) IsNil

func (e Env) IsNil(v Value) bool

IsNil returns true if and only if the given Emacs value is nil.

func (Env) IsNotNil

func (e Env) IsNotNil(v Value) bool

IsNotNil returns false if and only if the given Emacs value is nil.

func (Env) IsOverflowError

func (e Env) IsOverflowError(err error) bool

IsOverflowError returns whether err is an Emacs signal of type overflow-error. This function detects both Error and Signal.

func (Env) IsWrongTypeArgument

func (e Env) IsWrongTypeArgument(err error) bool

IsWrongTypeArgument returns whether err is an Emacs signal of type wrong-type-argument. This function detects both Error and Signal.

func (Env) Iter

func (e Env) Iter(list Value, elem Out, err *error) *Iter

Iter creates an Iter value that iterates over list. Iter.Next will set elem to the elements of the list, and *err to any error. Iter assumes that list is a true list. If list is circular, the iteration may never terminate.

Typical use, with *T implementing the Out interface:

var elem T
var err error
for i := env.Iter(list, &elem, &err); i.Ok(); i.Next() {
	// …
}
if err != nil {
	return err
}

See [Dolist] for a simpler iteration method.

func (Env) Lambda

func (e Env) Lambda(fun interface{}, opts ...Option) (Value, DeleteFunc, error)

Lambda exports the given function to Emacs as an anonymous lambda function. Unlike the global AutoLambda function, Env.Lambda requires a live environment and defines the Emacs function immediately. When calling the exported function from Emacs, arguments and return values are converted as described in the package documentation and the documentation for the AutoLambda function.

When you don’t need the function any more, unregister it by calling the returned DeleteFunc function (typically using defer). If you don’t call the delete function, the function will remain registered and require a bit of memory. After calling the delete function, calling the function from Emacs panics.

The function is always anonymous. Any Name option in opts is ignored.

By default, the function has no documentation string. To add one, pass a Doc option.

You can call Lambda safely from multiple goroutines.

func (Env) LambdaFunc

func (e Env) LambdaFunc(fun Func, arity Arity, doc Doc) (Value, DeleteFunc, error)

[LambdaFunc] exports the given function to Emacs as an anonymous lambda function. Unlike the global AutoLambda function, Env.LambdaFunc requires a live environment and defines the Emacs function immediately. Unlike Env.Lambda, functions registered by LambdaFunc don’t automatically convert their arguments and return values to and from Emacs.

When you don’t need the function any more, unregister it by calling the returned DeleteFunc function (typically using defer). If you don’t call the delete function, the function will remain registered and require a bit of memory. After calling the delete function, calling the function from Emacs panics.

You can call LambdaFunc safely from multiple goroutines.

func (Env) Length

func (e Env) Length(seq Value) (int, error)

Length returns the length of the sequence represented by seq. It returns an error if seq is not a sequence. Just like the Emacs length function, it may loop forever if seq is a circular object.

func (Env) Let

func (e Env) Let(variable Name, value In, body func() (Value, error)) (Value, error)

Let locally binds the variable to the value within body. This is like the Emacs Lisp let special form. Let returns the value and error returned by body, unless some other error occurs.

func (Env) LetMany

func (e Env) LetMany(bindings []Binding, body func() (Value, error)) (Value, error)

LetMany locally binds the given variables value within body. This is like the Emacs Lisp let special form. LetMany returns the value and error returned by body, unless some other error occurs.

func (Env) List

func (e Env) List(os ...In) (Value, error)

List creates and returns a new Emacs list containing the given values.

func (Env) MakeHash

func (e Env) MakeHash(test HashTest, sizeHint int) (Value, error)

MakeHash returns a new hash table with the given test and size hint.

func (Env) MakeInteractive

func (e Env) MakeInteractive(fun, spec Value) error

MakeInteractive sets the interactive specification of the given function. The function must refer to a module function.

func (Env) MakeVector

func (e Env) MakeVector(n int, init In) (Value, error)

MakeVector creates and returns an Emacs vector of size n. It initializes all elements to init.

func (Env) Maphash

func (e Env) Maphash(fun func(key, val Value) error, table Value) error

Maphash calls fun for each key–value pair in table. The order is arbitrary. If table is modified during iteration, the results are unpredictable.

func (Env) MaybeIntern

func (e Env) MaybeIntern(nameOrValue interface{}) (Value, error)

MaybeIntern returns nameOrValue as-is if it’s a Value and calls Env.Intern if it’s a Symbol, Name, or string. Otherwise it returns an error.

func (Env) Message

func (e Env) Message(err error) string

Message returns an error message for err. If err is an Emacs error, it uses error-message-string to obtain the Emacs error message. Otherwise, it returns err.Error().

func (Env) Nil

func (e Env) Nil() (Value, error)

Nil returns the interned symbol nil. It fails only if interning nil fails.

func (Env) OpenPipe

func (e Env) OpenPipe(process Value) (*os.File, error)

OpenPipe opens a writable pipe to the given Emacs pipe process. The pipe process must have been created with make-pipe-process. You can write to the returned pipe to provide input to the pipe process.

func (Env) ProcessInput

func (e Env) ProcessInput() error

ProcessInput processes pending input and returns whether the user has requested a quit. If ProcessInput returns an error, the caller should return the error to Emacs as soon as possible to allow Emacs to process the quit. Once Emacs regains control, it will quit and ignore the return value. Note that processing input can run arbitrary Lisp code, so don’t rely on global state staying the same after calling ProcessInput.

Example
package main

import (
	"log"
	"math/big"
	"time"
)

func main() {
	Export(mersennePrimeP, Doc("Return whether 2^N − 1 is probably prime."), Usage("N"))
}

func mersennePrimeP(e Env, n uint16) (bool, error) {
	tick := time.NewTicker(100 * time.Millisecond)
	defer tick.Stop()
	// Start long-running operation in another goroutine.  Note that we
	// don’t pass any Env or Value values to the goroutine.
	ch := make(chan bool)
	go testMersennePrime(n, ch)
	// Wait for either the operation to finish or the user to quit.
	for {
		select {
		case r := <-ch:
			return r, nil
		case <-tick.C:
			if err := e.ProcessInput(); err != nil {
				log.Print("quitting")
				return false, err // Emacs will ignore the return value
			}
		}
	}
}

func testMersennePrime(n uint16, ch chan<- bool) {
	x := big.NewInt(1)
	x.Lsh(x, uint(n))
	x.Sub(x, one)
	ch <- x.ProbablyPrime(10)
	log.Print("testMersennePrime finished")
}

var one = big.NewInt(1)

func init() {
	ExampleEnv_ProcessInput()
}
Output:

func (Env) Puthash

func (e Env) Puthash(key, value In, table Value) error

Puthash sets the value of key in table to value.

func (Env) ShouldQuit deprecated

func (e Env) ShouldQuit() bool

ShouldQuit returns whether the user has requested a quit. If ShouldQuit returns true, the caller should return to Emacs as soon as possible to allow Emacs to process the quit. Once Emacs regains control, it will quit and ignore the return value.

Deprecated: Use Env.ProcessInput instead.

func (Env) Str

func (e Env) Str(v Value) (string, error)

Str returns the string stored in v. It returns an error if v is not a string, or if it’s not a valid Unicode scalar value sequence. Str is not named String to avoid confusion with the fmt.Stringer.String method.

func (Env) Symbol

func (e Env) Symbol(v Value) (Symbol, error)

Symbol returns the name of the Emacs symbol v. It returns an error if v is not a symbol.

func (Env) Time

func (e Env) Time(v Value) (time.Time, error)

Time returns the Go equivalent of the Emacs time value in v. v can be any time value: nil (for the current time), a number of seconds since the epoch, a pair (ticks . hz), a pair (high low), a triple (high low μs), or a quadruple (high low μs ps). The picosecond value is truncated to nanosecond precision. If the Emacs time value would overflow a Go time, Time returns an error.

func (Env) Uint

func (e Env) Uint(v Value) (uint64, error)

Uint returns the integer stored in v. It returns an error if v is not an integer, or if it doesn’t fit into an uint64.

func (Env) Uncons

func (e Env) Uncons(cons Value) (car Value, cdr Value, err error)

Uncons returns the car and cdr of cons. It returns an error if cons is not a cons cell.

func (Env) UnconsOut

func (e Env) UnconsOut(cons Value, car, cdr Out) error

UnconsOut sets car and cdr to the car and cdr of cons. It returns an error if cons is not a cons cell. If UnconsOut fails, it is unspecified whether car and cdr have been modified.

func (Env) Var

func (e Env) Var(name Name, init In, doc Doc) error

Var is like the global Var function, except that it requires a live environment, defines the variable immediately, and returns errors instead of panicking.

func (Env) VecGet

func (e Env) VecGet(vector Value, i int) (Value, error)

VecGet returns the i-th element of vector. It returns an error if vector is not a vector.

func (Env) VecGetOut

func (e Env) VecGetOut(vector Value, i int, elem Out) error

VecGetOut sets elem to the value of the i-th element of vector. It returns an error if vector is not a vector.

func (Env) VecSet

func (e Env) VecSet(v Value, i int, elem Value) error

VecSet sets the i-th element of the given Emacs vector.

func (Env) VecSetIn

func (e Env) VecSetIn(v Value, i int, elem In) error

VecSetIn sets the i-th element of the given Emacs vector.

func (Env) VecSize

func (e Env) VecSize(v Value) (int, error)

VecSize returns the size of the given Emacs vector.

type Error

type Error struct {
	// The error symbol.
	Symbol ErrorSymbol

	// The unevaluated error data.
	Data List
}

Error is an error that causes to signal an error with the given symbol and data. Signaling an error will evaluate symbol and data lazily. The evaluation is best-effort since it can itself fail. If it fails the symbol and/or data might be lost, but Emacs will signal some error in any case. If you already have an evaluated symbol and data value, use Signal instead. ErrorSymbol.Error is a convenience factory function for Error values.

Example
package main

import "fmt"

func main() {
	Export(goError, Doc("Signal an error of type ‘example-error’.").WithUsage("int float vec"))

	err := exampleError.Error(Int(123), Vector{String("foo"), Float(0.7), T})
	fmt.Println(err)
}

func goError(f float32, v []uint16) (uint8, error) {
	return 55, exampleError.Error(Float(f), NewIn(v))
}

var exampleError = DefineError("example-error", "Example error")
Output:

Example error: 123, ["foo" 0.7 t]

func (Error) Error

func (x Error) Error() string

Error implements the error interface. It does a best-effort attempt to mimic the Emacs error‑message‑string function.

type ErrorSymbol

type ErrorSymbol struct {
	// contains filtered or unexported fields
}

ErrorSymbol represents an error symbol. Use DefineError to create ErrorSymbol values. The zero ErrorSymbol is not a valid error symbol.

func DefineError

func DefineError(name Name, message string, parents ...ErrorSymbol) ErrorSymbol

DefineError arranges for an error symbol to be defined using the Emacs function define‑error. Call it from an init function (i.e., before loading the dynamic module into Emacs) to define additional error symbols for your module. DefineError panics if name or message is empty, or if name is duplicate.

func (ErrorSymbol) Emacs

func (s ErrorSymbol) Emacs(e Env) (Value, error)

Emacs interns the error symbol in the default obarray and returns the symbol value.

func (ErrorSymbol) Error

func (s ErrorSymbol) Error(data ...In) error

Error returns an error that causes to signal an error with the given symbol and data. The return value is of type Error. Signaling an error will evaluate symbol and data lazily. The evaluation is best-effort since it can itself fail. If it fails the symbol and/or data might be lost, but Emacs will signal some error in any case. If you already have an evaluated symbol and data value, use Signal instead.

func (ErrorSymbol) String

func (s ErrorSymbol) String() string

String returns the message of the error symbol.

type Float

type Float float64

Float is a type with underlying type float64 that knows how to convert itself into an Emacs value.

func (Float) Emacs

func (f Float) Emacs(e Env) (Value, error)

Emacs creates an Emacs value representing the given floating-point number.

func (*Float) FromEmacs

func (f *Float) FromEmacs(e Env, v Value) error

FromEmacs sets *f to the floating-point number stored in v. It returns an error if v is not a floating-point value.

type Func

type Func func(Env, []Value) (Value, error)

Func is a Go function exported to Emacs. It has access to a live environment, takes arguments as a slice, and can return a value or an error.

func ImportFunc

func ImportFunc(name Name) Func

ImportFunc imports an Emacs function as a Go function. name must be the Emacs symbol name of the function. ImportFunc returns a new Func that calls the Emacs function name. Unlike Import, there is no type autoconversion.

ImportFunc must be called before Emacs loads the module. Typically you should initialize a global variable with the return value of ImportFunc.

You can call ImportFunc safely from multiple goroutines.

type Hash

type Hash struct {
	Test HashTest
	Data map[In]In
}

Hash represents the data for an Emacs hash table.

func (Hash) Emacs

func (h Hash) Emacs(e Env) (Value, error)

Emacs creates a new hash table using the test and data in h.

type HashOut

type HashOut struct {
	// New must return a new key and value each time it’s called.
	New func() (Out, Out)

	// FromEmacs fills Data with the pairs from the hash table.
	Data map[Out]Out
}

HashOut is an Out that converts an Emacs hash table to the map Data. The concrete key and value types are determined by the return values of the [HashOut.New] function.

func (*HashOut) FromEmacs

func (h *HashOut) FromEmacs(e Env, v Value) error

FromEmacs sets h.Data to a new map containing the same key–value pairs as the Emacs hash table in v. It returns an error if v is not a hash table. FromEmacs calls h.New for each key–value pair in v. h.New must return a new pair of Out values for the pair’s key and value. If FromEmacs returns an error, h.Data is not modified.

FromEmacs ignores the Emacs hash table test for v. This means that there may be multiple Emacs keys mapping to a single Go key if the hash functions aren’t consistent. For example, an Emacs hash table with string keys and hash test eq may contain two keys that are equal when converted to Go strings. In such a case, FromEmacs returns an error.

type HashTest

type HashTest Symbol

HashTest represents a test function for an Emacs hash table.

const (
	Eq    HashTest = "eq"
	Eql   HashTest = "eql"
	Equal HashTest = "equal"
)

Predefined hash table tests. To define your own test, use RegisterHashTest.

func HashTestFor

func HashTestFor(t reflect.Type) HashTest

HashTestFor returns a hash table test that is appropriate for the given type. It returns Eq for integral types, Eql for floating-point types, and Equal otherwise. HashTestFor ignores custom hash tests registered with RegisterHashTest.

func RegisterHashTest

func RegisterHashTest(name HashTest, hash CustomHasher) HashTest

RegisterHashTest registers a new custom hash table test. The name must be a unique nonempty name for the test, and hash must define the hash function and equality predicate. RegisterHashTest returns name.

func (HashTest) Emacs

func (t HashTest) Emacs(e Env) (Value, error)

Emacs interns the hash test symbol in the default obarray and returns the symbol object.

func (HashTest) String

func (t HashTest) String() string

String returns the hash test symbol name.

type Ignore

type Ignore struct{}

Ignore is an Out that does nothing.

func (Ignore) FromEmacs

func (Ignore) FromEmacs(Env, Value) error

FromEmacs does nothing.

type In

type In interface {
	// Emacs returns an Emacs object corresponding to the receiver, or an
	// error if the conversion fails.  Implementations should document
	// whether it always returns a new object or not.  They should also
	// document potential side effects.
	Emacs(Env) (Value, error)
}

In is a value that knows how to convert itself into an Emacs object. You can implement In for your own types if you want this package to convert them to Emacs values automatically. This package also defines a few wrapper implementations for primitive types such as In or String.

func NewIn

func NewIn(v interface{}) In

NewIn returns an In value that converts the dynamic type of v to an Emacs value. If v already implements In, NewIn returns it directly. Otherwise, if the dynamic type of v is known, NewIn returns one of the predefined In implementations (Int, Float, String, Reflect, …). Otherwise, NewIn returns an In instance that uses reflection to convert itself to Emacs.

type InFunc

type InFunc func(reflect.Value) In

InFunc is a function that returns an In for the given value.

func InFuncFor

func InFuncFor(t reflect.Type) (InFunc, error)

InFuncFor returns an InFunc for the given type. If there’s no known conversion from t to Emacs, InFuncFor returns an error.

type InitFunc

type InitFunc func(Env) error

InitFunc is an initializer function that should be run during module initialization. Use OnInit to register InitFunc functions. If an initialization function returns an error, the module loading itself will fail.

type Int

type Int int64

Int is a type with underlying type int64 that knows how to convert itself into an Emacs value.

func (Int) Emacs

func (i Int) Emacs(e Env) (Value, error)

Emacs creates an Emacs value representing the given integer. It returns an error if the integer value is too big for Emacs.

func (*Int) FromEmacs

func (i *Int) FromEmacs(e Env, v Value) error

FromEmacs sets *i to the integer stored in v. It returns an error if v is not an integer, or if doesn’t fit into an int64.

type Iter

type Iter struct {
	// contains filtered or unexported fields
}

Iter is an iterator over a list. Use Env.Iter to create Iter values. The zero Iter is not a valid iterator. Iter values can’t outlive the environment that created them. Don’t pass Iter values to other goroutines.

Typical use, with *T implementing the Out interface:

var elem T
var err error
for i := env.Iter(list, &elem, &err); i.Ok(); i.Next() {
	// …
}
if err != nil {
	return err
}
Example
// Assumes that env is a valid Env value.
sum := 0
var elem Int
var err error
for i := env.Iter(list, &elem, &err); i.Ok(); i.Next() {
	sum += int(elem)
}
if err != nil {
	panic(err)
}
fmt.Printf("sum is %d\n", sum)
Output:

func (*Iter) Next

func (i *Iter) Next()

Next sets the elem passed to Env.Iter to the next element in the list. If Next fails, it sets the error passed to Env.Iter, and Iter.Ok will return false.

func (*Iter) Ok

func (i *Iter) Ok() bool

Ok returns whether the iterator is still valid. It is valid if no error is set and there are still elements left in the list.

type Lambda

type Lambda struct {
	Fun   Func
	Arity Arity
	Doc   Doc
}

Lambda represents an anonymous function. When converting to Emacs, it exports Fun as an Emacs lambda function.

func AutoLambda

func AutoLambda(f interface{}, opts ...Option) Lambda

AutoLambda returns a Lambda object that exports the given function to Emacs as an anonymous lambda function. When calling the exported function from Emacs, arguments and return values are converted as described in the package documentation.

The function may accept any number of arguments. Optionally, the first argument may be of type Env. In this case, Emacs passes a live environment value that you can use to interact with Emacs. All other arguments are converted from Emacs as described in the package documentation. If not all arguments are convertible from Emacs values, AutoLambda panics.

The function must return either zero, one, or two results. If the last or only result is of type error, a non-nil value causes Emacs to trigger a non-local exit as appropriate. There may be at most one non-error result. Its value will be converted to an Emacs value as described in the package documentation. If the type of the non-error result can’t be converted to an Emacs value, AutoLambda panics. If there are invalid result patterns, AutoLambda panics.

The function is always anonymous. Any Name option in opts is ignored.

By default, the function has no documentation string. To add one, pass a Doc option.

You can call AutoLambda safely from multiple goroutines.

func (Lambda) Emacs

func (l Lambda) Emacs(e Env) (Value, error)

Emacs returns a new function object for the given Go function.

type List

type List []In

List represents an Emacs list.

func (List) Emacs

func (l List) Emacs(e Env) (Value, error)

Emacs creates a new list from the given elements.

type ListOut

type ListOut struct {
	// New must return a new list element each time it’s called.
	New func() Out

	// FromEmacs fills Data with the elements from the list.
	Data []Out
}

ListOut is an Out that converts an Emacs list to the slice Data. The concrete element type is determined by the return value of the New function.

func (*ListOut) FromEmacs

func (l *ListOut) FromEmacs(e Env, v Value) error

FromEmacs sets l.Data to a new slice containing the elements of the Emacs list v. It returns an error if v is not a list. FromEmacs calls l.New for each element in v. l.New must return a new Out value for the element. If FromEmacs returns an error, it doesn’t modify l.Data. FromEmacs assumes that v is a true list. In particular, it may loop forever if v is circular.

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager simplifies registering and maintaining Emacs entities. Often, entities such as functions, variables, or error symbols should be registered during initialization of the Go package, when Emacs hasn’t yet loaded the module. In a second phase, these entities then have to be defined as soon as Emacs has loaded the module. To support this form of two-phase initialization, Manager maintains a queue of QueuedItem objects for later definition.

Optionally, you can use a Manager to ensure that entities are named and/or that names are unique within the scope of the manager.

You can use NewManager to create Manager objects. The zero Manager is valid and equivalent to NewManager(0). Manager objects can’t be copied once they are initialized.

Usually you’d create one global manager object per entity type. All methods of Manager are safe for concurrent use, assuming the QueuedItems aren’t modified after registering them, and [QueuedItem.Define] is safe for concurrent use.

Example
package main

import "fmt"

// We assume that we want to allow module authors to register a Foo entity.
// Registration should be possible eagerly (if an Emacs environment is
// available) as well as lazily (before Emacs has loaded the module).  For that
// we use a Manager and pass DefineOnInit.
var foos = NewManager(RequireUniqueName | DefineOnInit)

// Define a type to hold the necessary information about a Foo.  The type needs
// to implement the QueuedItem interface.
type foo struct {
	name    Name
	message string
}

func (f foo) Define(e Env) error {
	return e.Invoke("message", Ignore{}, "defining foo %s: %s", f.name, f.message)
	// In real code you’d probably do something like
	// return e.Invoke("define-foo", Ignore{}, f.name, f.message)
}

// Define convenience functions to register definition of a Foo.
func DefineFooNow(e Env, name Name, message string) error {
	return foos.RegisterAndDefine(e, name, foo{name, message})
}

func DefineFooEventually(name Name, message string) error {
	return foos.Enqueue(name, foo{name, message})
}

func main() {
	for _, n := range []Name{"foo-1", "foo-1", ""} {
		if err := DefineFooEventually(n, fmt.Sprintf("hi from foo %q", n)); err != nil {
			fmt.Println(err)
		}
	}
}

func init() {
	// We would normally call ExampleManager here, but the test runner
	// already calls it for us.
}
Output:

duplicate name foo-1

func NewManager

func NewManager(flags ManagerFlag) *Manager

NewManager creates a new Manager object with the given flags. If flags includes RequireName, then all entities registered on this manager must have a nonempty name. If flags includes RequireUniqueName, then all named entities must have unique names. If flags includes DefineOnInit, NewManager arranges for Manager.DefineQueued to be called when the module is initialized. NewManager(0) is equivalent to new(Manager).

Having flags include RequireUniqueName but not RequireName is valid; in this case names are optional (i. e. the registration functions accept empty names), but if an entity is named, its name must be unique.

func (*Manager) DefineQueued

func (m *Manager) DefineQueued(e Env) error

DefineQueued defines all queued items using the given environment. DefineQueued may be called at most once. Usually, you should call it during module initialization, either using OnInit or by passing the DefineOnInit flag to NewManager. Once DefineQueued has been called, Manager.Enqueue and Manager.MustEnqueue can no longer be used. DefineQueued returns the error of the first failed definition, or nil if all definitions succeeded.

func (*Manager) Enqueue

func (m *Manager) Enqueue(name Name, item QueuedItem) error

Enqueue registers a QueuedItem for later definition. Enqueue is usually called from an init function, before Emacs has loaded the module. The name may not be empty if the flag RequireName has been passed to NewManager. The name must be unique if it’s nonempty and the flag RequireUniqueName has been passed to NewManager. If neither flag was passed, the name is ignored. Enqueue returns an error if Manager.RegisterAndDefine has already been called.

func (*Manager) MustEnqueue

func (m *Manager) MustEnqueue(name Name, item QueuedItem)

MustEnqueue registers a QueuedItem for later definition. MustEnqueue is usually called from an init function, before Emacs has loaded the module. The name may not be empty if the flag RequireName has been passed to NewManager. The name must be unique if it’s nonempty and the flag RequireUniqueName has been passed to NewManager. If neither flag was passed, the name is ignored. MustEnqueue panics if the name is invalid or if Manager.RegisterAndDefine has already been called. MustEnqueue is like Manager.Enqueue, except that it panics on all errors.

func (*Manager) RegisterAndDefine

func (m *Manager) RegisterAndDefine(e Env, name Name, item QueuedItem) error

RegisterAndDefine registers a QueuedItem and defines it immediately. Unlike Enqueue and MustEnqueue, RegisterAndDefine requires a live Env object and therefore only works after Emacs has loaded the module. The name may not be empty if the flag RequireName has been passed to NewManager. The name must be unique if it’s nonempty and the flag RequireUniqueName has been passed to NewManager. If neither flag was passed, the name is ignored.

type ManagerFlag

type ManagerFlag uint

ManagerFlag defines flags for NewManager.

const (
	// RequireName causes a [Manager] to fail if the name of an entity to
	// be managed is empty.
	RequireName ManagerFlag = 1 << iota

	// RequireUniqueName causes a [Manager] to fail if two named entities
	// have the same name.
	RequireUniqueName

	// DefineOnInit arranges for [Manager.DefineQueued] to be called when
	// the module is initialized.
	DefineOnInit
)

type Name

type Name Symbol

Name is a Symbol that names a definition such as a function or error symbol. You can use a Name as an Option in Export and ERTTest to set the function or test name.

func Var

func Var(name Name, init In, doc Doc) Name

Var arranges for an Emacs dynamic variable to be defined once the module is loaded. If doc is empty, the variable won’t have a documentation string. Var panics if the name is empty or already registered. Var returns name so you can assign it directly to a Go variable if you want.

Example
package main

import "fmt"

func main() {
	// Var panics when trying to export a variable name twice.
	defer func() { fmt.Println("panic:", recover()) }()
	Var("go-var", nil, "")
}

var _ = Var("go-var", String("hi"), "Example variable.")
Output:

panic: duplicate name go-var

func (Name) Emacs

func (n Name) Emacs(e Env) (Value, error)

Emacs interns the given symbol name in the default obarray and returns the symbol object.

func (*Name) FromEmacs

func (n *Name) FromEmacs(e Env, v Value) error

FromEmacs sets *n to the name of the Emacs symbol v. It returns an error if v is not a symbol.

func (Name) String

func (n Name) String() string

Name returns the symbol name.

type Option

type Option interface {
	// contains filtered or unexported methods
}

Option is an option for Export, AutoFunc, AutoLambda, and ERTTest. Its implementations are Name, Anonymous, Doc, and Usage.

type Out

type Out interface {
	// FromEmacs sets the receiver to a Go value corresponding to the Emacs
	// object.  Implementations should document whether FromEmacs modifies
	// the receiver in case of an error.
	FromEmacs(Env, Value) error
}

Out is a value that knows how to convert itself from an Emacs object. You can implement In for your own types if you want this package to convert them from Emacs values automatically. Pointers to wrapper implementations for In, such as *Int or *String, implement Out.

func NewOut

func NewOut(p interface{}) Out

NewOut returns an Out value that sets p to the Go representation of an Emacs value. Typically p is a pointer. Only a few types such as reflect.Value can be set without indirection. If p already implements Out, NewOut returns it directly. Otherwise, if the dynamic type of v is known, NewOut returns one of the predefined Out implementations (*Int, *Float, *String, Reflect, …). Otherwise, NewOut returns an Out instance that uses reflection to convert Emacs values.

type OutFunc

type OutFunc func(reflect.Value) Out

OutFunc is a function that returns an Out for the given value.

func OutFuncFor

func OutFuncFor(t reflect.Type) (OutFunc, error)

OutFuncFor returns an OutFunc for the given type. If there’s no known conversion from Emacs to t, OutFuncFor returns an error.

type QueuedItem

type QueuedItem interface {
	// Define should define the item using the given Emacs environment.
	Define(Env) error
}

QueuedItem is an item stored in a Manager’s queue.

type Reflect

type Reflect reflect.Value

Reflect is a type with underlying type reflect.Value that knows how to convert itself to and from an Emacs value.

func (Reflect) Emacs

func (r Reflect) Emacs(e Env) (Value, error)

Emacs attempts to convert r to an Emacs value.

func (Reflect) FromEmacs

func (r Reflect) FromEmacs(e Env, v Value) error

FromEmacs sets r to the Go representation of v. It returns an error if r isn’t settable.

type Result

type Result struct {
	Value In
	Err   error
}

Result contains the result of an asynchronous operation. If Err is set, Value is ignored.

type Signal

type Signal struct{ Symbol, Data Value }

Signal is an error that that causes Emacs to signal an error with the given symbol and data. This is the equivalent to Error if you already have an evaluated symbol and data value.

func (Signal) Error

func (Signal) Error() string

Error implements the error interface. Error returns a static string. Use Signal.Message to return the actual Emacs error message.

func (Signal) Message

func (s Signal) Message(e Env) string

Message returns the Emacs error message for this signal. It returns <error> if determining the message failed.

type String

type String string

String is a type with underlying type string that knows how to convert itself to an Emacs string.

func (String) Emacs

func (s String) Emacs(e Env) (Value, error)

Emacs creates an Emacs value representing the given string. It returns an error if the string isn’t a valid UTF-8 string.

func (*String) FromEmacs

func (s *String) FromEmacs(e Env, v Value) error

FromEmacs sets *s to the string stored in v. It returns an error if v is not a string, or if it’s not a valid Unicode scalar value sequence.

func (String) String

func (s String) String() string

String quotes the string to mimic the Emacs printed representation.

type Symbol

type Symbol string

Symbol represents an Emacs symbol. Env.Call interns Symbol values instead of converting them to an Emacs string.

const (
	Nil Symbol = "nil"
	T   Symbol = "t"
)

Common symbols.

func (Symbol) Emacs

func (s Symbol) Emacs(e Env) (Value, error)

Emacs interns the given symbol name in the default obarray and returns the symbol object.

func (*Symbol) FromEmacs

func (s *Symbol) FromEmacs(e Env, v Value) error

FromEmacs sets *s to the name of the Emacs symbol v. It returns an error if v doesn’t represent a symbol.

func (Symbol) String

func (s Symbol) String() string

Symbol returns the symbol name.

type Throw

type Throw struct{ Tag, Value Value }

Throw is an error that triggers the Emacs throw function.

func (Throw) Error

func (Throw) Error() string

Error implements the error interface.

type Time

type Time time.Time

Time is a type with underlying type time.Time that knows how to convert itself from and to an Emacs time value.

func (Time) Emacs

func (t Time) Emacs(e Env) (Value, error)

Emacs returns an Emacs timestamp as a pair (ticks . hz) or a quadruple (high low μs ps) in the same format as the Emacs function current-time.

func (*Time) FromEmacs

func (t *Time) FromEmacs(e Env, v Value) error

FromEmacs sets *t to the Go equivalent of the Emacs time value in v. v can be any time value: nil (for the current time), a number of seconds since the epoch, a pair (ticks . hz), a pair (high low), a triple (high low μs), or a quadruple (high low μs ps). The picosecond value is truncated to nanosecond precision. If the Emacs time value would overflow a Go time, FromEmacs returns an error.

func (Time) String

func (t Time) String() string

String formats the time as a string. It calls time.Time.String.

type Uint

type Uint uint64

Uint is a type with underlying type uint64 that knows how to convert itself into an Emacs value.

func (Uint) Emacs

func (i Uint) Emacs(e Env) (Value, error)

Emacs creates an Emacs value representing the given integer. It returns an error if the integer value is too big for Emacs.

func (*Uint) FromEmacs

func (i *Uint) FromEmacs(e Env, v Value) error

FromEmacs sets *i to the integer stored in v. It returns an error if v is not an integer, or if it doesn’t fit into an uint64.

type Uncons

type Uncons struct{ Car, Cdr Out }

Uncons represents a destructuring binding of a cons cell.

func (Uncons) FromEmacs

func (c Uncons) FromEmacs(e Env, cons Value) error

FromEmacs sets c.Car and c.Cdr to the values in cons. It returns an error if cons is not a cons cell. In case of an error, the value of c.Car and c.Cdr is unspecified.

type UnpackList

type UnpackList []Out

UnpackList represents a destructuring binding on an Emacs list.

func (*UnpackList) FromEmacs

func (u *UnpackList) FromEmacs(e Env, v Value) error

FromEmacs fills *u with elements from the list v. It returns an error if v is not a list. If the list is shorter than *u, FromEmacs sets the length of *u to the length of the list. If the list is longer than *u, FromEmacs converts only the first len(*u) elements of the list and ignores the rest. FromEmacs assumes that v is a true list. If v is dotted or cyclic, the contents of *u are unspecified. If FromEmacs returns an error, the contents of *u are also unspecified.

type UnpackVector

type UnpackVector []Out

UnpackVector represents a destructuring binding on an Emacs vector.

func (*UnpackVector) FromEmacs

func (u *UnpackVector) FromEmacs(e Env, v Value) error

FromEmacs fills *u with elements from the vector v. It returns an error if v is not a vector. If the vector is shorter than *u, FromEmacs sets the length of *u to the length of the vector. If the vector is longer than *u, FromEmacs converts only the first len(*u) elements of the vector and ignores the rest. If FromEmacs returns an error, the contents of *u are unspecified.

type Usage

type Usage string

Usage contains a list of argument names to be added to a documentation string. It should contain a plain space-separated list of argument names without enclosing parentheses. See Documentation Strings of Functions. Usage strings must be valid UTF-8 strings without embedded null characters or newlines. You can use a Usage as an Option in Export to set the argument list in the documentation string.

type Value

type Value struct {
	// contains filtered or unexported fields
}

Value represents an Emacs object. The zero Value is not valid. Various functions in this package return Value values. These functions are either methods on the Env type or take an Env argument. In any case, the returned Value values are only valid (or “live”) as long as the Env used to create them is valid. Don’t pass Value values to other goroutines. Two different Value values may represent the same Emacs value. Use Env.Eq instead of the == operator to compare values. See Conversion Between Lisp and Module Values for details.

func (Value) Emacs

func (v Value) Emacs(Env) (Value, error)

Emacs returns v. It never returns an error.

func (*Value) FromEmacs

func (v *Value) FromEmacs(e Env, u Value) error

FromEmacs sets *v to u. It never returns an error.

type Vector

type Vector []In

Vector represents an Emacs vector.

func (Vector) Emacs

func (v Vector) Emacs(e Env) (Value, error)

Emacs creates a new vector from the given elements.

type VectorOut

type VectorOut struct {
	// New must return a new vector element each time it’s called.
	New func() Out

	// [VectorOut.FromEmacs] fills Data with the elements from the vector.
	Data []Out
}

VectorOut is an Out that converts an Emacs vector to the slice Data. The concrete element type is determined by the return value of the New function.

func (*VectorOut) FromEmacs

func (v *VectorOut) FromEmacs(e Env, u Value) error

FromEmacs sets v.Data to a new slice containing the elements of the Emacs vector u. It returns an error if u is not a vector. FromEmacs calls v.New for each element in u. v.New must return a new Out value for the element. If FromEmacs returns an error, it doesn’t modify v.Data.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL