summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* linenoise: edit command line in external editor.Kaz Kylheku2015-09-162-0/+83
| | | | | | | | * linenoise/linenoise.c (tr, edit_in_editor): New static functions. (edit): edit_in_editor hooked in under Ctrl-X Ctrl-E. * txr.1: Documented.
* linenoise: Ctrl-X extended commands.Kaz Kylheku2015-09-161-1/+16
| | | | | | * linenoise/linenoise.c (edit): Handle the Ctrl-X key by setting a temporary flag. This sets the framework for commands prefixed by Ctrl-X.
* syntax: be tolerant of carriage returns.Kaz Kylheku2015-09-161-15/+16
| | | | | | | | | | | | | | This is needed for multi-line mode with CR line breaks. It also makes TXR tolerant when code is ported among systems with different line endings. * parser.l (NL): New lex named pattern, matching three possible line terminators: CR, NL or CR-NL. (grammar): In places where \n was previously matched, use {NL}. In a few places where \n is in a character class, add \r. In one place (comment matching), the the pattern . which implicitly doesn't match newlines had to be replaced with [^\r\n].
* linenoise: oldpos-related multi-line refresh issue.Kaz Kylheku2015-09-161-21/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The oldpos variable for tracing the previous cursor position as an absolute offset into the display data is not appropriate any more under enhanced multi-line mode. The reason is that edit operations can completely replace the buffer (e.g. history recall). When the buffer is replaced, because there can be arbitrary line breaks in the data, the oldpos variable's saved position has no meaning relative to the new buffer contents. But the only use of oldpos is to calculate the previous *row* of the cursor position! So, we can replace oldpos with a variable that just remembers the row directly. As a bonus, we can get rid of the calculation which tries to recover the oldrow from oldpos. * linenoise/linenoise.c (struct lino_state): Removed member oldpos. Added member oldrow. (struct row_values): Array reduced to two elements. (screen_rows): Doesn't take oldpos argument any more. Current cursor position returned in out.rows[1]. (refresh_multiline): Some variables renamed. rpos2 becomes nrow (new row position). old_rows is oldmaxrows to avoid confusion with l->oldrow. The rpos variable (old row position) is gone: its uses are replaced with l->oldrow. Near the end of the function, we save the new cursor row position (nrow) in l->oldrow, in the same spot where we previously saved the current position in l->oldpos. (edit): Initialize l->oldrow to 0. Remove initialization of l->oldpos.
* linenoise: remove multiline debug codeKaz Kylheku2015-09-161-28/+0
| | | | | | | * linenoise/linenoise.c (lndebug): Macro removed. The variables have changed; it won't work any more. We have GDB. (refresh_multiline): lndebug calls removed.
* linenoise: enhanced multi-line mode with line breaks.Kaz Kylheku2015-09-162-23/+106
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The linenoise multi-line mode is just a glorified line wrapper, and not actualy a multi-line editor, like in GNU Readline and others. This commit fixes it. The edit buffer can now contain line breaks, separated by carriage return characters. (In single-line mode, these characters continue to be displayed as ^M). The row and column calculations in the multi-line refresh follow this data representation. * linenoise/linenoise.c (sync_data_to_buf): This function now takes an extra argument telling it whether multi-line mode is in effect for the rendering. In multi-line mode, the prompt is now added to the display data, so that multi-line refresh is simplified by not having to account for the prompt length in various calculations. Also, in multi-line mode, carriage returns are rendered to display as CR-LF pairs, since they denote embedded line breaks. (complete_line): Pass mlmode to sync_data_to_buf. (struct row_values): New struct, for returning multiple row values out of a function. (screen_rows, col_offset_in_str): New static functions. (refresh_multiline): Modified to use screen_rows and col_offset_in_str for its calculations, and not to deal with the prompt at all, since the prompt is rolled into the display data. (refresh_line, edit_insert): Pass mlmode to sync_data_to_buf. * txr.1: Documented multi-line mode.
* linenoise: don't process carriage returns in history.Kaz Kylheku2015-09-161-4/+1
| | | | | | | | | * linenoise/linenoise.c (lino_hist_load): Don't look for and overwrite carriage returns with the null character; only do that for newlines. We already handle embedded carriage returns just fine by displaying them as ^M. There is a plan to use these characters for breaking up lines in an enhanced multi-line mode.
* linenoise: null-terminate display buffer.Kaz Kylheku2015-09-161-0/+1
| | | | | | | * linenoise/linenoise.c (sync_data_to_buffer): Add missing null terminator to l->buf. This hasn't caused a problem because no code relies on it being a C string. That may be about to change.
* linenoise: Ctrl-J toggles multi-line mode.Kaz Kylheku2015-09-161-0/+4
| | | | | * linenoise/linenoise.c (edit): Handle CTL('J') by toggling mlmode and refreshing the line.
* linenoise: bugfix: Ctrl-D checks wrong length field.Kaz Kylheku2015-09-161-1/+1
| | | | | * linenoise/linenoise.c (edit): Delete if the data length is nonzero, not the display length.
* linenoise: parenthesis-matching backward jump.Kaz Kylheku2015-09-152-0/+116
| | | | | | | | | | | * linenoise/linenoise.c (LINENOISE_PAREN_DELAY): New preprocessor symbol. (scan_match_rev, scan_rev, usec_delay, paren_jump): New static functions. (edit): Handle closing parenthesis, bracket and brace by inserting and calling paren_jump. * txr.1: Documented.
* Wording and grammar fix under permutationsKaz Kylheku2015-09-151-3/+3
| | | | | * txr.1: Fix inappropriately copy and pasted ungrammatical text "permutations is of zero length".
* False positive valgrind error: uninitialized sigset_t.Kaz Kylheku2015-09-151-0/+6
| | | | | | | | | | | | | | | The issue is that sigset_t is 1024 bits wide on Linux, but there aren't actually that many signals. Valgrind knows this and so when sigprocmask returns the old signal set, Valgrind only marks a portion of it as initialized, and not the entire 1024 bits. When this sigset_t is later passed into sig_set again, we do a memcmp on all 1024 bits and Valgrind complains about a use of uninitialized data. Test case: run valgrind ./txr -i and execute a (throw 'foo) expr. * signal.c (sig_mask): If we are compiling with Valgrind support, mark the old signal set defined just before passing it to sigprocmask, so it has no uninitialized bits.
* extended_jmp_buf members should be volatile.Kaz Kylheku2015-09-151-12/+14
| | | | | | | | | | | | | Instances of extended_jmp_buf structure are defined in automatic storage. The members are manipulated after setjmp and accessed after returning via longjmp. Therefore, they should be volatile-qualified. * signal.h (EJ_DBG_MEMB): Add volatile to dbg_depth. (extended_jmp_buf): Add volatile on all members in both versions of the structure. (extended_setjmp): Cast away volatile when passing sigset_t to sig_mask.
* Regex state-marking counter wraparound bug.Kaz Kylheku2015-09-151-1/+28
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When a NFA regex goes through more than 4.29 billion state transitions, the state coloring "visited" marker wraps around. There could still exist states with old values at or near zero, which destroys the correctness of the closure calculations. * regex.c (nfa_handle_wraparound): New static function. The wraparound situation is handled by detecting when the next marker value is UINT_MAX. When this happens, we visit all states, marking them to UINT_MAX. Then we visit them again, marking them to zero, and set the next marker value to 1. (nfa_free): Added comment about why we don't have a wraparound check, in case it isn't obvious. (nfa_run): Check for wraparound before eveyr nfa_closure call. (regex_machine_reset): Check for wraparound before nfa_closure call. Fix: store the counter back in the start state's visited field. (regex_machine_init): Initialize the n.visited field of the regex machine structure to zero. Not strictly necessary, since it's initialized moments later in regex_machine_reset, but good form. (regex_machine_feed): Check for wraparound before nfa_closure call.
* Use alloca for some temporary arrays in regex module.Kaz Kylheku2015-09-151-11/+5
| | | | | * regex.c (nfa_free): Use alloca for array of all states. (nfa_run): Use alloca for move, closure and stack arrays.
* Remove limit on NFA state size and allocate tightly.Kaz Kylheku2015-09-151-62/+63
| | | | | | | | | | | | | | | | | | | | | | | | | | | | * regex.c (struct regex): New member, nstates. (NFA_SET_SIZE): Preprocessor symbol removed. (struct nfa_machine): New member, nstates. (nfa_all_states): Function removed. (nfa_map_states): New static function. (nfa_count_one, nfa_count_states, nfa_collect_one): New static functions. (nfa_free): Takes nstates argument. Calculate array of all states using nfa_map_states over nfa_collect_one rather than nfa_all_states. The array is tightly allocated. Also the spanning tree traversal needs just one root, nfa.start. It's not clear why nfa_all_states used nfa.start and nfa.accept as roots. (nfa_closure): Takes nstates parameter; array bounds checking performed tightly against nstates rather than NFA_SET_SIZE. (nfa_move): Check against NFA_SET_SIZE removed. (nfa_run): Take nstates argument. Allocate arrays tightly. Pass nstates to nfa_closure. (regex_destroy): Pass regex->nstates to nfa_free. (regex_compile): Initialize regex->nstates. (regex_run): Pass regex->nstates to nfa_run. (regex_machine_reset): Pass nstates to nfa_closure. (regex_machine_init): Initialize n.nstates member of regex machine. Allocate arrays tightly. (regex_machine_feed): Pass nstates to nfa_closure.
* Fix memory leak in regexes.Kaz Kylheku2015-09-141-1/+1
| | | | | | * regex.c (nfa_free): The visited marker must be incremented, otherwise nfa_all_states will only collect start and accept.
* linenoise: handle SIGWINCH resize signal.Kaz Kylheku2015-09-141-2/+64
| | | | | | | | | | | | | | | | | | | | * linenoise/linenoise.c (struct lino_state): New member, need_resize. (lino_list_busy): New static variable. (handle_resize): New function. (complete_line, history_search, edit): Check for the tty read being interrupted, and in that case call handle_resize to put the resize into effect, and continue the loop to fetch another character. (sigwich_handler): New function. (linenoise): If we have SIGWINCH, install a handler for it temporarily. (link_into_list, unlink_from_list): Set global busy flag around list manipulations. The signal handler stays away if these are set. This means that if the user performs some action that requires a lino_t to be constructed (e.g. types Ctrl-R to search), while resizing the window at almost exactly the same time, we will lose the resize signal. Oh well!
* Implement ~/.txr_profile mechanism.Kaz Kylheku2015-09-134-1/+58
| | | | | | | | | | | | * parser.c (load_rcfile): New function. (repl): Compute profile file name and try to load it before entering loop. * sysif.c (statp): Linkage becomes external. * sysif.h (statp): Declaration updated. * txr.1: Documented.
* Don't supply trivial completion which matches prefix.Kaz Kylheku2015-09-131-0/+3
| | | | | | | * parser.c (find_matching_syms): Don't add an entry into the history if it is a full match for the completion prefix, because in the UI in then looks as if nothing happened when Tab as pressed.
* linenoise: recognize additional commands in search.Kaz Kylheku2015-09-132-3/+17
| | | | | | | | | * linenoise/linenoise.c (history_search): Editing keys should leave search mode and be processed in command mode. Also, let's have Ctrl-L and Ctrl-Z work, but stay in search mode. * txr.1: Documented.
* linenoise: suppress duplicates in Ctrl-R search.Kaz Kylheku2015-09-131-2/+8
| | | | | | * linenoise/linenoise.c (history_search): Don't step through identical lines, which looks as if Ctrl-R is being ignored.
* linenoise: support completion in the middle of line.Kaz Kylheku2015-09-122-17/+23
| | | | | | | | | * linenoise/linenoise.c (compare_completions): Restructure with help of new lino_copy function to collect completions just for the prefix of the line up to the cursor position, and recombine those with the suffix. * txr.1: Doc updated.
* linenoise: incorrect ESC treatment in completion.Kaz Kylheku2015-09-122-15/+2
| | | | | | | | | | * linenoise/linenoise.c (complete_line): ESC must not be treated specially when leaving completion mode; it must accept the completed line. The original code did this wrong in my opinion and I propagated the error. * txr.1: Remove all mention of special ESC treatment in completion mode.
* linenoise: Suppress unknown control characters.Kaz Kylheku2015-09-122-5/+9
| | | | | | | * linenoise/linenoise.c (edit): Don't let characters less than 32 be inserted. * txr.1: Documented that control characters are rejected.
* linenoise: Ctrl-R searchKaz Kylheku2015-09-122-3/+180
| | | | | | | | | | | * linenoise/linenoise.c (next_hist_match, history_search): New static function. (edit): New Ctrl-R case added to early switch that also handles Tab completion, and calls history_search. (lino_free): Adding null check, so we can safely call lino_free(0). history_search relies on this. * txr.1: Documented search.
* Treat comment lines in repl, and plug memory leak.Kaz Kylheku2015-09-112-4/+24
| | | | | | | | | | * parser.c (repl): If we continue the loop due to detecting a blank line, we must free that line, since we are outside of the unwind block (and continue would violate that block if we were). If a line contains nothing but a comment, then enter that line into the history. * txr.1: Documented treatment of commented lines.
* New :read command in repl for direct stdin parse.Kaz Kylheku2015-09-112-1/+48
| | | | | | | | * parser.c (read_eval_ret_last): New function. (repl): Use read_eval_ret_last for :read command. * txr.1: Document :read in new section on direct read from the terminal.
* Better EOF check in read-eval stream function.Kaz Kylheku2015-09-112-1/+11
| | | | | | | | | | | | | | | | | | | | | This makes a difference if we read from a TTY. Without this fix, two Ctrl-D's have to be issued before the code registers EOF and returns. The trick is that we know, after calling the parser, whether it hit EOF, because we have the recent token. If its value is zero, that's the EOF token. We can bail out of the loop instead of calling the parser again which will require another EOF (because prime_parser will not push an EOF token!) * parser.h (parser_eof): Declared. * parser.c (read_eval_stream): After lisp_parse and eval, check for EOF with the parser_eof function, and bail if so. (parser_eof): New function.
* Quit if input form is :quit not its value.Kaz Kylheku2015-09-112-3/+3
| | | | | | | | * parser.c (repl): Subtle difference. Test form's syntax for equality to :quit, not its value. The REPL should not terminate if a form happens to calculate :quit as a value. * txr.1: Updated.
* Document some special keys supported by linenoise.Kaz Kylheku2015-09-111-2/+5
| | | | * txr.1: document Home, End and Delete support.
* linenoise: Ctrl-C cleanly cancels completion.Kaz Kylheku2015-09-112-3/+18
| | | | | | | | | | * linenoise/linenoise.c (complete_line): If Ctrl-C is pressed in completion mode, we cancel completion and return 0 so the command loop reads a new character. * txr.1: Documented Ctrl-C in completion mode, and removed the falsehood that ESC is a cancel command, adding instead an explanation about the ESC handling is really for.
* linenoise: replace 9 with TAB; anticipate extension.Kaz Kylheku2015-09-111-8/+14
| | | | | | | * linenoise/linenoise.c (edit): Code block which handles tab completion before main command dispatch uses the TAB symbol instead of 9, and is refactored into a switch statement which will also handle a history search command.
* linenoise: lino_copy function.Kaz Kylheku2015-09-112-7/+35
| | | | | | | | | | | | * linenoise/linenoise.c (link_into_list, unlink_from_list): New static functions. (lino_make): Use link_into_list instead of open-coded list manipulation. (lino_copy): New function. (lino_free): Use unlink_from list instead of open-coded list manipulation. * linenoise/linenoise.h (lino_copy): Declared.
* Version 115.txr-115Kaz Kylheku2015-09-106-366/+504
| | | | | | | | | | * RELNOTES: Updated. * configure, txr.1: Bumped version and date. * share/txr/stdlib/ver.tl: Likewise. * txr.vim, tl.vim: Regenerated.
* Fix misspelled :toinger filter.Kaz Kylheku2015-09-103-5/+5
| | | | | | | | | | | | | | | | | | | The manual documents a filter called :tointeger, but it has never existed. The keyword was misspelled in the source code from the beginning as :toinger. I'm fixing the typo and renaming the filter to :toint at the same time. * filter.c (tointeger_k, toint_k): Former renamed to latter. (filter_init): Initialize toint_k with correctly spelled symbol. Register filter under toint_k. * filter.h (tointeger_k, toint_k): Former renamed to latter. * txr.1: Changed mention of :tointeger to :toint.
* Remove duplicate variable initialization.Kaz Kylheku2015-09-101-1/+0
| | | | | * eval.c (eval_init): Remove duplicate initialization of with_saved_vars_s.
* Bugfix: *args* not bound for command line expressions.Kaz Kylheku2015-09-102-10/+21
| | | | | | | | | | | | | | | | The documentation says that *args* is bound to nil, but actually it is not bound at all. Let us fix this by actualy binding *args* to the remaining arguments, and by also allowing modification of *args* to dynamically take effect. * txr.c: Set up value of *args* prior to processing any option which evaluates TXR Lisp. Afterwards, reload the argument list from that variable. * txr.1: Documented semantics of *args* during command line processing.
* Don't scan C source code for Lisp symbols.Kaz Kylheku2015-09-103-33/+58
| | | | | | | | | | | | | | * eval.c (eval_init): Register package-alist, package-name and package-symbols intrinsics. * genvim.txr: Rather than scanning C sources for TXR Lisp symbols, iterate over the packages and their symbols, collecting anything which has a binding or is self-evaluating. To get the stdlib symbols, we trigger the autoloads by doing boundp queries on a few symbols. * txr.1: Document package-alist, package-name and package-symbols.
* Bugfix: make self-path visible to Lisp.Kaz Kylheku2015-09-102-2/+26
| | | | | | | | | | | | | | | The self-path variable is not bound in TXR Lisp scripts or the command line. * txr.c (txr_main): Set self-path to "cmdline-expr" before command line Lisp evaluations. (For TXR pattern language syntax invoked in a -c, it continues to be "cmdline"). Set self-path to the file name when reading a Lisp file. Also, the legacy, undocumented *self-path* is only set for TXR scripts, and is reverted to being a special variable, not a global lexical. * txr.1: Documented self-path in more detail.
* Don't pass char to <ctype.h> function.Kaz Kylheku2015-09-101-2/+4
| | | | | | | * parser.c (provide_completions): Cast char argument to unsigned char in call to isalnum. The data comes from user input, which could be any byte. The char type may be signed (and usually is) and so may take on negative values.
* Completion doesn't iterate over all packages.Kaz Kylheku2015-09-101-10/+3
| | | | | | | | | | | When the completed symbol is unqualified, let's not complete across all packages, but just the user package. * parser.c (provide_completions): Substitute user_package if package is null, and call find_matching_syms once rather than iterating on all packages. Also, in this case, do not request symbol qualification.
* No completion on symbol in nonexistent package.Kaz Kylheku2015-09-101-0/+2
| | | | | * parser.c (provide_completions): If find_package returns nil, then just bail with no completions.
* linenoise: sort completions by length.Kaz Kylheku2015-09-101-0/+19
| | | | | | | | | | Give the shorter completions first, and lexicographically within each length equivalence class. This effectively gives the user a breadth-first search through the trie of possible suffixes. * linenoise/linenoise.c (compare_completions): New static function. (complete_line): Apply qsort to the collected vector of strings. Easy does it.
* C++: don't use int constant as enum initializer.Kaz Kylheku2015-09-091-1/+1
| | | | | * match.c (complex_open): Initialize member close of fpip_t using fpip_close enum constant.
* C++: need conversions in return value from alloca.Kaz Kylheku2015-09-091-2/+2
| | | | | * parser.c (provide_completions): Use convert macro to cast void * return value of alloca to char *.
* C++: avoid the compl identifier.Kaz Kylheku2015-09-091-5/+5
| | | | | | | * parser.c (find_matching_syms): Rename the compl variable to comple, because compl is a standard C++ macro which provides an alternate name for the ~ operator.
* C++: fix goto repl which skips initializations.Kaz Kylheku2015-09-091-3/+3
| | | | | | | * txr.c (txr_main): Move the labeled code to the end of the function, so it's not sitting in the scope of of names whose initialization is skipped. This is a better organization: thank you, C++.
* linenoise: fix g++ signed/unsigned warning.Kaz Kylheku2015-09-091-1/+2
| | | | | | * linenoise/linenoise.c (sync_data_to_buf): Cast l->dpos to the signed type ptrdiff_t when comparing to difference between two pointers.