Conversation
A split view shows two editors of the same document at once. Their actions shared the default window-level context, which gave every editor sequence two owners in that window -- and Qt fires neither of two owners, so the whole set went dead as soon as the view was split. Tabs were never affected, since Qt skips invisible widgets when matching. This was tried once before and reverted: the suite was crashing at the time and the change looked responsible. The crash was the lint thread outliving its editor, fixed separately; with that gone, six full runs on 3.10 are clean.
It showed the encoding from the global setting rather than the one the tab was opened or saved with, and worked out the line ending by re-reading up to 8KB of the file from disk on every tab change. Both meant a choice made from the Encoding or Line Endings menu never reached the display, and the second put file I/O on the UI thread. Both now read the tab's own state, the menus ask for a refresh after changing it, and a language indicator sits alongside them -- twelve languages are highlighted and until now nothing said which one was in effect.
Breakpoints only reached pdb when the debugger started, so a line marked or unmarked part-way through a session had no effect until the next run. Toggling one now sends the matching break or clear command, which pdb applies at its next prompt -- exactly when it should take effect.
A number repeated in a snippet body was only a tab stop the first time; the
rest expanded to plain text, so "${1:name} = ${1:name}" meant typing the same
name twice and nothing kept the two in step.
Repeats are now recorded as mirrors of their stop and rewritten as you type in
it. They are tracked as positions and a length rather than cursors, because a
cursor selection collapses when its whole content is replaced -- which is
exactly what the first keystroke over a placeholder does.
The middle column of marks showed occurrences of the word under the caret even while a search was open, so the one thing the user was actually looking for was the one thing it did not show. It now marks the search hits whenever something is being searched for, and falls back to the word under the caret otherwise. Search matching is on the typed string rather than whole identifiers, so "val" marks the line holding "value" -- which is what a search is for.
Folding was indentation-only, which suits Python but misreads the C-family languages now that they are highlighted: a brace placed on its own line left the header no more indented than its body, so the block did not fold at all. Those languages now fold on brace pairs, with the closing brace left visible. Braces inside strings and comments are skipped, since one in a string would throw every pair after it out of step.
The extra carets only went left and right, so any vertical move meant losing them and starting over. They now follow Up, Down, Home and End as well, each keeping its own column and stopping at a shorter line''s end. Left and right also take the primary caret along. It used to stay put while the extras moved, so a single arrow press pulled them out of alignment -- the one thing multiple carets exist to preserve.
Extra carets were positions with nothing behind them, so Shift with an arrow key did nothing and there was no way to select the same span on several lines at once. Each caret now keeps an anchor, Shift extends them all together, and the spans are washed in the caret colour. Insert, Backspace and Delete go through one operation -- replace each caret''s range with this text -- rather than three sets of offset arithmetic. A caret without a selection covers a zero-length range, so inserting and replacing are the same thing, and the positions afterwards fall out of one calculation.
Everything the editor paints itself -- line numbers, indent guides, change markers, the minimap, syntax -- had one set of colours, tuned against a dark background. Choosing a light qt-material style left the minimap dark, the guides invisible and the syntax washed out. There are now two sets, and picking a style moves the colours with it. A colour the user chose stays: the test is whether a value is still one of the known defaults, since the settings file writes every colour back and cannot say which ones were deliberate.
The generic highlighter held one regular expression per keyword and ran every one of them over every line -- 44 passes per line for TypeScript. They are now a single alternation, which measures 72 microseconds per line down to 17.5, so a 20,000-line file highlights in 0.37s rather than 1.52s.
The panel listed outcomes and jumped to a line, but the reason lived only in the terminal it never showed. It now runs with --tb=short, keeps each failure''s traceback, and shows the selected test''s in a pane below the list. A coverage box adds --cov and reports the total beside the summary. It needs pytest-cov in the project being tested rather than in the editor, so leaving it off costs nothing and turning it on says plainly when the plugin is missing.
Every sequence was written down where it was used -- one in each menu builder, the toolbar and the editor -- so nothing could be reassigned without editing the source, and a clash only showed up as a key that did nothing. They now live in one table keyed by command, and everything reads its keys from there. A dialog under Style lists every command, refuses to save while two of them claim the same keys, and records only what differs from a default so a later change to a default still reaches the user. Ctrl+Shift+Escape is spelled Ctrl+Shift+Esc to match what Qt itself produces; otherwise the first save recorded that command as changed without anyone touching it.
Each editor started a server of its own, so five open TypeScript files meant five processes each indexing the whole project -- five times the memory and startup cost, with five separate ideas of the same code. A session now owns the process, keyed by command and project root, and the per-file client keeps only its own version number and requests. Replies go back to whichever tab asked and diagnostics to the tab holding that URI. The server shuts down when the last of its tabs closes, which is also where didClose is sent; saving sends didSave, without which some servers never run their slower checks at all.
Signature help, find references, quick fixes and document symbols were the parts of the protocol still unused. Signature help and references sit beside hover in the right-click menu, and a quick fix applies the edits the server offers. Only actions that carry edits are listed: a command-only action needs another round trip, and offering one that does nothing when pressed is worse than not offering it. The diagnostics sent with a fix request are the server''s own objects rather than the editor''s converted form, which does not count lines the same way.
Hunks could be staged but never unstaged, so putting the wrong one in left no way back except the command line, and nothing committed the index -- which is the whole point of staging hunk by hunk. Unstaging returns the index to the committed content and leaves the working tree alone; a file that was never committed is dropped from the index instead. Committing commits the index, so the unstaged edits stay where they are. Both sit in the right-click menu beside staging. Stash save, list and pop, and listing and resolving conflicts, round out the git service. Resolving refuses a file that is not in conflict: git accepts "checkout --ours" there quite happily, but all it does is quietly stage a file nobody asked to stage.
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 672 |
| Duplication | 12 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
- The traceback parser matched banners with a regex whose lazy middle sits between two repeated fences, which backtracks exponentially on a line of nothing but fence characters -- and pytest prints plenty of those. It scans instead. - Saving a shortcut called a reload method that was never written, so the change only reached tabs opened afterwards and never the menus or toolbar at all. Actions are bound through one place now and all of them follow a save. - handle_message grew past the complexity limit; each reply is the same shape, so one table dispatches them. - Resolving a conflict, unstaging and the exception tests each had a smaller fix: an unnecessary list(), an assertion comparing a call with itself, one with its arguments the wrong way round, and two raises blocks holding two calls apiece.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



