about summary refs log tree commit diff
Commit message (Collapse)AuthorAgeFilesLines
* README.md: mention tt as related work HEAD mastersterni2022-04-051-1/+3
|
* README.md: Mention support for some SGR escape sequencesSören Tempel2021-07-151-0/+1
|
* Move example_escs.py to contrib/Sören Tempel2021-07-151-0/+0
|
* pty.color: use named constants in 256 color conversionsterni2021-07-151-7/+24
| | | | | This should make the code a bit more readable, hopefully. Also simplify the conditions while we're at it.
* Represent sgr_type as an IntEnumsterni2021-07-151-44/+132
| | | | | | | This makes the huge SGR parsing conditional more readable, also it is now easier to distinguish between unsupported and non-standard (and thus technically invalid) SGR parameters if we ever want to do something with that information.
* Generate max. one event for a SGR sequence with colons as seperatorssterni2021-07-151-15/+31
| | | | | | | | | | | | | | | Sequences with colons are used when only the first parameter determines the kind of SGR event caused by the sequence and the rest of the parameters are additional arguments. This means that the arguments can contain numbers which are meaningful by themselves, like 0 (reset). This means that if such a sequence is not supported by saneterm we previously erroneously interpreted arguments in such a way that we generated wrong events. This happened for example in vte's sgr-test.sh which relied on kitty's non standard underline escape sequences which we don't support at this time: https://sw.kovidgoyal.net/kitty/protocol-extensions.html#colored-and-styled-underlines
* pty.parse_extended_color: convert TypeError into AssertionErrorsterni2021-07-151-34/+41
| | | | | | | | | A TypeError is raised in Color.__init__() to show that the color constructed is invalid. In parse_extended_color() this is a parse failure and should cause an AssertionError instead. Take this opportunity to refactor the (parse) error handling in this function to use a single try … except statement.
* Move parsing of CSI escape sequences into dedicated functionssterni2021-07-151-159/+182
| | | | | | | | | This breaks up the deeply indented blocks which implemented this in pty.Parser.parse() before. It also allows us to simplify the control flow a bit: The two nested try … except blocks for StopIteration (to detect if we need to postpone parsing) and AssertionError (to detect if we don't understand what looked like an escape sequence or handle other parse errors) into a single one.
* example_escs.py: add script to test SGR escape sequencessterni2021-07-151-0/+107
| | | | | | | | | | | | | | | | | | | | This script emits most of the SGR escape sequences supported by saneterm, so rendering of them can easily be tested. It is not a perfect test case since it only emits nested sequences in a limited fashion. Similar test tools: * sgr-test.sh from vte: https://gitlab.gnome.org/GNOME/vte/-/blob/c17e6d12da00a94c3768be6671182a6a039ec0c0/perf/sgr-test.sh * 256test.sh from vte: https://gitlab.gnome.org/GNOME/vte/-/blob/c17e6d12da00a94c3768be6671182a6a039ec0c0/perf/256test.sh * msgcat --color=test from gettext (only uses 16 colors, sequences for some text styles are broken like italic and underline sometimes) * lolcat -t [-i] is useful for testing true color support
* Document tests and make them easier to runsterni2021-07-152-5/+20
| | | | | | | | * Add a shebang and make the tests.py skript executable * Document how to run the tests in the README * Add docstrings to the tests (which are displayed with -v)
* Track text style in Terminal and reuse TextTagssterni2021-07-154-108/+222
| | | | | | | | | | | | | | | | | | | | | | | | | | | | This change addresses the previous layer violation mentioned in a previous commit: Instead of inflating the Parser code by tracking state which is not necessary for parsing, we now just emit events describing text style changes in the parser code. The necessary updates to actual display state is then handled in the Terminal object. We use this to map the changes to display style introduced by events to _individual_ TextTags instead of creating a composite TextTag for every styled stretch of text. This makes TextTags reusable since they are less specific: Instead of a single italic, green background and bold face tag, we now have three different ones which are quite likely to occur again. Thus we'll store (references to) already created tags in a dictionary to be reused. Note that we can't use Gtk's TextTag lookup mechanism which allows to reuse TextTags in the TextTagTable of a buffer by name since this would not allow us to create TextTags on demand. Precreating all 13824 possible color tags is of course not an option. While this change doesn't bring a big performance improvement it should prevent performance from degrading over time since it limits the number of tags being created, allocated and managed in the Gtk TextBuffer.
* saneterm.color: link to WP on X11 color namessterni2021-07-151-1/+1
|
* TODO.txt: update list of escape sequences to supportsterni2021-07-151-4/+9
|
* Implement a reasonable subset of SGR escape sequencessterni2021-07-156-4/+426
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | SGR (Select Graphical Representation) escape sequences are CSI escape sequences ending in the final byte 'm'. They are described in the ECMA-48 standard, but we also support a compatible extension which is commonly used nowadays, namely extended colors (256 colors and true 24 bit colors) which are specified in ITU-T Rec. T.416. SGR sequences are probably the most commonly used escape sequences and a lot of CLI tools now feel much more familiar in saneterm. The implemented SGR sequences for example allow: * to change the current text's foreground and background color in the three commonly used color modes 8/16 colors, 256 colors and 24 bit true color. * to change the current text's appearance: italic, bold, underline, strikethrough and more are supported. The current implementation uses a new TextStyle object which is added to pty.Parser's state to track the inherintly stateful changes in text appearance described by SGR escape sequences. When the TextStyle object changes, a TEXT_STYLE event is emitted and the a Gtk.TextTag is created from the TextStyle and registered in the widget's TextBuffer. For the most part this is quite straightforward, just two areas deserve more attention: * The extended colors (256 colors and 24 bit true color) are a bit more complicated to parse which is handled by parse_extended_color(). This function doesn't fully support everything the recommendation mandates. Especially true color will need more real world testing, e. g. lolcat(1) a heavy user of true color doesn't even emit true color escape sequences conforming to the standard. * Color handling in general contributes to most of the complexity: * There are three ways to specify colors via SGR escape sequences we support which all need to be converted to Gdk.RGBA objects. This is handled by saneterm.color.Color. True color is trivial, for 256 colors we implement the conversion instead of generating a lookup table (like XTerm does). For the 8 basic colors in their normal and bright variants, we use hard coded list of X11 color names for now. This probably should become configurable in the future. * Many implementation use the intensity escape sequences to influence color vibrance: SGR 2 is interpreted as dim wrt to colors and SGR 1 not only makes the text bold but also chooses brighter colors. So far we interpret SGR 1, 2 and 22 only in terms of font weight. EMCA-48 permits both. Changing the color intensity as well increases complexity and has little benefit, so this should probably be kept this way. * Instead we implement the 90-97 and 100-107 non-standard bright color SGR escape sequences. The current implementation is, however, not without issues: * Tracking the text style state in the parser is probably a layer violation — pty.Parser should instead translate the escape sequences into events and the state tracking done in saneterm.terminal. * Performance is poor if a lot of escape sequences are in the input. This is due to two reasons: a) insert_data is called with little chunks of text which decreases performance and b) a lot of anonymous Gtk TextTags are created which hurts performance a lot. We should investigate a way to deduplicate the created TextTags (by using names?) and possibly decouple the application of tags from the insertion of text itself.
* pty.Parser: parse and filter out CSI escape sequencessterni2021-07-151-0/+83
| | | | | | | | | | | | | | | | | | | | Add a parser for CSI escape sequences as specified in ECMA-48 (5th edition). All other escape sequences starting with \033 (like OSC escape sequences) aren't supported yet and will be added to the terminal's buffer like before. No CSI escape sequence generates a dedicated event so far, the only effect of them being parsed is that they are omitted from the output in the terminal. This makes the output of programs making heavy use of e. g. SGR escape sequences much more readable. If the end of input is hit while parsing an escape sequence, we postpone parsing it until the next invocation of parse(). Additionally we rely on backtracking to deal with unknown and invalid escape sequences: By setting a hint that the sequence is to be ignored and backtracking, the rest of the parser behaves normally and emits the invalid/unknown sequence as normal text.
* pty.Parser: track pos in iterator, support postponing parsingsterni2021-07-152-15/+241
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The next step for pty.Parser will be to support parsing ANSI CSI escape sequences which consist of multiple codepoints, but need to be treated as an unit. Thus we need to be able to push some unparsed input to the next invocation of parse(). The way I've chosen to support this is by supporting backtracking in an iterator which wraps the input string. This way we'll be able to keep consuming input from the iterator in the main for loop, but can backtrack in case we hit the end of input or encounter a parse failure. I opted to implement this iterator in the form of an object that tracks an index into a string. For one this feature also helps us in the parser: We need to track the current index anyways and it is also helpful for checking if the end of input has been reached. Additionally this seems like the only feasible way to implement such a backtracking iterator wrapper: The other alternative would've been to copy.deepcopy() the iterator at a point we may want to return to — however this is not practical as deepcopy will hit a recursion depth error with the moderately sized chunks of input we handle in parse(). This commit introduces the new iterator and adapts our parser code for it and lays the groundwork for resuming from unparsed input of a previous invocation of parse(). Additionally it also ships a set of unit tests for the iterator, many methods of which are still unused in the main parser code.
* Move Pty related classes to own module/fileSören Tempel2021-06-292-50/+54
|
* Support bell character by parsing pty input into eventssterni2021-06-292-1/+90
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit introduces a new object, the PtyParser, which will be handling pty input in the future. It receives (utf-8 decoded) input and emits a series of events which encode pty output we want to represent in the UI: * The most basic event type is TEXT which is plain text we need to add to the TermBuffer. * Additionally BELL is now supported which indicates we want to beep (if enabled in gtk) and set the urgency flag of the window. Events seems to be a simple way to indicate future special behavior and by splitting the data read from the pty we can easily skip control characters which we don't want to render (and thus get rid of ugly codepoint boxes). Due to the use of yield and string slices, this approach should also be efficient enough. Using events instead of triggering the desired action in handle_pty ad-hoc also has the advantage that we can split the parsing logic into a separate object which is interesting for the following reasons: * Especially when we want to support a subset of ANSI control sequences we'll need to track parser state: - ANSI escape sequences are multiple codepoints long, so we need to track a parser state in order to keep it incremental. - ANSI escape sequences allow changing the font properties (style, weight, color) which is implemented in a stateful way, we'll also need to keep track of. * The parser is implemented independently of the rest of the application and especially the UI, so we'll be able to unit test it easily.
* Add Shift-Insert keybinding to paste primary clipboardSören Tempel2021-06-263-1/+9
| | | | | | | This is basically yet another workaround for a bug in Gtk since Gtk pastes the secondary clipboard by default. However, since every terminal emulator I have used in the past pastes the primary clipboard on Shift-Insert saneterm should too.
* termview: Rename LimitTextBuffer to TermBufferSören Tempel2021-06-261-3/+4
| | | | More accurate since it also handles copy/paste stuff now.
* search: Don't focus navigation button on clickSören Tempel2021-06-091-0/+1
| | | | | | This way, the search_entry itself is not unfocused and key combinations like ctrl+g and ctrl+shift+g, which cycle through matched strings, continue to work.
* saneterm: move search bar to top of windowSören Tempel2021-06-081-3/+3
| | | | | | This is what most applications (with the exception of firefox) do. Notably, this is also what evince does which inspired the design of the current search bar version.
* Add buttons to search bar for cycling through matchesSören Tempel2021-06-082-3/+32
| | | | | | Currently there are still some focus issue, i.e. if the button are pressed these are focused and the Ctrl+G/Ctrl+Shift+G keybindings no longer work. That will be fixed in a future commit.
* completion: also match paths containing a ~ characterSören Tempel2021-06-061-0/+5
| | | | | Currently, the tilde character is not replaced by $HOME in the file name which may cause issues with application not expanding tilde themselves.
* TODO.txt: Update with stuff I noticed the past few daysSören Tempel2021-06-041-4/+19
|
* Improve custom delete_from_cursor implementationSören Tempel2021-06-041-10/+14
| | | | | * Fix Gtk.TextIter movement * Only handle movements of type WORD_ENDS for now
* Prevent Gtk from clearing the primary selectionSören Tempel2021-06-031-0/+20
| | | | This is a horrible workaround for https://gitlab.gnome.org/GNOME/gtk/-/issues/317
* README.md: Add FAQ entry regarding primary clipboard handlingSören Tempel2021-06-031-0/+8
|
* completion: suggest shortest match firstSören Tempel2021-06-021-0/+3
|
* TODO.txt: Update and clarify some entriesSören Tempel2021-06-021-2/+9
|
* termview: update _last_mark even on newlineSören Tempel2021-06-011-2/+1
| | | | | | | | Most REPLs will write a new prompt on newline but when starting a graphical application from a shell (e.g. gitk) no output will be written to the PTY after the newline. This causes _last_mark to not be updated and causes cursor_at_end to always return False making it impossible to quit the application using termios.VINTR.
* termview: assign name and func in loop conditionSören Tempel2021-06-011-2/+1
|
* Allow toggling wordwrap/autoscroll using a key bindingSören Tempel2021-06-012-6/+11
| | | | | | I find it somewhat unpleasent to heavily rely on the mouse. Especially considering that toggeling autoscroll is something I do a lot (e.g. when using cat(1) on a text document).
* terminal: Create terminal-specific action signals using a dictSören Tempel2021-06-011-7/+10
|
* Add command-line flag to hide the vertical scrollbarSören Tempel2021-06-012-2/+8
| | | | | Unfortunately, it does not seem to be possible to hide the scrollbar using the standard Gtk CSS configuration mechanism.
* README.md: Update FAQ to mention implemented buffer searchSören Tempel2021-06-011-2/+2
|
* TODO.txt: Add todo entry regarding echo modeSören Tempel2021-05-311-1/+4
|
* README.md: Fix font configuration in example CSS configuration fileSören Tempel2021-05-311-4/+8
|
* README.md: Change cursor color too in configuration exampleSören Tempel2021-05-311-0/+1
|
* completion: Fix check for absolute pathSören Tempel2021-05-311-1/+1
|
* README.md: Update features sectionSören Tempel2021-05-311-7/+4
|
* TODO.txt: UpdateSören Tempel2021-05-311-2/+0
|
* Document limitation of __clear_viewSören Tempel2021-05-311-0/+1
|
* Add comment to update_sizeSören Tempel2021-05-311-0/+6
|
* Preliminary tab completion supportSören Tempel2021-05-315-3/+136
|
* Scroll to string matched by SearchBarSören Tempel2021-05-302-4/+7
|
* terminal: Restore focus to TermView after closing SearchBarSören Tempel2021-05-301-0/+9
|
* Preliminary TextBuffer SearchBar supportSören Tempel2021-05-303-3/+83
| | | | | | Still lacking some configuration options (highlight all, case insensitive search, …) and focus is not currently restored to the TermView on close currently.
* Add ctrl+l keybinding to clear everything except current lineSören Tempel2021-05-293-2/+11
|
* Only import gi (and specify Gtk version) onceSören Tempel2021-05-294-9/+2
|