This document describes Emacsy version 0.4.1.26-89e9-dirty, An embeddable Emacs-like library using GNU Guile.
• Preface | ||
• Introduction | ||
• The Garden | ||
• Installation | Installing Emacsy. | |
• Hello Emacsy | ||
• Api | ||
• Contributing | Your help needed! | |
• Acknowledgments | Thanks! | |
• Resources | ||
• GNU Free Documentation License | The license of this manual. | |
• Programming Index | Data types, functions, and variables. | |
• Keyboard command Index | Keyboard commands. | |
• Concept Index | Concepts. | |
— The Detailed Node Listing — Introduction | ||
---|---|---|
• Vision | ||
Vision | ||
• Motivation | ||
• Overlooked Treasure | ||
• Emacsy | ||
• Goals | ||
• Anti-goals | ||
• Emacsy Features | ||
Installation | ||
• Requirements | Software needed to build and run Emacsy. | |
• Running the Test Suites | Testing Emacsy. | |
Hello Emacsy | ||
• Embedder's API | Unlimited power. | |
• The Simplest Application Ever | Hello Emacsy! | |
• Conclusion | And now what? | |
• Plaintext Please | Use the Source. | |
Api | ||
• C Api | ||
• Emacsy Facade | ||
• Event | ||
• Keymap | ||
• Command | ||
• Block | ||
• KLECL | Key-Lookup-Execute-Command-Loop | |
• Kbd-Macro | Keyboard Macros | |
• Buffer | ||
• Text | ||
• Minibuffer | ||
• Core | ||
• Advice | ||
• Window | Window module (optional) | |
• Help | ||
• Self-doc | Self-documentation | |
Contributing | ||
• Building from Git | The latest and greatest. | |
• Running Emacsy From the Source Tree | Hacker tricks. | |
• The Perfect Setup | The right tools. | |
• Coding Style | Hygiene of the contributor. | |
• Submitting Patches | Share your work. | |
Next: Introduction, Previous: Top, Up: Top [Contents][Index]
This project is an experiment, actually two experiments. Firstly, it’s an experiment to see whether there’s any interest and utility in an embeddable Emacs-like environment. Secondly, I’d like to see how literate programming fares in comparison to the conventional approach. Let me elaborate a little on each.
Emacs is the extensible programmer’s text editor. For decades, it’s gobbled up functionality that sometimes seems far removed from text editing. I will expand upon why I believe this is the case and what particular functionality I hope to replicate later. I’d like to discuss a little about why I’m bothering to start with Emacs rather than just writing something entirely new. Emacs has fostered a community of people that are comfortable using, customising, and extending Emacs while its running. The last part is most important in my mind. Extending Emacs is a natural part of its use; it’s a tinkerer’s dream toy. And I want to grease the rails for people who already get what kind of tool I’m trying to provide. Had I chosen another perfectly competent language like Lua instead of a Lisp, that would erect a barrier to that track. Were I to write a completely different API, that’s yet another barrier. Were I to “modernize” the terminology used by Emacs, e.g., say “key shortcut” instead of “key binding”, or “window” instead of “frame”, that’s a barrier to drawing the community of people that already get it to try this out.
Let me say a little about why I’m choosing to do this as a literate program1. I’ve written a lot of code, none of which was written literately. Recently I had an experience that made me want to try something different. I began a group project. There wasn’t that much code. Yet not too far into the project, it had become opaque to one of the original contributors. This was a small codebase with someone who was there from the start, and already we were having problems. Maybe the code was bad. Maybe we were bad programmers (Eek!). Whatever the case, assuming there’s no simple fix for opaque code, it is something that can be addressed. Better communication about the code may help. So I would like to invest a good faith effort in attempting to write this program in a literate fashion.
A few notes on my personal goals for this document and the code. The writing style I’m leaving as informal for purposes of expediency and lowering the barrier of contribution. Also for expediency, my initial interest is in fleshing out the functionality. I’m not concerned about optimality of the implementation yet. Only in cases where the design cannot be reimplemented to be more efficient would I be concerned. If we can make a useable system, optimization will follow and hopefully be informed by profiling.
There’s a ton of work left to do! Please feel free to contribute to the effort.
Next: The Garden, Previous: Preface, Up: Top [Contents][Index]
Emacsy is inspired by the Emacs text editor, but it is not an attempt to create another text editor. This project "extracts" the kernel of Emacs that makes it so extensible. There’s a joke that Emacs is a great operating system—lacking only a decent editor. Emacsy is the Emacs OS sans the text editor. Although Emacsy shares no code with Emacs, it does share a vision. This project is aimed at Emacs users and software developers.
• Vision |
Up: Introduction [Contents][Index]
Emacs has been extended to do much more than text editing. It can get your email, run a chat client, do video editing2, and more. For some the prospect of chatting from within one’s text editor sounds weird. Why would anyone want to do that? Because Emacs gives them so much control. Frustrated by a particular piece of functionality? Disable it. Unhappy with some unintuitive key binding? Change it. Unimpressed by built-in functionality? Rewrite it. And you can do all that while Emacs is running. You don’t have to exit and recompile.
The purpose of Emacsy is to bring the Emacs way of doing things to other applications natively. In my mind, I imagine Emacs consuming applications from the outside, while Emacsy combines with applications from the inside—thereby allowing an application to be Emacs-like without requiring it to use Emacs as its frontend. I would like to hit \verb|M-x| in other applications to run commands. I would like to see authors introduce a new version: “Version 3.0, now extendable with Emacsy.” I would like hear power users ask, “Yes, but is it Emacsy?”
• Motivation | ||
• Overlooked Treasure | ||
• Emacsy | ||
• Goals | ||
• Anti-goals | ||
• Emacsy Features |
Next: Overlooked Treasure, Up: Vision [Contents][Index]
This project was inspired by my frustration creating interactive applications with the conventional edit-run-compile style of development. Finding the right abstraction for the User Interface (UI) that will compose well is not easy. Additionally, If the application is a means to an end and not an end in itself (which is common for academic and in-house tools), then the UI is usually the lowest development priority. Changing the UI is painful, so often mediocre UIs rule. Emacsy allows the developer—or the user—to reshape and extend the UI and application easily at runtime.
Next: Emacsy, Previous: Motivation, Up: Vision [Contents][Index]
Emacs has a powerful means of programmatically extending itself while it is running. Not many successful applications can boast of that, but I believe a powerful idea within Emacs has been overlooked as an Emacsism rather than an idea of general utility. Let me mention another idea that might have become a Lispism but has since seen widespread adoption.
The Lisp programming language introduced the term Read-Eval-Print-Loop (REPL, pronounced rep-pel), an interactive programming feature present in many dynamic languages: Python, Ruby, MATLAB, Mathematica, Lua to name a few. The pseudo code is given below.
<<Lisp REPL>>= (while #t (print (eval (read)))) The REPL interaction pattern is to enter one complete expression, hit the return key, and the result of that expression will be displayed. It might look like this:
> (+ 1 2) 3
The kernel of Emacs is conceptually similar to the REPL, but the level of interaction is more fine grained. A REPL assumes a command line interface. Emacs assumes a keyboard interface. I have not seen the kernel of Emacs exhibited in any other applications, but I think it is of similar utility to the REPL—and entirely separate from text editing. I’d like to name this the Key-Lookup-Execute-Command-Loop (KLECL, pronounced clec-cull).
Next: Goals, Previous: Overlooked Treasure, Up: Vision [Contents][Index]
Long-time Emacs users will be familiar with this idea, but new Emacs users may not be. For instance, when a user hits the ’a’ key, then an ’a’ is inserted into their document. Let’s pull apart the functions to see what that actually looks like with respect to the KLECL.
> (read-key) #\a > (lookup-key #\a) self-insert-command > (execute-command 'self-insert-command) #t
Key sequences in Emacs are associated with commands. The fact that each command is implemented in Lisp is an implementation detail and not essential to the idea of a KLECL.
Note how flexible the KLECL is: One can build a REPL out of a KLECL, or a text editor, or a robot simulator (as shown in the video). Emacs uses the KLECL to create an extensible text editor. Emacsy uses the KLECL to make other applications similarly extensible.
Next: Anti-goals, Previous: Emacsy, Up: Vision [Contents][Index]
The goals of this project are as follows.
Emacsy will use Guile Scheme to make it easy to embed within C and C++ programs.
Emacsy should be easy enough to learn that the uninitiated may easily make parametric changes, e.g., key ’a’ now does what key ’b’ does and vice versa. Programmers in any language ought to be able to make new commands for themselves. And old Emacs hands should be able to happily rely on old idioms and function names to change most anything.
Emacsy should be configured with a sensible set of defaults (opinions). Out of the box, it is not tabla rasa, a blank slate, where the user must choose every detail, every time. However, if the user wants to choose every detail, they can.
It wouldn’t be Emacs-like if you couldn’t tinker with it.
New commands can be defined in Guile Scheme or C/C++.
That is to say, commands can call other commands. No special arrangements must be considered in the general case.
The core functions that must be called by the embedding application will be few and straightforward to use.
Next: Emacsy Features, Previous: Goals, Up: Vision [Contents][Index]
Just as important as a project’s goals are its anti-goals: the things it is not intended to do.
Emacsy will not do general purpose text editing out of the box, although it will have a minibuffer.
Emacs is full featured programmer’s text editor with more bells and whistles than most people will ever have the time to fully explore. Emacsy extracts the Emacs spirit of application and UI extensibility to use within other programs.
There have been many attempts to replace Emacs and elisp with an newer Lisp dialect. Emacsy is not one of them.
Although Emacsy may adopt some of naming conventions of Emacs, it will not use elisp and will not attempt to be in any way source code compatible with Emacs.
I will not steal your runloop. You call Emacsy when it suits your application not the other way around.
Previous: Anti-goals, Up: Vision [Contents][Index]
These are the core features from Emacs that will be implemented in Emacsy.
Next: Installation, Previous: Introduction, Up: Top [Contents][Index]
Now for a little entertainment.
Next: Hello Emacsy, Previous: The Garden, Up: Top [Contents][Index]
Emacsy is available for download from its website at http://www.gnu.org/pub/gnu/emacsy/. This section describes the software requirements of Emacsy, as well as how to install it and get ready to use it.
• Requirements | Software needed to build and run Emacsy. | |
• Running the Test Suites | Testing Emacsy. |
Next: Running the Test Suites, Up: Installation [Contents][Index]
This section lists requirements when building Emacsy from source. The build procedure for Emacsy is the same as for GNU software, and is not covered here. Please see the files README and INSTALL in the Emacsy source tree for additional details.
Emacsy depends on the following packages:
The following dependencies are optional:
Previous: Requirements, Up: Installation [Contents][Index]
After a successful configure
and make
run, it is a good
idea to run the test suites.
make check
Next: Api, Previous: Installation, Up: Top [Contents][Index]
I have received a lot of questions asking, what does Emacsy3 actually do? What restrictions does it impose on the GUI toolkit? How is it possible to not use any Emacs code? I thought it might be best if I were to provide a minimal example program, so that people can see code that illustrates Emacsy API usage.
• Embedder's API | Unlimited power. | |
• The Simplest Application Ever | Hello Emacsy! | |
• Conclusion | And now what? | |
• Plaintext Please | Use the Source. |
Next: The Simplest Application Ever, Up: Hello Emacsy [Contents][Index]
Here are a few function prototypes defined in emacsy.h, see C Api for the full list.
Initialize Emacsy.
Enqueue a keyboard event.
Run an iteration of Emacsy’s event loop, does not block.
Return the mode line.
Terminate Emacsy; run termination hook.
Next: Conclusion, Previous: Embedder's API, Up: Hello Emacsy [Contents][Index]
Let’s exercise these functions in a minimal FreeGLUT program we’ll call hello-emacsy.4. This simple program will display an integer, the variable counter, that one can increment or decrement.
Hello Emacsy’s state is captured by one global variable. Hello Emacsy will display this number.
Initialize everything in main and enter our runloop.
Initialize GLUT.
Initialize Guile.
Initialize Emacsy.
Register primitives.
Try to load hello-emacsy.scm
Enter GLUT main loop, not return.
Let’s look at how Emacsy interacts with your application’s runloop since that’s probably the most concerning part of embedding. First, let’s pass some input to Emacsy.
Send key events to Emacsy.
int key; // The Key event (not processed yet).
The keys C-a and C-b return 1
and 2
respectively. We want to map these to their actual character values.
The function display_func is run for every frame that’s drawn. It’s effectively our runloop, even though the actual runloop is in FreeGLUT.
Our application has just one job: Display the counter variable.
Setup the display buffer the drawing.
Process events in Emacsy.
Display Emacsy message/echo area.
Display Emacsy mode line.
Draw a string function. Draws a string at (x, y) on the screen.
At this point, our application can process key events, accept input on the minibuffer, and use nearly all of the facilities that Emacsy offers, but it can’t change any application state, which makes it not very interesting yet.
Let’s define a new primitive Scheme procedure get-counter, so
Emacsy can access the application’s state. This will define
a C function SCM scm_get_counter (void)
and a Scheme procedure
(get-counter)
.
Let’s define another primitive Scheme procedure to alter the application’s state.
Once we have written these primitive procedures, we need to register them with the Scheme runtime.
Locate the hello-emacsy.scm Guile initialization and load it.
We generate the file example/hello-emacsy.c.x by running the
command: guile-snarf example/hello-emacsy.c
. Emacsy can now
access and alter the application’s internal state.
Bind inc-counter to =
.
Bind inc-counter to -
.
Let’s implement another command that will ask the user for a number to set the counter to.
Now we can hit M-x change-counter and we’ll be prompted for the new value we want. There we have it. We have made the simplest application ever more Emacs-y.
We can add commands easily by changing and reloading the file. But we can do better. Let’s start a REPL we can connect to. example/hello-emacsy.scm.
(use-modules (system repl server)) (spawn-server)
Start a server on port 37146.
Next: Plaintext Please, Previous: The Simplest Application Ever, Up: Hello Emacsy [Contents][Index]
We implemented a simple interactive application that displays a number. We embedded Emacsy into it: sending events to Emacsy and displaying the minibuffer. We implemented primitive procedures so Emacsy could access and manipulate the application’s state. We extended the user interface to accept new commands + and - to change the state.
Now we can telnet localhost 37146 to get a REPL.
Previous: Conclusion, Up: Hello Emacsy [Contents][Index]
/* Emacsy --- An embeddable Emacs-like library using GNU Guile Copyright (C) 2012, 2013 Shane Celis <shane.celis@gmail.com> Copyright (C) 2019, Jan (janneke) Nieuwenhuizen <janneke@gnu.org> This file is part of Emacsy. Emacsy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Emacsy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Emacsy. If not, see <http://www.gnu.org/licenses/>. */ /* * Let's exercise these functions in a minimal FreeGLUT program we'll call * @verb{|hello-emacsy|}.@footnote{Note: Emacsy does not rely on FreeGLUT. * One could use Gtk+, Ncurses, Qt, or whatever}. This simple program * will display an integer, the variable @var{counter}, that one can * increment or decrement. * * @image{images/minimal-emacsy-example,,,,.png} */ #ifndef SCM_MAGIC_SNARFER #include <libgen.h> #ifdef __APPLE__ #include <GLUT/glut.h> #else #include <GL/glut.h> #endif #include <emacsy.h> #include <stdio.h> #include <string.h> #include <unistd.h> #endif #include <libguile.h> void display_func (); void keyboard_func (unsigned char glut_key, int x, int y); void draw_string (int, int, char*); char * try_load_startup (char const* prefix, char const* dir, char const* startup_script); void primitives_init (); /* * @defvar int counter = 0; * Hello Emacsy's state is captured by one global variable. * Hello Emacsy will display this number. * @end defvar */ int counter = 0; int interactive = 1; /* * Initialize everything in @var{main} and enter our runloop. */ int main (int argc, char *argv[]) { int err; /* glutInit (&argc, argv); * Initialize GLUT. */ glutInit (&argc, argv); glutInitDisplayMode (GLUT_RGB|GLUT_DOUBLE); glutInitWindowSize (500, 500); glutCreateWindow ("Hello, Emacsy!"); glutDisplayFunc (display_func); if (interactive) glutKeyboardFunc (keyboard_func); /* void scm_init_guile (); * Initialize Guile. */ scm_init_guile (); /* emacsy_initialize (@dots {}); * Initialize Emacsy. */ if (argc == 2 && strcmp ("--batch", argv[1]) == 0) interactive = 0; err = emacsy_initialize (interactive ? EMACSY_INTERACTIVE : EMACSY_NON_INTERACTIVE); if (err) exit (err); /* primitives_init (); * Register primitives. */ primitives_init (); /* char * try_load_startup (@dots{}); * Try to load @file{hello-emacsy.scm} */ char const *startup_script = "hello-emacsy.scm"; char prefix[PATH_MAX]; strcpy (prefix, argv[0]); if (getenv ("_")) strcpy (prefix, getenv ("_")); dirname (dirname (prefix)); if (!try_load_startup (0, 0, startup_script) &&!try_load_startup (getenv ("EMACSY_SYSCONFDIR"), "/", startup_script) &&!try_load_startup (prefix, "/", startup_script) &&!try_load_startup (prefix, "/etc/emacsy/", startup_script)) fprintf (stderr, "error: failed to find '%s'.\n", startup_script); /* void glutMainLoop (); * Enter GLUT main loop, not return. */ glutMainLoop (); return 0; } /* * @subsection Runloop Interaction * * Let's look at how Emacsy interacts with your application's runloop * since that's probably the most concerning part of embedding. First, * let's pass some input to Emacsy. */ /* void keyboard_func (unsigned char glut_key, int x, int y) * Send key events to Emacsy. */ void keyboard_func (unsigned char glut_key, int x, int y) { /* * int key; // The Key event (not processed yet). */ int key; int mod_flags; int glut_mod_flags = glutGetModifiers (); mod_flags = 0; if (glut_mod_flags & GLUT_ACTIVE_SHIFT) mod_flags |= EMACSY_MODKEY_SHIFT; if (glut_mod_flags & GLUT_ACTIVE_CTRL) mod_flags |= EMACSY_MODKEY_CONTROL; if (glut_mod_flags & GLUT_ACTIVE_ALT) mod_flags |= EMACSY_MODKEY_META; if (glut_key == 8) glut_key = 127; else if (glut_key == 127) { glut_key = 4; mod_flags += EMACSY_MODKEY_CONTROL; } /* * The keys @verb{|C-a|} and @verb{|C-b|} return @code{1} and @code{2} * respectively. We want to map these to their actual character values. */ key = mod_flags & EMACSY_MODKEY_CONTROL ? glut_key + ('a' - 1) : glut_key; emacsy_key_event (key, mod_flags); glutPostRedisplay (); } /* void display_func () * The function @var{display_func} is run for every frame that's * drawn. It's effectively our runloop, even though the actual runloop is * in FreeGLUT. * * Our application has just one job: Display the counter variable. */ void display_func () { /* glClear (GL_COLOR_BUFFER_BIT); * Setup the display buffer the drawing. */ glClear (GL_COLOR_BUFFER_BIT); glMatrixMode (GL_PROJECTION); glLoadIdentity (); glOrtho (0.0, 500.0, 0.0, 500.0, -2.0, 500.0); gluLookAt (0, 0, 2, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glMatrixMode (GL_MODELVIEW); glColor3f (1, 1, 1); char counter_string[255]; sprintf (counter_string, "%d", counter); draw_string (250, 250, counter_string); /* * Process events in Emacsy. */ if (emacsy_tick () & EMACSY_QUIT_APPLICATION_P) { emacsy_terminate (); exit (0); } glutSetWindowTitle (emacsy_current_buffer ()); /* * Display Emacsy message/echo area. */ draw_string (0, 5, emacsy_message_or_echo_area ()); /* * Display Emacsy mode line. */ draw_string (0, 30, emacsy_mode_line ()); glutSwapBuffers (); } /* void draw_string (int x, int y, char *string) * * Draw a string function. * Draws a string at (x, y) on the screen. */ void draw_string (int x, int y, char *string) { glLoadIdentity (); glTranslatef (x, y, 0.); glScalef (0.2, 0.2, 1.0); while (*string) glutStrokeCharacter (GLUT_STROKE_ROMAN, *string++); } /* * At this point, our application can process key events, accept input on * the minibuffer, and use nearly all of the facilities that Emacsy * offers, but it can't change any application state, which makes it not * very interesting yet. */ /* * @subsection Plugging Into Your App */ // /* * @deffn {Scheme Procedure} get-counter * @deffnx {C Function} SCM scm_get_counter () * Let's define a new primitive Scheme procedure @var{get-counter}, so * Emacsy can access the application's state. This will define * a @var{C} function @code{SCM scm_get_counter (void)} and a Scheme procedure * @code{(get-counter)}. * * @end deffn */ SCM_DEFINE (scm_get_counter, "get-counter", /* required arg count */ 0, /* optional arg count */ 0, /* variable length args? */ 0, (), "Returns value of counter.") { return scm_from_int (counter); } /* * @deffn {Scheme Procedure} set-counter! value * @deffnx {C Function} SCM scm_set_counter_x (SCM value) * Let's define another primitive Scheme procedure to alter the * application's state. * @end deffn */ SCM_DEFINE (scm_set_counter_x, "set-counter!", /* required, optional, var. length? */ 1, 0, 0, (SCM value), "Sets value of counter.") { counter = scm_to_int (value); glutPostRedisplay (); return SCM_UNSPECIFIED; } /* void primitives_init () * Once we have written these primitive procedures, we need to register * them with the Scheme runtime. */ void primitives_init () { #ifndef SCM_MAGIC_SNARFER #include "hello-emacsy.c.x" #endif } /* char * try_load_startup (char const* prefix, char const* dir, char const* startup_script) * Locate the @file{hello-emacsy.scm} Guile initialization and load it. */ char * try_load_startup (char const* prefix, char const* dir, char const* startup_script) { static char file_name[PATH_MAX]; if (prefix) strcpy (file_name, prefix); if (dir) strcat (file_name, dir); strcat (file_name, startup_script); if (access (file_name, R_OK) != -1) { fprintf (stderr, "Loading '%s'.\n", file_name); scm_c_primitive_load (file_name); return file_name; } else fprintf (stderr, "no such file '%s'.\n", file_name); return 0; }
;;; Emacsy --- An embeddable Emacs-like library using GNU Guile ;;; ;;; Copyright (C) 2012, 2013 Shane Celis <shane.celis@gmail.com> ;;; ;;; This file is part of Emacsy. ;;; ;;; Emacsy is free software: you can redistribute it and/or modify ;;; it under the terms of the GNU General Public License as published by ;;; the Free Software Foundation, either version 3 of the License, or ;;; (at your option) any later version. ;;; ;;; Emacsy is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with Emacsy. If not, see <http://www.gnu.org/licenses/>. ;; We generate the file @file{example/hello-emacsy.c.x} by running the ;; command: @code{guile-snarf example/hello-emacsy.c}. Emacsy can now ;; access and alter the application's internal state. ;;. ;; @subsection Changing the UI Now let's use these new procedures to ;; create interactive commands and bind them to keys by changing our ;; config file @file{example/hello-emacsy.scm}. (use-modules (emacsy emacsy)) ;;. (define-interactive (incr-counter #:optional (n (universal-argument-pop!))) "Increment the counter." (set-counter! (+ (get-counter) n))) ;;. (define-interactive (decr-counter #:optional (n (universal-argument-pop!))) "Decrement the counter." (set-counter! (- (get-counter) n))) ;; Bind @var{inc-counter} to @code{=}. (define-key global-map "=" 'incr-counter) ;; Bind @var{inc-counter} to @code{-}. (define-key global-map "-" 'decr-counter) ;; We can now hit @verb{|-|} and @verb{|=|} to decrement and increment the ;; @var{counter}. This is fine, but what else can we do with it? We could ;; make a macro that increments 5 times by hitting ;; @verb{|C-x ( = = = = = C-x )|}, then hit @verb{|C-e|} to run that macro. ;; (set! debug-on-error? #t) ;; Let's implement another command that will ask the user for a number to ;; set the counter to. ;;. ;; Now we can hit @verb{|M-x change-counter|} and we'll be prompted for ;; the new value we want. There we have it. We have made the simplest ;; application ever more @emph{Emacs-y}. (define-interactive (change-counter) "Change the counter to a new value." (set-counter! (string->number (read-from-minibuffer "New counter value: ")))) ;; @subsection Changing it at Runtime ;; ;; We can add commands easily by changing and reloading the file. But ;; we can do better. Let's start a REPL we can connect to. ;; @file{example/hello-emacsy.scm}. ;;. ;; @example ;; (use-modules (system repl server)) ;; (spawn-server) ;; @end example ;; Start a server on port 37146. ;;. ;; Start a server on port 37146. (use-modules (system repl server)) (spawn-server)
/* Emacsy --- An embeddable Emacs-like library using GNU Guile Copyright (C) 2012, 2013 Shane Celis <shane.celis@gmail.com> Copyright (C) 2019, Jan (janneke) Nieuwenhuizen <janneke@gnu.org> This file is part of Emacsy. Emacsy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Emacsy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Emacsy. If not, see <http://www.gnu.org/licenses/>. */ #ifndef __EMACSY_H #define __EMACSY_H 1 #ifdef __cplusplus extern "C" { #endif #include <libguile.h> /* Here are the constants for the C API. */ /* */ /* */ /* <emacsy-c-api:Defines>= */ #define EMACSY_MODKEY_COUNT 6 #define EMACSY_MODKEY_ALT 1 // A #define EMACSY_MODKEY_CONTROL 2 // C #define EMACSY_MODKEY_HYPER 4 // H #define EMACSY_MODKEY_META 8 // M #define EMACSY_MODKEY_SUPER 16 // s #define EMACSY_MODKEY_SHIFT 32 // S #define EMACSY_MOUSE_BUTTON_DOWN 0 #define EMACSY_MOUSE_BUTTON_UP 1 #define EMACSY_MOUSE_MOTION 2 #define EMACSY_INTERACTIVE 1 #define EMACSY_NON_INTERACTIVE 0 /* Here are the return flags that may be returned by \verb|emacsy_tick|. */ /* */ /* */ /* <emacsy-c-api:Defines>= */ #define EMACSY_QUIT_APPLICATION_P 1 #define EMACSY_ECHO_AREA_UPDATED_P 2 #define EMACSY_MODELINE_UPDATED_P 4 #define EMACSY_RAN_UNDEFINED_COMMAND_P 8 /* * Emacsy provides a C API to ease integration with C and C++ * programs. The C API is given below. */ /* Initialize Emacsy. */ int emacsy_initialize (int init_flags); /* Enqueue a keyboard event. */ void emacsy_key_event (int char_code, int modifier_key_flags); /* Enqueue a mouse event. */ void emacsy_mouse_event (int x, int y, int state, int button, int modifier_key_flags); /* Run an iteration of Emacsy's event loop, does not block. */ int emacsy_tick (); /* Return the message or echo area. */ char *emacsy_message_or_echo_area (); /* Return the mode line. */ char *emacsy_mode_line (); /* Return the name of the current buffer. */ char *emacsy_current_buffer (); /* Run a hook. */ int emacsy_run_hook_0 (char const *hook_name); /* Return the minibuffer point. */ int emacsy_minibuffer_point (); /* Terminate Emacsy; run termination hook. */ int emacsy_terminate (); /* Attempt to load a module. */ int emacsy_load_module (char const *module_name); /* Load a file in the emacsy environment. */ //int emacsy_load(const char *file_name); /* Convert the modifier_key_flags into a Scheme list of symbols. */ SCM modifier_key_flags_to_list(int modifier_key_flags); /* SCM scm_c_string_to_symbol (char const* str) */ SCM scm_c_string_to_symbol (char const* str); /* Ref @var{name} from emacsy module. */ SCM scm_c_emacsy_ref (char const* name); #ifdef __cplusplus } #endif #endif // __EMACSY_H
Next: Contributing, Previous: Hello Emacsy, Up: Top [Contents][Index]
I expounded on the virtues of the Key Lookup Execute Command Loop (KLECL) in see Overlooked Treasure. Now we’re going to implement a KLECL, which requires fleshing out some concepts. We need events, keymaps, and commands. Let’s begin with events.
• C Api | ||
• Emacsy Facade | ||
• Event | ||
• Keymap | ||
• Command | ||
• Block | ||
• KLECL | Key-Lookup-Execute-Command-Loop | |
• Kbd-Macro | Keyboard Macros | |
• Buffer | ||
• Text | ||
• Minibuffer | ||
• Core | ||
• Advice | ||
• Window | Window module (optional) | |
• Help | ||
• Self-doc | Self-documentation |
Next: Emacsy Facade, Up: Api [Contents][Index]
Emacsy provides a C API to ease integration with C and C++ programs. The C API is given below.
Initialize Emacsy.
Enqueue a keyboard event.
Enqueue a mouse event.
Run an iteration of Emacsy’s event loop, does not block.
Return the mode line.
Run a hook.
Return the minibuffer point.
Terminate Emacsy; run termination hook.
Attempt to load a module.
The function scm_c_use_module throws an exception if it cannot find the module, so we have to split that functionality into a body function load_module_try and an error handler load_module_error.
Attempt to load a module. Returns 0 if no errors, and non-zero otherwise.
Convert integer flags to a list of symbols.
Ref name from emacsy module.
So that users of our library don’t have to import all of our nicely partitioned modules individually, we’ll expose a facade module that re-exports all of the public interfaces for each module. Just use
(use-modules (emacsy emacsy))
or
#:use-module (emacsy emacsy)
Next: Keymap, Previous: Emacsy Facade, Up: Api [Contents][Index]
One of the idioms we want to capture from Emacs is this.
(define-key global-map "M-f" 'some-command)
They [[keymap]] and [[command]] module will deal with most of the above, except for the [[kbd]] procedure. That’s something events will be concerned with. One may define a converter for a [[kbd-entry]] to an event of the proper type. Note that a [[kbd-string]] is broken into multiple [[kbd-entries]] on whitespace boundaries, e.g., “C-x C-f” is a [[kbd-string]] that when parsed becomes two [[kbd-entries]] “C-x” and “C-f”.
Basic event class.
Event to capture key strokes, including the modifier keys.
Event to capture key strokes, including the modifier keys.
Event to capture mouse events.
Event to capture mouse drag events.
Now we have the function [[kbd-entry->key-event]]. [[kbd]] needs to know about this and any other converter function. So let’s register it.
Let’s write the converter for the [[<key-event>]] class that will accept the same kind of strings that Emacs does. If the [[kbd-entry]] does not match the event-type, we return false [[#f]].
For the modifier keys, we are going to emulate Emacs to a fault.
Now we convert the [[<key-event>]] back to a [[kbd-entry]].
Instead of using [[define-generic]] I’ve written a convenience macro [[define-generic-public]] that exports the symbol to the current module. This mimics the functionality of [[define-public]]. In general, any *-public macro will export the symbol or syntax to the
Display the <key-event> in a nice way.
The kbd-entry for mouse events is similar to key events. The regular expression is ^(([ACHMsS]-)*)((up-|down-|drag-)?mouse-([123]))\$.
The keymap stores the mapping between key strokes—or events—and commands. Emacs uses lists for its representation of keymaps. Emacsy instead uses a class that stores entries in a hash table. Another difference for Emacsy is that it does not convert S-C-a to a different representation like [33554433]; it leaves it as a string that is expected to be turned into a canonical representation “C-A”.
Here is an example of the keymap representation in Emacs.
> (let ((k (make-sparse-keymap))) (define-key k "a" 'self-insert-command) (define-key k "<mouse-1>" 'mouse-drag-region) (define-key k "C-x C-f" 'find-file-at-point) k) (keymap (24 keymap (6 . find-file-at-point)) (mouse-1 . mouse-drag-region) (97 . self-insert-command))
When I initially implemented Emacsy, I replicated Emacs’ keymap representation, but I realized it wasn’t necessary. And it seems preferrable to make the representation more transparent to casual inspection. Also, Emacsy isn’t directly responsible for the conversion of keyboard events into [[key-event]]s—that’s a lower level detail that the embedding application must handle. Here is the same keymap as above but in Emacsy.
> (let ((k (make-keymap))) (define-key k "a" 'self-insert-command) (define-key k "mouse-1" 'mouse-drag-region) (define-key k "C-x C-f" 'find-file-at-point) k) #<keymap a self-insert-command C-x #<keymap C-f find-file-at-point> mouse-1 mouse-drag-region>
There are a few differences in how the keymap is produced, and the representation looks slightly different too. For one thing it’s not a list.
Our keymap class has a hashtable of entries and possibly a parent keymap.
If words of command are not clear and distinct, if orders are not thoroughly understood, then the general is to blame.
The command module is responsible for a couple things. In Emacs one defines commands by using the special form [[(interactive)]] within the body of the procedure. Consider this simple command.
(defun hello-command () (interactive) (message "Hello, Emacs!"))
Emacsy uses a more Scheme-like means of defining commands as shown below.
(define-interactive (hello-command) (message "Hello, Emacsy!"))
One deviation from Emacs I want to see within Emacsy is to have the commands be more context sensitive. To illustrate the problem when I hit M-x TAB TAB it autocompletes all the available commands into a buffer. In my case that buffer contains 4,840 commands. This doesn’t seem to hurt command usability, but it does hurt the command discoverability.
I want Emacsy to have command sets that are analogous to keymaps. There will be a global command set [[global-cmdset]] similar to the global keymap [[global-map]]. And in the same way that major and minor modes may add keymaps to a particular buffer, so too may they add command maps.
The class holds the entries, a string completer for tab completion, and potentially a parent command map.
We have accessors for adding, removing, and testing what’s in the set. Note that the parent set is never mutated.
We’re going to capture these blocking continuations into a class.
[[call-blockable]] will handle any aborts to the [[’block]] prompt. If the thunk aborts, it adds an instance of the class [[<blocking-continuation>]] to a list of such instances.
To possibly resume these continuations, we’re going to call [[block-tick]]. Additionally, continuations come in two flavors: serial and non-serial. The constraints on resuming are different. A non-serial block can be resumed whenever the [[continue-when?]] thunk return true. A serial block, however, will only be resumed after every other serial block that has a greater number, meaning more recent, has been resumed.
In addition to simply yielding we can block until a particular condition is met.
And if we have [[block-until]], it’s easy to write [[block-while]].
Sometimes we may just want to kill a blocking continuation. One could just forget the reference and let it be garbage collected. Here, we’re going to throw an exception such that whatever the continuation was doing can potentially be cleaned up.
A box without hinges, key, or lid, yet golden treasure inside is hid.
We finally have all the pieces to properly build the KLECL. First, we have to accept input.
With the command loop I’ve also adopted a prefix of [[primitive-]] which signifies that it does not do any error handling. The command loop sets up a fair amount of state.
Each command loop is given a different number.
This is a convenience procedure to enqueue a key event.
And mainly for testing purposes we also want to discard all input. Or there are cases where we want to unread an event and push it to the front of the queue rather than the rear.
[[read-event]] is the lowest-level procedure for grabbing events. It will block if there are no events to read.
read-key-sequence #:optional prompt #:key keymaps
We also check all the maps for a quit key, typically defined as C-g.
I find it convenient to begin emitting messages in case of error. However, I would like for there to be a clean separation between Emacsy and its KLECL such that someone may write a clean vim-y using it if they so chose. So this message will merely go to the stdout\; however, it will be redefined later.
primitive-command-tick #:optional prompt #:key keymaps undefined-command XXX Rename this to klec, for Key-Lookup-Execute-Command (KLEC)—just missing the loop component?
Now let’s write the command loop without any error handling. This seems a little messy with the continue predicate procedure being passed along. I’m not sure yet, how best to organize it.
We have finished the KLECL. Note that although we have used Emacs-like function names, we have not implemented the Emacs-like UI yet. We have not defined any default key bindings. I want to encourage people to explore different user interfaces based on the KLECL, and one can start from this part of the code. If one wanted to create a modal UI, one could use the [[(emacsy klecl)]] module and not have to worry about any “pollution” of Emacs-isms.
…
We will now add a keyboard macro facility familiar to Emacs users. We hook into the [[read-event]] procedure using a hook.
XXX This also may record the key event that stops the keyboard macro, which it shouldn’t.
FIXME
In addition to regular keyboard macros, Emacsy can execute keyboard macros such that they reproduce the keys at the same pace as they were recorded.
And when you gaze long into an abyss the abyss also gazes into you.
A buffer in Emacs represents text, including its mode, local variables, etc. A Emacsy buffer is not necessarily text. It can be extended to hold whatever the host application is interested in. Emacs’ concepts of buffer, window, and mode are directly analogous to the model, view, and controller respectively—the MVC pattern.
A convenience macro to work with a given buffer.
A convenience macro to do some work
Buffer’s have a name, and there is always a current buffer or it’s false. Note that methods do not work as easily with optional arguments. It seems best to define each method with a different number of arguments as shown below.
This is scary, we will override it when we have <text-buffer>.
method
• Mru-stack |
The buffers are kept in a most recently used stack that has the following operators: add!, remove!, contains?, recall!, and list.
The order of the elements may not change yet the index may be moved around.
Next: Minibuffer, Previous: Buffer, Up: Api [Contents][Index]
Editing and stuff.
.
Alias for delete-forward-char
Alias for delete-backward-char
A child of <buffer>, such as <text-buffer>, <minibuffer> or a custom UI buffer may override these, for efficiency or otherwise.
<text-buffer> inherits from buffer and implements the simplest text editing for the Gap Buffer.
The minibuffer provides a rich interactive textual input system. It offers TAB completion and history. The implementation of it inherits from the <text-buffer>.
We define a keymap with all the typical self-insert-commands that would be expected in an editable buffer
When we show the minibuffer, we’ll show the prompt, the contents (user editable), and the minibuffer-message if applicable.
history can be #f, a symbol, or a <cursor-list>.
We want to be able to look up file names.
Some commands for manipulating the minibuffer history.
Next: Advice, Previous: Minibuffer, Up: Api [Contents][Index]
Now we’re going to put in place some core functionality that makes Emacsy an Emacs-like library.
We need a global keymap.
Sometimes we may want to track the motion events generated by a mouse. We don’t do this all the time because it seems unnecessarily taxing.
When the minibuffer is entered, we want to clear the echo-area. Because the echo-area is defined in core, it seems best to deal with it in core rather than placing echo-area handling code in minibuffer.
These are most of the C API calls.
There is one command that I consider fundamental for an Emacs-like program. Whenever I’m presented with a program that claims to be Emacs-like, I try this out M-: (+ 1 2). If it doesn’t work then it may have Emacs-like key bindings, but it’s not Emacs-like. That command is [[eval-expression]]. Let’s write it.
The second fundamental command is [[execute-extended-command]] invoked with M-x.
This [[universal-argument]] command is written using a different style than is typical for interative Emacs commands. Most Emacs commands are written with their state, keymaps, and ancillary procedures as public variables. This style has a benefit of allowing one to manipulate or extend some pieces; however, there are some benefits to having everything encapsulated in this command procedure. For instance, if the minibuffer were written in this style, one could invoke recursive minibuffers.
We want to be able to load a scheme file.
The *scratch* buffer.
Override kill-buffer; make sure the buffer list does not become empty.
Wise men don’t need advice. Fools won’t take it.
No enemy is worse than bad advice.
Emacs has a facility to define “advice” these are pieces of code that run before, after, or around an already defined function. This article provides a good example.
How will this work? Before we try to make the macro, let’s focus on building up the functions. We want to have a function that we can substitute for the original function which will have a number of before, after, and around pieces of advice that can be attached to it.
Emacsy aims to offer the minimal amount of intrusion to acquire big gains in program functionality. Windows is an optional module for Emacsy. If you want to offer windows that behave like Emacs windows, you can, but you aren’t required to.
The window class contains a renderable window that is associated with a buffer.
The internal window class contains other windows.
Emacs uses the edges of windows (left top right bottom), but I’m more comfortable using bounded coordinate systems (left bottom width height). So let’s write some converters.
Be careful with deep-clone. If you deep clone one window that has references to other windows, you will clone entire object graph.
Cycling order for recenter-top-bottom.
Emacs offers a fantastic comprehensive help system. Emacsy intends to replicate most of this functionality. One distinction that would be nice to make is to partition Scheme values into procedures, variables, and parameters. In Scheme, all these kinds of values are the handled the same way. In Emacs, each are accessible by the help system distinctly. For instance, [[C-h f]] looks up functions, [[C-h v]] looks up variables. In addition to defining what kind of value a variable holds, this also allows one to include documentation for values which is not included in Guile Scheme by default. (XXX fact check.)
XXX Rename from variable-documentation to just documentation.
We also want to be able to collect up all the variables in some given module.
Parameters behave similarly to variables; however, whenever they are defined, their values are set.
Next: Acknowledgments, Previous: Api, Up: Top [Contents][Index]
• Building from Git | The latest and greatest. | |
• Running Emacsy From the Source Tree | Hacker tricks. | |
• The Perfect Setup | The right tools. | |
• Coding Style | Hygiene of the contributor. | |
• Submitting Patches | Share your work. |
Next: Running Emacsy From the Source Tree, Up: Contributing [Contents][Index]
If you want to hack Emacsy itself, it is recommended to use the latest version from the Git repository:
git clone git://git.savannah.gnu.org/emacsy.git
The easiest way to set up a development environment for Emacsy is, of course, by using Guix! The following command starts a new shell where all the dependencies and appropriate environment variables are set up to hack on Emacsy:
GUIX_PACKAGE_PATH=guix guix environment -l .guix.scm
Finally, you have to invoke make check
to run tests
(see Running the Test Suites). If anything fails, take a look at
installation instructions (see Installation) or send a emacsysage to
the bug-emacsy@gnu.org mailing list.
Next: The Perfect Setup, Previous: Building from Git, Up: Contributing [Contents][Index]
First, you need to have an environment with all the dependencies
available (see Building from Git), and then simply prefix each
command by ./pre-inst-env
(the pre-inst-env script
lives in the top build tree of Emacsy).
Next: Coding Style, Previous: Running Emacsy From the Source Tree, Up: Contributing [Contents][Index]
The Perfect Setup to hack on Emacsy is basically the perfect setup used for Guile hacking (see Using Guile in Emacs in Guile Reference Manual). First, you need more than an editor, you need Emacs, empowered by the wonderful Geiser.
Geiser allows for interactive and incremental development from within Emacs: code compilation and evaluation from within buffers, access to on-line documentation (docstrings), context-sensitive completion, M-. to jump to an object definition, a REPL to try out your code, and more (see Introduction in Geiser User Manual).
Next: Submitting Patches, Previous: The Perfect Setup, Up: Contributing [Contents][Index]
In general our code follows the GNU Coding Standards (see GNU Coding Standards). However, they do not say much about Scheme, so here are some additional rules.
Scheme code in Emacsy is written in a purely functional style.
When writing Scheme code, we follow common wisdom among Scheme programmers. In general, we follow the Riastradh’s Lisp Style Rules. This document happens to describe the conventions mostly used in Guile’s code too. It is very thoughtful and well written, so please do read it.
If you do not use Emacs, please make sure to let your editor knows these rules.
Additionally, in Emacsy we prefer to format if
statements like this
(if foo? trivial-then (let ((bar (the-longer …))) more-complicated … else))
Previous: Coding Style, Up: Contributing [Contents][Index]
Development is done using the Git distributed version control system.
Thus, access to the repository is not strictly necessary. We welcome
contributions in the form of patches as produced by git
format-patch
sent to the guile-user@gnu.org mailing list.
Please write commit logs in the ChangeLog format (see Change Logs in GNU Coding Standards); you can check the commit history for examples.
Encountering a problem or bug can be very frustrating for you as a user or potential contributor. For us as Emacsy maintainers, the preferred bug report includes a beautiful and tested patch that we can integrate without any effort.
However, please don’t let our preference stop you from reporting a bug. There’s one thing much worse for us than getting a bug report without a patch: Reading a complaint or rant online about your frustrations and how our work sucks, without having heard directly what you experienced.
So if you report a problem, will it be fixed? And when? The most honest answer is: It depends. Let’s curry that informationless honesty with a more helpful and more blunt reminder of a mantra of free software:
- Q:
When will it be finished?
- A:
It will be ready sooner if you help.
Join us on #guile
on the Freenode IRC network or on
guile-user@gnu.org to share your experience—good or bad.
Please send bug reports with full details to guile-user@gnu.org.
Next: Resources, Previous: Contributing, Up: Top [Contents][Index]
We would like to thank the following people for their help:
Next: GNU Free Documentation License, Previous: Acknowledgments, Up: Top [Contents][Index]
Next: Programming Index, Previous: Resources, Up: Top [Contents][Index]
Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. http://fsf.org/ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
The purpose of this License is to make a manual, textbook, or other functional and useful document free in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.
This License is a kind of “copyleft”, which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.
We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.
This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The “Document”, below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as “you”. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law.
A “Modified Version” of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.
A “Secondary Section” is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them.
The “Invariant Sections” are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none.
The “Cover Texts” are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words.
A “Transparent” copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not “Transparent” is called “Opaque”.
Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only.
The “Title Page” means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, “Title Page” means the text near the most prominent appearance of the work’s title, preceding the beginning of the body of the text.
The “publisher” means any person or entity that distributes copies of the Document to the public.
A section “Entitled XYZ” means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as “Acknowledgements”, “Dedications”, “Endorsements”, or “History”.) To “Preserve the Title” of such a section when you modify the Document means that it remains a section “Entitled XYZ” according to this definition.
The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License.
You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, and you may publicly display copies.
If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document’s license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.
If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.
It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.
You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:
If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version’s license notice. These titles must be distinct from any other section titles.
You may add a section Entitled “Endorsements”, provided it contains nothing but endorsements of your Modified Version by various parties—for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.
You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.
You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.
In the combination, you must combine any sections Entitled “History” in the various original documents, forming one section Entitled “History”; likewise combine any sections Entitled “Acknowledgements”, and any sections Entitled “Dedications”. You must delete all sections Entitled “Endorsements.”
You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.
You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.
A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an “aggregate” if the copyright resulting from the compilation is not used to limit the legal rights of the compilation’s users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document’s Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate.
Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail.
If a section in the Document is Entitled “Acknowledgements”, “Dedications”, or “History”, the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title.
You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, or distribute it is void, and will automatically terminate your rights under this License.
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it.
The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License “or any later version” applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. If the Document specifies that a proxy can decide which future versions of this License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Document.
“Massive Multiauthor Collaboration Site” (or “MMC Site”) means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A “Massive Multiauthor Collaboration” (or “MMC”) contained in the site means any set of copyrightable works thus published on the MMC site.
“CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license published by that same organization.
“Incorporate” means to publish or republish a Document, in whole or in part, as part of another Document.
An MMC is “eligible for relicensing” if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, and (2) were thus incorporated prior to November 1, 2008.
The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing.
To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page:
Copyright (C) year your name. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''.
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the “with…Texts.” line with this:
with the Invariant Sections being list their titles, with the Front-Cover Texts being list, and with the Back-Cover Texts being list.
If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation.
If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.
Next: Keyboard command Index, Previous: GNU Free Documentation License, Up: Top [Contents][Index]
Jump to: | (
*
<
A B C D E F G H I K L M N O P Q R S T U V W |
---|
Jump to: | (
*
<
A B C D E F G H I K L M N O P Q R S T U V W |
---|
Next: Concept Index, Previous: Programming Index, Up: Top [Contents][Index]
Jump to: | B C D E F G I K L M N O P Q R S U |
---|
Jump to: | B C D E F G I K L M N O P Q R S U |
---|
Previous: Keyboard command Index, Up: Top [Contents][Index]
Jump to: | B C F I L T |
---|
Jump to: | B C F I L T |
---|
Emacsy has since been converted from a literate noweb program to plain Guile Scheme and this Info document
Kickstarter page http://kck.st/IY0Bau
Note: Emacsy does not rely on FreeGLUT. One could use Gtk+, Ncurses, Qt, or whatever