What this adds
Fifteen commits working through the editor's remaining gaps, plus the defects
found while doing so.
Architecture
five open TypeScript files meant five processes each indexing the whole
project. A session now owns the process, keyed by command and project root,
while the per-file client keeps only its own version number and requests.
Replies go back to whichever tab asked, diagnostics to the tab holding that
URI, and the server stops when its last tab closes.
used, so nothing could be reassigned without editing the source. They live in
one table now, read by the menus, the toolbar and the editor alike, with a
dialog under Style that refuses to save while two commands claim the same keys.
from the global setting and worked out the line ending by re-reading up to 8KB
from disk on every tab change -- so a choice made in the Encoding or Line
Endings menu never appeared, and file I/O ran on the UI thread. A language
indicator sits alongside them.
Editing
Carets that hold their own selections (Shift with any arrow key extends them
all), vertical movement and Home/End for multiple carets, snippet placeholders
that only need typing once, brace-based folding for the C-family languages, and
minimap marks that follow the search rather than the word under the caret.
Language server
Signature help, find references, quick fixes and document symbols. Only actions
carrying edits are offered: a command-only action needs another round trip, and
one that does nothing when pressed is worse than none.
Git
Unstaging, committing the index, stash save/list/pop, and listing and resolving
conflicts. Staging a hunk had no counterpart, so putting the wrong one in left
no way back short of the command line.
Testing and appearance
Per-failure tracebacks and a coverage total in the test panel, and a light set
of the editor's own colours -- everything it paints itself was tuned against a
dark background, so a light style left the minimap dark and the guides invisible.
Defects found along the way
at whichever test next spun an event loop. Behind it was
QThread: Destroyed while thread is still running, which Qt reports throughqFatal: notraceback, and a crash site far from the cause. Closing an editor stopped its
workers but left the debounce timers running, and a timer firing afterwards
started a lint thread nothing was left to wait for.
each clash quietly disabled both features --
Ctrl+Dstopped duplicatinglines and
F5/F9stopped reaching the toolbar.stayed put while the extras moved.
resolve_conflictsucceeded on files with no conflict, where allcheckout --oursdoes is quietly stage a file nobody asked to stage.rather than the server's own objects, which do not even count lines the same
way.
UnicodeDecodeErrorsat afterValueErrorin two readers, making thedecode branch unreachable.
Performance
The generic highlighter ran one regular expression per keyword over every line
-- 44 passes per line for TypeScript. As a single alternation that measures 72
microseconds per line down to 17.5, so a 20,000-line file highlights in 0.37s
rather than 1.52s.
Verification
ruff check .clean. 1669 tests pass, run three times over on 3.11 and threetimes on 3.10 -- the version and platform where the crash above appeared.