├── .gitignore
├── .gitmodules
├── FAQ
├── HACKING
├── Makefile.am
├── README
├── THANKS
├── build-aux
├── .gitignore
├── mkdotzee.lua
└── run-tests.lua
├── configure.ac
├── luarocks-config.lua.in
├── m4
├── .gitignore
└── ax_lua.m4
├── mkrockspecs.lua
├── rockspecs.lua
├── tests
├── Makefile.am
├── describe-thing_1.lua
├── describe-thing_1.output
├── describe-thing_2.lua
├── describe-thing_2.output
├── edit-copy.lua
├── edit-copy.output
├── edit-cut.lua
├── edit-cut.output
├── edit-delete-horizontal-space.lua
├── edit-delete-horizontal-space.output
├── edit-delete-next-character.lua
├── edit-delete-next-character.output
├── edit-delete-previous-character.lua
├── edit-delete-previous-character.output
├── edit-delete-word-backward.lua
├── edit-delete-word-backward.output
├── edit-delete-word.lua
├── edit-delete-word.output
├── edit-indent-relative.lua
├── edit-indent-relative.output
├── edit-indent.lua
├── edit-indent.output
├── edit-insert-character.lua
├── edit-insert-character.output
├── edit-insert-newline-and-indent.lua
├── edit-insert-newline-and-indent.output
├── edit-insert-newline.lua
├── edit-insert-newline.output
├── edit-paste.lua
├── edit-paste.output
├── edit-revert.lua
├── edit-revert.output
├── edit-select-other-end.lua
├── edit-select-other-end.output
├── edit-shell-command.lua
├── edit-shell-command.output
├── edit-undo.lua
├── edit-undo.output
├── edit-undo_2.lua
├── edit-undo_2.output
├── fixed-screen
│ ├── move-next-page.lua
│ ├── move-next-page.output
│ ├── move-previous-page.lua
│ └── move-previous-page.output
├── goal-column.lua
├── goal-column.output
├── help-key.lua
├── help-key.output
├── interactive
│ ├── describe-thing_1.lua
│ ├── describe-thing_1.output
│ ├── describe-thing_2.lua
│ ├── describe-thing_2.output
│ ├── edit-copy.lua
│ ├── edit-copy.output
│ ├── edit-cut.lua
│ ├── edit-cut.output
│ ├── edit-delete-horizontal-space.lua
│ ├── edit-delete-horizontal-space.output
│ ├── edit-delete-next-character.lua
│ ├── edit-delete-next-character.output
│ ├── edit-delete-previous-character.lua
│ ├── edit-delete-previous-character.output
│ ├── edit-delete-word-backward.lua
│ ├── edit-delete-word-backward.output
│ ├── edit-delete-word.lua
│ ├── edit-delete-word.output
│ ├── edit-find-backward.lua
│ ├── edit-find-backward.output
│ ├── edit-find.lua
│ ├── edit-find.output
│ ├── edit-goto-column.lua
│ ├── edit-goto-column.output
│ ├── edit-goto-line.lua
│ ├── edit-goto-line.output
│ ├── edit-indent.lua
│ ├── edit-indent.output
│ ├── edit-insert-newline-and-indent.lua
│ ├── edit-insert-newline-and-indent.output
│ ├── edit-insert-newline.lua
│ ├── edit-insert-newline.output
│ ├── edit-insert-quoted.lua
│ ├── edit-insert-quoted.output
│ ├── edit-paste.lua
│ ├── edit-paste.output
│ ├── edit-replace.lua
│ ├── edit-replace.output
│ ├── edit-revert.lua
│ ├── edit-revert.output
│ ├── edit-select-other-end.lua
│ ├── edit-select-other-end.output
│ ├── edit-shell-command.lua
│ ├── edit-shell-command.output
│ ├── edit-undo.lua
│ ├── edit-undo.output
│ ├── execute-command.lua
│ ├── execute-command.output
│ ├── goal-column.lua
│ ├── goal-column.output
│ ├── help-key.lua
│ ├── help-key.output
│ ├── macro-play.lua
│ ├── macro-play.output
│ ├── move-end-file.lua
│ ├── move-end-file.output
│ ├── move-end-line.lua
│ ├── move-end-line.output
│ ├── move-next-character.lua
│ ├── move-next-character.output
│ ├── move-next-line.lua
│ ├── move-next-line.output
│ ├── move-next-paragraph.lua
│ ├── move-next-paragraph.output
│ ├── move-next-word.lua
│ ├── move-next-word.output
│ ├── move-previous-character.lua
│ ├── move-previous-character.output
│ ├── move-previous-line.lua
│ ├── move-previous-line.output
│ ├── move-previous-paragraph.lua
│ ├── move-previous-paragraph.output
│ ├── move-previous-word.lua
│ ├── move-previous-word.output
│ ├── move-start-file.lua
│ ├── move-start-file.output
│ ├── move-start-line.lua
│ ├── move-start-line.output
│ ├── preferences-set-variable.lua
│ ├── preferences-set-variable.output
│ ├── resume_search.lua
│ └── resume_search.output
├── move-end-file.lua
├── move-end-file.output
├── move-end-line.lua
├── move-end-line.output
├── move-goto-character.lua
├── move-goto-character.output
├── move-goto-column.lua
├── move-goto-column.output
├── move-goto-line.lua
├── move-goto-line.output
├── move-next-character.lua
├── move-next-character.output
├── move-next-line.lua
├── move-next-line.output
├── move-next-paragraph.lua
├── move-next-paragraph.output
├── move-next-word.lua
├── move-next-word.output
├── move-previous-character.lua
├── move-previous-character.output
├── move-previous-line.lua
├── move-previous-line.output
├── move-previous-paragraph.lua
├── move-previous-paragraph.output
├── move-previous-word.lua
├── move-previous-word.output
├── move-start-file.lua
├── move-start-file.output
├── move-start-line.lua
├── move-start-line.output
├── preferences-set-variable.lua
├── preferences-set-variable.output
├── preferences-set-variable_nonexistent_variable.lua
├── preferences-set-variable_nonexistent_variable.output
├── regression
│ ├── 33910_execute-kbd-macro_with_edit-insert-quoted.lua
│ ├── 33910_execute-kbd-macro_with_edit-insert-quoted.output
│ ├── 34086_call-last-kbd-macro.lua
│ ├── 34086_call-last-kbd-macro.output
│ ├── 34087_undo_macro.lua
│ ├── 34087_undo_macro.output
│ ├── 34193_interactive_insert.lua
│ ├── 34193_interactive_insert.output
│ ├── 35562_search-backward.lua
│ ├── 35562_search-backward.output
│ ├── 35567_minibuffer_ding_non_printable.lua
│ ├── 35567_minibuffer_ding_non_printable.output
│ ├── forward-char_at_end.lua
│ └── forward-char_at_end.output
└── test.input
├── zee-git-1.rockspec
└── zee
├── .gitignore
├── astr.lua
├── bind.lua
├── buffer.lua
├── completion.lua
├── cua_bindings.lua
├── cut.lua
├── edit.lua
├── emacs_bindings.lua
├── eval.lua
├── file.lua
├── getkey.lua
├── help.lua
├── init.lua.in
├── keycode.lua
├── macro.lua
├── main.lua
├── minibuf.lua
├── move.lua
├── search.lua
├── shell.lua
├── term.lua
├── term_curses.lua
├── undo.lua
├── variables.lua
└── zee.in
/.gitignore:
--------------------------------------------------------------------------------
1 | /zee-[0-9]*.rock
2 | /zee-[0-9]*.rockspec
3 | *~
4 | /COPYING
5 | /ChangeLog
6 | /INSTALL
7 | /README-release
8 | /aclocal.m4
9 | /autom4te.cache
10 | /config.cache
11 | /config.log
12 | /config.status
13 | /config.status.lineno
14 | /configure
15 | /configure.lineno
16 | /luarocks
17 | /luarocks-config.lua
18 | /release-notes*
19 | /zee*.tar.gz
20 | Makefile
21 | Makefile.in
22 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "gnulib"]
2 | path = gnulib
3 | url = git://git.sv.gnu.org/gnulib
4 |
--------------------------------------------------------------------------------
/FAQ:
--------------------------------------------------------------------------------
1 | Zee FAQ - Frequently Asked Questions
2 |
3 | Copyright (c) 1997-2012 Free Software Foundation, Inc.
4 |
5 | Copying and distribution of this file, with or without
6 | modification, are permitted in any medium without royalty
7 | provided the copyright notice and this notice are preserved.
8 |
9 | ------------------------------------------------------------------------------
10 |
11 | INDEX
12 |
13 | 1 Functionality
14 | 1.1 Some keys don't work (e.g. `C-h' does backspace).
15 | 1.2 The META/ALT key doesn't work in xterm.
16 | 1.3 How do I handle non-ASCII characters?
17 |
18 | 2 General questions
19 | 2.1 What does `Zee' mean?
20 | 2.2 Does Zee support Unicode/UTF-8?
21 |
22 | ------------------------------------------------------------------------------
23 |
24 | 1 Functionality
25 |
26 | 1.1 Some keys don't work (e.g. `C-h' does backspace).
27 |
28 | The terminfo entry for your terminal type is probably incorrect.
29 | Rebuilding Zee against the latest ncurses may help.
30 |
31 | With Mac OS X, Terminal.app outputs different escape sequences
32 | than described by the xterm-color terminfo entry. Make sure you
33 | have the default terminal type preference set to xterm-256color,
34 | or else run Zee with:
35 |
36 | TERM=xterm-256color zee
37 |
38 | 1.2 The META/ALT key doesn't work in xterm.
39 |
40 | This is probably because you are using "8-bit input".
41 | Using the following X resources should make things work:
42 |
43 | XTerm*eightBitInput: false
44 | UXTerm*eightBitInput: false
45 |
46 | Typically you'll want to put these lines in your ~/.Xresources
47 | file.
48 |
49 | 1.3 How do I handle non-ASCII characters?
50 |
51 | Zee uses the operating system's locale support, so you need to
52 | set an appropriate locale; how you do this depends on your OS.
53 | However, Zee only works with 8-bit locales.
54 |
55 | ------------------------------------------------------------------------------
56 |
57 | 2 General questions
58 |
59 | 2.1 What does `Zee' mean?
60 |
61 | It's a short name related to `Zile', the name of the editor from
62 | which Zee is descended.
63 |
64 | 2.2 Does Zee support Unicode/UTF-8?
65 |
66 | No, but this is planned.
67 |
--------------------------------------------------------------------------------
/HACKING:
--------------------------------------------------------------------------------
1 | Zee developers' notes
2 | ---------------------
3 |
4 | Copyright (c) 2011-2014 Free Software Foundation, Inc.
5 |
6 | Copying and distribution of this file, with or without
7 | modification, are permitted in any medium without royalty
8 | provided the copyright notice and this notice are preserved.
9 |
10 |
11 | Coding style
12 | ------------
13 |
14 | Rather than attempt an exhaustive list, the following points address
15 | just FDQs (Frequently Discussed Questions).
16 |
17 | 0. Follow the style of existing code. Consistency is more important
18 | than any particular element of style.
19 |
20 | 1. Avoid reversed comparisons. Arguably a good idea in C, but in Lua
21 | "if a = 0 then..." is a syntax error, so there's no need to inflict
22 | "if 0 == a then..." on those who don't like that style.
23 |
24 | 2. Put space around operators and variables: "for i = 0, #t", not
25 | "for i=0,#t". The latter is cramped and harder to read.
26 |
27 | 3. Use one-line conditionals sparingly. As a rule of thumb, only use
28 | them when the entire line is shorter than 70 characters. Their use is
29 | encouraged in code of the form "if CONDITION then return end", and a
30 | one-line "if...then...else...end" may often be superior to the
31 | quasi-ternary operator "x and a or b" (where if "a" can be false
32 | results in "b").
33 |
34 |
35 | Making a release
36 | ----------------
37 |
38 | To make a release you need woger, from
39 | http://rrt.sc3d.org/Software/woger and the dependencies it lists for
40 | releasing on Github and Freecode.
41 |
42 | * Write the release notes in release-notes-$VERSION
43 |
44 | * Run:
45 |
46 | make release
47 |
--------------------------------------------------------------------------------
/Makefile.am:
--------------------------------------------------------------------------------
1 | # Top-level Makefile.am
2 | #
3 | # Copyright (c) 1997-2016 Free Software Foundation, Inc.
4 | #
5 | # This file is part of Zee.
6 | #
7 | # This program is free software; you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation; either version 3, or (at your option)
10 | # any later version.
11 | #
12 | # This program is distributed in the hope that it will be useful, but
13 | # WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | # General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with this program. If not, see .
19 |
20 | CLOC = cloc --force-lang=lua,in
21 |
22 | ACLOCAL_AMFLAGS = -I m4
23 |
24 | LUA_PATH ?= ;
25 | LUA_ENV = LUA_PATH_5_3="$(abs_srcdir)/?.lua;$(abs_srcdir)/?/init.lua;$(LUA_PATH_5_3)"
26 |
27 | doc_DATA = FAQ
28 |
29 | BUILT_SOURCES = \
30 | $(PACKAGE)/init.lua \
31 | $(PACKAGE)/$(PACKAGE).in
32 |
33 | bin_SCRIPTS = $(PACKAGE)/$(PACKAGE)
34 |
35 | LUA_RUNTIME = \
36 | $(PACKAGE)/astr.lua \
37 | $(PACKAGE)/eval.lua \
38 | $(PACKAGE)/main.lua \
39 | $(PACKAGE)/variables.lua \
40 | $(PACKAGE)/move.lua \
41 | $(PACKAGE)/buffer.lua \
42 | $(PACKAGE)/completion.lua \
43 | $(PACKAGE)/shell.lua \
44 | $(PACKAGE)/getkey.lua \
45 | $(PACKAGE)/help.lua \
46 | $(PACKAGE)/file.lua \
47 | $(PACKAGE)/cut.lua \
48 | $(PACKAGE)/edit.lua \
49 | $(PACKAGE)/macro.lua \
50 | $(PACKAGE)/minibuf.lua \
51 | $(PACKAGE)/search.lua \
52 | $(PACKAGE)/undo.lua \
53 | $(PACKAGE)/term.lua \
54 | $(PACKAGE)/keycode.lua \
55 | $(PACKAGE)/bind.lua \
56 | $(PACKAGE)/cua_bindings.lua \
57 | $(PACKAGE)/term_curses.lua
58 |
59 | pkgdata_DATA = $(PACKAGE)/init.lua \
60 | $(LUA_RUNTIME) \
61 | $(PACKAGE)/emacs_bindings.lua
62 |
63 | PRODUCTIONSOURCES = \
64 | $(LUA_RUNTIME) \
65 | $(PACKAGE)/$(PACKAGE).in \
66 | $(PACKAGE)/init.lua.in \
67 | tests/Makefile.am \
68 | Makefile.am \
69 | configure.ac
70 |
71 | $(PACKAGE)/init.lua: Makefile.am $(PACKAGE)/init.lua.in
72 | cat $(PACKAGE)/init.lua.in > $@
73 | for i in $(LUA_RUNTIME); do echo 'require ("'`echo $$i | sed -e 's|\\.lua$$||'`'")' >> $@; done
74 |
75 | install-data-hook:
76 | PACKAGE="$(PACKAGE)" PACKAGE_NAME="$(PACKAGE_NAME)" $(LUA_ENV) $(LUA) $(DESTDIR)$(bindir)/$(PACKAGE) --no-init-file --eval "loadfile ('$(srcdir)/build-aux/mkdot$(PACKAGE).lua') ()" > $@.tmp
77 | $(INSTALL_DATA) $@.tmp $(DESTDIR)$(pkgdatadir)/dot$(PACKAGE).sample
78 | rm -f $@.tmp
79 |
80 | include tests/Makefile.am
81 |
82 | loc:
83 | $(CLOC) $(PRODUCTIONSOURCES) $(srcdir)/build-aux/mkdot$(PACKAGE).lua $(srcdir)/mkrockspecs.lua $(srcdir)/rockspecs.lua
84 |
85 | loc-tests:
86 | $(CLOC) $(ALL_TESTS) $(srcdir)/build-aux/run-tests.lua
87 |
88 | rockspecs:
89 | rm -f *.rockspec
90 | $(LUA) mkrockspecs.lua $(PACKAGE) $(VERSION)
91 | $(LUA) mkrockspecs.lua $(PACKAGE) git
92 |
93 | release: rockspecs
94 | git diff --exit-code && \
95 | git push && \
96 | git tag -a -m "Release tag" v$(VERSION) && \
97 | git push --tags && \
98 | LUAROCKS_CONFIG=$(abs_srcdir)/luarocks-config.lua luarocks --tree=$(abs_srcdir)/luarocks build $(PACKAGE)-$(VERSION)-1.rockspec && \
99 | woger luarocks package=$(PACKAGE) version=$(VERSION)
100 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | Zee
2 | ===
3 |
4 | Zee is free software, licensed under the GNU GPL.
5 |
6 | Copyright (c) 1997-2016 Free Software Foundation, Inc.
7 |
8 | **Copying and distribution of this file, with or without modification,
9 | are permitted in any medium without royalty provided the copyright
10 | notice and this notice are preserved.**
11 |
12 |
13 | INTRODUCTION
14 | ============
15 |
16 | Zee is a lightweight editor. Zee is aimed at small footprint systems
17 | and quick editing sessions (it starts up and shuts down instantly).
18 | Zee's home page is at:
19 |
20 | >
21 |
22 | Zee is written in Lua 5.3 using POSIX APIs, and requires these
23 | additional modules:
24 |
25 | * Lua stdlib
26 | * lrexlib
27 | (the rex_gnu module must be built)
28 | * luaposix
29 | (the curses module must be built)
30 | * alien
31 |
32 | For the exact versions required, see `rockspecs.lua`.
33 |
34 |
35 | INSTALLING
36 | ==========
37 |
38 | The simplest way to install the latest release of Zee is to use
39 | [Luarocks][]
40 |
41 | [Luarocks]: http://luarocks.org/
42 |
43 | Run:
44 |
45 | luarocks install zee
46 |
47 | Development sources are available from the web page. You can build the
48 | latest development sources with:
49 |
50 | luarocks build https://github.com/rrthomas/zee/raw/master/zee-git-1.rockspec
51 |
52 |
53 | REPORTING BUGS
54 | ==============
55 |
56 | If Zee doesn't work for you, before you report the problem, please try
57 | upgrading to the latest released version first, to see whether your
58 | issue has been fixed already. If you can, please also check whether
59 | the latest development sources still exhibit the problem.
60 |
61 | Please file bug reports in the issue tracker at the home page (see
62 | above).
63 |
64 | If you're not an experienced bug reporter, please read this before
65 | reporting a bug:
66 |
67 | >
68 |
69 | Zee has a suite of tests in the source distribution, which you can run
70 | with:
71 |
72 | make check
73 |
74 | If, when you report a bug, you can create a similar test that
75 | demonstrates it, the maintainers will be most grateful, and it will
76 | prevent them from accidentally reintroducing the bug in a subsequent
77 | release.
78 |
79 |
80 | RELATED WORK
81 | ============
82 |
83 | [Zim][http://zim-wiki.org/]
84 | [Leo][http://webpages.charter.net/edreamleo/front.html]
85 |
--------------------------------------------------------------------------------
/THANKS:
--------------------------------------------------------------------------------
1 | The Zee maintainers would like to thank all those who worked on GNU
2 | Zile, from which Zee is derived.
3 |
4 | In particular:
5 |
6 | * Gary Vaughan contributed to the Lua version of Zile,
7 | from which Zee was directly adapted.
8 |
9 | * Alistair Turnbull contributed to the C version
10 | of Zee, from which code was directly translated for Lua Zee.
11 |
--------------------------------------------------------------------------------
/build-aux/.gitignore:
--------------------------------------------------------------------------------
1 | /announce-gen
2 | /config.guess
3 | /config.sub
4 | /do-release-commit-and-tag
5 | /install-sh
6 | /gendocs.sh
7 | /gitlog-to-changelog
8 | /gnu-web-doc-update
9 | /gnupload
10 | /missing
11 | /useless-if-before-free
12 | /vc-list-files
13 | /update-copyright
14 |
--------------------------------------------------------------------------------
/build-aux/mkdotzee.lua:
--------------------------------------------------------------------------------
1 | -- Produce dotzee.sample
2 | --
3 | -- Copyright (c) 2012-2014 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | -- This script should be run as zee -e "loadfile ('script.lua') ()"
21 |
22 | -- Don't note where the contents of this file comes from or that it's
23 | -- auto-generated, because it's ugly in a user configuration file.
24 | io.write (
25 | [[
26 | -- ]] .. os.getenv ("PACKAGE_NAME") .. [[ configuration
27 |
28 | -- Rebind keys with:
29 | -- bind_key("key", "func")
30 |
31 | ]])
32 |
33 | for name, var in pairs (env) do
34 | if not command_exists (name) then
35 | io.writelines ("-- " .. var.doc:gsub ("\n", "\n; "),
36 | "-- Default value is " .. var.val .. ".",
37 | "call_command (\"preferences-set-variable\", \"" .. name .. "\", \"" .. var.val .. "\")",
38 | "")
39 | end
40 | end
41 |
42 | os.exit ()
43 |
--------------------------------------------------------------------------------
/build-aux/run-tests.lua:
--------------------------------------------------------------------------------
1 | -- run-tests
2 | --
3 | -- Copyright (c) 2010-2015 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | posix = require "posix"
21 | std = require "std".barrel ()
22 |
23 | -- N.B. Tests that use macro-play must note that keyboard input
24 | -- is only evaluated once the script has finished running.
25 |
26 | -- The following are defined in the environment for a build
27 | local srcdir = os.getenv ("srcdir") or "."
28 | local abs_srcdir = os.getenv ("abs_srcdir") or "."
29 | local builddir = os.getenv ("builddir") or "."
30 |
31 | local pass = 0
32 | local fail = 0
33 |
34 | local editor_cmd = std.io.catfile (builddir, "zee", os.getenv ("PACKAGE"))
35 | local srcdir_pat = string.escape_pattern (srcdir)
36 |
37 | function run_test (test, name, edit_file, cmd, args)
38 | posix.spawn {"cp", io.catfile (srcdir, "tests", "test.input"), edit_file}
39 | posix.spawn {"chmod", "+w", edit_file}
40 | local status = posix.spawn {cmd, table.unpack (args)}
41 | if status == 0 then
42 | if posix.spawn {"diff", test .. ".output", edit_file} == 0 then
43 | posix.spawn {"rm", "-f", edit_file, edit_file .. "~"}
44 | return true
45 | else
46 | std.debug (name .. " failed to produce correct output")
47 | end
48 | else
49 | std.debug (name .. " failed to run with error code " .. tostring (status))
50 | end
51 | end
52 |
53 | for _, name in ipairs (arg) do
54 | local test = name:gsub ("%.lua$", "")
55 | if io.open (test .. ".output") ~= nil then
56 | name = test:gsub (io.catfile (srcdir, "tests/"), "")
57 | local edit_file = test:gsub ("^" .. srcdir_pat, builddir) .. ".input"
58 | local args = {"--no-init-file", edit_file, "--eval", ("loadfile('%s.lua') ()"):format (test:gsub ("^" .. srcdir_pat, abs_srcdir))}
59 |
60 | posix.spawn {"mkdir", "-p", posix.dirname (edit_file)}
61 |
62 | if run_test (test, name, edit_file, editor_cmd, args) then
63 | pass = pass + 1
64 | else
65 | fail = fail + 1
66 | end
67 | end
68 | end
69 |
70 | posix.spawn {"tset"}
71 | std.debug (string.format ("%d pass(es) and %d failure(s)", pass, fail))
72 |
73 | os.exit (fail)
74 |
--------------------------------------------------------------------------------
/configure.ac:
--------------------------------------------------------------------------------
1 | dnl configure.ac
2 | dnl
3 | dnl Copyright (c) 1997-2016 Free Software Foundation, Inc.
4 | dnl
5 | dnl This file is part of Zee.
6 | dnl
7 | dnl This program is free software; you can redistribute it and/or modify
8 | dnl it under the terms of the GNU General Public License as published
9 | dnl by the Free Software Foundation; either version 3, or (at your
10 | dnl option) any later version.
11 | dnl
12 | dnl This program is distributed in the hope that it will be useful, but
13 | dnl WITHOUT ANY WARRANTY; without even the implied warranty of
14 | dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | dnl General Public License for more details.
16 | dnl
17 | dnl You should have received a copy of the GNU General Public License
18 | dnl along with this program. If not, see .
19 |
20 | AC_PREREQ([2.61])
21 |
22 | dnl Initialise autoconf and automake
23 | AC_INIT([Zee], [0.7.2], [https://github.com/rrthomas/zee])
24 | AC_CONFIG_AUX_DIR([build-aux])
25 | AM_INIT_AUTOMAKE([-Wall -Werror std-options foreign silent-rules])
26 |
27 | dnl Lua
28 | AX_PROG_LUA
29 |
30 | dnl Generate output
31 | AC_CONFIG_FILES([Makefile zee/zee luarocks-config.lua], [chmod +x zee/zee])
32 | AC_OUTPUT
33 |
--------------------------------------------------------------------------------
/luarocks-config.lua.in:
--------------------------------------------------------------------------------
1 | rocks_trees = {
2 | "@abs_srcdir@/luarocks"
3 | }
4 |
--------------------------------------------------------------------------------
/m4/.gitignore:
--------------------------------------------------------------------------------
1 | /00gnulib.m4
2 | /gnulib-cache.m4
3 | /gnulib-common.m4
4 | /gnulib-comp.m4
5 | /gnulib-tool.m4
6 | /onceonly.m4
7 |
--------------------------------------------------------------------------------
/mkrockspecs.lua:
--------------------------------------------------------------------------------
1 | -- Generate rockspecs from a prototype with variants
2 |
3 | local table = require "std.table"
4 | local tree = require "std.tree"
5 |
6 | if select ("#", ...) < 2 then
7 | io.stderr:write "Usage: mkrockspecs PACKAGE VERSION\n"
8 | os.exit ()
9 | end
10 |
11 | package_name = select (1, ...)
12 | version = select (2, ...)
13 |
14 | function format (x, indent)
15 | indent = indent or ""
16 | if type (x) == "table" then
17 | local s = "{\n"
18 | for i, v in ipairs (table.sort (table.keys (x))) do
19 | if type (v) ~= "number" then
20 | s = s..indent..v.." = "..format (x[v], indent.." ")..",\n"
21 | end
22 | end
23 | for i, v in ipairs (x) do
24 | s = s..indent..format (v, indent.." ")..",\n"
25 | end
26 | return s..indent:sub (1, -3).."}"
27 | elseif type (x) == "string" then
28 | return string.format ("%q", x)
29 | else
30 | return tostring (x)
31 | end
32 | end
33 |
34 | flavour = "" -- a global, visible in loadfile
35 | for f, spec in pairs (loadfile ("rockspecs.lua") ()) do
36 | if f ~= "default" then
37 | local specfile = package_name.."-"..(f ~= "" and f:lower ().."-" or "")..version.."-1.rockspec"
38 | h = io.open (specfile, "w")
39 | assert (h)
40 | flavour = f
41 | local specs = loadfile ("rockspecs.lua") () -- reload to get current flavour interpolated
42 | local spec = tree.merge (tree (specs.default), tree (specs[f]))
43 | local s = ""
44 | for i, v in ipairs (table.sort (table.keys (spec))) do
45 | s = s..v.." = "..format (spec[v], " ").."\n"
46 | end
47 | h:write (s)
48 | h:close ()
49 | os.execute ("luarocks lint " .. specfile)
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/rockspecs.lua:
--------------------------------------------------------------------------------
1 | -- Rockspec data
2 |
3 | -- Variables to be interpolated:
4 | --
5 | -- package_name
6 | -- version
7 |
8 | local default = {
9 | package = package_name,
10 | version = version.."-1",
11 | source = {
12 | url = "git://github.com/rrthomas/"..package_name..".git",
13 | },
14 | description = {
15 | summary = "Experimental lightweight editor",
16 | detailed = [[
17 | Zee is a lightweight editor. Zee is aimed at small footprint
18 | systems and quick editing sessions (it starts up and shuts down
19 | instantly).]],
20 | homepage = "http://github.com/rrthomas/"..package_name.."/",
21 | license = "GPLv3+",
22 | },
23 | dependencies = {
24 | "lua == 5.3",
25 | "stdlib >= 41.2.0",
26 | "luaposix == 33.3.1", -- FIXME: Fix to use lcurses package
27 | "lrexlib-gnu >= 2.8.0",
28 | "alien >= 0.7.1",
29 | },
30 | build = {
31 | type = "command",
32 | build_command = "LUA=$(LUA) autoreconf -i && ./configure --prefix=$(PREFIX) --libdir=$(LIBDIR) --datadir=$(LUADIR) && make clean && make",
33 | install_command = "make install",
34 | copy_directories = {},
35 | },
36 | }
37 |
38 | if version ~= "git" then
39 | default.source.branch = "v"..version
40 | end
41 |
42 | return {default=default, [""]={}}
43 |
--------------------------------------------------------------------------------
/tests/Makefile.am:
--------------------------------------------------------------------------------
1 | # Tests Makefile.am
2 | #
3 | # Copyright (c) 1997-2014 Free Software Foundation, Inc.
4 | #
5 | # This file is part of Zee.
6 | #
7 | # This program is free software; you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation; either version 3, or (at your option)
10 | # any later version.
11 | #
12 | # This program is distributed in the hope that it will be useful, but
13 | # WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | # General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with this program. If not, see .
19 |
20 | RUNTESTS = $(LUA) $(srcdir)/build-aux/run-tests.lua
21 |
22 | TERM ?= vt100
23 |
24 | # FIXME: Make interactive tests look up keybindings so they are resistant to default bindings changing
25 | TESTS_NORMAL = \
26 | $(srcdir)/tests/*.lua \
27 | $(srcdir)/tests/interactive/*.lua \
28 | $(srcdir)/tests/regression/*.lua
29 |
30 | TESTS_FIXED_SCREEN = \
31 | $(srcdir)/tests/fixed-screen/*.lua
32 |
33 | TEST_OUTPUTS = \
34 | $(srcdir)/tests/*.output \
35 | $(srcdir)/tests/interactive/*.output \
36 | $(srcdir)/tests/regression/*.output \
37 | $(srcdir)/tests/fixed-screen/*.output
38 |
39 | ALL_TESTS = \
40 | $(TESTS_NORMAL) \
41 | $(TESTS_FIXED_SCREEN)
42 |
43 | TESTS_ENVIRONMENT = \
44 | abs_srcdir=$(abs_srcdir) \
45 | srcdir=$(srcdir) \
46 | abs_builddir=$(abs_builddir) \
47 | PACKAGE=$(PACKAGE) \
48 | TERM=$(TERM)
49 |
50 | # Use to find which test hangs:
51 | check-debug:
52 | $(LUA_ENV) $(TESTS_ENVIRONMENT) $(RUNTESTS) $(TESTS_NORMAL) > /dev/null
53 |
54 | # FIXME: nproc and xargs --max-procs are GNU-specific
55 | check-local: $(builddir)/zee/zee
56 | COLUMNS=80 LINES=24 $(TESTS_ENVIRONMENT) $(RUNTESTS) $(TESTS_FIXED_SCREEN) > /dev/null
57 | NPROC=`nproc`; \
58 | echo $(TESTS_NORMAL) | $(LUA_ENV) $(TESTS_ENVIRONMENT) xargs --max-procs=$$NPROC --max-args=$$(( `echo $(TESTS_NORMAL) | wc -w` / $$NPROC + 1 )) $(RUNTESTS) > /dev/null
59 |
--------------------------------------------------------------------------------
/tests/describe-thing_1.lua:
--------------------------------------------------------------------------------
1 | call_command ("help-thing", "move-next-character")
2 | call_command ("file-save")
3 | call_command ("file-quit")
4 |
--------------------------------------------------------------------------------
/tests/describe-thing_1.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/describe-thing_2.lua:
--------------------------------------------------------------------------------
1 | call_command ("help-thing", "tab-width")
2 | call_command ("file-save")
3 | call_command ("file-quit")
4 |
--------------------------------------------------------------------------------
/tests/describe-thing_2.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/edit-copy.lua:
--------------------------------------------------------------------------------
1 | call_command ("edit-select-on")
2 | call_command ("move-next-character")
3 | call_command ("move-next-character")
4 | call_command ("move-next-character")
5 | call_command ("move-next-character")
6 | call_command ("edit-copy")
7 | call_command ("edit-paste")
8 | call_command ("file-save")
9 | call_command ("file-quit")
10 |
--------------------------------------------------------------------------------
/tests/edit-copy.output:
--------------------------------------------------------------------------------
1 | HereHere is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/edit-cut.lua:
--------------------------------------------------------------------------------
1 | call_command ("edit-select-on")
2 | call_command ("move-next-line")
3 | call_command ("move-next-line")
4 | call_command ("edit-cut")
5 | call_command ("file-save")
6 | call_command ("file-quit")
7 |
--------------------------------------------------------------------------------
/tests/edit-cut.output:
--------------------------------------------------------------------------------
1 |
2 | And more than one paragraph.
3 |
--------------------------------------------------------------------------------
/tests/edit-delete-horizontal-space.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-next-character")
2 | call_command ("move-next-character")
3 | call_command ("move-next-character")
4 | call_command ("move-next-character")
5 | call_command ("edit-delete-horizontal-space")
6 | call_command ("file-save")
7 | call_command ("file-quit")
8 |
--------------------------------------------------------------------------------
/tests/edit-delete-horizontal-space.output:
--------------------------------------------------------------------------------
1 | Hereis a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/edit-delete-next-character.lua:
--------------------------------------------------------------------------------
1 | call_command ("edit-delete-next-character")
2 | call_command ("file-save")
3 | call_command ("file-quit")
4 |
--------------------------------------------------------------------------------
/tests/edit-delete-next-character.output:
--------------------------------------------------------------------------------
1 | ere is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/edit-delete-previous-character.lua:
--------------------------------------------------------------------------------
1 | insert_string ("aa")
2 | call_command ("edit-delete-previous-character")
3 | call_command ("file-save")
4 | call_command ("file-quit")
5 |
--------------------------------------------------------------------------------
/tests/edit-delete-previous-character.output:
--------------------------------------------------------------------------------
1 | aHere is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/edit-delete-word-backward.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-end-line")
2 | call_command ("edit-delete-word-backward")
3 | call_command ("file-save")
4 | call_command ("file-quit")
5 |
--------------------------------------------------------------------------------
/tests/edit-delete-word-backward.output:
--------------------------------------------------------------------------------
1 | Here is a sample
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/edit-delete-word.lua:
--------------------------------------------------------------------------------
1 | call_command ("edit-delete-word")
2 | call_command ("edit-delete-word")
3 | call_command ("edit-delete-word")
4 | call_command ("file-save")
5 | call_command ("file-quit")
6 |
--------------------------------------------------------------------------------
/tests/edit-delete-word.output:
--------------------------------------------------------------------------------
1 | sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/edit-indent-relative.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-next-line")
2 | call_command ("move-next-line")
3 | call_command ("edit-indent-relative")
4 | insert_string ("f")
5 | call_command ("edit-indent-relative")
6 | insert_string ("fffff")
7 | call_command ("edit-indent-relative")
8 | insert_string ("aaa")
9 | call_command ("file-save")
10 | call_command ("file-quit")
11 |
--------------------------------------------------------------------------------
/tests/edit-indent-relative.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 | f fffff aaa
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/edit-indent.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-next-line")
2 | call_command ("move-next-line")
3 | call_command ("edit-indent")
4 | call_command ("edit-indent")
5 | insert_string ("tab")
6 | call_command ("file-save")
7 | call_command ("file-quit")
8 |
--------------------------------------------------------------------------------
/tests/edit-indent.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 | tab
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/edit-insert-character.lua:
--------------------------------------------------------------------------------
1 | insert_string ("a")
2 | call_command ("file-save")
3 | call_command ("file-quit")
4 |
--------------------------------------------------------------------------------
/tests/edit-insert-character.output:
--------------------------------------------------------------------------------
1 | aHere is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/edit-insert-newline-and-indent.lua:
--------------------------------------------------------------------------------
1 | call_command ("edit-insert-newline-and-indent")
2 | call_command ("move-next-line")
3 | call_command ("edit-insert-newline-and-indent")
4 | call_command ("move-next-line")
5 | call_command ("edit-insert-newline-and-indent")
6 | call_command ("edit-insert-newline-and-indent")
7 | call_command ("file-save")
8 | call_command ("file-quit")
9 |
--------------------------------------------------------------------------------
/tests/edit-insert-newline-and-indent.output:
--------------------------------------------------------------------------------
1 |
2 | Here is a sample file.
3 |
4 | It has several lines.
5 |
6 |
7 |
8 | And more than one paragraph.
9 |
--------------------------------------------------------------------------------
/tests/edit-insert-newline.lua:
--------------------------------------------------------------------------------
1 | call_command ("edit-insert-newline")
2 | call_command ("edit-insert-newline")
3 | call_command ("edit-insert-newline")
4 | insert_string ("a")
5 | call_command ("file-save")
6 | call_command ("file-quit")
7 |
--------------------------------------------------------------------------------
/tests/edit-insert-newline.output:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | aHere is a sample file.
5 | It has several lines.
6 |
7 | And more than one paragraph.
8 |
--------------------------------------------------------------------------------
/tests/edit-paste.lua:
--------------------------------------------------------------------------------
1 | call_command ("edit-select-on")
2 | call_command ("move-next-line")
3 | call_command ("move-next-line")
4 | call_command ("edit-cut")
5 | call_command ("move-next-line")
6 | call_command ("move-next-line")
7 | call_command ("move-next-line")
8 | call_command ("edit-paste")
9 | call_command ("file-save")
10 | call_command ("file-quit")
11 |
--------------------------------------------------------------------------------
/tests/edit-paste.output:
--------------------------------------------------------------------------------
1 |
2 | And more than one paragraph.
3 | Here is a sample file.
4 | It has several lines.
5 |
--------------------------------------------------------------------------------
/tests/edit-revert.lua:
--------------------------------------------------------------------------------
1 | call_command ("edit-delete-next-character")
2 | call_command ("edit-delete-next-character")
3 | call_command ("edit-delete-next-character")
4 | call_command ("edit-delete-next-character")
5 | call_command ("edit-revert")
6 | call_command ("file-save")
7 | call_command ("file-quit")
8 |
--------------------------------------------------------------------------------
/tests/edit-revert.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/edit-select-other-end.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-next-character")
2 | call_command ("move-next-character")
3 | call_command ("move-next-character")
4 | call_command ("move-next-character")
5 | call_command ("edit-select-on")
6 | call_command ("forward-line")
7 | call_command ("forward-line")
8 | call_command ("edit-select-other-end")
9 | insert_string ("f")
10 | call_command ("file-save")
11 | call_command ("file-quit")
12 |
--------------------------------------------------------------------------------
/tests/edit-select-other-end.output:
--------------------------------------------------------------------------------
1 | Heref is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/edit-shell-command.lua:
--------------------------------------------------------------------------------
1 | call_command ("edit-select-on")
2 | call_command ("move-next-line")
3 | call_command ("move-next-line")
4 | call_command ("move-next-line")
5 | call_command ("move-next-line")
6 | call_command ("edit-shell-command", "sort")
7 | call_command ("file-save")
8 | call_command ("file-quit")
9 |
--------------------------------------------------------------------------------
/tests/edit-shell-command.output:
--------------------------------------------------------------------------------
1 |
2 | And more than one paragraph.
3 | Here is a sample file.
4 | It has several lines.
5 |
--------------------------------------------------------------------------------
/tests/edit-undo.lua:
--------------------------------------------------------------------------------
1 | call_command ("edit-delete-next-character")
2 | call_command ("edit-delete-next-character")
3 | call_command ("edit-delete-next-character")
4 | call_command ("edit-delete-next-character")
5 | call_command ("edit-undo")
6 | call_command ("edit-undo")
7 | call_command ("edit-undo")
8 | call_command ("file-save")
9 | call_command ("file-quit")
10 |
--------------------------------------------------------------------------------
/tests/edit-undo.output:
--------------------------------------------------------------------------------
1 | ere is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/edit-undo_2.lua:
--------------------------------------------------------------------------------
1 | call_command ("edit-insert-character", "a")
2 | call_command ("edit-undo")
3 | call_command ("edit-insert-character", "b")
4 | call_command ("file-save")
5 | call_command ("file-quit")
6 |
--------------------------------------------------------------------------------
/tests/edit-undo_2.output:
--------------------------------------------------------------------------------
1 | bHere is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/fixed-screen/move-next-page.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-next-page")
2 | insert_string ("a")
3 | call_command ("file-save")
4 | call_command ("file-quit")
5 |
--------------------------------------------------------------------------------
/tests/fixed-screen/move-next-page.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 | a
--------------------------------------------------------------------------------
/tests/fixed-screen/move-previous-page.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-end-file")
2 | call_command ("move-previous-page")
3 | insert_string ("a")
4 | call_command ("file-save")
5 | call_command ("file-quit")
6 |
--------------------------------------------------------------------------------
/tests/fixed-screen/move-previous-page.output:
--------------------------------------------------------------------------------
1 | aHere is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/goal-column.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-next-character")
2 | call_command ("move-next-character")
3 | call_command ("move-next-character")
4 | call_command ("move-next-character")
5 | call_command ("move-next-line")
6 | call_command ("move-next-line")
7 | call_command ("move-next-line")
8 | insert_string ("a")
9 | call_command ("file-save")
10 | call_command ("file-quit")
11 |
--------------------------------------------------------------------------------
/tests/goal-column.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And amore than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/help-key.lua:
--------------------------------------------------------------------------------
1 | call_command ("help-key", "Ctrl-f")
2 | call_command ("file-save")
3 | call_command ("file-quit")
4 |
--------------------------------------------------------------------------------
/tests/help-key.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/describe-thing_1.lua:
--------------------------------------------------------------------------------
1 | -- help-thing "move-next-character" Return
2 | -- file-save file-quit
3 | call_command ("macro-play", "Ctrl-Alt-x", "h", "e", "l", "p", "-", "t", "h", "i", "n", "g", "Return", "m", "o", "v", "e", "-", "n", "e", "x", "t", "-", "c", "h", "a", "r", "a", "c", "t", "e", "r", "Return", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/describe-thing_1.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/describe-thing_2.lua:
--------------------------------------------------------------------------------
1 | -- help-thing "tab-width" Return
2 | -- file-save file-quit
3 | call_command ("macro-play", "Ctrl-Alt-x", "h", "e", "l", "p", "-", "t", "h", "i", "n", "g", "Return", "i", "n", "d", "e", "n", "t", "-", "w", "i", "d", "t", "h", "Return", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/describe-thing_2.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-copy.lua:
--------------------------------------------------------------------------------
1 | -- edit-select-on move-next-character move-next-character move-next-character move-next-character
2 | -- edit-copy edit-paste file-save file-quit
3 | call_command ("macro-play", "Ctrl-@", "Right", "Right", "Right", "Right", "Ctrl-c", "Ctrl-v", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/edit-copy.output:
--------------------------------------------------------------------------------
1 | HereHere is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-cut.lua:
--------------------------------------------------------------------------------
1 | -- edit-select-on edit-goto-line 3 Return edit-cut
2 | -- file-save file-quit
3 | call_command ("macro-play", "Ctrl-@", "Ctrl-Alt-g", "3", "Return", "Ctrl-x", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/edit-cut.output:
--------------------------------------------------------------------------------
1 |
2 | And more than one paragraph.
3 |
--------------------------------------------------------------------------------
/tests/interactive/edit-delete-horizontal-space.lua:
--------------------------------------------------------------------------------
1 | -- move-next-character move-next-character move-next-character move-next-character delete-horizontal-space
2 | -- file-save file-quit
3 | call_command ("macro-play", "Right", "Right", "Right", "Right", "Ctrl-Alt-d", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/edit-delete-horizontal-space.output:
--------------------------------------------------------------------------------
1 | Hereis a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-delete-next-character.lua:
--------------------------------------------------------------------------------
1 | -- edit-delete-next-character file-save file-quit
2 | call_command ("macro-play", "Delete", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/edit-delete-next-character.output:
--------------------------------------------------------------------------------
1 | ere is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-delete-previous-character.lua:
--------------------------------------------------------------------------------
1 | -- a a edit-delete-previous-character file-save file-quit
2 | call_command ("macro-play", "a", "a", "Ctrl-?", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/edit-delete-previous-character.output:
--------------------------------------------------------------------------------
1 | aHere is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-delete-word-backward.lua:
--------------------------------------------------------------------------------
1 | -- move-end-line edit-kill-word-backward file-save file-quit
2 | call_command ("macro-play", "End", "Ctrl-Alt-?", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/edit-delete-word-backward.output:
--------------------------------------------------------------------------------
1 | Here is a sample
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-delete-word.lua:
--------------------------------------------------------------------------------
1 | -- edit-kill-word edit-kill-word edit-kill-word file-save file-quit
2 | call_command ("macro-play", "Ctrl-Delete", "Ctrl-Delete", "Ctrl-Delete", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/edit-delete-word.output:
--------------------------------------------------------------------------------
1 | sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-find-backward.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-next-line")
2 | call_command ("move-next-line")
3 | -- edit-find-backward e . e Return f file-save file-quit
4 | call_command ("macro-play", "Ctrl-Alt-f", "e", ".", "e", "Return", "f", "Ctrl-s", "Ctrl-q")
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-find-backward.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has sfeveral lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-find.lua:
--------------------------------------------------------------------------------
1 | -- edit-find [ a ] . p Return f file-save file-quit
2 | call_command ("macro-play", "Ctrl-f", "[", "a", "]", ".", "p", "Return", "f", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/edit-find.output:
--------------------------------------------------------------------------------
1 | Here is a sampfle file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-goto-column.lua:
--------------------------------------------------------------------------------
1 | -- edit-goto-column 8 Return a file-save file-quit
2 | call_command ("macro-play", "Ctrl-Alt-c", "8", "Return", "a", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/edit-goto-column.output:
--------------------------------------------------------------------------------
1 | Here isa a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-goto-line.lua:
--------------------------------------------------------------------------------
1 | -- edit-goto-line 4 Return a file-save file-quit
2 | call_command ("macro-play", "Ctrl-Alt-g", "4", "Return", "a", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/edit-goto-line.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | aAnd more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-indent.lua:
--------------------------------------------------------------------------------
1 | -- edit-goto-line 3 Return edit-indent edit-indent t a b
2 | -- file-save file-quit
3 | call_command ("macro-play", "Ctrl-Alt-g", "3", "Return", "Alt-Tab", "Alt-Tab", "t", "a", "b", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/edit-indent.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 | tab
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-insert-newline-and-indent.lua:
--------------------------------------------------------------------------------
1 | -- edit-insert-newline-and-indent edit-goto-line 3 Return
2 | -- edit-insert-newline-and-indent edit-goto-line 5 Return
3 | -- edit-insert-newline-and-indent edit-insert-newline-and-indent file-save file-quit
4 | call_command ("macro-play", "Return", "Ctrl-Alt-g", "3", "Return", "Return", "Ctrl-Alt-g", "5", "Return", "Return", "Return", "Ctrl-s", "Ctrl-q")
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-insert-newline-and-indent.output:
--------------------------------------------------------------------------------
1 |
2 | Here is a sample file.
3 |
4 | It has several lines.
5 |
6 |
7 |
8 | And more than one paragraph.
9 |
--------------------------------------------------------------------------------
/tests/interactive/edit-insert-newline.lua:
--------------------------------------------------------------------------------
1 | -- edit-insert-newline edit-insert-newline edit-insert-newline a file-save file-quit
2 | call_command ("macro-play", "Return", "Return", "Return", "a", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/edit-insert-newline.output:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | aHere is a sample file.
5 | It has several lines.
6 |
7 | And more than one paragraph.
8 |
--------------------------------------------------------------------------------
/tests/interactive/edit-insert-quoted.lua:
--------------------------------------------------------------------------------
1 | -- edit-insert-quoted Ctrl-a edit-insert-quoted Ctrl-h edit-insert-quoted Ctrl-z edit-insert-quoted Ctrl-q
2 | -- edit-insert-quoted ESC O P edit-insert-quoted Tab file-save file-quit
3 | call_command ("macro-play", "Ctrl-Alt-q", "Ctrl-a", "Ctrl-Alt-q", "Ctrl-h", "Ctrl-Alt-q", "Ctrl-z", "Ctrl-Alt-q", "Ctrl-q", "Ctrl-Alt-q", "Escape", "O", "P", "Ctrl-Alt-q", "Tab", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/edit-insert-quoted.output:
--------------------------------------------------------------------------------
1 | OP Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-paste.lua:
--------------------------------------------------------------------------------
1 | -- edit-select-on edit-goto-line 3 Return edit-cut move-end-file edit-paste
2 | -- file-save file-quit
3 | call_command ("macro-play", "Ctrl-@", "Ctrl-Alt-g", "3", "Return", "Ctrl-x", "Ctrl-End", "Ctrl-v", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/edit-paste.output:
--------------------------------------------------------------------------------
1 |
2 | And more than one paragraph.
3 | Here is a sample file.
4 | It has several lines.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-replace.lua:
--------------------------------------------------------------------------------
1 | -- query-replace l e Return b d Return ! file-save file-quit
2 | call_command ("macro-play", "Ctrl-r", "l", "e", "Return", "b", "d", "Return", "!", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/edit-replace.output:
--------------------------------------------------------------------------------
1 | Here is a sampbd fibd.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-revert.lua:
--------------------------------------------------------------------------------
1 | -- edit-delete-next-character edit-delete-next-character edit-delete-next-character edit-delete-next-character
2 | -- Alt-x edit-revert Return
3 | -- file-save file-quit
4 | call_command ("macro-play", "Delete", "Delete", "Delete", "Delete", "Ctrl-Alt-x", "e", "d", "i", "t", "-", "r", "e", "v", "e", "r", "t", "Return", "Ctrl-s", "Ctrl-q")
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-revert.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-select-other-end.lua:
--------------------------------------------------------------------------------
1 | -- move-next-character move-next-character move-next-character move-next-character
2 | -- edit-select-toggle move-end-file edit-select-other-end f file-save file-quit
3 | call_command ("macro-play", "Right", "Right", "Right", "Right", "Ctrl-@", "Ctrl-End", "Alt-Space", "f", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/edit-select-other-end.output:
--------------------------------------------------------------------------------
1 | Heref is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-shell-command.lua:
--------------------------------------------------------------------------------
1 | -- edit-select-on edit-goto-line 5 Return shell-command-on-region "sort" Return
2 | -- file-save file-quit
3 | call_command ("macro-play", "Ctrl-@", "Ctrl-Alt-g", "5", "Return", "Ctrl-Alt-s", "s", "o", "r", "t", "Return", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/edit-shell-command.output:
--------------------------------------------------------------------------------
1 |
2 | And more than one paragraph.
3 | Here is a sample file.
4 | It has several lines.
5 |
--------------------------------------------------------------------------------
/tests/interactive/edit-undo.lua:
--------------------------------------------------------------------------------
1 | -- edit-delete-next-character edit-delete-next-character edit-delete-next-character edit-delete-next-character edit-undo edit-undo edit-undo
2 | -- file-save file-quit
3 | call_command ("macro-play", "Delete", "Delete", "Delete", "Delete", "Ctrl-z", "Ctrl-z", "Ctrl-z", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/edit-undo.output:
--------------------------------------------------------------------------------
1 | ere is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/execute-command.lua:
--------------------------------------------------------------------------------
1 | -- Alt-x move-next-character Return a file-save file-quit
2 | call_command ("macro-play", "Ctrl-Alt-x", "m", "o", "v", "e", "-", "n", "e", "x", "t", "-", "c", "h", "a", "r", "a", "c", "t", "e", "r", "Return", "a", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/execute-command.output:
--------------------------------------------------------------------------------
1 | Haere is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/goal-column.lua:
--------------------------------------------------------------------------------
1 | -- move-next-character move-next-character move-next-character move-next-character
2 | -- move-next-line move-next-line move-next-line a file-save file-quit
3 | call_command ("macro-play", "Right", "Right", "Right", "Right", "Down", "Down", "Down", "a", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/goal-column.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And amore than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/help-key.lua:
--------------------------------------------------------------------------------
1 | -- help-key Ctrl-f
2 | -- file-save file-quit
3 | call_command ("macro-play", "Ctrl-Alt-x", "h", "e", "l", "p", "-", "k", "e", "y", "Return", "Right", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/help-key.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/macro-play.lua:
--------------------------------------------------------------------------------
1 | -- macro-record move-next-word a macro-stop call-last-kbd-macro
2 | -- file-save file-quit
3 | call_command ("macro-play", "Ctrl-Alt-x", "m", "a", "c", "r", "o", "-", "r", "e", "c", "o", "r", "d", "Return", "Ctrl-Right", "a", "Ctrl-Alt-x", "m", "a", "c", "r", "o", "-", "s", "t", "o", "p", "Return", "Alt-Return", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/macro-play.output:
--------------------------------------------------------------------------------
1 | Herea isa a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/move-end-file.lua:
--------------------------------------------------------------------------------
1 | -- move-end-file a file-save file-quit
2 | call_command ("macro-play", "Ctrl-End", "a", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/move-end-file.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 | a
--------------------------------------------------------------------------------
/tests/interactive/move-end-line.lua:
--------------------------------------------------------------------------------
1 | -- move-end-line a file-save file-quit
2 | call_command ("macro-play", "End", "a", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/move-end-line.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.a
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/move-next-character.lua:
--------------------------------------------------------------------------------
1 | -- move-next-character move-next-character edit-delete-next-character file-save file-quit
2 | call_command ("macro-play", "Right", "Right", "Delete", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/move-next-character.output:
--------------------------------------------------------------------------------
1 | Hee is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/move-next-line.lua:
--------------------------------------------------------------------------------
1 | -- move-next-line move-next-line a file-save file-quit
2 | call_command ("macro-play", "Down", "Down", "a", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/move-next-line.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 | a
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/move-next-paragraph.lua:
--------------------------------------------------------------------------------
1 | -- move-next-paragraph a file-save file-quit
2 | call_command ("macro-play", "Alt-]", "a", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/move-next-paragraph.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 | a
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/move-next-word.lua:
--------------------------------------------------------------------------------
1 | -- move-next-word move-next-word move-next-word move-next-word a file-save file-quit
2 | call_command ("macro-play", "Ctrl-Right", "Ctrl-Right", "Ctrl-Right", "Ctrl-Right", "a", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/move-next-word.output:
--------------------------------------------------------------------------------
1 | Here is a samplea file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/move-previous-character.lua:
--------------------------------------------------------------------------------
1 | -- move-end-line move-previous-character move-previous-character edit-delete-previous-character
2 | -- file-save file-quit
3 | call_command ("macro-play", "End", "Left", "Left", "Ctrl-?", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/move-previous-character.output:
--------------------------------------------------------------------------------
1 | Here is a sample fie.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/move-previous-line.lua:
--------------------------------------------------------------------------------
1 | -- move-end-file move-previous-line move-previous-line move-previous-line a file-save file-quit
2 | call_command ("macro-play", "Ctrl-End", "Up", "Up", "Up", "a", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/move-previous-line.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | aIt has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/move-previous-paragraph.lua:
--------------------------------------------------------------------------------
1 | -- move-end-file move-previous-paragraph a file-save file-quit
2 | call_command ("macro-play", "Ctrl-End", "Alt-[", "a", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/move-previous-paragraph.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 | a
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/move-previous-word.lua:
--------------------------------------------------------------------------------
1 | -- move-end-line move-previous-word move-previous-word a file-save file-quit
2 | call_command ("macro-play", "End", "Ctrl-Left", "Ctrl-Left", "a", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/move-previous-word.output:
--------------------------------------------------------------------------------
1 | Here is a asample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/move-start-file.lua:
--------------------------------------------------------------------------------
1 | -- move-end-file a move-start-file b file-save file-quit
2 | call_command ("macro-play", "Ctrl-End", "a", "Ctrl-Home", "b", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/interactive/move-start-file.output:
--------------------------------------------------------------------------------
1 | bHere is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 | a
--------------------------------------------------------------------------------
/tests/interactive/move-start-line.lua:
--------------------------------------------------------------------------------
1 | -- edit-goto-line 2 Return move-next-word move-next-word move-next-word move-start-line a
2 | -- file-save file-quit
3 | call_command ("macro-play", "Ctrl-Alt-g", "2", "Return", "Ctrl-Right", "Ctrl-Right", "Ctrl-Right", "Home", "a", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/move-start-line.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | aIt has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/preferences-set-variable.lua:
--------------------------------------------------------------------------------
1 | -- preferences-set-variable "case-fold-search" Return false Return
2 | -- edit-find "I" Return a file-save file-quit
3 | call_command ("macro-play", "Ctrl-Alt-x", "p", "r", "e", "f", "e", "r", "e", "n", "c", "e", "s", "-", "s", "e", "t", "-", "v", "a", "r", "i", "a", "b", "l", "e", "Return", "c", "a", "s", "e", "l", "e", "s", "s", "-", "s", "e", "a", "r", "c", "h", "Return", "f", "a", "l", "s", "e", "Return", "Ctrl-f", "I", "Return", "a", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/preferences-set-variable.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | Iat has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/interactive/resume_search.lua:
--------------------------------------------------------------------------------
1 | -- search-forward "ra" isearch-forward ENTER 2 isearch-forward isearch-forward ENTER 3
2 | -- file-save file-quit
3 | call_command ("macro-play", "Ctrl-f", "r", "a", "Ctrl-f", "Return", "2", "Ctrl-f", "Ctrl-f", "Return", "3", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/interactive/resume_search.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one para2gra3ph.
5 |
--------------------------------------------------------------------------------
/tests/move-end-file.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-end-file")
2 | insert_string ("a")
3 | call_command ("file-save")
4 | call_command ("file-quit")
5 |
--------------------------------------------------------------------------------
/tests/move-end-file.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 | a
--------------------------------------------------------------------------------
/tests/move-end-line.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-end-line")
2 | insert_string ("a")
3 | call_command ("file-save")
4 | call_command ("file-quit")
5 |
--------------------------------------------------------------------------------
/tests/move-end-line.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.a
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/move-goto-character.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-goto-character", 40)
2 | insert_string ("fff")
3 | call_command ("file-save")
4 | call_command ("file-quit")
5 |
--------------------------------------------------------------------------------
/tests/move-goto-character.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lfffines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/move-goto-column.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-goto-column", 8)
2 | insert_string ("a")
3 | call_command ("file-save")
4 | call_command ("file-quit")
5 |
--------------------------------------------------------------------------------
/tests/move-goto-column.output:
--------------------------------------------------------------------------------
1 | Here isa a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/move-goto-line.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-goto-line", "4")
2 | insert_string ("a")
3 | call_command ("file-save")
4 | call_command ("file-quit")
5 |
--------------------------------------------------------------------------------
/tests/move-goto-line.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | aAnd more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/move-next-character.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-next-character")
2 | call_command ("move-next-character")
3 | call_command ("edit-delete-next-character")
4 | call_command ("file-save")
5 | call_command ("file-quit")
6 |
--------------------------------------------------------------------------------
/tests/move-next-character.output:
--------------------------------------------------------------------------------
1 | Hee is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/move-next-line.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-next-line")
2 | call_command ("move-next-line")
3 | call_command ("move-next-line")
4 | insert_string ("a")
5 | call_command ("file-save")
6 | call_command ("file-quit")
7 |
--------------------------------------------------------------------------------
/tests/move-next-line.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | aAnd more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/move-next-paragraph.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-next-paragraph")
2 | insert_string ("a")
3 | call_command ("file-save")
4 | call_command ("file-quit")
5 |
--------------------------------------------------------------------------------
/tests/move-next-paragraph.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 | a
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/move-next-word.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-next-word")
2 | call_command ("move-next-word")
3 | call_command ("move-next-word")
4 | call_command ("move-next-word")
5 | insert_string ("a")
6 | call_command ("file-save")
7 | call_command ("file-quit")
8 |
--------------------------------------------------------------------------------
/tests/move-next-word.output:
--------------------------------------------------------------------------------
1 | Here is a samplea file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/move-previous-character.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-end-line")
2 | call_command ("move-previous-character")
3 | call_command ("move-previous-character")
4 | call_command ("edit-delete-previous-character")
5 | call_command ("file-save")
6 | call_command ("file-quit")
7 |
--------------------------------------------------------------------------------
/tests/move-previous-character.output:
--------------------------------------------------------------------------------
1 | Here is a sample fie.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/move-previous-line.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-end-file")
2 | call_command ("move-previous-line")
3 | call_command ("move-previous-line")
4 | call_command ("move-previous-line")
5 | insert_string ("a")
6 | call_command ("file-save")
7 | call_command ("file-quit")
8 |
--------------------------------------------------------------------------------
/tests/move-previous-line.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | aIt has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/move-previous-paragraph.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-end-file")
2 | call_command ("move-previous-paragraph")
3 | insert_string ("a")
4 | call_command ("file-save")
5 | call_command ("file-quit")
6 |
--------------------------------------------------------------------------------
/tests/move-previous-paragraph.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 | a
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/move-previous-word.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-end-line")
2 | call_command ("move-previous-word")
3 | call_command ("move-previous-word")
4 | insert_string ("a")
5 | call_command ("file-save")
6 | call_command ("file-quit")
7 |
--------------------------------------------------------------------------------
/tests/move-previous-word.output:
--------------------------------------------------------------------------------
1 | Here is a asample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/move-start-file.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-end-file")
2 | insert_string ("a")
3 | call_command ("move-start-file")
4 | insert_string ("b")
5 | call_command ("file-save")
6 | call_command ("file-quit")
7 |
--------------------------------------------------------------------------------
/tests/move-start-file.output:
--------------------------------------------------------------------------------
1 | bHere is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 | a
--------------------------------------------------------------------------------
/tests/move-start-line.lua:
--------------------------------------------------------------------------------
1 | call_command ("move-next-line")
2 | call_command ("move-next-word")
3 | call_command ("move-next-word")
4 | call_command ("move-next-word")
5 | call_command ("move-start-line")
6 | insert_string ("a")
7 | call_command ("file-save")
8 | call_command ("file-quit")
9 |
--------------------------------------------------------------------------------
/tests/move-start-line.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | aIt has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/preferences-set-variable.lua:
--------------------------------------------------------------------------------
1 | call_command ("preferences-set-variable", "caseless-search", false)
2 | execute_command ("edit-find", "I")
3 | insert_string ("a")
4 | call_command ("file-save")
5 | call_command ("file-quit")
6 |
--------------------------------------------------------------------------------
/tests/preferences-set-variable.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | Iat has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/preferences-set-variable_nonexistent_variable.lua:
--------------------------------------------------------------------------------
1 | call_command ("preferences-set-variable", "unknown-variable", true)
2 | call_command ("file-save")
3 | call_command ("file-quit")
4 |
--------------------------------------------------------------------------------
/tests/preferences-set-variable_nonexistent_variable.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/regression/33910_execute-kbd-macro_with_edit-insert-quoted.lua:
--------------------------------------------------------------------------------
1 | -- FIXME: Although F1 usually outputs ^[OP, this test will fail
2 | -- when the terminal outputs something else instead.
3 |
4 | -- edit-insert-quoted F1 Return
5 | -- file-save file-quit
6 | call_command ("macro-play", "Ctrl-Alt-q", "F1", "Return", "Ctrl-s", "Ctrl-q")
7 |
--------------------------------------------------------------------------------
/tests/regression/33910_execute-kbd-macro_with_edit-insert-quoted.output:
--------------------------------------------------------------------------------
1 | OP
2 | Here is a sample file.
3 | It has several lines.
4 |
5 | And more than one paragraph.
6 |
--------------------------------------------------------------------------------
/tests/regression/34086_call-last-kbd-macro.lua:
--------------------------------------------------------------------------------
1 | -- macro-record "foo" Return Up macro-stop
2 | -- call-last-kbd-macro call-last-kbd-macro call-last-kbd-macro file-save file-quit
3 | call_command ("macro-play", "Ctrl-Alt-x", "m", "a", "c", "r", "o", "-", "r", "e", "c", "o", "r", "d", "Return", "f", "o", "o", "Return", "Up", "Ctrl-Alt-x", "m", "a", "c", "r", "o", "-", "s", "t", "o", "p", "Return", "Alt-Return", "Alt-Return", "Alt-Return", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/regression/34086_call-last-kbd-macro.output:
--------------------------------------------------------------------------------
1 | foo
2 | foo
3 | foo
4 | foo
5 | Here is a sample file.
6 | It has several lines.
7 |
8 | And more than one paragraph.
9 |
--------------------------------------------------------------------------------
/tests/regression/34087_undo_macro.lua:
--------------------------------------------------------------------------------
1 | -- macro-record foo Return macro-stop call-last-kbd-macro undo
2 | -- file-save file-quit
3 | call_command ("macro-play", "Ctrl-Alt-x", "m", "a", "c", "r", "o", "-", "r", "e", "c", "o", "r", "d", "Return", "f", "o", "o", "Return", "Ctrl-Alt-x", "m", "a", "c", "r", "o", "-", "s", "t", "o", "p", "Return", "Alt-m", "Ctrl-_", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/regression/34087_undo_macro.output:
--------------------------------------------------------------------------------
1 | foo
2 | Here is a sample file.
3 | It has several lines.
4 |
5 | And more than one paragraph.
6 |
--------------------------------------------------------------------------------
/tests/regression/34193_interactive_insert.lua:
--------------------------------------------------------------------------------
1 | -- Regression:
2 | -- crash after accepting an empty argument to insert
3 |
4 | -- insert Return
5 | -- file-save file-quit
6 | call_command ("macro-play", "Ctrl-Alt-x", "i", "n", "s", "e", "r", "t", "Return", "Ctrl-g", "Ctrl-s", "Ctrl-q")
7 |
--------------------------------------------------------------------------------
/tests/regression/34193_interactive_insert.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/regression/35562_search-backward.lua:
--------------------------------------------------------------------------------
1 | -- Alt-x search-backward Return Ctrl-g
2 | -- file-save file-quit
3 | call_command ("macro-play", "Ctrl-Alt-x", "s", "e", "a", "r", "c", "h", "-", "b", "a", "c", "k", "w", "a", "r", "d", "Return", "Ctrl-g", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/regression/35562_search-backward.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/tests/regression/35567_minibuffer_ding_non_printable.lua:
--------------------------------------------------------------------------------
1 | -- edit-shell-command "echo foo" Alt-x Return file-save file-quit
2 | call_command ("macro-play", "Ctrl-Alt-s", "e", "c", "h", "o", "Space", "f", "o", "o", "Alt-x", "Return", "Ctrl-s", "Ctrl-q")
3 |
--------------------------------------------------------------------------------
/tests/regression/35567_minibuffer_ding_non_printable.output:
--------------------------------------------------------------------------------
1 | foo
2 | Here is a sample file.
3 | It has several lines.
4 |
5 | And more than one paragraph.
6 |
--------------------------------------------------------------------------------
/tests/regression/forward-char_at_end.lua:
--------------------------------------------------------------------------------
1 | -- move-end-file a move-next-character
2 | -- file-save file-quit
3 | call_command ("macro-play", "Ctrl-End", "a", "Right", "Ctrl-s", "Ctrl-q")
4 |
--------------------------------------------------------------------------------
/tests/regression/forward-char_at_end.output:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 | a
--------------------------------------------------------------------------------
/tests/test.input:
--------------------------------------------------------------------------------
1 | Here is a sample file.
2 | It has several lines.
3 |
4 | And more than one paragraph.
5 |
--------------------------------------------------------------------------------
/zee-git-1.rockspec:
--------------------------------------------------------------------------------
1 | build = {
2 | build_command = "LUA=$(LUA) autoreconf -i && ./configure --prefix=$(PREFIX) --libdir=$(LIBDIR) --datadir=$(LUADIR) && make clean && make",
3 | copy_directories = {
4 | },
5 | install_command = "make install",
6 | type = "command",
7 | }
8 | dependencies = {
9 | "lua == 5.3",
10 | "stdlib >= 41.2.0",
11 | "luaposix == 33.3.1",
12 | "lrexlib-gnu >= 2.8.0",
13 | "alien >= 0.7.1",
14 | }
15 | description = {
16 | detailed = "Zee is a lightweight editor. Zee is aimed at small footprint\
17 | systems and quick editing sessions (it starts up and shuts down\
18 | instantly).",
19 | homepage = "http://github.com/rrthomas/zee/",
20 | license = "GPLv3+",
21 | summary = "Experimental lightweight editor",
22 | }
23 | package = "zee"
24 | source = {
25 | url = "git://github.com/rrthomas/zee.git",
26 | }
27 | version = "git-1"
28 |
--------------------------------------------------------------------------------
/zee/.gitignore:
--------------------------------------------------------------------------------
1 | /TAGS
2 | /zee
3 | /init.lua
4 |
--------------------------------------------------------------------------------
/zee/astr.lua:
--------------------------------------------------------------------------------
1 | -- Efficient string buffers
2 | --
3 | -- Copyright (c) 2011-2015 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | local Object = require "std.object"
21 |
22 | alien.default.memchr:types ("pointer", "pointer", "int", "size_t")
23 |
24 | local allocation_chunk_size = 16
25 | AStr = Object {
26 | -- Primitive methods
27 |
28 | _init = function (self, init, len)
29 | if type (init) == "string" then
30 | self.buf = alien.array ("char", #init, alien.buffer (init))
31 | self.length = #init
32 | elseif type (init) == "number" then
33 | self.buf = alien.array ("char", math.max (init, 1))
34 | self.length = init
35 | elseif type (init) == "userdata" then
36 | self.buf = alien.array ("char", len, alien.buffer (init))
37 | self.length = len
38 | else
39 | self.buf = alien.array ("char", init)
40 | self.length = #init
41 | end
42 | return self
43 | end,
44 |
45 | __tostring = function (self)
46 | return self.buf.buffer:tostring (#self)
47 | end,
48 |
49 | __index = function (self, n)
50 | return self.buf[n]
51 | end,
52 |
53 | __len = function (self)
54 | return self.length
55 | end,
56 |
57 | sub = function (self, from, to)
58 | to = to or self.length
59 | return AStr (self:topointer (from), to - from + 1)
60 | end,
61 |
62 | set_len = function (self, n)
63 | if n > self.buf.length or n < self.buf.length / 2 then
64 | self.buf:realloc (n + allocation_chunk_size)
65 | end
66 | self.length = n
67 | end,
68 |
69 | move = function (self, to, from, n)
70 | assert (math.max (from, to) + n <= #self + 1)
71 | alien.memmove (self:topointer (to), self:topointer (from), n)
72 | end,
73 |
74 | set = function (self, from, c, n)
75 | assert (from + n <= #self + 1)
76 | alien.memset (self:topointer (from), c:byte (), n)
77 | end,
78 |
79 | remove = function (self, from, n)
80 | local b, e, eob = from, from + n, #self + 1
81 | assert (e <= eob)
82 | self:move (e, b, eob - e)
83 | self:set_len (#self - n)
84 | end,
85 |
86 | insert = function (self, from, n)
87 | assert (from <= #self + 1)
88 | self:set_len (#self + n)
89 | self:move (from + n, from, #self + 1 - (from + n))
90 | self:set (from, '\0', n)
91 | end,
92 |
93 | replace = function (self, from, rep, len)
94 | local len = len or #rep
95 | assert (from + len <= #self + 1)
96 | if type (rep) ~= "userdata" and type (rep) ~= "string" then
97 | rep = rep:topointer ()
98 | end
99 | alien.memmove (self:topointer (from), rep, len)
100 | return self
101 | end,
102 |
103 | rchr = function (self, c, from)
104 | local b = self.buf
105 | for i = from - 1, 1, -1 do
106 | if b[i] == c then return i end
107 | end
108 | end,
109 |
110 | start_of_line = function (self, o)
111 | local prev = self:rchr (string.byte ('\n'), o)
112 | return prev and prev + 1 or 1
113 | end,
114 |
115 | end_of_line = function (self, o)
116 | local next = alien.default.memchr (self:topointer (o), string.byte ('\n'), #self - (o - 1))
117 | return next and self.buf.buffer:tooffset (next) or #self + 1
118 | end,
119 |
120 |
121 | -- Derived methods
122 |
123 | topointer = function (self, offset)
124 | return self.buf.buffer:topointer (offset)
125 | end,
126 |
127 | cat = function (self, src)
128 | local oldlen = #self
129 | self:insert (oldlen + 1, #src)
130 | return self:replace (oldlen + 1, src:topointer (), #src)
131 | end,
132 |
133 | prev_line = function (self, o)
134 | local so = self:start_of_line (o)
135 | return so ~= 1 and self:start_of_line (so - 1) or nil
136 | end,
137 |
138 | next_line = function (self, o)
139 | local eo = self:end_of_line (o)
140 | return eo <= #self and eo + 1 or nil
141 | end,
142 |
143 | lines = function (self)
144 | local lines = -1
145 | local next = 1
146 | repeat
147 | next = self:next_line (next)
148 | lines = lines + 1
149 | until not next
150 | return lines
151 | end,
152 | }
153 |
154 | local have_memrchr = pcall (load 'alien.default.memrchr:types ("pointer", "pointer", "int", "size_t")')
155 | if have_memrchr then
156 | AStr.rchr = function (self, c, from)
157 | local p = alien.default.memrchr(self:topointer (), c, from - 1)
158 | return p and self.buf.buffer:tooffset (p)
159 | end
160 | end
161 |
--------------------------------------------------------------------------------
/zee/bind.lua:
--------------------------------------------------------------------------------
1 | -- Key bindings
2 | --
3 | -- Copyright (c) 2010-2015 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | -- Key binding.
21 |
22 | _last_command = nil
23 | _this_command = nil
24 | _interactive = 0
25 |
26 | function interactive ()
27 | return _interactive > 0
28 | end
29 |
30 | function call_command (f, ...)
31 | thisflag = {defining_macro = lastflag.defining_macro}
32 |
33 | -- Execute the command.
34 | _this_command = f
35 | _interactive = _interactive + 1
36 | local ok = not execute_command (f, ...) -- FIXME: Most of this (except _interactive) should be inside execute_command
37 | _interactive = math.max (0, _interactive - 1)
38 | _last_command = _this_command
39 |
40 | if buf and _last_command ~= "edit-undo" then
41 | buf.next_undo = buf.last_undo
42 | end
43 |
44 | lastflag = thisflag
45 |
46 | return ok
47 | end
48 |
49 | function get_and_run_command ()
50 | local key = get_key_chord ()
51 | local name = binding_to_command (key)
52 |
53 | popup_clear ()
54 | minibuf_clear ()
55 |
56 | if command_exists (name) then
57 | call_command (name)
58 | else
59 | minibuf_error (tostring (key) .. " is undefined")
60 | end
61 | end
62 |
63 | root_bindings = {}
64 | bindings = root_bindings
65 |
66 | local function key_canon (keystr)
67 | local key = tostring (keycode (keystr)) -- canonicalize the string
68 | if not key then
69 | minibuf_error (string.format ("Key sequence %s is invalid", keystr))
70 | return
71 | end
72 | return key
73 | end
74 |
75 | function key_unbind (keystr)
76 | local key = key_canon (keystr)
77 | if key then
78 | bindings[key] = nil
79 | end
80 | end
81 |
82 | function key_bind (keystr, cmd)
83 | local key = key_canon (keystr)
84 | if key then
85 | if not command_exists (cmd) then -- Possible if called non-interactively
86 | minibuf_error (string.format ("No such function `%s'", cmd))
87 | return
88 | end
89 |
90 | bindings[key] = cmd
91 | end
92 | end
93 |
94 | function bind_printing_chars (cmd)
95 | -- Bind all printing keys to given command
96 | for i = 0, 0xff do
97 | if posix.isprint (string.char (i)) then
98 | bindings[string.char (i)] = cmd
99 | end
100 | end
101 | -- Bind special key names to edit-insert-character
102 | functional.map (function (e)
103 | bindings[tostring (keycode (e))] = cmd
104 | end,
105 | std.ielems,
106 | {"Space", "Tab", "Return"})
107 | end
108 |
109 | bind_printing_chars ("edit-insert-character")
110 | -- FIXME: Make Escape bindable and make it possible to escape to top level
111 |
112 | function binding_to_command (key)
113 | return bindings[tostring (key)]
114 | end
115 |
116 | function command_to_binding (cmd)
117 | local keys = {}
118 | for k, n in pairs (bindings) do
119 | if n == cmd then
120 | table.insert (keys, k)
121 | end
122 | end
123 | return keys
124 | end
125 |
--------------------------------------------------------------------------------
/zee/buffer.lua:
--------------------------------------------------------------------------------
1 | -- Buffer type, functions and commands
2 | --
3 | -- Copyright (c) 2010-2012 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 |
21 | -- Buffer methods that know about the gap.
22 |
23 | function get_buffer_pre_cursor (bp)
24 | return bp.text:sub (1, get_buffer_pt (bp) - 1)
25 | end
26 |
27 | function get_buffer_post_cursor (bp)
28 | return bp.text:sub (get_buffer_pt (bp) + bp.gap)
29 | end
30 |
31 | function get_buffer_pt (bp)
32 | return bp.pt
33 | end
34 |
35 | local function set_buffer_pt (bp, o)
36 | if o < bp.pt then
37 | bp.text:move (o + bp.gap, o, bp.pt - o)
38 | bp.text:set (o, '\0', math.min (bp.pt - o, bp.gap))
39 | elseif o > bp.pt then
40 | bp.text:move (bp.pt, bp.pt + bp.gap, o - bp.pt)
41 | bp.text:set (o + bp.gap - math.min (o - bp.pt, bp.gap), '\0', math.min (o - bp.pt, bp.gap))
42 | end
43 | bp.pt = o
44 | end
45 |
46 | local function realo_to_o (bp, o)
47 | if o == nil then
48 | return o
49 | elseif o <= bp.pt then
50 | return o
51 | elseif o >= bp.pt + bp.gap then
52 | return o - bp.gap
53 | end
54 | assert (false) -- FIXME: crash with an error
55 | end
56 |
57 | local function o_to_realo (bp, o)
58 | return o < bp.pt and o or o + bp.gap
59 | end
60 |
61 | function get_buffer_size (bp)
62 | return realo_to_o (bp, #bp.text + 1) - 1
63 | end
64 |
65 | function buffer_line_len (bp, o)
66 | o = o or get_buffer_line_o (bp)
67 | return realo_to_o (bp, bp.text:end_of_line (o_to_realo (bp, o))) -
68 | realo_to_o (bp, bp.text:start_of_line (o_to_realo (bp, o)))
69 | end
70 |
71 | -- Replace `del' chars after cursor with `s'.
72 | -- `s' can be a string or an AStr.
73 | local min_gap = 1024 -- Minimum gap size after resize
74 | local max_gap = 4096 -- Maximum permitted gap size
75 | function replace_string (del, s)
76 | if buf.readonly then
77 | minibuf_error ("File is readonly")
78 | return false
79 | end
80 |
81 | local newlen = #s
82 | undo_save_block (buf.pt, del, newlen)
83 |
84 | -- Adjust gap.
85 | local oldgap = buf.gap
86 | if oldgap + del < newlen then
87 | -- If gap would vanish, open it to min_gap.
88 | buf.text:insert (buf.pt, (newlen + min_gap) - (buf.gap + del))
89 | buf.gap = min_gap
90 | else
91 | if oldgap + del > max_gap + newlen then
92 | -- If gap would be larger than max_gap, restrict it to max_gap.
93 | buf.text:remove (buf.pt + newlen + max_gap, (oldgap + del) - (max_gap + newlen))
94 | buf.gap = max_gap
95 | else
96 | buf.gap = oldgap + del - newlen
97 | end
98 |
99 | -- Zero any new bit of gap.
100 | if buf.gap > oldgap then
101 | buf.text:set (buf.pt + oldgap, '\0', buf.gap - oldgap)
102 | end
103 | end
104 |
105 | -- Insert `newlen' chars.
106 | buf.text:replace (buf.pt + buf.gap, s)
107 |
108 | -- Adjust markers.
109 | for m in pairs (buf.markers) do
110 | if m.o > buf.pt then
111 | m.o = math.max (buf.pt, m.o + newlen - del)
112 | end
113 | end
114 |
115 | buf.modified = true
116 | return true
117 | end
118 |
119 | function insert_string (s)
120 | local ok = replace_string (0, s)
121 | if ok then
122 | assert (move_char (#s))
123 | end
124 | return ok
125 | end
126 |
127 | function get_buffer_char (bp, o)
128 | local n = o_to_realo (bp, o)
129 | return string.char (bp.text[n])
130 | end
131 |
132 | function buffer_prev_line (bp, o)
133 | return realo_to_o (bp, bp.text:prev_line (o_to_realo (bp, o)))
134 | end
135 |
136 | function buffer_next_line (bp, o)
137 | return realo_to_o (bp, bp.text:next_line (o_to_realo (bp, o)))
138 | end
139 |
140 | function buffer_start_of_line (bp, o)
141 | return realo_to_o (bp, bp.text:start_of_line (o_to_realo (bp, o)))
142 | end
143 |
144 | function buffer_end_of_line (bp, o)
145 | return realo_to_o (bp, bp.text:end_of_line (o_to_realo (bp, o)))
146 | end
147 |
148 | function get_buffer_line_o (bp)
149 | return realo_to_o (bp, bp.text:start_of_line (o_to_realo (bp, bp.pt)))
150 | end
151 |
152 | -- Copy a region of text into an AStr.
153 | function get_buffer_region (bp, r)
154 | local as = AStr (r.finish - r.start)
155 | if r.start < get_buffer_pt (bp) then
156 | as:replace (1, bp.text:sub (r.start, math.min (r.finish, get_buffer_pt (bp)) - 1))
157 | end
158 | if r.finish > get_buffer_pt (bp) then
159 | local n = r.start - get_buffer_pt (bp)
160 | local done = math.max (-n, 0)
161 | local from = math.max (n, 0)
162 | as:replace (done + 1, bp.text:sub (get_buffer_pt (bp) + bp.gap + from, bp.gap + r.finish - 1))
163 | end
164 | return as
165 | end
166 |
167 |
168 | -- Buffer methods that don't know about the gap.
169 |
170 | function get_buffer_line (bp)
171 | return bp.line
172 | end
173 |
174 | -- Get filename.
175 | function get_buffer_filename (bp)
176 | return bp.filename
177 | end
178 |
179 |
180 | function delete_char ()
181 | execute_command ("edit-select-off")
182 |
183 | if end_of_buffer () then
184 | return minibuf_error ("End of buffer")
185 | end
186 |
187 | if end_of_line () then
188 | thisflag.need_resync = true
189 | end
190 | buf.modified = replace_string (1, "")
191 | return buf.modified
192 | end
193 |
194 |
195 | -- Allocate a new buffer, set the default local variable values, and
196 | -- insert it into the buffer list.
197 | function buffer_new () -- FIXME: Constructor which we can pass other arguments
198 | return {pt = 1, line = 0, gap = 0, text = AStr (""),
199 | markers = setmetatable ({}, {__mode = "k"}),
200 | modified = false}
201 | end
202 |
203 | -- Make a region from two offsets
204 | function region_new (o1, o2)
205 | return {start = math.min (o1, o2), finish = math.max (o1, o2)}
206 | end
207 |
208 | function get_region_size (rp)
209 | return rp.finish - rp.start
210 | end
211 |
212 | -- Return the selection
213 | function calculate_the_selection ()
214 | if not buf.mark then
215 | return minibuf_error ("There is no selection")
216 | end
217 |
218 | return region_new (buf.pt, buf.mark.o)
219 | end
220 |
221 | function delete_region (r)
222 | goto_offset (r.start)
223 | replace_string (get_region_size (r), "")
224 | end
225 |
226 | function in_region (o, x, r)
227 | return o + x >= r.start and o + x < r.finish
228 | end
229 |
230 |
231 | -- Marker datatype
232 |
233 | local function marker_new (o)
234 | local marker = {o = o}
235 | buf.markers[marker] = true
236 | return marker
237 | end
238 |
239 | function copy_marker (m)
240 | return marker_new (m.o)
241 | end
242 |
243 | function cursor_marker ()
244 | return marker_new (get_buffer_pt (buf))
245 | end
246 |
247 | Define ("edit-select-on",
248 | [[
249 | Start selecting text.
250 | ]],
251 | function ()
252 | buf.mark = cursor_marker ()
253 | end
254 | )
255 |
256 | Define ("edit-select-off",
257 | [[
258 | Stop selecting text.
259 | ]],
260 | function ()
261 | buf.mark = nil
262 | end
263 | )
264 |
265 | Define ("edit-select-toggle",
266 | [[
267 | Toggle selection mode.
268 | ]],
269 | function ()
270 | if buf.mark then
271 | execute_command ("edit-select-off")
272 | else
273 | execute_command ("edit-select-on")
274 | end
275 | end
276 | )
277 |
278 | Define ("edit-select-other-end",
279 | [[
280 | When selecting text, move the cursor to the other end of the selection.
281 | ]],
282 | function ()
283 | if not buf.mark then
284 | return minibuf_error ("No selection")
285 | end
286 |
287 | local tmp = get_buffer_pt (buf)
288 | goto_offset (buf.mark.o)
289 | buf.mark.o = tmp
290 | thisflag.need_resync = true
291 | end
292 | )
293 |
294 | tab_width = 8
295 |
296 | -- Return a safe indent width.
297 | function indent_width ()
298 | return math.max (tonumber (get_variable ("indent-width")), 1)
299 | end
300 |
301 |
302 | -- Basic movement routines
303 |
304 | function move_char (n)
305 | local ltest, new_goalc, n2
306 | if n > 0 then
307 | ltest, new_goalc = end_of_line, 0
308 | n2 = math.min (n, get_buffer_size (buf) + 1 - get_buffer_pt (buf))
309 | else
310 | ltest, new_goalc = beginning_of_line, math.huge
311 | n2 = math.max (n, -get_buffer_pt (buf) + 1)
312 | end
313 |
314 | -- Count lines we're about to move over.
315 | local r
316 | if n2 < 0 then
317 | r = buf.text:sub (get_buffer_pt (buf) + n2, get_buffer_pt (buf) - 1)
318 | else
319 | r = buf.text:sub (get_buffer_pt (buf) + buf.gap, get_buffer_pt (buf) + buf.gap + n2 - 1)
320 | end
321 | local _, lines = rex_gnu.gsub (r, "\n", "%0")
322 | if lines > 0 then
323 | thisflag.need_resync = true
324 | buf.line = buf.line + lines * (n2 > 0 and 1 or -1)
325 | end
326 |
327 | -- Move.
328 | set_buffer_pt (buf, get_buffer_pt (buf) + n2)
329 |
330 | -- If we moved to a line end from inside the line, set goalc to an extreme value.
331 | if ltest () then
332 | set_goalc (new_goalc)
333 | end
334 |
335 | return n == n2
336 | end
337 |
338 | function goto_offset (o)
339 | move_char (o - get_buffer_pt (buf))
340 | end
341 |
342 | -- Get the goal column, expanding tabs.
343 | function get_goalc ()
344 | return #make_string_printable (get_line ():sub (1, get_buffer_pt (buf) - get_buffer_line_o (buf)))
345 | end
346 |
347 | function set_goalc (c)
348 | buf.goalc = c
349 | end
350 |
351 | function move_line (n)
352 | local dir, func = 1, buffer_next_line
353 | if n < 0 then
354 | dir, func = -1, buffer_prev_line
355 | n = -n
356 | end
357 |
358 | if _last_command ~= "move-next-line" and _last_command ~= "move-previous-line" then
359 | set_goalc (get_goalc ())
360 | end
361 |
362 | while n > 0 do
363 | local o = func (buf, buf.pt)
364 | if o == nil then
365 | break
366 | end
367 | set_buffer_pt (buf, o)
368 | n = n - 1
369 | buf.line = buf.line + dir
370 | end
371 |
372 | set_buffer_pt (buf, get_buffer_line_o (buf) + #make_string_printable (get_line (), buf.goalc))
373 | thisflag.need_resync = true
374 | return n ~= 0
375 | end
376 |
377 | function get_line ()
378 | return get_buffer_region (buf, region_new (get_buffer_line_o (buf), buffer_end_of_line (buf, get_buffer_pt (buf))))
379 | end
380 |
381 | function is_empty_line ()
382 | return buffer_line_len (buf) == 0
383 | end
384 |
385 | function is_blank_line ()
386 | return regex_match (get_line (), "^[ \t]*$")
387 | end
388 |
389 | -- Returns the character following the cursor.
390 | function following_char ()
391 | if end_of_buffer () then
392 | return nil
393 | end
394 | return get_buffer_char (buf, get_buffer_pt (buf))
395 | end
396 |
397 | -- Return the character preceding the cursor.
398 | function preceding_char ()
399 | if beginning_of_buffer () then
400 | return nil
401 | end
402 | return get_buffer_char (buf, get_buffer_pt (buf) - 1)
403 | end
404 |
405 | -- Return true if cursor is at the beginning of the buffer.
406 | function beginning_of_buffer ()
407 | return get_buffer_pt (buf) == 1
408 | end
409 |
410 | -- Return true if cursor is at the end of the buffer.
411 | function end_of_buffer (void)
412 | return get_buffer_pt (buf) > get_buffer_size (buf)
413 | end
414 |
415 | -- Return true if cursor is at the beginning of a line.
416 | function beginning_of_line ()
417 | return get_buffer_pt (buf) == get_buffer_line_o (buf)
418 | end
419 |
420 | -- Return true if cursor is at the end of a line.
421 | function end_of_line ()
422 | return get_buffer_pt (buf) - get_buffer_line_o (buf) == buffer_line_len (buf)
423 | end
424 |
--------------------------------------------------------------------------------
/zee/completion.lua:
--------------------------------------------------------------------------------
1 | -- Completion facility functions
2 | --
3 | -- Copyright (c) 2007, 2009-2012 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | -- Completions table:
21 | -- {
22 | -- completions: list of completion strings
23 | -- matches: list of matches
24 | -- match: the current matched string
25 | -- }
26 | -- FIXME: Use Objects here and elsewhere, and add an __index
27 | -- metamethod that works like strict.lua.
28 |
29 | -- Make a new completions table
30 | function completion_new (completions)
31 | return {completions = set (completions or {}), matches = {}}
32 | end
33 |
34 | -- Write the matches in `l' in a set of columns. The width of the
35 | -- columns is chosen to be big enough for the longest string, with a
36 | -- COLUMN_GAP-character gap between each column.
37 | local COLUMN_GAP = 3
38 | function completion_write (cp, width)
39 | local maxlen = 0
40 | for i, v in ipairs (cp.matches) do
41 | maxlen = math.max (maxlen, #v)
42 | end
43 | maxlen = maxlen + COLUMN_GAP
44 | local numcols = math.floor ((width - 1) / maxlen)
45 | local col = 0
46 |
47 | local s = "Possible completions are:\n"
48 | for i, v in ipairs (cp.matches) do
49 | s = s .. string.format ("%-" .. maxlen .. "s", v)
50 | col = (col + 1) % numcols
51 | if col == 0 then
52 | s = s .. '\n'
53 | end
54 | end
55 | return s
56 | end
57 |
58 | -- Returns the length of the common prefix of s1 and s2.
59 | local function common_prefix_length (s1, s2)
60 | local len = math.min (#s1, #s2)
61 | for i = 1, len do
62 | if s1:sub (i, i) ~= s2:sub (i, i) then
63 | return i - 1
64 | end
65 | end
66 | return len
67 | end
68 |
69 | -- Arguments:
70 | --
71 | -- cp - the completions
72 | -- search - the prefix to search for
73 | --
74 | -- Returns false if `search' is not a prefix of any completion, and true
75 | -- otherwise.
76 | --
77 | -- The effect on cp is as follows:
78 | --
79 | -- completions - unchanged
80 | -- matches - replaced with the list of matching completions, sorted
81 | -- match - replaced with the longest common prefix of the matches
82 | --
83 | -- To format the completions for a popup, call completion_write
84 | -- after this function.
85 | -- FIXME: To see the completions in a popup, you should call
86 | -- completion_popup after this method. You may want to call
87 | -- completion_remove_suffix and/or completion_remove_prefix in between
88 | -- to keep the list manageable. (See C Zee's completion.lua.)
89 | function completion_try (cp, search)
90 | cp.matches = {}
91 |
92 | local fullmatch = false
93 | for c in pairs (cp.completions) do
94 | if type (c) == "string" then
95 | if string.sub (c, 1, #search) == search then
96 | table.insert (cp.matches, c)
97 | if c == search then
98 | fullmatch = true
99 | end
100 | end
101 | end
102 | end
103 |
104 | if #cp.matches == 0 then
105 | return false
106 | end
107 |
108 | table.sort (cp.matches)
109 | cp.match = cp.matches[1]
110 | local prefix_len = #cp.match
111 | for _, v in ipairs (cp.matches) do
112 | prefix_len = math.min (prefix_len, common_prefix_length (cp.match, v))
113 | end
114 | cp.match = cp.match:sub (1, prefix_len)
115 |
116 | return true
117 | end
118 |
119 | -- Popup the completion window.
120 | function popup_completion (cp)
121 | popup_set (completion_write (cp, win.ewidth))
122 | term_display ()
123 | end
124 |
--------------------------------------------------------------------------------
/zee/cua_bindings.lua:
--------------------------------------------------------------------------------
1 | -- CUA key bindings
2 |
3 | -- Command execution
4 | key_bind ("Ctrl-Alt-x", "execute-command")
5 | key_bind ("Ctrl-Alt-s", "edit-shell-command")
6 | key_bind ("Ctrl-Alt-z", "file-suspend")
7 |
8 | -- Navigation. Mostly arrows and things.
9 |
10 | -- Character/line
11 | key_bind ("Left", "move-previous-character")
12 | key_bind ("Right", "move-next-character")
13 | key_bind ("Up", "move-previous-line")
14 | key_bind ("Down", "move-next-line")
15 | -- Word/paragraph
16 | key_bind ("Ctrl-Left", "move-previous-word")
17 | key_bind ("Ctrl-Right", "move-next-word")
18 | key_bind ("Alt-[", "move-previous-paragraph") -- FIXME
19 | key_bind ("Alt-]", "move-next-paragraph") -- FIXME
20 | -- Line/page
21 | key_bind ("Home", "move-start-line")
22 | key_bind ("End", "move-end-line")
23 | key_bind ("PageUp", "move-previous-page")
24 | key_bind ("PageDown", "move-next-page")
25 | -- Whole buffer
26 | key_bind ("Ctrl-Home", "move-start-file")
27 | key_bind ("Ctrl-End", "move-end-file")
28 | -- Window
29 | key_bind ("Ctrl-l", "view-refresh")
30 |
31 | -- Selection
32 | key_bind ("Ctrl-@", "edit-select-toggle")
33 | key_bind ("Alt-Space", "edit-select-other-end") -- FIXME
34 |
35 | -- Absolute navigation. These are like navigation commands but they
36 | -- don't become selection commands when combined with SHIFT.
37 | key_bind ("Ctrl-Alt-g", "move-goto-line")
38 | key_bind ("Ctrl-Alt-c", "move-goto-column")
39 |
40 | -- Save
41 | key_bind ("Ctrl-s", "file-save")
42 | -- Quit
43 | key_bind ("Ctrl-q", "file-quit")
44 |
45 | -- Undo
46 | key_bind ("Ctrl-z", "edit-undo")
47 | -- Cut selection to clipboard
48 | key_bind ("Ctrl-x", "edit-cut")
49 | key_bind ("Ctrl-Delete", "edit-delete-word")
50 | -- Copy selection to clipboard
51 | key_bind ("Ctrl-c", "edit-copy")
52 | -- Delete without modifying clipboard
53 | key_bind ("Backspace", "edit-delete-previous-character")
54 | key_bind ("Ctrl-?", "edit-delete-previous-character")
55 | key_bind ("Ctrl-Backspace", "edit-delete-word-backward")
56 | key_bind ("Ctrl-Alt-?", "edit-delete-word-backward")
57 | key_bind ("Delete", "edit-delete-next-character")
58 | key_bind ("Ctrl-Alt-d", "edit-delete-horizontal-space")
59 | -- Paste
60 | key_bind ("Ctrl-v", "edit-paste")
61 |
62 | -- Search
63 | key_bind ("Ctrl-f", "edit-find")
64 | key_bind ("Ctrl-Alt-f", "edit-find-backward")
65 | key_bind ("Ctrl-r", "edit-replace")
66 |
67 | -- Insert special characters
68 | key_bind ("Alt-Tab", "edit-indent") -- FIXME: Should be Ctrl-Alt-i
69 | key_bind ("Ctrl-Alt-q", "edit-insert-quoted")
70 | key_bind ("Tab", "edit-indent-relative")
71 | key_bind ("Ctrl-Return", "edit-insert-newline") -- FIXME: binding doesn't work
72 | key_bind ("Return", "edit-insert-newline-and-indent")
73 |
74 | -- Macros
75 | key_bind ("Ctrl-(", "macro-record")
76 | key_bind ("Ctrl-)", "macro-stop")
77 | key_bind ("Alt-Return", "macro-play") -- FIXME
78 |
--------------------------------------------------------------------------------
/zee/cut.lua:
--------------------------------------------------------------------------------
1 | -- Cut and paste
2 | --
3 | -- Copyright (c) 2010-2012 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | local cut_buffer_text = AStr ("")
21 |
22 | local function copy_or_cut_the_region (cut)
23 | local r = calculate_the_selection ()
24 | if r == true then
25 | return true
26 | end
27 |
28 | cut_buffer_text = get_buffer_region (buf, r)
29 | if cut then
30 | if buf.readonly then
31 | minibuf_error ("Read only text copied to cut buffer")
32 | else
33 | delete_region (r)
34 | end
35 | end
36 | execute_command ("edit-select-off")
37 | end
38 |
39 | Define ("edit-cut",
40 | [[
41 | Cut the selection.
42 | The text is deleted, unless the buffer is read-only, and saved in the
43 | paste buffer; the `edit-paste' command retrieves it.
44 | ]],
45 | function ()
46 | return copy_or_cut_the_region (true)
47 | end
48 | )
49 |
50 | Define ("edit-copy",
51 | [[
52 | Copy the selection to the paste buffer.
53 | ]],
54 | function ()
55 | return copy_or_cut_the_region (false)
56 | end
57 | )
58 |
59 | Define ("edit-paste",
60 | [[
61 | Insert the contents of the paste buffer.
62 | ]],
63 | function ()
64 | return not insert_string (cut_buffer_text)
65 | end
66 | )
67 |
--------------------------------------------------------------------------------
/zee/edit.lua:
--------------------------------------------------------------------------------
1 | -- Basic editing functions
2 | --
3 | -- Copyright (c) 2010-2012 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program; see the file COPYING. If not, write to the
19 | -- Free Software Foundation, Fifth Floor, 51 Franklin Street, Boston,
20 | -- MA 02111-1301, USA.
21 |
22 | Define ("edit-insert-character",
23 | [[
24 | Insert the character you type.
25 | Whichever character you type to run this command is inserted.
26 | ]],
27 | function (key)
28 | local key = key and key:byte () or term_keytobyte (lastkey ())
29 | execute_command ("edit-select-off")
30 | if not key then
31 | return ding ()
32 | end
33 | insert_string (string.char (key))
34 | end
35 | )
36 |
37 | -- Indentation command
38 | -- Go to cur_goalc () in the previous non-blank line.
39 | local function previous_nonblank_goalc ()
40 | local cur_goalc = get_goalc ()
41 | local ok = true
42 |
43 | -- Find previous non-blank line, if any.
44 | repeat
45 | ok = not move_line (-1)
46 | until not ok or not is_blank_line ()
47 |
48 | -- Go to `cur_goalc' in that non-blank line.
49 | while ok and not end_of_line () and get_goalc () < cur_goalc do
50 | ok = move_char (1)
51 | end
52 | end
53 |
54 | Define ("edit-indent-relative",
55 | [[
56 | Indent line or insert a tab.
57 | ]],
58 | function ()
59 | local cur_goalc = get_goalc ()
60 | local target_goalc = 0
61 | local m = cursor_marker ()
62 | local ok
63 |
64 | execute_command ("edit-select-off")
65 | previous_nonblank_goalc ()
66 |
67 | -- Now find the next blank char.
68 | if preceding_char () ~= '\t' or get_goalc () <= cur_goalc then
69 | while not end_of_line () and not following_char ():match ("%s") do
70 | move_char (1)
71 | end
72 | end
73 |
74 | -- Find next non-blank char.
75 | while not end_of_line () and following_char ():match ("%s") do
76 | move_char (1)
77 | end
78 |
79 | -- Target column.
80 | if not end_of_line () then
81 | target_goalc = get_goalc ()
82 | end
83 | goto_offset (m.o)
84 |
85 | -- Indent.
86 | undo_start_sequence ()
87 | if target_goalc > 0 then
88 | -- If not at EOL on target line, insert spaces & tabs up to
89 | -- target_goalc.
90 | while get_goalc () < target_goalc do
91 | ok = insert_string (' ')
92 | end
93 | else
94 | -- if already at EOL on target line, insert a tab.
95 | ok = call_command ("insert-tab")
96 | end
97 | undo_end_sequence ()
98 |
99 | return ok
100 | end
101 | )
102 |
103 | Define ("edit-insert-newline-and-indent",
104 | [[
105 | Insert a newline, then indent.
106 | Indentation is done using the `edit-indent-relative' function, except
107 | that if there is a character in the first column of the line above,
108 | no indenting is performed.
109 | ]],
110 | function ()
111 | execute_command ("edit-select-off")
112 |
113 | undo_start_sequence ()
114 | if insert_string ("\n") then
115 | local m = cursor_marker ()
116 | local pos
117 |
118 | -- Check where last non-blank goalc is.
119 | previous_nonblank_goalc ()
120 | pos = get_goalc ()
121 | local indent = pos > 0 or (not end_of_line () and following_char ():match ("%s"))
122 | goto_offset (m.o)
123 | -- Only indent if we're in column > 0 or we're in column 0 and
124 | -- there is a space character there in the last non-blank line.
125 | if indent then
126 | execute_command ("edit-indent-relative")
127 | end
128 | end
129 | undo_end_sequence ()
130 | end
131 | )
132 |
133 |
134 | Define ("edit-delete-next-character",
135 | [[
136 | Delete the following character.
137 | Join lines if the character is a newline.
138 | ]],
139 | function ()
140 | delete_char ()
141 | end
142 | )
143 |
144 | Define ("edit-delete-previous-character",
145 | [[
146 | Delete the previous character.
147 | Join lines if the character is a newline.
148 | ]],
149 | function ()
150 | if not move_char (-1) then
151 | minibuf_error ("Beginning of buffer")
152 | return true
153 | end
154 |
155 | delete_char ()
156 | end
157 | )
158 |
159 | Define ("edit-delete-horizontal-space",
160 | [[
161 | Delete all spaces and tabs around the cursor.
162 | ]],
163 | function ()
164 | undo_start_sequence ()
165 |
166 | while not end_of_line () and following_char ():match ("%s") do
167 | delete_char ()
168 | end
169 |
170 | while not beginning_of_line () and preceding_char ():match ("%s") do
171 | execute_command ("edit-delete-previous-character")
172 | end
173 |
174 | undo_end_sequence ()
175 | end
176 | )
177 |
178 | Define ("edit-indent",
179 | [[
180 | Indent to next multiple of `indent-width'.
181 | ]],
182 | function ()
183 | local t = indent_width ()
184 | return not insert_string (string.rep (' ', t - get_goalc () % t))
185 | end
186 | )
187 |
188 | Define ("edit-insert-newline",
189 | [[
190 | Insert a newline.
191 | ]],
192 | function ()
193 | return not insert_string ("\n")
194 | end
195 | )
196 |
197 | -- FIXME: Inserting a tab seems to insert some spaces too, and mess up
198 | -- the buffer (overwriting characters after the tab?)
199 | Define ("edit-insert-quoted",
200 | [[
201 | Read next input character and insert it.
202 | This is useful for inserting control characters.
203 | ]],
204 | function ()
205 | minibuf_write ("Ctrl-q-")
206 | insert_string (string.char (bit32.band (getkey_unfiltered (GETKEY_DEFAULT), 0xff)))
207 | minibuf_clear ()
208 | end
209 | )
210 |
211 | local function delete_text (move_func)
212 | local pt = get_buffer_pt (buf)
213 | undo_start_sequence ()
214 | execute_command (move_func)
215 | delete_region (region_new (pt, get_buffer_pt (buf)))
216 | undo_end_sequence ()
217 | goto_offset (pt)
218 | end
219 |
220 | Define ("edit-delete-word",
221 | [[
222 | Delete forward up to the end of a word.
223 | ]],
224 | function ()
225 | return delete_text ("move-next-word")
226 | end
227 | )
228 |
229 | Define ("edit-delete-word-backward",
230 | [[
231 | Delete backward up to the end of a word.
232 | ]],
233 | function ()
234 | return delete_text ("move-previous-word")
235 | end
236 | )
237 |
--------------------------------------------------------------------------------
/zee/emacs_bindings.lua:
--------------------------------------------------------------------------------
1 | -- Emacs key bindings
2 |
3 | -- Command execution
4 | key_bind ("Alt-x", "execute-command")
5 | key_bind ("Alt-!", "edit-shell-command")
6 |
7 | -- Navigation. Mostly arrows and things.
8 |
9 | -- Character/line
10 | key_bind ("Left", "move-previous-character")
11 | key_bind ("Ctrl-b", "move-previous-character")
12 | key_bind ("Right", "move-next-character")
13 | key_bind ("Ctrl-f", "move-next-character")
14 | key_bind ("Up", "move-previous-line")
15 | key_bind ("Ctrl-p", "move-previous-line")
16 | key_bind ("Down", "move-next-line")
17 | key_bind ("Ctrl-n", "move-next-line")
18 | -- Word/paragraph
19 | key_bind ("Ctrl-Left", "move-previous-word")
20 | key_bind ("Alt-Left", "move-previous-word")
21 | key_bind ("Alt-b", "move-previous-word")
22 | key_bind ("Ctrl-Right", "move-next-word")
23 | key_bind ("Alt-Right", "move-next-word")
24 | key_bind ("Alt-f", "move-next-word")
25 | key_bind ("Alt-{", "move-previous-paragraph")
26 | key_bind ("Alt-}", "move-next-paragraph")
27 | -- Line/page
28 | key_bind ("Home", "move-start-line")
29 | key_bind ("Ctrl-a", "move-start-line")
30 | key_bind ("End", "move-end-line")
31 | key_bind ("Ctrl-e", "move-end-line")
32 | key_bind ("PageUp", "move-previous-page")
33 | key_bind ("Alt-v", "move-previous-page")
34 | key_bind ("PageDown", "move-next-page")
35 | key_bind ("Ctrl-v", "move-next-page")
36 | -- Whole buffer
37 | key_bind ("Ctrl-Home", "move-start-file")
38 | key_bind ("Alt-<", "move-start-file")
39 | key_bind ("Ctrl-End", "move-end-file")
40 | key_bind ("Alt->,", "move-end-file")
41 | -- Window
42 | key_bind ("Ctrl-l", "view-refresh")
43 |
44 | -- Absolute navigation. These are like navigation commands but they
45 | -- don't become selection commands when combined with SHIFT.
46 | key_bind ("Ctrl-Alt-g", "move-goto-column")
47 | key_bind ("Alt-g", "move-goto-line")
48 |
49 | -- Selection
50 | -- select-other-end
51 | key_bind ("Ctrl-@", "edit-select-toggle")
52 |
53 | -- Save
54 | key_bind ("Alt-s", "file-save")
55 | -- Suspend
56 | key_bind ("Ctrl-z", "file-suspend")
57 | -- Quit
58 | key_bind ("Ctrl-Alt-q", "file-quit")
59 |
60 | -- Undo
61 | key_bind ("Ctrl-_", "edit-undo")
62 | -- Cut selection to clipboard
63 | key_bind ("Ctrl-w", "edit-cut")
64 | key_bind ("Alt-d", "edit-delete-word")
65 | -- Copy selection to clipboard
66 | key_bind ("Alt-w", "edit-copy")
67 | -- Delete without modifying clipboard
68 | key_bind ("Backspace", "edit-delete-previous-character")
69 | key_bind ("Ctrl-d", "edit-delete-next-character")
70 | key_bind ("Delete", "edit-delete-next-character")
71 | key_bind ("Alt-\\", "edit-delete-horizontal-space")
72 | -- Paste
73 | key_bind ("Ctrl-y", "edit-paste")
74 |
75 | -- Search
76 | key_bind ("Ctrl-s", "edit-find")
77 | key_bind ("Ctrl-r", "edit-find-backward")
78 | key_bind ("Alt-%", "edit-replace")
79 |
80 | -- Insert special characters
81 | key_bind ("Ctrl-j", "edit-insert-newline")
82 | key_bind ("Return", "edit-insert-newline-and-indent")
83 | key_bind ("Tab", "edit-indent-relative")
84 | key_bind ("Ctrl-q", "edit-insert-quoted")
85 | key_bind ("Alt-i", "edit-indent")
86 |
87 | -- Macros
88 | key_bind ("Alt-(", "macro-record")
89 | key_bind ("Alt-)", "macro-stop")
90 | key_bind ("Alt-e", "macro-play")
91 |
--------------------------------------------------------------------------------
/zee/eval.lua:
--------------------------------------------------------------------------------
1 | -- User commands
2 | --
3 | -- Copyright (c) 2009-2016 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program; see the file COPYING. If not, write to the
19 | -- Free Software Foundation, Fifth Floor, 51 Franklin Street, Boston,
20 | -- MA 02111-1301, USA.
21 |
22 |
23 | -- User things
24 | env = {}
25 |
26 | -- Turn texinfo markup into plain text
27 | local function texi (s)
28 | s = s:gsub ("@i{([^}]+)}", function (s) return s:upper () end)
29 | s = s:gsub ("@kbd{([^}]+)}", "%1") -- FIXME: look up binding of command
30 | return s
31 | end
32 |
33 | function Define (name, doc, value)
34 | env[name] = {
35 | doc = texi (doc:chomp ()),
36 | val = value,
37 | }
38 | end
39 |
40 | function get_doc (name)
41 | if command_exists (name) then
42 | return env[name].doc
43 | elseif env[name] and env[name].doc then
44 | return (string.format ("%s is a variable.\n\nIts value is %s\n\n%s",
45 | name, get_variable (name), env[name].doc))
46 | end
47 | end
48 |
49 | function execute_command (name, ...)
50 | return command_exists (name) and env[name].val (...)
51 | end
52 |
53 | local function loadchunk (func, err)
54 | if func == nil then
55 | minibuf_error (string.format ("Error evaluating Lua: %s", err))
56 | return true
57 | end
58 | return func ()
59 | end
60 |
61 | Define ("eval",
62 | [[
63 | Evaluate a Lua chunk CHUNK.
64 | ]],
65 | function (chunk)
66 | return loadchunk (load (chunk))
67 | end
68 | )
69 |
70 | Define ("load",
71 | [[
72 | Load and evaluate a Lua chunk from FILE.
73 | ]],
74 | function (file)
75 | return loadchunk (loadfile (file))
76 | end
77 | )
78 |
79 | function command_exists (c)
80 | return env[c] and type (env[c].val) == "function"
81 | end
82 |
83 |
84 | -- FIXME: Make this non-interactive: need to change Define so it
85 | -- defines functions in _G, and hence can accept non-interactive
86 | -- functions (which still need documentation, but should not appear in
87 | -- menu).
88 | Define ("execute-command",
89 | [[
90 | Read command name, then run it.
91 | ]],
92 | function ()
93 | local name = minibuf_read_completion ("Command: ",
94 | completion_new (filter (function (e)
95 | return command_exists (e)
96 | end,
97 | std.ielems, table.keys (env))),
98 | "command")
99 | if name == "" then
100 | return true
101 | end
102 | return execute_command (name)
103 | end
104 | )
105 |
--------------------------------------------------------------------------------
/zee/file.lua:
--------------------------------------------------------------------------------
1 | -- Disk file handling
2 | --
3 | -- Copyright (c) 2009-2014 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | -- FIXME: Reload when file changes on disk
21 |
22 | function exist_file (filename)
23 | if posix.stat (filename) then
24 | return true
25 | end
26 | local _, err = posix.errno ()
27 | return err ~= posix.ENOENT
28 | end
29 |
30 | local function is_regular_file (filename)
31 | local st = posix.stat (filename)
32 | return st and st.type == "regular"
33 | end
34 |
35 | -- Return nonzero if file exists and can be written.
36 | local function check_writable (filename)
37 | local ok = posix.euidaccess (filename, "w")
38 | return ok and ok >= 0
39 | end
40 |
41 | -- Write buffer to given file name with given mode.
42 | alien.default.write:types ("ptrdiff_t", "int", "pointer", "size_t")
43 | local function write_file (filename, mode)
44 | local h = posix.creat (filename, mode)
45 | if h then
46 | local s = get_buffer_pre_cursor (buf)
47 | local ret = alien.default.write (h, s.buf.buffer:topointer (), #s)
48 | if ret == #s then
49 | s = get_buffer_post_cursor (buf)
50 | ret = alien.default.write (h, s.buf.buffer:topointer (), #s)
51 | if ret == #s then
52 | ret = true
53 | end
54 | end
55 |
56 | local ret2 = posix.close (h)
57 | if ret == true and ret2 ~= 0 then -- writing error takes precedence over closing error
58 | ret = ret2
59 | end
60 |
61 | return ret
62 | end
63 | end
64 |
65 | Define ("file-save",
66 | [[
67 | Save buffer in visited file.
68 | ]],
69 | function ()
70 | local ret = write_file (buf.filename, "rw-rw-rw-")
71 | if not ret then
72 | return minibuf_error (string.format ("Error writing `%s'%s", buf.filename,
73 | ret == -1 and ": " .. posix.errno () or ""))
74 | end
75 |
76 | minibuf_write ("Wrote " .. buf.filename)
77 | buf.modified = false
78 | undo_set_unchanged (buf.last_undo)
79 | end
80 | )
81 |
82 | Define ("file-quit",
83 | [[
84 | Quit, unless there are unsaved changes.
85 | ]],
86 | function ()
87 | if buf.modified then
88 | return minibuf_error ("Unsaved changes: use `file-save' or `edit-revert'")
89 | end
90 |
91 | thisflag.quit = true
92 | end
93 | )
94 |
95 | alien.default.read:types ("ptrdiff_t", "int", "pointer", "size_t")
96 | function read_file (filename)
97 | buf = buffer_new ()
98 | local len = posix.stat (filename, "size")
99 | local h = posix.open (filename, posix.O_RDONLY)
100 | if h and len then
101 | buf.text = AStr (len)
102 | if alien.default.read (h, buf.text:topointer (), len) == len then
103 | buf.filename = filename
104 | buf.readonly = not check_writable (filename)
105 | end
106 | posix.close (h)
107 | end
108 | if not buf.filename then
109 | return minibuf_error (string.format ("Error reading file `%s': %s", filename, posix.errno ()))
110 | end
111 | end
112 |
113 | -- Function called on unexpected error or crash (SIGSEGV).
114 | -- Attempts to save modified buffer.
115 | -- If doabort is true, aborts to allow core dump generation;
116 | -- otherwise, exit.
117 | function editor_exit (doabort)
118 | io.stderr:write ("Trying to save buffer (if modified)...\r\n")
119 |
120 | if buf and buf.modified then
121 | local file = buf.filename .. string.upper (PACKAGE) .. "SAVE"
122 | io.stderr:write (string.format ("Saving %s...\r\n", file))
123 | write_file (file, "rw-------")
124 | end
125 |
126 | term_close ()
127 | if doabort then
128 | posix.abort ()
129 | else
130 | posix._exit (2)
131 | end
132 | end
133 |
134 | Define ("file-suspend",
135 | [[
136 | Stop editor and return to superior process.
137 | ]],
138 | function ()
139 | posix.raise (posix.SIGTSTP)
140 | end
141 | )
142 |
143 | -- Signal an error, and abort any ongoing macro definition.
144 | function ding ()
145 | if thisflag.defining_macro then
146 | cancel_macro_definition ()
147 | end
148 |
149 | if win then
150 | term_beep ()
151 | end
152 | -- enable call chaining with `return ding ()'
153 | return true
154 | end
155 |
--------------------------------------------------------------------------------
/zee/getkey.lua:
--------------------------------------------------------------------------------
1 | -- Getting and ungetting key strokes
2 | --
3 | -- Copyright (c) 2010-2012 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | -- Maximum time to avoid screen updates when catching up with buffered
21 | -- input, in milliseconds.
22 | local MAX_RESYNC_MS = 500
23 |
24 | local _last_key
25 |
26 | -- Return last key pressed
27 | function lastkey ()
28 | return _last_key
29 | end
30 |
31 | -- Get a keystroke, waiting for up to delay ms, and translate it into a
32 | -- keycode.
33 | local function getkeystroke (delay)
34 | _last_key = term_getkey (delay)
35 |
36 | if _last_key and thisflag.defining_macro then
37 | add_key_to_macro (_last_key)
38 | end
39 |
40 | return _last_key
41 | end
42 |
43 | -- Return the next keystroke, refreshing the screen only when the input
44 | -- buffer is empty, or MAX_RESYNC_MS have elapsed since the last
45 | -- screen refresh.
46 | local next_refresh = {}
47 | local refresh_wait = {
48 | sec = math.floor (MAX_RESYNC_MS / 1000),
49 | usec = (MAX_RESYNC_MS % 1000) * 1000,
50 | }
51 |
52 | local function getkey (delay, norefresh)
53 | local now = posix.gettimeofday ()
54 | local keycode = getkeystroke (0)
55 |
56 | if not norefresh and (not keycode or posix.timercmp (now, next_refresh) >= 0) then
57 | term_display ()
58 | term_refresh ()
59 | next_refresh = posix.timeradd (now, refresh_wait)
60 | end
61 |
62 | if not keycode then
63 | keycode = getkeystroke (delay)
64 | end
65 |
66 | return keycode
67 | end
68 |
69 | function getkey_unfiltered (delay)
70 | local c = term_getkey_unfiltered (delay)
71 | _last_key = c
72 | if thisflag.defining_macro then
73 | add_key_to_macro (c)
74 | end
75 | return c
76 | end
77 |
78 | -- Wait for GETKEY_DELAYED ms or until a key is pressed.
79 | -- The key is then available with getkey.
80 | function waitkey ()
81 | ungetkey (getkey (GETKEY_DELAYED))
82 | end
83 |
84 | -- Unget a key as if it had not been fetched.
85 | function ungetkey (key)
86 | term_ungetkey (key)
87 |
88 | if thisflag.defining_macro then
89 | remove_key_from_macro ()
90 | end
91 | end
92 |
93 | -- Get a key chord from the keyboard.
94 | function get_key_chord (norefresh)
95 | return getkey (GETKEY_DEFAULT, norefresh) or get_key_chord (norefresh)
96 | end
97 |
--------------------------------------------------------------------------------
/zee/help.lua:
--------------------------------------------------------------------------------
1 | -- Self documentation facility functions
2 | --
3 | -- Copyright (c) 2010-2012 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | Define ("help-thing",
21 | [[
22 | Display the help for the given command or variable.
23 | ]],
24 | function (name)
25 | name = name or (interactive () and
26 | minibuf_read_completion ("Describe command or variable: ",
27 | completion_new (table.keys (env)), "thing"))
28 | if name == "" then
29 | return true
30 | end
31 |
32 | local where = ""
33 | if command_exists (name) then
34 | local keys = command_to_binding (name)
35 | if #keys > 0 then
36 | where = string.format ("\n\nBound to: %s", table.concat (keys, ", "))
37 | end
38 | end
39 |
40 | local doc = get_doc (name) or "No help available"
41 | popup_set (string.format ("Help for `%s':\n\n%s%s", name, doc, where))
42 | end
43 | )
44 |
45 | Define ("help-key",
46 | [[
47 | Display the command invoked by a key combination.
48 | ]],
49 | function (keystr)
50 | local key
51 | if keystr then
52 | key = keycode (keystr)
53 | else
54 | minibuf_write ("Describe key: ")
55 | key = get_key_chord (true)
56 | end
57 | if key then
58 | local name = binding_to_command (key)
59 | local binding = tostring (key)
60 | if not name then
61 | return minibuf_error (binding .. " is undefined")
62 | end
63 | local doc = get_doc (name)
64 | if doc then
65 | popup_set (string.format ("%s runs the command `%s'.\n%s", binding, name, doc))
66 | end
67 | end
68 | end
69 | )
70 |
--------------------------------------------------------------------------------
/zee/init.lua.in:
--------------------------------------------------------------------------------
1 | std = require "std".barrel ()
2 | set = require "std.set"
3 | functional = require "std.functional"
4 | list = require "std.list"
5 | tree = require "std.tree"
6 | posix = require "posix"
7 | rex_gnu = require "rex_gnu"
8 | alien = require "alien"
9 | curses = require "curses" -- part of luaposix
10 | --require "std.strict" -- optional stdlib module: FIXME get this working again
11 |
--------------------------------------------------------------------------------
/zee/keycode.lua:
--------------------------------------------------------------------------------
1 | -- Key encoding and decoding functions
2 | --
3 | -- Copyright (c) 2010-2015 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 |
21 | -- Map of key names to code.
22 | local KBD_NONPRINT = 283
23 | local keynametocode = {}
24 |
25 | local non_modifier_name = set {
26 | "Backspace", "Delete", "Down", "End", "F1", "F10", "F11", "F12",
27 | "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "Home", "Insert",
28 | "Left", "PageDown", "PageUp", "Return", "Right", "Tab", "Up",
29 | "Space", "Escape"
30 | }
31 | local modifier_name = set {"Ctrl-", "Alt-"}
32 |
33 | for i in set.elems (non_modifier_name) do
34 | keynametocode[i] = KBD_NONPRINT
35 | end
36 | keynametocode["Space"] = string.byte (' ')
37 |
38 | for i = 0x0, 0x7f do
39 | if posix.isprint (string.char (i)) and i ~= string.byte ('\\') then
40 | keynametocode[string.char (i)] = i
41 | end
42 | end
43 |
44 | -- Array of key names
45 | local keyname = set.union (modifier_name, non_modifier_name)
46 |
47 | -- Insert printable characters in the ASCII range.
48 | for i = 0, 0x7f do
49 | if posix.isprint (string.char (i)) then
50 | set.insert (keyname, string.char (i))
51 | end
52 | end
53 |
54 | local function normalize_modifier (mod)
55 | return mod:sub (1, 1):upper () .. mod:sub (2, -2):lower ()
56 | end
57 |
58 | -- A key code has one `key' and some optional modifiers.
59 | -- For comparisons to work, keycodes are immutable atoms.
60 | local keycode_mt = {
61 | -- Output the write syntax for this keycode (e.g. Ctrl-Alt-F1).
62 | __tostring = function (self)
63 | if not self then
64 | return "invalid keycode: nil"
65 | end
66 |
67 | local s = (self.CTRL and "Ctrl-" or "") .. (self.ALT and "Alt-" or "")
68 |
69 | if not self.key then
70 | return "invalid keycode: " .. s .. "nil"
71 | end
72 |
73 | return s .. self.key
74 | end,
75 |
76 | -- Normalise modifier lookups to capitalized & sans `-' suffix.
77 | -- hasmodifier = keycode.ALT or keycode["c"]
78 | __index = function (self, mod)
79 | mod = normalize_modifier (mod)
80 | return rawget (self, mod)
81 | end,
82 |
83 | -- Return the immutable atom for this keycode with modifier added.
84 | -- ctrlkey = "Ctrl-" + key
85 | __add = function (self, mod)
86 | if "string" == type (self) then mod, self = self, mod end
87 | mod = normalize_modifier (mod)
88 | if self[mod] then return self end
89 | return keycode (mod .. "-" .. tostring (self))
90 | end,
91 |
92 | -- Return the immutable atom for this keycode with modifier removed.
93 | -- withoutmeta = key - "Alt-"
94 | __sub = function (self, mod)
95 | if "string" == type (self) then mod, self = self, mod end
96 | mod = normalize_modifier (mod)
97 | local keystr = tostring (self):gsub (mod .. "%-", "")
98 | return keycode (keystr)
99 | end,
100 | }
101 |
102 | -- Extract a modifier prefix of a key string.
103 | local function getmodifier (s)
104 | for match in set.elems (modifier_name) do
105 | if match == s:sub (1, #match) then
106 | return match, s:sub (#match + 1)
107 | end
108 | end
109 | return nil, s
110 | end
111 |
112 | -- Convert a single keychord string to its key code.
113 | keycode = functional.memoize (function (chord)
114 | local key, tail = setmetatable ({}, keycode_mt), chord
115 |
116 | local mod
117 | repeat
118 | mod, tail = getmodifier (tail)
119 | if mod == "Ctrl-" then
120 | key.CTRL = true
121 | elseif mod == "Alt-" then
122 | key.ALT = true
123 | end
124 | until not mod
125 | if not set.member (keyname, tail) then return nil end
126 | key.key = tail
127 | key.code = keynametocode[tail]
128 |
129 | return key
130 | end)
131 |
--------------------------------------------------------------------------------
/zee/macro.lua:
--------------------------------------------------------------------------------
1 | -- Macro facility functions
2 | --
3 | -- Copyright (c) 2010-2012 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | local macro = {}
21 |
22 | -- FIXME: macros should be executed immediately and abort on error;
23 | -- they should be stored as a macro list, not a series of
24 | -- keystrokes. Macros should return success/failure.
25 | function add_key_to_macro (key)
26 | table.insert (macro, key)
27 | end
28 |
29 | function remove_key_from_macro ()
30 | table.remove (macro)
31 | end
32 |
33 | function cancel_macro_definition ()
34 | macro = {}
35 | thisflag.defining_macro = false
36 | end
37 |
38 | Define ("macro-record",
39 | [[
40 | Record subsequent keyboard input, defining a macro.
41 | The commands are recorded even as they are executed.
42 | Use `macro-stop' to finish recording and make the macro available.
43 | ]],
44 | function ()
45 | if thisflag.defining_macro then
46 | minibuf_error ("Already defining a keyboard macro")
47 | return true
48 | end
49 |
50 | if macro ~= nil then
51 | cancel_macro_definition ()
52 | end
53 |
54 | minibuf_write ("Defining keyboard macro...")
55 |
56 | thisflag.defining_macro = true
57 | macro = {}
58 | end
59 | )
60 |
61 | Define ("macro-stop",
62 | [[
63 | Finish defining a keyboard macro.
64 | The definition was started by `macro-record'.
65 | The macro is now available for use via `macro-play'.
66 | ]],
67 | function ()
68 | if not thisflag.defining_macro then
69 | minibuf_error ("Not defining a keyboard macro")
70 | return true
71 | end
72 |
73 | thisflag.defining_macro = false
74 | end
75 | )
76 |
77 | local function process_keys (keys)
78 | local cur = term_buf_len ()
79 |
80 | for i = #keys, 1, -1 do
81 | term_ungetkey (keys[i])
82 | end
83 |
84 | undo_start_sequence ()
85 | while term_buf_len () > cur do
86 | get_and_run_command ()
87 | end
88 | undo_end_sequence ()
89 | end
90 |
91 | Define ("macro-play",
92 | [[
93 | Play back the last macro that you defined.
94 | ]],
95 | function (...)
96 | local m = {...}
97 | if #m > 0 then
98 | m = functional.map (keycode, std.ielems, m)
99 | elseif interactive () then
100 | m = macro
101 | if m == nil then
102 | minibuf_error ("No macro has been defined")
103 | return true
104 | end
105 | end
106 |
107 | process_keys (m)
108 | end
109 | )
110 |
--------------------------------------------------------------------------------
/zee/main.lua:
--------------------------------------------------------------------------------
1 | -- Program invocation, startup and shutdown
2 | --
3 | -- Copyright (c) 2010-2015 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | -- Derived constants
21 | VERSION_STRING = PACKAGE_NAME .. " " .. VERSION
22 |
23 | local COPYRIGHT_STRING = ""
24 |
25 | local program_name = posix.basename (arg[0] or PACKAGE)
26 | spec = program_name .. " " .. VERSION .. [[
27 |
28 | Copyright (C) 2015 Free Software Foundation, Inc.
29 | ]] .. PACKAGE_NAME .. " comes with ABSOLUTELY NO WARRANTY." .. [[
30 |
31 | You may redistribute copies of ]] .. PACKAGE_NAME .. [[
32 |
33 |
34 | under the terms of the GNU General Public License.
35 | For more information about these matters, see the file named COPYING.
36 |
37 | Usage: ]] .. program_name .. [[
38 |
39 |
40 | An editor.
41 |
42 | Exit status is 0 if OK, 1 if it cannot start up, for example because
43 | of an invalid command-line argument, and 2 if it crashes or runs out
44 | of memory.
45 |
46 | ~/.]] .. PACKAGE .. [[ is the user init file
47 |
48 | -q, --no-init-file do not load ~/.]] .. PACKAGE .. [[
49 |
50 | -e, --eval=CHUNK evaluate Lua chunk CHUNK
51 | -n, --line=LINE start editing at line LINE
52 | --version display version information, then exit
53 | --help display this help, then exit
54 |
55 | Please report bugs at ]] .. PACKAGE_BUGREPORT .. [[
56 | ]]
57 | -- -b, --batch run non-interactively
58 |
59 |
60 | -- Runtime constants
61 |
62 | -- Display attributes
63 | display = {}
64 |
65 | -- Keyboard handling
66 |
67 | GETKEY_DEFAULT = -1
68 | GETKEY_DELAYED = 2000
69 |
70 |
71 | -- Global flags, stored in thisflag and lastflag.
72 | -- need_resync: a resync is required.
73 | -- quit: the user has asked to quit.
74 | -- defining_macro: we are defining a macro.
75 |
76 |
77 | -- The current window
78 | win = nil
79 |
80 | -- The current buffer
81 | buf = nil
82 |
83 | -- The global editor flags.
84 | thisflag = {}
85 | lastflag = {}
86 |
87 |
88 | local function segv_sig_handler (signo)
89 | io.stderr:write (prog.name .. ": " .. PACKAGE_NAME ..
90 | " crashed. Please send a bug report to <" ..
91 | PACKAGE_BUGREPORT .. ">.\r\n")
92 | editor_exit (true)
93 | end
94 |
95 | local function other_sig_handler (signo)
96 | local msg = progran_name .. ": terminated with signal " .. signo .. ".\n" .. debug.traceback ()
97 | io.stderr:write (msg:gsub ("\n", "\r\n"))
98 | editor_exit (false)
99 | end
100 |
101 | local function signal_init ()
102 | -- Set up signal handling
103 | posix.signal(posix.SIGSEGV, segv_sig_handler)
104 | posix.signal(posix.SIGBUS, segv_sig_handler)
105 | posix.signal(posix.SIGHUP, other_sig_handler)
106 | posix.signal(posix.SIGINT, other_sig_handler)
107 | posix.signal(posix.SIGTERM, other_sig_handler)
108 | end
109 |
110 | function main ()
111 | signal_init ()
112 | local OptionParser = require "std.optparse"
113 | local parser = OptionParser (spec)
114 | _G.arg, _G.opts = parser:parse (_G.arg)
115 |
116 | if #arg ~= 1 and not (#arg == 0 and opts.eval) then
117 | parser:opterr ("Need a file or expression")
118 | end
119 |
120 | os.setlocale ("")
121 | win = {}
122 |
123 | local w, h = term_width (), term_height ()
124 | win = {topdelta = 0, start_column = 0, last_line = 0}
125 | win.fwidth = 2
126 | term_init ()
127 | resize_window ()
128 |
129 | if not opts.no_init_file then
130 | local s = os.getenv ("HOME")
131 | if s then
132 | execute_command ("load", s .. "/." .. PACKAGE)
133 | end
134 | end
135 |
136 | -- Load file
137 | local ok = true
138 | if #arg == 1 then
139 | ok = not read_file (arg[1])
140 | if ok then
141 | execute_command ("move-goto-line", opts.line or 1)
142 | end
143 | end
144 |
145 | -- Evaluate Lua chunks given on the command line.
146 | if type (opts.eval) == "string" then -- If only one argument, put it in a table
147 | opts.eval = {opts.eval}
148 | end
149 | for _, c in ipairs (opts.eval or {}) do
150 | if execute_command ("eval", c) then
151 | break
152 | end
153 | if thisflag.quit then
154 | break
155 | end
156 | end
157 |
158 | if ok and #arg == 1 then
159 | lastflag.need_resync = true
160 |
161 | -- Refresh minibuffer in case there's a pending error message.
162 | minibuf_refresh ()
163 |
164 | -- Leave cursor in correct position.
165 | term_redraw_cursor ()
166 |
167 | -- Run the main loop.
168 | while not thisflag.quit do
169 | if lastflag.need_resync then
170 | window_resync (win)
171 | end
172 | get_and_run_command ()
173 | end
174 | end
175 |
176 | -- Tidy and close the terminal.
177 | term_finish ()
178 |
179 | -- Print any error message.
180 | if not ok then
181 | io.stderr:write (minibuf_contents .. "\n")
182 | end
183 | -- FIXME: Add startup banner (how to quit and get menu)
184 | end
185 |
--------------------------------------------------------------------------------
/zee/minibuf.lua:
--------------------------------------------------------------------------------
1 | -- Minibuffer
2 | --
3 | -- Copyright (c) 2010-2012 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | local function term_minibuf_write (s)
21 | end
22 |
23 | -- FIXME: Turn minibuf_read inside out so it's a minor mode
24 | -- Read a string from the minibuffer.
25 | function minibuf_read (prompt, cp)
26 | local quit, value, pos = false, "", 0
27 |
28 | -- FIXME: Stop these definitions appearing in global environment
29 | -- (Have nested environments)
30 | Define ("minibuf-insert-character", "",
31 | function ()
32 | local key = term_keytobyte (lastkey ())
33 | if not key then
34 | ding ()
35 | return true
36 | end
37 | value = value:sub (1, pos) .. string.char (key) .. value:sub (pos + 1)
38 | pos = pos + 1
39 | end)
40 |
41 | Define ("minibuf-exit", "",
42 | function ()
43 | quit = true
44 | end)
45 |
46 | Define ("minibuf-quit", "",
47 | function ()
48 | value = ""
49 | quit = true
50 | end)
51 |
52 | Define ("minibuf-move-start-line", "",
53 | function ()
54 | pos = 0
55 | end)
56 |
57 | Define ("minibuf-move-end-line", "",
58 | function ()
59 | pos = #value
60 | end)
61 |
62 | Define ("minibuf-move-previous-character", "",
63 | function ()
64 | if pos > 0 then
65 | pos = pos - 1
66 | else
67 | ding ()
68 | end
69 | end)
70 |
71 | Define ("minibuf-move-next-character", "",
72 | function ()
73 | if pos < #value then
74 | pos = pos + 1
75 | else
76 | ding ()
77 | end
78 | end)
79 |
80 | Define ("minibuf-delete-previous-character", "",
81 | function ()
82 | if pos > 0 then
83 | value = value:sub (1, pos - 1) .. value:sub (pos + 1)
84 | pos = pos - 1
85 | else
86 | ding ()
87 | end
88 | end)
89 |
90 | Define ("minibuf-delete-next-character", "",
91 | function ()
92 | if pos < #value then
93 | value = value:sub (1, pos) .. value:sub (pos + 2)
94 | else
95 | ding ()
96 | end
97 | end)
98 |
99 | Define ("minibuf-previous-page", "",
100 | function ()
101 | if cp == nil then
102 | ding ()
103 | else
104 | popup_scroll_down ()
105 | end
106 | end)
107 |
108 | Define ("minibuf-next-page", "",
109 | function ()
110 | if cp == nil then
111 | ding ()
112 | else
113 | popup_scroll_up ()
114 | end
115 | end)
116 |
117 | Define ("minibuf-complete", "",
118 | function ()
119 | if not cp or #cp.matches == 0 then
120 | ding ()
121 | else
122 | if value ~= cp.match then
123 | value = cp.match
124 | pos = #value
125 | else
126 | popup_scroll_down_and_loop ()
127 | end
128 | end
129 | end)
130 |
131 | local minibuf_bindings = {}
132 | bindings = minibuf_bindings
133 | bind_printing_chars ("minibuf-insert-character")
134 | key_bind ("Return", "minibuf-exit")
135 | key_bind ("Ctrl-Alt-z", "file-suspend")
136 | key_bind ("Ctrl-g", "minibuf-quit")
137 | key_bind ("Home", "minibuf-move-start-line")
138 | key_bind ("End", "minibuf-move-end-line")
139 | key_bind ("Left", "minibuf-move-previous-character")
140 | key_bind ("Right", "minibuf-move-next-character")
141 | key_bind ("Backspace", "minibuf-delete-previous-character")
142 | key_bind ("Ctrl-?", "minibuf-delete-previous-character")
143 | key_bind ("Delete", "minibuf-delete-next-character")
144 | key_bind ("PageUp", "minibuf-previous-page")
145 | key_bind ("PageDown", "minibuf-next-page")
146 | key_bind ("Tab", "minibuf-complete")
147 |
148 | local saved
149 | repeat
150 | if cp then
151 | completion_try (cp, value)
152 | popup_completion (cp)
153 | end
154 |
155 | minibuf_write (prompt)
156 | minibuf_refresh ()
157 |
158 | local w, h = term_width (), term_height ()
159 | local margin = 1
160 | local n = 0
161 |
162 | if #prompt + pos + 1 >= w then
163 | margin = margin + 1
164 | term_addstr ('$')
165 | n = pos - pos % (w - #prompt - 2)
166 | end
167 |
168 | term_addstr (value:sub (n + 1, math.min (w - #prompt - margin, #value - n)))
169 |
170 | if #value - n >= w - #prompt - margin then
171 | term_move (h - 1, w - 1)
172 | term_addstr ('$')
173 | end
174 |
175 | term_move (h - 1, #prompt + margin - 1 + pos % (w - #prompt - margin))
176 | term_refresh ()
177 |
178 | local key = get_key_chord (true)
179 | local name = binding_to_command (key)
180 | if command_exists (name) then
181 | call_command (name)
182 | else
183 | ding ()
184 | end
185 | until quit
186 |
187 | minibuf_clear ()
188 | if cp then
189 | popup_clear ()
190 | term_display ()
191 | end
192 | bindings = root_bindings
193 | return value
194 | end
195 |
196 |
197 | -- Minibuffer wrapper functions.
198 |
199 | minibuf_contents = nil
200 |
201 | function minibuf_refresh ()
202 | if win then
203 | if minibuf_contents then
204 | term_move (term_height () - 1, 0)
205 | term_clrtoeol ()
206 | term_addstr (minibuf_contents:sub (1, math.min (#minibuf_contents, term_width ())))
207 | end
208 | term_refresh ()
209 | end
210 | end
211 |
212 | -- Clear the minibuffer.
213 | function minibuf_clear ()
214 | minibuf_write ("")
215 | end
216 |
217 | -- Write the specified string in the minibuffer.
218 | function minibuf_write (s)
219 | if s ~= minibuf_contents then
220 | minibuf_contents = s
221 | minibuf_refresh ()
222 | end
223 | end
224 |
225 | -- Write the specified error string in the minibuffer and signal an error.
226 | function minibuf_error (s)
227 | minibuf_write (s)
228 | return ding ()
229 | end
230 |
231 | -- Read a string from the minibuffer using a completion.
232 | function minibuf_read_completion (fmt, cp, class_name)
233 | while true do
234 | local ms = minibuf_read (fmt, cp)
235 | if ms == "" then -- Cancelled.
236 | ding ()
237 | return nil
238 | else
239 | -- Complete partial words if possible.
240 | if completion_try (cp, ms) then
241 | ms = cp.match
242 | end
243 |
244 | if set.member (cp.completions, ms) then
245 | minibuf_clear ()
246 | return ms
247 | else
248 | minibuf_error (string.format ("There is no " .. class_name .. " named `%s'", ms))
249 | waitkey ()
250 | end
251 | end
252 | end
253 | end
254 |
255 | -- Read a non-negative number from the minibuffer.
256 | function minibuf_read_number (prompt)
257 | local n
258 | repeat
259 | local ms = minibuf_read (prompt)
260 | if not ms then
261 | return ding ()
262 | else
263 | n = tonumber (ms, 10)
264 | end
265 | if not n then
266 | minibuf_write ("Please enter a number.")
267 | end
268 | until n
269 |
270 | return n
271 | end
272 |
--------------------------------------------------------------------------------
/zee/move.lua:
--------------------------------------------------------------------------------
1 | -- Movement commands
2 | --
3 | -- Copyright (c) 2010-2012 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | Define ("move-start-line",
21 | [[
22 | Move the cursor to the beginning of the line.
23 | ]],
24 | function ()
25 | goto_offset (get_buffer_line_o (buf))
26 | set_goalc (0)
27 | end
28 | )
29 |
30 | Define ("move-start-line-text",
31 | [[
32 | Move the cursor to the first non-whitespace character on this line.
33 | ]],
34 | function ()
35 | goto_offset (get_buffer_line_o (buf))
36 | while not end_of_line () and following_char ():match ("%s") do
37 | move_char (1)
38 | end
39 | end
40 | )
41 |
42 | Define ("move-end-line",
43 | [[
44 | Move the cursor to the end of the line.
45 | ]],
46 | function ()
47 | goto_offset (get_buffer_line_o (buf) + buffer_line_len (buf))
48 | set_goalc (math.huge)
49 | end
50 | )
51 |
52 | Define ("move-previous-character",
53 | [[
54 | Move the cursor left one character.
55 | ]],
56 | function ()
57 | return not move_char (-1)
58 | end
59 | )
60 |
61 | Define ("move-next-character",
62 | [[
63 | Move the cursor right one character.
64 | ]],
65 | function ()
66 | return not move_char (1)
67 | end
68 | )
69 |
70 | Define ("move-previous-line",
71 | [[
72 | Move cursor vertically up one line.
73 | If there is no character in the target line exactly over the current column,
74 | the cursor is positioned after the character in that line which spans this
75 | column, or at the end of the line if it is not long enough.
76 | ]],
77 | function ()
78 | return move_line (-1)
79 | end
80 | )
81 |
82 | Define ("move-next-line",
83 | [[
84 | Move cursor vertically down one line.
85 | If there is no character in the target line exactly under the current column,
86 | the cursor is positioned after the character in that line which spans this
87 | column, or at the end of the line if it is not long enough.
88 | ]],
89 | function ()
90 | return move_line (1)
91 | end
92 | )
93 |
94 | Define ("move-start-file",
95 | [[
96 | Move the cursor to the beginning of the file.
97 | ]],
98 | function ()
99 | goto_offset (1)
100 | end
101 | )
102 |
103 | Define ("move-end-file",
104 | [[
105 | Move the cursor to the end of the file.
106 | ]],
107 | function ()
108 | goto_offset (get_buffer_size (buf) + 1)
109 | end
110 | )
111 |
112 | Define ("move-previous-page",
113 | [[
114 | Scroll text of current window downward near full screen.
115 | ]],
116 | function ()
117 | return move_line (-win.eheight)
118 | end
119 | )
120 |
121 | Define ("move-next-page",
122 | [[
123 | Scroll text of current window upward near full screen.
124 | ]],
125 | function ()
126 | return move_line (win.eheight)
127 | end
128 | )
129 |
130 | -- Move through words
131 | local function move_word (dir)
132 | local gotword = false
133 | repeat
134 | while not (dir > 0 and end_of_line or beginning_of_line) () do
135 | if get_buffer_char (buf, get_buffer_pt (buf) - (dir < 0 and 1 or 0)):match ("%w") then
136 | gotword = true
137 | elseif gotword then
138 | break
139 | end
140 | move_char (dir)
141 | end
142 | until gotword or not move_char (dir)
143 | return gotword
144 | end
145 |
146 | Define ("move-next-word",
147 | [[
148 | Move the cursor forward one word.
149 | ]],
150 | function ()
151 | return not move_word (1)
152 | end
153 | )
154 |
155 | Define ("move-previous-word",
156 | [[
157 | Move the cursor backwards one word.
158 | ]],
159 | function ()
160 | return not move_word (-1)
161 | end
162 | )
163 |
164 | local function move_paragraph (dir, line_extremum)
165 | repeat until not is_empty_line () or move_line (dir)
166 | repeat until is_empty_line () or move_line (dir)
167 |
168 | if is_empty_line () then
169 | execute_command ("move-start-line")
170 | else
171 | execute_command (line_extremum)
172 | end
173 | end
174 |
175 | Define ("move-previous-paragraph",
176 | [[
177 | Move the cursor backward to the start of the paragraph.
178 | ]],
179 | function ()
180 | move_paragraph (-1, "move-start-line")
181 | end
182 | )
183 |
184 | Define ("move-next-paragraph",
185 | [[
186 | Move the cursor forward to the end of the paragraph.
187 | ]],
188 | function ()
189 | move_paragraph (1, "move-end-line")
190 | end
191 | )
192 |
193 | Define ("move-goto-character",
194 | [[
195 | Move to character @i{position}. Beginning of buffer is character 1.
196 | ]],
197 | function (n)
198 | n = tonumber (n)
199 | if not n and interactive () then
200 | n = minibuf_read_number ("Goto char: ")
201 | end
202 | if type (n) ~= "number" then
203 | return true
204 | end
205 |
206 | goto_offset (math.min (get_buffer_size (buf) + 1, math.max (n, 1)))
207 | end
208 | )
209 |
210 | Define ("move-goto-line",
211 | [[
212 | Move the cursor to the given line.
213 | Line 1 is the beginning of the buffer.
214 | ]],
215 | function (n)
216 | n = tonumber (n)
217 | if not n and interactive () then
218 | n = minibuf_read_number ("Goto line: ")
219 | end
220 | if type (n) ~= "number" then
221 | return true
222 | end
223 |
224 | move_line ((math.max (n, 1) - 1) - get_buffer_line (buf))
225 | execute_command ("move-start-line")
226 | end
227 | )
228 |
229 | -- FIXME: Abstract out the interactive input of arguments à la C Zee
230 | Define ("move-goto-column",
231 | [[
232 | Move the cursor to the given column.
233 | ]],
234 | function (n)
235 | n = tonumber (n)
236 | if not n and interactive () then
237 | n = minibuf_read_number ("Goto column: ")
238 | end
239 | if type (n) ~= "number" then
240 | return true
241 | end
242 |
243 | goto_offset (math.min (math.max (n, 1), buffer_line_len (buf)) - 1 + get_buffer_line_o (buf))
244 | end
245 | )
246 |
--------------------------------------------------------------------------------
/zee/search.lua:
--------------------------------------------------------------------------------
1 | -- Search and replace functions
2 | --
3 | -- Copyright (c) 2010-2012 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | -- Return true if there are no upper-case letters in the given string.
21 | -- If `regex' is true, ignore escaped letters.
22 | local function no_upper (s)
23 | local quote_flag = false
24 | for i = 1, #s do
25 | if s[i] == '\\' then
26 | quote_flag = not quote_flag
27 | elseif not quote_flag and s[i] == s[i]:upper () then
28 | return false
29 | end
30 | end
31 | return true
32 | end
33 |
34 | local re_flags = rex_gnu.flags ()
35 | local re_find_err
36 |
37 | local function find_substr (as, s, forward, notbol, noteol, icase)
38 | local ret
39 | local ok, r = pcall (rex_gnu.new, s, bit32.bor (re_flags.SYNTAX_EGREP, icase and re_flags.ICASE or 0))
40 | if ok then
41 | local ef = 0
42 | if notbol then
43 | ef = bit32.bor (ef, re_flags.not_bol)
44 | end
45 | if noteol then
46 | ef = bit32.bor (ef, re_flags.not_eol)
47 | end
48 | if not forward then
49 | ef = bit32.bor (ef, re_flags.backward)
50 | end
51 | local match_from, match_to = r:find (as, nil, ef)
52 | if match_from then
53 | if forward then
54 | ret = match_to + 1
55 | else
56 | ret = match_from
57 | end
58 | end
59 | else
60 | re_find_err = r
61 | end
62 |
63 | return ret
64 | end
65 |
66 | function regex_match (s, pat)
67 | return find_substr (s, pat, true, false, false, false) ~= nil
68 | end
69 |
70 | local function search (s, forward)
71 | if #s < 1 then
72 | return false
73 | end
74 |
75 | -- Attempt match.
76 | local o = get_buffer_pt (buf)
77 | local notbol = forward and o > 1
78 | local noteol = not forward and o <= get_buffer_size (buf)
79 | local downcase = get_variable ("caseless-search") and no_upper (s)
80 | local as = (forward and get_buffer_post_cursor or get_buffer_pre_cursor) (buf)
81 | local pos = find_substr (as, s, forward, notbol, noteol, downcase)
82 | if not pos then
83 | return false
84 | end
85 |
86 | goto_offset (pos + (forward and (get_buffer_pt (buf) - 1) or 0))
87 | thisflag.need_resync = true
88 | return true
89 | end
90 |
91 |
92 | -- Incremental search engine.
93 | -- FIXME: Once the search is underway, "find next" is hard-wired to Ctrl-f.
94 | -- Having it hard-wired is obviously broken, but something neutral like Return
95 | -- would be better, or look up current binding of relevant command.
96 | -- The proposed meaning of Escape obviates the current behaviour of Return.
97 | local last_search
98 | local function isearch (forward, pattern)
99 | local old_mark
100 | if buf.mark then
101 | old_mark = copy_marker (buf.mark)
102 | end
103 |
104 | buf.search = true
105 |
106 | local last = true
107 | local start = get_buffer_pt (buf)
108 | local cur = start
109 | while true do
110 | -- Make the minibuf message.
111 | local ms = string.format ("%sI-search%s: %s",
112 | (last and "" or "Failing "),
113 | forward and "" or " backward",
114 | pattern)
115 |
116 | -- Regex error.
117 | if re_find_err then
118 | ms = ms .. string.format (" [%s]", re_find_err)
119 | re_find_err = nil
120 | end
121 |
122 | minibuf_write (ms)
123 |
124 | local c = interactive () and get_key_chord ()
125 |
126 | if not c then
127 | elseif c == keycode "Ctrl-g" then
128 | goto_offset (start)
129 | buf.mark = old_mark
130 | ding ()
131 | break
132 | elseif c == keycode "BACKSPACE" then
133 | if #pattern > 0 then
134 | pattern = pattern:sub (1, -2)
135 | cur = start
136 | goto_offset (start)
137 | else
138 | ding ()
139 | end
140 | elseif c == keycode "Ctrl-Alt-q" then
141 | minibuf_write (string.format ("%s^Q-", ms))
142 | pattern = pattern .. string.char (getkey_unfiltered (GETKEY_DEFAULT))
143 | elseif c == keycode "Ctrl-Alt-f" or c == keycode "Ctrl-f" then -- Invert direction.
144 | forward = c == keycode "Ctrl-f"
145 | if #pattern > 0 then -- Find next match.
146 | cur = get_buffer_pt (buf)
147 | last_search = pattern -- Save search string.
148 | elseif last_search then
149 | pattern = last_search
150 | end
151 | elseif c.ALT or c.CTRL or c == keycode "Return" or term_keytobyte (c) == nil then
152 | if #pattern > 0 then
153 | last_search = pattern -- Save search string.
154 | end
155 | if c ~= keycode "Return" then
156 | ungetkey (c)
157 | end
158 | break
159 | else
160 | pattern = pattern .. string.char (term_keytobyte (c))
161 | end
162 |
163 | if #pattern > 0 then
164 | goto_offset (cur)
165 | last = search (pattern, forward)
166 | if not c then
167 | break
168 | end
169 | else
170 | last = true
171 | end
172 |
173 | window_resync (win)
174 | term_display ()
175 | end
176 |
177 | -- done
178 | buf.search = false
179 |
180 | return true
181 | end
182 |
183 | Define ("edit-find",
184 | [[
185 | Do incremental search forward for regular expression.
186 | As you type characters, they add to the search string and are found.
187 | Type @kbd{Return} to exit, leaving cursor at location found.
188 | Type @kbd{Ctrl-f} to search again forward, @kbd{Ctrl-Alt-f} to search again backward.
189 | @kbd{Ctrl-g} when search is successful aborts and moves cursor to starting
190 | point.
191 | ]],
192 | function (s)
193 | isearch (true, s or "")
194 | end
195 | )
196 |
197 | Define ("edit-find-backward",
198 | [[
199 | Do incremental search backward for regular expression.
200 | As you type characters, they add to the search string and are found.
201 | Type @kbd{Return} to exit, leaving cursor at location found.
202 | Type @kbd{Ctrl-Alt-f} to search again backward, @kbd{Ctrl-f} to search again forward.
203 | @kbd{Ctrl-g} when search is successful aborts and moves cursor to starting
204 | point.
205 | ]],
206 | function (s)
207 | isearch (false, s or "")
208 | end
209 | )
210 |
211 | -- Check the case of a string.
212 | -- Returns "uppercase" if it is all upper case, "capitalized" if just
213 | -- the first letter is, and nil otherwise.
214 | local function check_case (s)
215 | if regex_match (s, "^[[:upper:]]+$") then
216 | return "uppercase"
217 | elseif regex_match (s, "^[[:upper:]][^[:upper:]]*") then
218 | return "capitalized"
219 | end
220 | end
221 |
222 | -- Recase str according to newcase.
223 | local function recase (s, newcase)
224 | local bs = ""
225 | local i, len
226 |
227 | if newcase == "capitalized" or newcase == "upper" then
228 | bs = bs .. s[1]:upper ()
229 | else
230 | bs = bs .. s[1]:lower ()
231 | end
232 |
233 | for i = 2, #s do
234 | bs = bs .. (newcase == "upper" and string.upper or string.lower) (s[i])
235 | end
236 |
237 | return bs
238 | end
239 |
240 | -- FIXME: Make edit-replace run on selection.
241 | Define ("edit-replace",
242 | [[
243 | Replace occurrences of a regular expression with other text.
244 | As each match is found, the user must type a character saying
245 | what to do with it.
246 | ]],
247 | function (find)
248 | local find = find or (interactive () and minibuf_read ("Query replace string: "))
249 | if not find then
250 | return ding ()
251 | end
252 | local find_no_upper = no_upper (find)
253 |
254 | local repl = interactive () and minibuf_read (string.format ("Query replace `%s' with: ", find))
255 | if repl == "" then
256 | ding ()
257 | end
258 |
259 | local noask = false
260 | local count = 0
261 | local ok = true
262 | while search (find, true) do
263 | local c = keycode ' '
264 |
265 | if not noask then
266 | if thisflag.need_resync then
267 | window_resync (win)
268 | end
269 | minibuf_write (string.format ("Replace `%s' with `%s' (y, n, !, ., q)? ", find, repl))
270 | c = get_key_chord ()
271 | minibuf_clear ()
272 |
273 | if c == keycode "q" then -- Quit immediately.
274 | break
275 | elseif c == keycode "Ctrl-g" then
276 | ding ()
277 | break
278 | elseif c == keycode "!" then -- Replace all without asking.
279 | noask = true
280 | end
281 | end
282 |
283 | if c == keycode " " or c == keycode "y" or c == keycode "." or c == keycode "!" then
284 | -- Perform replacement.
285 | count = count + 1
286 | local case_repl = repl
287 | local r = region_new (get_buffer_pt (buf) - #find, get_buffer_pt (buf))
288 | if find_no_upper and get_variable ("case-replace") then
289 | local case_type = check_case (get_buffer_region (buf, r))
290 | if case_type then
291 | case_repl = recase (repl, case_type)
292 | end
293 | end
294 | local m = cursor_marker ()
295 | goto_offset (r.start)
296 | replace_string (#find, case_repl)
297 | goto_offset (m.o)
298 |
299 | if c == keycode "." then -- Replace and quit.
300 | break
301 | end
302 | elseif c ~= keycode "n" and c ~= keycode "Return" and c ~= keycode "Delete" then
303 | ungetkey (c)
304 | ok = false
305 | break
306 | end
307 | end
308 |
309 | if thisflag.need_resync then
310 | window_resync (win)
311 | end
312 |
313 | if ok then
314 | minibuf_write (string.format ("Replaced %d occurrence%s", count, count ~= 1 and "s" or ""))
315 | end
316 |
317 | return not ok
318 | end
319 | )
320 |
--------------------------------------------------------------------------------
/zee/shell.lua:
--------------------------------------------------------------------------------
1 | -- Run shell commands
2 | --
3 | -- Copyright (c) 2010-2012 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | Define ("edit-shell-command",
21 | [[
22 | Reads a line of text using the minibuffer and creates an inferior shell
23 | to execute the line as a command; passes the selection as input to the
24 | shell command.
25 | If the shell command produces any output, it is inserted into the
26 | file, replacing the selection if any.
27 | ]],
28 | function (cmd)
29 | if not cmd and interactive () then
30 | cmd = minibuf_read ("Shell command: ")
31 | end
32 | if cmd == "" then
33 | return ding ()
34 | end
35 |
36 | local ok = true
37 |
38 | local h, tempfile
39 | if buf.mark then
40 | tempfile = os.tmpname ()
41 |
42 | h = io.open (tempfile, "w")
43 | if not h then
44 | ok = minibuf_error ("Cannot open temporary file")
45 | else
46 | local fd = posix.fileno (h)
47 | local s = get_buffer_region (buf, calculate_the_selection ())
48 | local written, err = alien.default.write (fd, s.buf.buffer:topointer (), #s)
49 | if not written then
50 | ok = minibuf_error ("Error writing to temporary file: " .. err)
51 | end
52 | end
53 | end
54 |
55 | if ok then
56 | local cmdline = string.format ("%s 2>&1%s", cmd, tempfile and " <" .. tempfile or "")
57 | local pipe = io.popen (cmdline, "r")
58 | if not pipe then
59 | ok = minibuf_error ("Cannot open pipe to process")
60 | else
61 | local out = pipe:read ("*a")
62 | pipe:close ()
63 |
64 | if #out == 0 then
65 | minibuf_write ("(Shell command succeeded with no output)")
66 | else
67 | local del = 0
68 | if buf.mark then
69 | local r = calculate_the_selection ()
70 | goto_offset (r.start)
71 | del = get_region_size (r)
72 | end
73 | replace_string (del, out)
74 | end
75 | end
76 | end
77 |
78 | -- A sub-process may have caught a SIGWINCH, so assume one did.
79 | curses.ungetch (curses.KEY_RESIZE)
80 |
81 | if h then
82 | h:close ()
83 | end
84 | if tempfile then
85 | os.remove (tempfile)
86 | end
87 |
88 | return not ok
89 | end
90 | )
91 |
--------------------------------------------------------------------------------
/zee/term.lua:
--------------------------------------------------------------------------------
1 | -- Display engine
2 | --
3 | -- Copyright (c) 2009-2012 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | -- Window table:
21 | -- {
22 | -- topdelta: top line delta from cursor
23 | -- last_line: last cursor line number
24 | -- fwidth, fheight: actual width and height of the window
25 | -- ewidth, eheight: editing width and height of the window
26 | -- }
27 |
28 | function window_resync (wp)
29 | local n = get_buffer_line (buf)
30 | local delta = n - wp.last_line
31 |
32 | if delta ~= 0 then
33 | if (delta > 0 and wp.topdelta + delta < wp.eheight) or (delta < 0 and wp.topdelta >= -delta) then
34 | wp.topdelta = wp.topdelta + delta
35 | elseif n > wp.eheight / 2 then
36 | wp.topdelta = math.floor (wp.eheight / 2)
37 | else
38 | wp.topdelta = n
39 | end
40 | wp.last_line = n
41 | end
42 | end
43 |
44 | Define ("view-refresh",
45 | [[
46 | Refresh the display.
47 | ]],
48 | function ()
49 | term_clear ()
50 | term_display ()
51 | term_refresh ()
52 | end
53 | )
54 |
55 | function resize_window ()
56 | -- Resize window horizontally.
57 | win.fwidth = term_width ()
58 | win.ewidth = win.fwidth
59 |
60 | -- Resize window vertically.
61 | win.fheight = term_height ()
62 | win.eheight = win.fheight
63 | win.eheight = win.eheight - math.min (win.eheight, 2)
64 | end
65 |
66 | -- Tidy up the term ready to exit (temporarily or permanently!).
67 | function term_tidy ()
68 | term_move (term_height () - 1, 0)
69 | term_clrtoeol ()
70 | term_attrset (display.normal)
71 | term_refresh ()
72 | end
73 |
74 | -- Tidy and close the terminal ready to exit.
75 | function term_finish ()
76 | term_tidy ()
77 | term_close ()
78 | end
79 |
80 | -- Prints a line on the terminal.
81 | --
82 | -- line - the line number within the buffer
83 | -- startcol - the horizontal scroll offset
84 | -- o - the starting offset of the line
85 | -- rp - the highlight rectangle, or nil if none
86 | --
87 | -- If any part of the line is off the left-hand side of the screen,
88 | -- prints a `$' character in the left-hand column. If any part is off
89 | -- the right, prints a `$' character in the right-hand column. Any
90 | -- part that is within the highlight region is highlighted. If the
91 | -- final position is within the highlight region then the remainder of
92 | -- the line is also highlighted.
93 | local function draw_line (line, startcol, o, rp)
94 | term_move (line, 0)
95 |
96 | -- Draw body of line.
97 | local x = 0
98 | local line_len = buffer_line_len (buf, o)
99 | for i = startcol, math.huge do
100 | if i >= line_len or x >= win.ewidth then
101 | break
102 | end
103 | term_attrset ((rp and in_region (o, i, rp)) and display.reverse or display.normal)
104 | local c = get_buffer_char (buf, o + i)
105 | if posix.isprint (c) then
106 | term_addstr (c)
107 | x = x + 1
108 | else
109 | local s = make_string_printable (c, nil, x)
110 | term_addstr (s:sub (1, math.min (#s, win.fwidth - x)))
111 | x = x + #s
112 | end
113 | end
114 |
115 | term_addstr (string.rep (" ", win.fwidth - x))
116 | term_attrset (display.normal)
117 |
118 | -- Draw end of line.
119 | if x >= win.fwidth then
120 | term_move (line, win.fwidth - 1)
121 | term_addstr ('$')
122 | end
123 | end
124 |
125 | local function calculate_highlight_region ()
126 | if buf.mark == nil then
127 | return nil
128 | end
129 | return region_new (get_buffer_pt (buf), buf.mark.o)
130 | end
131 |
132 | local function draw_border ()
133 | term_attrset (display.reverse)
134 | term_addstr (string.rep ('-', win.ewidth))
135 | term_attrset (display.normal)
136 | end
137 |
138 | local function draw_status_line (line, wp)
139 | term_move (line, 0)
140 | draw_border()
141 |
142 | term_attrset (display.reverse)
143 | term_move (line, 0)
144 | local n = get_buffer_line (buf)
145 |
146 | local as = "--"
147 |
148 | -- Buffer state flags
149 | if buf.modified and buf.readonly then
150 | as = as .. "%*"
151 | elseif buf.modified then
152 | as = as .. "**"
153 | elseif buf.readonly then
154 | as = as .. "%%"
155 | else
156 | as = as .. "--"
157 | end
158 |
159 | -- File name
160 | as = as .. string.format (" %-15s ", buf.filename)
161 |
162 | -- Percentage of the way through the file
163 | as = as .. string.format ("%3d%%", ((get_buffer_pt (buf) - 1) * 100 // math.max (get_buffer_size (buf), 1)))
164 |
165 | -- Coordinates
166 | as = as .. string.format (" %-9s (", string.format ("(%d,%d)", n + 1, get_goalc ()))
167 |
168 | -- Mode flags
169 | local flags = {}
170 | if thisflag.defining_macro then
171 | table.insert (flags, "Def")
172 | end
173 | if buf.search then
174 | table.insert (flags, "Search")
175 | end
176 | as = as .. table.concat (flags, " ") .. ")"
177 |
178 | -- Display status line
179 | term_addstr (as:sub (1, term_width ()))
180 | term_attrset (display.normal)
181 | end
182 |
183 | local start_column = 0 -- start column of the window (>0 if scrolled sideways).
184 | local cursor_screen_column = 0 -- screen column of cursor
185 |
186 | local function draw_window (topline, wp)
187 | local rp = calculate_highlight_region ()
188 |
189 | -- Find the first line to display on the first screen line.
190 | local o = buffer_start_of_line (buf, get_buffer_pt (buf))
191 | local i = wp.topdelta
192 | while i > 0 and o > 1 do
193 | o = assert (buffer_prev_line (buf, o))
194 | i = i - 1
195 | end
196 |
197 | -- Draw the window lines.
198 | for i = topline, wp.eheight + topline do
199 | -- Clear the line.
200 | term_move (i, 0)
201 | term_clrtoeol ()
202 |
203 | -- If at the end of the buffer, don't write any text.
204 | if o ~= nil then
205 | draw_line (i, start_column, o, rp)
206 |
207 | if start_column > 0 then
208 | term_move (i, 0)
209 | term_addstr ('$')
210 | end
211 |
212 | o = buffer_next_line (buf, o)
213 | end
214 | end
215 |
216 | -- Draw the status line only if there is available space after the
217 | -- buffer text space.
218 | if wp.fheight > wp.eheight then
219 | draw_status_line (topline + wp.eheight, wp)
220 | end
221 | end
222 |
223 |
224 | -- Popup
225 |
226 | -- Contents of popup window.
227 | local popup_text
228 | local popup_line = 0
229 |
230 | -- Set the popup string to `s'.
231 | function popup_set (s)
232 | popup_text = s and AStr (s)
233 | popup_line = 0
234 | end
235 |
236 | -- Clear the popup string.
237 | function popup_clear ()
238 | popup_set ()
239 | end
240 |
241 | -- Scroll the popup text and loop having reached the bottom.
242 | function popup_scroll_down_and_loop ()
243 | popup_line = popup_line + win.fheight - 3
244 | if popup_line > popup_text:lines () then
245 | popup_line = 0
246 | end
247 | term_display ()
248 | end
249 |
250 | -- Scroll down the popup text.
251 | function popup_scroll_down ()
252 | local h = win.fheight - 3
253 | popup_line = math.min (popup_line + h, popup_text:lines () + 1 - h)
254 | term_display ()
255 | end
256 |
257 | -- Scroll up the popup text.
258 | function popup_scroll_up ()
259 | popup_line = popup_line - math.min (win.fheight - 3, popup_line)
260 | term_display ()
261 | end
262 |
263 | -- Draw the popup window.
264 | local function draw_popup ()
265 | assert (popup_text)
266 |
267 | -- Number of lines of popup_text that will fit on the terminal.
268 | -- Allow 3 for the border above, and minibuffer and status line below.
269 | local h = win.fheight - 3
270 | -- Number of lines.
271 | local l = popup_text:lines ()
272 | -- Position of top of popup == number of lines not to use.
273 | local y = math.max (h - l - 1, 0)
274 |
275 | term_move (y, 0)
276 | draw_border ()
277 |
278 | -- Draw popup text, and blank lines to bottom of window.
279 | local o = 1
280 | for l = 0, popup_line - 1 do
281 | o = popup_text:next_line (o)
282 | end
283 | for i = 1, h - y + 1 do
284 | if o then
285 | term_addstr (tostring (popup_text:sub (o, popup_text:end_of_line (o))))
286 | o = popup_text:next_line (o)
287 | end
288 | term_clrtoeol ()
289 | end
290 | end
291 |
292 | -- Scans `s' and replaces each character with a string of one or
293 | -- more printable characters. The returned string is suitable for
294 | -- printing at screen column `col' (default 0); the screen column
295 | -- only matters if `s' contains tab characters.
296 | --
297 | -- Scanning stops when the screen column reaches or exceeds `goal',
298 | -- or when `s' is exhausted. The number of input characters
299 | -- scanned is returned as a second return value. If no `goal' is
300 | -- passed, `math.huge' is assumed.
301 | --
302 | -- Characters that are already printable expand to themselves.
303 | -- Characters from 0 to 26 are replaced with strings from `^@' to
304 | -- `^Z'.
305 | -- Tab characters are replaced with enough spaces (but always
306 | -- at least one) to reach a screen column that is a multiple of
307 | -- `tab_width'.
308 | -- Newline characters must not occur in `s'.
309 | -- Other characters are replaced with a backslash followed by
310 | -- their hex character code.
311 | function make_string_printable (s, goal, col)
312 | col = col or 0
313 | goal = goal or math.huge
314 |
315 | local ctrls = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ"
316 | local ret, pos = "", 0
317 | for i = 1, #s do
318 | local c = s[i] -- if s is a string c is a string, otherwise a byte
319 | if type (c) == "number" then c = string.char (c) end
320 | assert (c ~= '\n')
321 |
322 | local x = col + #ret
323 | if x >= goal then
324 | break
325 | end
326 |
327 | if c == '\t' then
328 | ret = ret .. string.rep (' ', tab_width - (x % tab_width))
329 | elseif string.byte (c) < #ctrls then
330 | ret = ret .. '^' .. ctrls[string.byte (c) + 1]
331 | elseif posix.isprint (c) then
332 | ret = ret .. c
333 | -- FIXME: For double-width characters add a '\0' too so the length of
334 | -- 'ret' matches the display width.
335 | else
336 | ret = ret .. '\\' .. string.format ("%x", string.byte (c))
337 | end
338 |
339 | pos = pos + 1
340 | end
341 |
342 | return ret
343 | end
344 |
345 | -- Calculate start_column and cursor_screen_column.
346 | --
347 | -- `start_column' is always a multiple of a third of a screen width. It is
348 | -- chosen so as to put the cursor in the middle third, unless the cursor is near
349 | -- one or other end of the line, in which case it is chosen to show as much of
350 | -- the line as possible.
351 | local function calculate_start_column ()
352 | local width = win.ewidth
353 | local third_width = math.max (1, math.floor (width / 3))
354 |
355 | -- Calculate absolute columns of cursor and end of line.
356 | local x = get_goalc ()
357 | local length = #make_string_printable (get_line ())
358 |
359 | -- Choose start_column.
360 | if x < third_width or length < width then
361 | -- No-brainer cases: show left-hand end of line.
362 | start_column = 0
363 | else
364 | -- Put cursor in the middle third.
365 | start_column = x - (x % third_width) - third_width
366 | -- But scroll left if the right-hand end of the line stays on the screen.
367 | while start_column + width >= length + third_width do
368 | start_column = start_column - third_width
369 | end
370 | end
371 |
372 | -- Consequently, calculate screen-relative column.
373 | cursor_screen_column = x - start_column
374 | end
375 |
376 | function term_display ()
377 | calculate_start_column ()
378 | draw_window (0, win)
379 | if popup_text then
380 | draw_popup ()
381 | end
382 | term_redraw_cursor ()
383 | end
384 |
385 | function term_redraw_cursor ()
386 | term_move (win.topdelta, cursor_screen_column)
387 | end
388 |
--------------------------------------------------------------------------------
/zee/term_curses.lua:
--------------------------------------------------------------------------------
1 | -- Curses terminal
2 | --
3 | -- Copyright (c) 2009-2012 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | local codetokey, keytocode, key_buf
21 |
22 | local ESC = 0x1b
23 | local ESCDELAY = 500
24 |
25 | local resumed = true
26 |
27 | local function keypad (on)
28 | local capstr = curses.tigetstr (on and "smkx" or "rmkx")
29 | if capstr then
30 | io.stdout:write (capstr)
31 | io.stdout:flush ()
32 | end
33 | end
34 |
35 | function term_init ()
36 | curses.initscr ()
37 |
38 | display = {
39 | normal = curses.A_NORMAL,
40 | standout = curses.A_STANDOUT,
41 | underline = curses.A_UNDERLINE,
42 | reverse = curses.A_REVERSE,
43 | blink = curses.A_BLINK,
44 | dim = curses.A_DIM,
45 | bold = curses.A_BOLD,
46 | protect = curses.A_PROTECT,
47 | invisible = curses.A_INVIS,
48 |
49 | black = curses.COLOR_BLACK,
50 | red = curses.COLOR_RED,
51 | green = curses.COLOR_GREEN,
52 | yellow = curses.COLOR_YELLOW,
53 | blue = curses.COLOR_BLUE,
54 | magenta = curses.COLOR_MAGENTA,
55 | cyan = curses.COLOR_CYAN,
56 | white = curses.COLOR_WHITE,
57 | }
58 |
59 | key_buf = list {}
60 |
61 | -- from curses key presses to editor keycodes
62 | codetokey = tree {}
63 |
64 | -- from editor keycodes back to curses key presses
65 | keytocode = {}
66 |
67 | -- Starting with specially named keys:
68 | for code, key in pairs {
69 | [0x9] = "Tab",
70 | [0xd] = "Return",
71 | [0x20] = "Space",
72 | [0x7f] = "Ctrl-?",
73 | ["kbs"] = "Backspace",
74 | ["kdch1"] = "Delete",
75 | ["kDC5"] = "Ctrl-Delete",
76 | ["kcud1"] = "Down",
77 | ["kend"] = "End",
78 | ["kEND5"] = "Ctrl-End",
79 | ["kf1"] = "F1",
80 | ["kf2"] = "F2",
81 | ["kf3"] = "F3",
82 | ["kf4"] = "F4",
83 | ["kf5"] = "F5",
84 | ["kf6"] = "F6",
85 | ["kf7"] = "F7",
86 | ["kf8"] = "F8",
87 | ["kf9"] = "F9",
88 | ["kf10"] = "F10",
89 | ["kf11"] = "F11",
90 | ["kf12"] = "F12",
91 | ["khome"] = "Home",
92 | ["kHOM5"] = "Ctrl-Home",
93 | ["kich1"] = "Insert",
94 | ["kcub1"] = "Left",
95 | ["kLFT5"] = "Ctrl-Left",
96 | ["knp"] = "PageDown",
97 | ["kpp"] = "PageUp",
98 | ["kcuf1"] = "Right",
99 | ["kRIT5"] = "Ctrl-Right",
100 | ["kspd"] = "Ctrl-z",
101 | ["kcuu1"] = "Up"
102 | } do
103 | local codes = nil
104 | if type (code) == "string" then
105 | local s = curses.tigetstr (code)
106 | if s then
107 | codes = {}
108 | for i = 1, #s do
109 | table.insert (codes, s:byte (i))
110 | end
111 | end
112 | else
113 | codes = {code}
114 | end
115 |
116 | if codes then
117 | key = keycode (key)
118 | keytocode[key] = codes
119 | codetokey[codes] = key
120 | end
121 | end
122 |
123 | -- Reverse lookup of a lone ESC.
124 | keytocode[keycode "Escape"] = {ESC}
125 |
126 | -- ...fallback to 0x7f for backspace if terminfo doesn't know better
127 | if not curses.tigetstr ("kbs") then
128 | keytocode[keycode "Backspace"] = {0x7f}
129 | end
130 | if not codetokey[{0x7f}] then
131 | codetokey[{0x7f}] = keycode "Backspace"
132 | end
133 |
134 | -- ...inject remaining ASCII key codes
135 | for code = 0, 0x7f do
136 | local key = nil
137 | if not codetokey[{code}] then
138 | -- control keys
139 | if code < 0x20 then
140 | key = keycode ("Ctrl-" .. string.char (code + 0x40):lower ())
141 |
142 | -- printable keys
143 | elseif code < 0x80 then
144 | key = keycode (string.char (code))
145 |
146 | -- meta keys
147 | else
148 | local basekey = codetokey[{code - 0x80}]
149 | if type (basekey) == "table" and basekey.key then
150 | key = "Alt-" + basekey
151 | end
152 | end
153 |
154 | if key ~= nil then
155 | codetokey[{code}] = key
156 | keytocode[key] = {code}
157 | end
158 | end
159 | end
160 |
161 | curses.echo (false)
162 | curses.nl (false)
163 | curses.raw (true)
164 | curses.stdscr ():meta (true)
165 | curses.stdscr ():intrflush (false)
166 | curses.stdscr ():keypad (false)
167 |
168 | posix.signal (posix.SIGCONT, function () resumed = true end)
169 | end
170 |
171 | function term_close ()
172 | -- Revert terminal to cursor mode before exiting.
173 | keypad (false)
174 |
175 | curses.endwin ()
176 | end
177 |
178 | function term_getkey_unfiltered (delay)
179 | if #key_buf > 0 then
180 | return table.remove (key_buf)
181 | end
182 |
183 | -- Put terminal in application mode if necessary.
184 | if resumed then
185 | keypad (true)
186 | resumed = nil
187 | end
188 |
189 | curses.stdscr ():timeout (delay)
190 |
191 | local c
192 | repeat
193 | c = curses.stdscr ():getch ()
194 | if curses.KEY_RESIZE == c then
195 | resize_window ()
196 | execute_command ("move-redraw")
197 | end
198 | until curses.KEY_RESIZE ~= c
199 |
200 | return c
201 | end
202 |
203 | local function unget_codes (codes)
204 | key_buf = list.concat (key_buf, std.ireverse (codes))
205 | end
206 |
207 | function term_getkey (delay)
208 | local codes, key = {}
209 |
210 | local c = term_getkey_unfiltered (delay)
211 | if c == ESC then
212 | -- Detecting ESC is tricky...
213 | c = term_getkey_unfiltered (ESCDELAY)
214 | if c == nil then
215 | -- ...if nothing follows quickly enough, assume ESC keypress...
216 | key = keycode "Escape"
217 | else
218 | -- ...see whether the following chars match an escape sequence...
219 | codes = { ESC }
220 | while true do
221 | table.insert (codes, c)
222 | key = codetokey[codes]
223 | if key and key.key then
224 | -- ...return the codes for the matched escape sequence.
225 | break
226 | elseif key == nil then
227 | -- ...no match, rebuffer unmatched chars and return Escape.
228 | unget_codes (list.tail (list (codes)))
229 | key = keycode "Escape"
230 | break
231 | end
232 | -- ...partial match, fetch another char and try again.
233 | c = term_getkey_unfiltered (GETKEY_DEFAULT)
234 | end
235 | end
236 | else
237 | -- Detecting non-Escape involves fetching chars and matching...
238 | while true do
239 | if c ~= nil then
240 | table.insert (codes, c)
241 | end
242 | key = codetokey[codes]
243 | if c == nil or (key and key.key) then
244 | -- ...code lookup matched a key, return it.
245 | break
246 | elseif key == nil then
247 | -- ...or return nil for an invalid lookup code.
248 | key = nil
249 | break
250 | end
251 | -- ...for a partial match, fetch another char and try again.
252 | c = term_getkey_unfiltered (GETKEY_DEFAULT)
253 | end
254 | end
255 |
256 | if key == keycode "Escape" then
257 | local another = term_getkey (GETKEY_DEFAULT)
258 | if another then key = "Alt-" + another end
259 | end
260 |
261 | if c == nil then
262 | return nil
263 | end
264 | return key
265 | end
266 |
267 |
268 | -- If key can be represented as an ASCII byte, return it, otherwise
269 | -- return nil.
270 | function term_keytobyte (key)
271 | local codes = keytocode[key]
272 | if codes and #codes == 1 and 0xff >= codes[1] then
273 | return codes[1]
274 | end
275 | return nil
276 | end
277 |
278 | function term_ungetkey (key)
279 | local codevec = list {}
280 |
281 | if key ~= nil then
282 | if key.ALT then
283 | codevec = list { ESC }
284 | key = key - "Alt-"
285 | end
286 |
287 | local code = keytocode[key]
288 | if code then
289 | codevec = list.concat (codevec, code)
290 | end
291 | end
292 |
293 | unget_codes (codevec)
294 | end
295 |
296 | function term_buf_len ()
297 | return #key_buf
298 | end
299 |
300 | function term_move (y, x)
301 | curses.stdscr ():move (y, x)
302 | end
303 |
304 | function term_clrtoeol ()
305 | curses.stdscr ():clrtoeol ()
306 | end
307 |
308 | function term_refresh ()
309 | curses.stdscr ():refresh ()
310 | end
311 |
312 | function term_clear ()
313 | curses.stdscr ():clear ()
314 | end
315 |
316 | function term_addstr (s)
317 | curses.stdscr ():addstr (s)
318 | end
319 |
320 | function term_attrset (attrs)
321 | curses.stdscr ():attrset (attrs or 0)
322 | end
323 |
324 | function term_beep ()
325 | curses.beep ()
326 | end
327 |
328 | function term_width ()
329 | return curses.cols ()
330 | end
331 |
332 | function term_height ()
333 | return curses.lines ()
334 | end
335 |
--------------------------------------------------------------------------------
/zee/undo.lua:
--------------------------------------------------------------------------------
1 | -- Undo facility functions
2 | --
3 | -- Copyright (c) 2010-2012 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | -- Save a reverse delta for doing undo.
21 | local function undo_save (ty, o, osize, size)
22 | local u = {type = ty, next = buf.last_undo, o = o}
23 |
24 | if ty == "replace block" then
25 | u.size = size
26 | u.text = get_buffer_region (buf, region_new (o, o + osize))
27 | u.unchanged = not buf.modified
28 | end
29 |
30 | buf.last_undo = u
31 | end
32 |
33 |
34 | function undo_start_sequence ()
35 | undo_save ("start sequence", get_buffer_pt (buf))
36 | end
37 |
38 | function undo_end_sequence ()
39 | undo_save ("end sequence")
40 | end
41 |
42 | function undo_save_block (o, osize, size)
43 | undo_save ("replace block", o, osize, size)
44 | end
45 |
46 | -- Set unchanged flags to false.
47 | function undo_set_unchanged (u)
48 | while u do
49 | u.unchanged = false
50 | u = u.next
51 | end
52 | end
53 |
54 | -- Revert an action.
55 | -- Return the next undo entry.
56 | local function revert_action (up)
57 | if up.type == "end sequence" then
58 | undo_start_sequence ()
59 | up = up.next
60 | while up.type ~= "start sequence" do
61 | up = revert_action (up)
62 | end
63 | undo_end_sequence ()
64 | end
65 |
66 | goto_offset (up.o)
67 | if up.type == "replace block" then
68 | replace_string (up.size, up.text)
69 | goto_offset (up.o)
70 | if up.unchanged then
71 | buf.modified = false
72 | end
73 | end
74 |
75 | return up.next
76 | end
77 |
78 | Define ("edit-undo",
79 | [[
80 | Undo some previous changes.
81 | Repeat this command to undo more changes.
82 | ]],
83 | function ()
84 | if not buf.next_undo then
85 | minibuf_error ("No further undo information")
86 | buf.next_undop = buf.last_undo
87 | return true
88 | end
89 |
90 | buf.next_undo = revert_action (buf.next_undo)
91 | minibuf_write ("Undo!")
92 | end
93 | )
94 |
95 | Define ("edit-revert",
96 | [[
97 | Undo until buffer is unmodified.
98 | ]],
99 | function ()
100 | while buf.modified do
101 | execute_command ("edit-undo")
102 | end
103 | end
104 | )
105 |
--------------------------------------------------------------------------------
/zee/variables.lua:
--------------------------------------------------------------------------------
1 | -- Editor variables
2 | --
3 | -- Copyright (c) 2010-2012 Free Software Foundation, Inc.
4 | --
5 | -- This file is part of Zee.
6 | --
7 | -- This program is free software; you can redistribute it and/or modify it
8 | -- under the terms of the GNU General Public License as published by
9 | -- the Free Software Foundation; either version 3, or (at your option)
10 | -- any later version.
11 | --
12 | -- This program is distributed in the hope that it will be useful, but
13 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
14 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | -- General Public License for more details.
16 | --
17 | -- You should have received a copy of the GNU General Public License
18 | -- along with this program. If not, see .
19 |
20 | Define ("indent-width", "Number of spaces inserted for an indentation.",
21 | 2)
22 | Define ("caseless-search", "Whether searching ignores case by default.",
23 | true)
24 | Define ("case-replace", "Whether `query-replace' should preserve case.",
25 | false)
26 |
27 |
28 | function get_variable (var)
29 | return (env[var] or {}).val
30 | end
31 |
32 | function preferences_set_variable (var, val)
33 | env[var] = env[var] or {}
34 | env[var].val = val
35 | end
36 |
37 | Define ("preferences-set-variable",
38 | [[
39 | Set a variable to the specified value.
40 | ]],
41 | function (var, val)
42 | var = var or (interactive () and
43 | minibuf_read_completion ("Set variable: ",
44 | completion_new (filter (function (e)
45 | return not command_exists (e)
46 | end,
47 | std.ielems, table.keys (env))),
48 | "variable"))
49 | if var == "" then
50 | return true
51 | end
52 |
53 | if val == nil and interactive () then
54 | val = minibuf_read (string.format ("Set %s to value: ", var))
55 | end
56 | if val == nil then
57 | return ding ()
58 | end
59 | preferences_set_variable (var, val)
60 | end
61 | )
62 |
--------------------------------------------------------------------------------
/zee/zee.in:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | A=--[[ exec @LUA@ "$0" "$@" # -*- mode: lua; -*- ]]A
3 | --
4 | -- Program initialisation
5 | --
6 | -- Copyright (c) 2010-2014 Free Software Foundation, Inc.
7 | --
8 | -- This file is part of Zee.
9 | --
10 | -- This program is free software; you can redistribute it and/or modify it
11 | -- under the terms of the GNU General Public License as published by
12 | -- the Free Software Foundation; either version 3, or (at your option)
13 | -- any later version.
14 | --
15 | -- This program is distributed in the hope that it will be useful, but
16 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
17 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 | -- General Public License for more details.
19 | --
20 | -- You should have received a copy of the GNU General Public License
21 | -- along with this program. If not, see .
22 |
23 |
24 | -- Constants set by configure
25 | PACKAGE = "@PACKAGE@"
26 | PACKAGE_NAME = "@PACKAGE_NAME@"
27 | PACKAGE_BUGREPORT = "@PACKAGE_BUGREPORT@"
28 | VERSION = "@VERSION@"
29 |
30 | require "luarocks.loader"
31 | require (PACKAGE)
32 |
33 |
34 | local function err (err)
35 | term_close ()
36 | print ("Internal error. Please report this bug with steps to reproduce the problem.")
37 | print (debug.traceback(err, 2))
38 | os.exit (2)
39 | end
40 |
41 | xpcall (main, err)
42 |
--------------------------------------------------------------------------------