side-vim 0.1.0__tar.gz → 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: side-vim
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: Vim mode for PySide6's QPlainTextEdit
5
5
  Author: sprytnyk.dev
6
6
  License-Expression: MIT
@@ -191,22 +191,5 @@ Set these up by hand before the first tag:
191
191
  goes into GitHub. See the [PyPI setup guide](https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc/)
192
192
  and [GitHub approval guide](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/review-deployments).
193
193
 
194
- For each release:
195
-
196
- 1. On `main`, check the README and run `make check`. If key handling changed,
197
- run `make mac-keys` on a Mac.
198
- 2. Run `uv version X.Y.Z`. Write the dated `CHANGELOG.md` section from the commits
199
- since the previous release, using only sections with entries: Breaking,
200
- Highlights, Fixes, Changes and Removed. Review it before committing.
201
- 3. Build and test the wheel in a temporary environment. Make the signed
202
- `chore(release): vX.Y.Z` commit and signed `vX.Y.Z` tag with key
203
- `0xC00C0F0D647BD3C6`. Push `main` and that tag to `origin`.
204
- 4. The release workflow runs CI, checks that the tag matches the package version,
205
- and builds the wheel and source distribution. Review the run and approve the
206
- `pypi` job. It publishes those files using
207
- [uv trusted publishing](https://docs.astral.sh/uv/guides/integration/github/#publishing-to-pypi).
208
- 5. Confirm the version is on PyPI, then create a GitHub release using just the
209
- changelog section as its notes. Attach no files.
210
-
211
194
  The project [release skill](https://github.com/sprytnyk/side-vim/blob/main/.claude/skills/release/SKILL.md)
212
195
  has the command sequence and approval points.
@@ -179,22 +179,5 @@ Set these up by hand before the first tag:
179
179
  goes into GitHub. See the [PyPI setup guide](https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc/)
180
180
  and [GitHub approval guide](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/review-deployments).
181
181
 
182
- For each release:
183
-
184
- 1. On `main`, check the README and run `make check`. If key handling changed,
185
- run `make mac-keys` on a Mac.
186
- 2. Run `uv version X.Y.Z`. Write the dated `CHANGELOG.md` section from the commits
187
- since the previous release, using only sections with entries: Breaking,
188
- Highlights, Fixes, Changes and Removed. Review it before committing.
189
- 3. Build and test the wheel in a temporary environment. Make the signed
190
- `chore(release): vX.Y.Z` commit and signed `vX.Y.Z` tag with key
191
- `0xC00C0F0D647BD3C6`. Push `main` and that tag to `origin`.
192
- 4. The release workflow runs CI, checks that the tag matches the package version,
193
- and builds the wheel and source distribution. Review the run and approve the
194
- `pypi` job. It publishes those files using
195
- [uv trusted publishing](https://docs.astral.sh/uv/guides/integration/github/#publishing-to-pypi).
196
- 5. Confirm the version is on PyPI, then create a GitHub release using just the
197
- changelog section as its notes. Attach no files.
198
-
199
182
  The project [release skill](https://github.com/sprytnyk/side-vim/blob/main/.claude/skills/release/SKILL.md)
200
183
  has the command sequence and approval points.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "side-vim"
3
- version = "0.1.0"
3
+ version = "0.1.1"
4
4
  description = "Vim mode for PySide6's QPlainTextEdit"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "side-vim"
3
- version = "0.1.0"
3
+ version = "0.1.1"
4
4
  description = "Vim mode for PySide6's QPlainTextEdit"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -177,6 +177,7 @@ class VimMode(QObject):
177
177
  self._want_at: tuple[int, Version] | None = None
178
178
  self._block_on = False
179
179
  self._plain_width = editor.cursorWidth()
180
+ self._plain_overwrite = editor.overwriteMode()
180
181
  # The undo steps vim knows, newest last: Qt's steps from the top of the
181
182
  # document's stack, and the few only vim has. Valid while _version() is still
182
183
  # _synced.
@@ -274,7 +275,7 @@ class VimMode(QObject):
274
275
  self._set_mode(Mode.NORMAL)
275
276
  self._on_cursor_moved()
276
277
  else:
277
- self._update_cursor_width()
278
+ self._update_cursor()
278
279
 
279
280
  def detach(self) -> None:
280
281
  """Take vim off the editor for good."""
@@ -325,12 +326,12 @@ class VimMode(QObject):
325
326
  self._saved_flags = None
326
327
  if self._mode is Mode.INSERT and self._read_only():
327
328
  self._leave_insert()
328
- self._update_cursor_width()
329
+ self._update_cursor()
329
330
  if kind in (QEvent.Type.FocusIn, QEvent.Type.FocusOut):
330
331
  self._caret.restart_blink()
331
332
  if kind == QEvent.Type.FontChange:
332
333
  # the editor lays out the text again first
333
- QTimer.singleShot(0, self, self._update_cursor_width)
334
+ QTimer.singleShot(0, self, self._update_cursor)
334
335
  return False
335
336
 
336
337
  def _token(self, event: QKeyEvent) -> str | None:
@@ -452,7 +453,7 @@ class VimMode(QObject):
452
453
  cursor = self._editor.textCursor()
453
454
  cursor.setPosition(self._to_qt(lines, pos))
454
455
  self._editor.setTextCursor(cursor)
455
- self._update_cursor_width()
456
+ self._update_cursor()
456
457
 
457
458
  def _put(self, lines: Lines, pos: Pos) -> None:
458
459
  """Go to pos, kept on a character of a line that exists, as Normal mode wants."""
@@ -602,7 +603,7 @@ class VimMode(QObject):
602
603
  if self._mouse_down:
603
604
  self._adopt_selection(cursor)
604
605
  else:
605
- self._update_cursor_width()
606
+ self._update_cursor()
606
607
  return
607
608
  lines = self._lines()
608
609
  pos = self._from_qt(lines, cursor.position())
@@ -610,32 +611,44 @@ class VimMode(QObject):
610
611
  if self._to_qt(lines, fixed) != cursor.position():
611
612
  self._go(lines, fixed)
612
613
  else:
613
- self._update_cursor_width()
614
+ self._update_cursor()
614
615
 
615
- def _update_cursor_width(self) -> None:
616
+ def _update_cursor(self) -> None:
616
617
  """A block cursor in Normal mode, the editor's own cursor in Insert mode. In
617
- Visual mode the editor's cursor is hidden and the Caret draws vim's."""
618
+ Visual mode the editor's cursor is hidden and the Caret draws vim's.
619
+
620
+ Qt draws a wide cursor by inverting what's under it, so a dim character, like a
621
+ comment, stays dim on the block. In overwrite mode Qt draws the character in
622
+ the background colour on the block, as vim does, so overwrite mode is on
623
+ outside Insert mode. Typing doesn't change, since vim takes the keys there."""
618
624
  visual = self._enabled and self._mode in VISUAL_MODES and self._end is not None
619
625
  if self._enabled and self._mode is not Mode.INSERT:
620
626
  if not self._block_on:
621
627
  self._plain_width = self._editor.cursorWidth()
628
+ self._plain_overwrite = self._editor.overwriteMode()
622
629
  self._block_on = True
623
- self._set_cursor_width(0 if visual else char_width(self._editor, self._position()))
630
+ width = 0 if visual else char_width(self._editor, self._position())
631
+ self._set_cursor(width, overwrite=True)
624
632
  elif self._block_on:
625
633
  self._block_on = False
626
- self._set_cursor_width(self._plain_width)
634
+ self._set_cursor(self._plain_width, self._plain_overwrite)
627
635
  self._hide_editor_cursor(visual)
628
636
  # a read-only editor draws no cursor of its own
629
637
  no_cursor = not self._editor.textInteractionFlags() & DRAWS_CURSOR
630
638
  normal = self._enabled and self._mode is Mode.NORMAL and no_cursor
631
639
  self._caret.show_at(self._position() if visual or normal else None)
632
640
 
633
- def _set_cursor_width(self, width: int) -> None:
634
- """Qt repaints only the cursor's new area when its width changes, so the block
635
- turning into Insert mode's line left the rest of the block on screen."""
636
- if self._editor.cursorWidth() != width:
637
- self._editor.viewport().update(self._editor.cursorRect())
638
- self._editor.setCursorWidth(width)
641
+ def _set_cursor(self, width: int, overwrite: bool) -> None:
642
+ """Qt repaints only the cursor's new area when its width changes, and nothing
643
+ when overwrite mode changes, so the block turning into Insert mode's line left
644
+ the rest of the block on screen. Both areas are repainted here; the old one is
645
+ read first, since overwrite mode makes it wider."""
646
+ editor = self._editor
647
+ if (editor.cursorWidth(), editor.overwriteMode()) != (width, overwrite):
648
+ editor.viewport().update(editor.cursorRect())
649
+ editor.setOverwriteMode(overwrite)
650
+ editor.setCursorWidth(width)
651
+ editor.viewport().update(editor.cursorRect())
639
652
 
640
653
  def _hide_editor_cursor(self, hide: bool) -> None:
641
654
  """Width 0 doesn't hide the editor's cursor everywhere: on a screen scaled by a
@@ -815,7 +828,7 @@ class VimMode(QObject):
815
828
  self._editor.setTextCursor(cursor)
816
829
  finally:
817
830
  self._busy = False
818
- self._update_cursor_width()
831
+ self._update_cursor()
819
832
 
820
833
  def _adopt_selection(self, cursor: QTextCursor) -> None:
821
834
  """Visual mode for a selection the mouse or the app made: the same characters,
@@ -847,7 +860,7 @@ class VimMode(QObject):
847
860
  and not self._mouse_down
848
861
  )
849
862
  if valid and self._qt_selection(self._lines()) == (cursor.anchor(), cursor.position()):
850
- self._update_cursor_width()
863
+ self._update_cursor()
851
864
  elif cursor.hasSelection():
852
865
  self._adopt_selection(cursor)
853
866
  else:
@@ -1329,7 +1342,7 @@ class VimMode(QObject):
1329
1342
  def _set_mode(self, mode: Mode) -> None:
1330
1343
  changed = mode is not self._mode
1331
1344
  self._mode = mode
1332
- self._update_cursor_width()
1345
+ self._update_cursor()
1333
1346
  if changed:
1334
1347
  self.mode_changed.emit(mode)
1335
1348
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes