aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ring.c
AgeCommit message (Collapse)AuthorFilesLines
15 hoursupdated copyright to 2026Robin Haberkorn1-1/+1
4 daysavoid unnecessary cleanups of recovery filesRobin Haberkorn1-14/+19
* After the last commit 0b593eb7d0e6907b19cdbb605caf1becae351004 we tried to clean up (unlink) recovery files for all dirty buffers. This resulted in superfluous file deletions before any recovery file was dumped; after disabling file recovery and even in batch mode. It's not tolerable that SciTECO scripts try to unlink files as a side effect e.g. of EW. Also, sometimes you may have to clean up recovery dumps even in batch mode, e.g. in Quit hooks. * Also, it was broken for dirty unnamed buffers, which would cause glib errors. * That's why we had to add another buffer state for dirty files with outdated recovery dumps (TECO_BUFFER_DIRTY_OUTDATED_DUMP). Once a dump was written, a buffer never directly transitions into the TECO_BUFFER_DIRTY_NO_DUMP state again. We can now reliably unlink() only where we'd expect a recovery file to exist in the first place.
4 daysfixed left-over recovery filesRobin Haberkorn1-3/+3
* It was possible to provoke left-over recovery files even if the editor does *not* crash: 1. If you dirtified the buffer (state = TECO_BUFFER_DIRTY), it would be dumped to a recovery file (TECO_BUFFER_DIRTY_DUMPED). 2. If you dirtify the buffer again, the state will become TECO_BUFFER_DIRTY again, so it's up for dumping in the next cycle. 3. If you now save and exit (e.g. `:EX`) the recovery file is not deleted since the state is not TECO_BUFFER_DIRTY_DUMPED. * A buffer can have a recovery file both for TECO_BUFFER_DIRTY and TECO_BUFFER_DIRTY_DUMPED, so we must clean up afterwards in both states. * Of course, it may __not__ yet have a recovery file in the TECO_BUFFER_DIRTY state. The g_unlink() might therefore be superfluous on those files. Moreover, if you disable recovery files, SciTECO will now still try to unlink the recovery file. These operations could only be avoided by adding yet another state, e.g. TECO_BUFFER_DIRTY_OUTDATED_DUMP, so that after the first dump you will never switch back into TECO_BUFFER_DIRTY.
4 daysteco_string_t is now passed by value like a scalar if the callee isn't ↵Robin Haberkorn1-9/+9
expected to modify it * When passing a struct that should not be modified, I usually use a const pointer. * Strings however are small 2-word objects and they are often now already passed via separate `gchar*` and gsize parameters. So it is consistent to pass teco_string_t by value as well. A teco_string_t will usually fit into registers just like a pointer. * It's now obvious which function just _uses_ and which function _modifies_ a string. There is also no chance to pass a NULL pointer to those functions.
6 daysTECO_DEFINE_STATE() no longer constructs callback names for mandatory ↵Robin Haberkorn1-3/+8
callbacks, but tries to use static assertions * Requiring state callbacks by generating their names (e.g. NAME##_input) has several disadvantages: * The callback is not explicitly referenced when the state is defined. So an unintroduced reader will see some static function, which is nowhere referenced and still doesn't cause "unused" warnings. * You cannot choose the name of function that implements the callback freely. * In "substates" you need to generate a callback function if you want to provide a default. You also need to provide dummy wrapper functions whenever you want to reuse some existing function as the implementation. * Instead, we are now using static assertions to check whether certain callbacks have been implemented. Unfortunately, this does not work on all compilers. In particular GCC won't consider references to state objects fully constant (even though they are) and does not allow them in _Static_assert (G_STATIC_ASSERT). This could only be made to work in newer GCC with -std=c2x or -std=gnu23 in combination with constexpr. It does work on Clang, though. So I introduced TECO_ASSERT_SAFE() which also passes if the expression is *not* constant. These static assertions are not crucial - they do not check anything that can differ between systems. So we can always rely on the checks performed by FreeBSD CI for instance. Also, you will of course quickly notice missing callbacks at runtime - with and without additional runtime assertions. * All mandatory callbacks must still be explicitly initialized in the TECO_DEFINE_STATE calls. * After getting rid of generated callback implementations, the TECO_DEFINE_STATE macros can finally be qualified with `static`. * The TECO_DECLARE_STATE() macro has been removed. It no longer abstracts anything and cannot be used to declare static teco_state_t anyway. Also TECO_DEFINE_UNDO_CALL() also doesn't have a DECLARE counterpart.
9 daysfixed clicking the "(Unnamed)" buffer in 0EB popupsRobin Haberkorn1-5/+4
* When constructing the list of popup items, the unnamed buffer is stored as the empty string instead of a prerendered "(Unnamed)". Using the empty string simplifies autocompletions, which will actually have to insert nothing at all (in addition to terminating the string). * Since unnamed buffers are now special in the popup list, we can render them with special icons as well. Currently, only on Curses we use a file symbol with a question mark. There doesn't appear to be a fitting standard Freedesktop icon to use on GTK and there isn't even any fitting standard emblem to lay over the default file icon.
13 daysfixup: renamed "backups" to "recovery files"Robin Haberkorn1-22/+24
* Other editors call "backup files" previous copies of saved files. This role would be served by savepoint files in SciTECO. * Likewise filename~ would point to such a backup file. It therefore makes sense that savepoint files also end in tildes (.teco-n-filename~). * Security copies of modified buffers would be called "auto-saves" (Emacs) or "swap files" (Vim). Both of these terms is IMHO misleading, so SciTECO now uses the term "recovery file". * "Recovery files" are now named #filename# just like in Emacs.
2025-12-18fixup: must not use teco_view_save_to_file() when creating backup/recovery filesRobin Haberkorn1-1/+16
* It emits undo tokens which would bring internal datastructures - especially the undo stack - out of sync. * We now document that teco_view_save_to_channel() will always be without undo token emission.
2025-12-17implemented backup file mechanismRobin Haberkorn1-12/+94
* The backup mechanism is supposed to guard against crashes of SciTECO and unexpected program terminations (e.g. power cycling, etc.) * In a given interval (no matter whether busy or idlying on the prompt) SciTECO saves all modified buffers with the filename~ (like most other editors). As an optimization files are not backed up if they have been backed up previously to avoid pointless and possibly slow file system writes. * While the backup mechanism exists outside of the usual undo-paradigm - backup file creating is not bound to character input and it makes no sense to restore the exact state of backup files - there are some interesting interactions: * When a buffer is dirtyfied or saved that was previously backed up, it must always be reset to the DIRTY state on rubout, so backups are eventually recreated. * When a buffer is dirtyfied first (was clean), the backup file must be removed on rubout as well - we don't expect backup files for clean buffers. * There is currently no automatic way to restore backup files. This could potentially be done by opener.tes and session.tes in the future, although you couldn't currently always get meaningful user feedback (whether he wants to restore the file). Perhaps we should at least log a message when detecting backup files that are newer than the file that is being opened.
2025-10-07throw an error immediately after nEB if n != 0Robin Haberkorn1-18/+23
* When typing nEBfilename$ (n != 0) you would find out that the construct is invalid only after typing out the entire command. We now throw an error immediately, ie. only Escape or string termination will be expected in interactive mode. * In batch mode, nothing should have changed.
2025-07-26properly document some functions in expressions.c and simplified codeRobin Haberkorn1-6/+2
* Practically all calls to teco_expressions_args() must be preceded by teco_expressions_eval(). * In code paths where we know that teco_expressions_args() > 0, it is safe to call teco_expressions_pop_num(0) instead of teco_expressions_pop_num_calc(). This is both easier and faster. * teco_expressions_pop_num_calc() is for simple applications where you just want to get a command argument with default (implied) values. Since it includes teco_expressions_eval(), we can avoid superfluous calls. * -EC...$ turned out to be broken and is fixed now. A test case has been added.
2025-07-23if EX falis because of a dirty buffer, the buffer's id is now included in ↵Robin Haberkorn1-4/+8
the error message
2025-07-19fixed <EF> and <EW> with invalid buffer ids (was crashing)Robin Haberkorn1-2/+9
* regression introduced in 2baa14add6d9976c29b27cf4470bb458a0198694
2025-07-19<EW> now accepts a numeric argument to specify the buffer to saveRobin Haberkorn1-34/+46
* In this case we always save the given buffer and never the current Q-Register. * The current Q-Register is only saved without any numeric argument. The same semantics make sense for <EF> so that Q*EF closes the current buffer even when editing a Q-Register. * This variant is present in Video TECO.
2025-07-18revised command topicsRobin Haberkorn1-1/+1
* Added some keywords. * Consistently added command variants with all modifiers. In principle including modifiers in the topics is unnecessary - you can always strip the modifiers and look up the raw command. However, looking up a command with modifiers can speed up the process (compare looking up ?S<TAB> vs ?::S<TAB> * The `@` modifier is listed only for commands without string arguments.
2025-07-13implemented <ER> command for reading a file into the current bufferRobin Haberkorn1-1/+35
* This command exists in Video TECO. In Video TECO it also supports reading multiple files with a glob pattern -- we do not support that as I am not convinced of its usefulness. * teco_view_load() has been extended, so it can read into dot without discarding the existing document.
2025-07-11<EF> supports a numeric buffer id nowRobin Haberkorn1-44/+75
* ED hooks are not executed in this case * <EF> is now allowed even when editing a Q-Reg, unless you try to close the current buffer
2025-04-13fixed undoing bitfields on WindowsRobin Haberkorn1-3/+3
* It turns out that `bool` (_Bool) in bitfields may cause padding to the next 32-bit word. This was only observed on MinGW. I am not entirely sure why, although the C standard does not guarantee much with regard to bitfield memory layout and there are 64-bit available due to passing anyway. Actually, they could also be layed out in a different order. * I am now consistently using guint instead of `bool` in bitfields to prevent any potential surprises. * The way that guint was aliased with bitfield structs for undoing teco_machine_main_t and teco_machine_qregspec_t flags was therefore insecure. It was not guaranteed that the __flags field really "captures" all of the bit field. Even with `guint v : 1` fields, this was not guaranteed. We would have required a static assertion for robustness. Alternatively, we could have declared a `gsize __flags` variable as well. This __should__ be safe since gsize should always be pointer sized and correspond to the platform's alignment. However, it's also not 100% guaranteed. Using classic ANSI C enums with bit operations to encode multiple fields and flags into a single integer also doesn't look very attractive. * Instead, we now define scalar types with their own teco_undo_push() shortcuts for the bitfield structs. This is in one way simpler and much more robust, but on the other hand complicates access to the flag variables. * It's a good question whether a `struct __attribute__((packed))` bitfield with guint fields would be a reliable replacement for flag enums, that are communicated with the "outside" (TECO) world. I am not going to risk it until GCC gives any guarantees, though. For the time being, bitfields are only used internally where the concrete memory layout (bit positions) is not crucial. * This fixes the test suite and therefore probably CI and nightly builds on Windows. * Test case: Rub out `@I//` or `@Xq` until before the `@`. The parser doesn't know that `@` is still set and allows all sorts of commands where `@` should be forbidden. * It's unknown how long this has been broken on Windows - quite possibly since v2.0.
2025-03-01fixed clicking the file completion popup in ~/Robin Haberkorn1-0/+4
* Popup entries are added with expanded directory names, so we have to skip the expanded directory names from the clicked popup entries.
2025-02-23support mouse interaction with popup windowsRobin Haberkorn1-1/+1
* Curses allows scrolling with the scroll wheel at least if mouse support is enabled via ED flags. Gtk always supported that. * Allow clicking on popup entries to fully autocomplete them. Since this behavior - just like auto completions - is parser state-dependant, I introduced a new state method (insert_completion_cb). All the implementations are currently in cmdline.c since there is some overlap with the process_edit_cmd_cb implementations. * Fixed pressing undefined function keys while showing the popup. The popup area is no longer redrawn/replaced with the Scintilla view. Instead, continue to show the popup.
2025-01-19support :EF for saving a file before closing itRobin Haberkorn1-0/+58
Analoguous to :EX, but always saves the file like EW$, not only if it's dirty.
2025-01-13updated copyright to 2025Robin Haberkorn1-1/+1
2024-12-08fixed rubbing out file open with glob patternsRobin Haberkorn1-5/+4
* This would crash if <EB> opened more than one file, e.g. EB*.c$. The reason is that teco_current_doc_undo_edit() must be called before every teco_ring_edit(). * Unfortunately, this is not reproduceable with sciteco --no-profile --fake-cmdline '@EB"foo*.txt"{HK}' since the crashes actually happen when printing messages in interactive mode. That's why no test case has been added.
2024-10-18fixed the "Editing local registers in macro calls" checkRobin Haberkorn1-0/+2
* The previous check could result in false positives if you are editing a local Q-Register, that will be destroyed at the end of the current macro frame, and call another non-colon modified macro. * It must instead be invalid to keep the register edited only if it belongs to the local Q-Registers that are about to be freed. In other words, the table that the currently edited Q-Register belongs to, must be the one we're about to destroy. * This fixes the solarized.toggle (F5) macro when using the Solarized color scheme.
2024-09-19"special" Q-Registers now support EQq/.../ (load) and E%q/.../ (save) commandsRobin Haberkorn1-1/+1
* @EQ$/.../ sets the current directory from the contents of the given file. @E%$/.../ stores the currend directory in the given file. * @EQ*/.../ will fail, just like ^U*...$. @E%*/.../ stores the current buffer's name in the given file. * It's especially useful with the clipboard registers. There could still be a minor bug in @E%~/.../ with regard to EOL normalization as teco_view_save() will use the EOL style of the current document, which may not be the style of the Q-Reg contents. Conversions can generally be avoided for these particular commands. But without teco_view_save() we'd have to care about save point creation.
2024-09-11improved file name autocompletionRobin Haberkorn1-1/+1
* pressing ^W in FG now deletes the entire directory component as in EB * commands without glob patterns (eg. EW) can now autocomplete file names containing glob patterns * When the autocompletion contains a glob character in commands accepting glob patterns like EB or EN, we now escape the glob pattern. This already helps if the remaining file name can be autocompleted in one go. Unfortunately, this is still insufficient if we can only partially complete and the partial completion contains glob characters. For instance, if there are 2 files: `file?.txt` and `file?.foo`, completing after `f` will insert `ile[?].`. The second try to press Tab will already do nothing. To fully support these cases, we need a version of teco_file_auto_complete() accepting glob patterns. Perhaps we can simply append `*` to the given glob pattern.
2024-01-21updated copyright to 2024Robin Haberkorn1-1/+1
2023-04-05updated copyright to 2023Robin Haberkorn1-1/+1
2022-06-21updated copyright to 2022 and updated TODORobin Haberkorn1-1/+1
2021-10-11optimized character representation settingRobin Haberkorn1-2/+0
* Esp. with the new Scintilla version, the representation setting as part of every SCI_SETDOCPOINTER has turned out to be a performance bottleneck. * The new Scintilla has a custom tweak/patch that disables any automatic representation setting in Scintilla itself. It is now sufficient to initialize the SciTECO-style representations only once in the lifetime of any view.
2021-05-30THE GREAT CEEIFICATION EVENTRobin Haberkorn1-0/+580
This is a total conversion of SciTECO to plain C (GNU C11). The chance was taken to improve a lot of internal datastructures, fix fundamental bugs and lay the foundations of future features. The GTK user interface is now in an useable state! All changes have been squashed together. The language itself has almost not changed at all, except for: * Detection of string terminators (usually Escape) now takes the string building characters into account. A string is only terminated outside of string building characters. In other words, you can now for instance write I^EQ[Hello$world]$ This removes one of the last bits of shellisms which is out of place in SciTECO where no tokenization/lexing is performed. Consequently, the current termination character can also be escaped using ^Q/^R. This is used by auto completions to make sure that strings are inserted verbatim and without unwanted sideeffects. * All strings can now safely contain null-characters (see also: 8-bit cleanliness). The null-character itself (^@) is not (yet) a valid SciTECO command, though. An incomplete list of changes: * We got rid of the BSD headers for RB trees and lists/queues. The problem with them was that they used a form of metaprogramming only to gain a bit of type safety. It also resulted in less readble code. This was a C++ desease. The new code avoids metaprogramming only to gain type safety. The BSD tree.h has been replaced by rb3ptr by Jens Stimpfle (https://github.com/jstimpfle/rb3ptr). This implementation is also more memory efficient than BSD's. The BSD list.h and queue.h has been replaced with a custom src/list.h. * Fixed crashes, performance issues and compatibility issues with the Gtk 3 User Interface. It is now more or less ready for general use. The GDK lock is no longer used to avoid using deprecated functions. On the downside, the new implementation (driving the Gtk event loop stepwise) is even slower than the old one. A few glitches remain (see TODO), but it is hoped that they will be resolved by the Scintilla update which will be performed soon. * A lot of program units have been split up, so they are shorter and easier to maintain: core-commands.c, qreg-commands.c, goto-commands.c, file-utils.h. * Parser states are simply structs of callbacks now. They still use a kind of polymorphy using a preprocessor trick. TECO_DEFINE_STATE() takes an initializer list that will be merged with the default list of field initializers. To "subclass" states, you can simply define new macros that add initializers to existing macros. * Parsers no longer have a "transitions" table but the input_cb() may use switch-case statements. There are also teco_machine_main_transition_t now which can be used to implement simple transitions. Additionally, you can specify functions to execute during transitions. This largely avoids long switch-case-statements. * Parsers are embeddable/reusable now, at least in parse-only mode. This does not currently bring any advantages but may later be used to write a Scintilla lexer for TECO syntax highlighting. Once parsers are fully embeddable, it will also be possible to run TECO macros in a kind of coroutine which would allow them to process string arguments in real time. * undo.[ch] still uses metaprogramming extensively but via the C preprocessor of course. On the downside, most undo token generators must be initiated explicitly (theoretically we could have used embedded functions / trampolines to instantiate automatically but this has turned out to be dangereous). There is a TECO_DEFINE_UNDO_CALL() to generate closures for arbitrary functions now (ie. to call an arbitrary function at undo-time). This simplified a lot of code and is much shorter than manually pushing undo tokens in many cases. * Instead of the ridiculous C++ Curiously Recurring Template Pattern to achieve static polymorphy for user interface implementations, we now simply declare all functions to implement in interface.h and link in the implementations. This is possible since we no longer hace to define interface subclasses (all state is static variables in the interface's *.c files). * Headers are now significantly shorter than in C++ since we can often hide more of our "class" implementations. * Memory counting is based on dlmalloc for most platforms now. Unfortunately, there is no malloc implementation that provides an efficient constant-time memory counter that is guaranteed to decrease when freeing memory. But since we use a defined malloc implementation now, malloc_usable_size() can be used safely for tracking memory use. malloc() replacement is very tricky on Windows, so we use a poll thread on Windows. This can also be enabled on other supported platforms using --disable-malloc-replacement. All in all, I'm still not pleased with the state of memory limiting. It is a mess. * Error handling uses GError now. This has the advantage that the GError codes can be reused once we support error catching in the SciTECO language. * Added a few more test suite cases. * Haiku is no longer supported as builds are instable and I did not manage to debug them - quite possibly Haiku bugs were responsible. * Glib v2.44 or later are now required. The GTK UI requires Gtk+ v3.12 or later now. The GtkFlowBox fallback and sciteco-wrapper workaround are no longer required. * We now extensively use the GCC/Clang-specific g_auto feature (automatic deallocations when leaving the current code block). * Updated copyright to 2021. SciTECO has been in continuous development, even though there have been no commits since 2018. * Since these changes are so significant, the target release has been set to v2.0. It is planned that beginning with v3.0, the language will be kept stable.