Skip to content

Conversation

@SilentMalachite
Copy link
Owner

This change implements core Vim-style line operations for deleting (dd), yanking (yy), and pasting (p).

  • The delete_line (dd) functionality was improved to more intuitively handle deleting the last line of a file by removing the preceding newline.
  • The yank_line (yy) functionality was implemented to copy the current line, including its newline character, to the clipboard.
  • The paste (p) function was significantly improved to correctly handle line-wise pasting, inserting the clipboard content below the current line, which is consistent with Vim's behavior.
  • Added comprehensive unit tests for all new and modified operations at both the editor and application layers. These tests uncovered and led to the correction of several pre-existing and newly introduced bugs, improving overall robustness.

Description

Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📚 Documentation update
  • 🔧 Code refactoring (no functional changes, no api changes)
  • ⚡ Performance improvement
  • 🧪 Test addition or improvement
  • 🔨 Build/CI related changes

Related Issues

Fixes #(issue number)
Closes #(issue number)
Related to #(issue number)

Changes Made

Testing

Test Environment

  • OS:
  • Terminal:
  • Rust version:

Test Cases

  • All existing tests pass
  • New tests added (if applicable)
  • Manual testing performed
  • Cross-platform compatibility verified (if applicable)

Manual Testing Checklist

  • Basic editor functionality (insert, delete, navigate)
  • Vim keybindings work correctly
  • File operations (open, save) work
  • Buffer management works
  • Window splitting/navigation works
  • LSP features work (if applicable)
  • No crashes or panics observed
  • Performance is acceptable

Screenshots/Demos

Breaking Changes

Checklist

  • I have read the CONTRIBUTING.md guide
  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published

Additional Notes

This change implements core Vim-style line operations for deleting (`dd`), yanking (`yy`), and pasting (`p`).

- The `delete_line` (`dd`) functionality was improved to more intuitively handle deleting the last line of a file by removing the preceding newline.
- The `yank_line` (`yy`) functionality was implemented to copy the current line, including its newline character, to the clipboard.
- The `paste` (`p`) function was significantly improved to correctly handle line-wise pasting, inserting the clipboard content below the current line, which is consistent with Vim's behavior.
- Added comprehensive unit tests for all new and modified operations at both the editor and application layers. These tests uncovered and led to the correction of several pre-existing and newly introduced bugs, improving overall robustness.
Copilot AI review requested due to automatic review settings August 22, 2025 21:02
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements core Vim-style line operations including dd (delete line), yy (yank line), and p (paste). The changes enhance the editor's Vim compatibility by providing proper line-wise operations with appropriate cursor positioning and clipboard management.

Key changes:

  • Enhanced delete_line to handle edge cases like deleting the last line or only line
  • Added yank_line functionality to copy lines with proper newline handling
  • Improved paste function to support both line-wise and character-wise pasting modes
  • Added comprehensive test coverage for all new operations

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
crates/scriptoris/src/editor.rs Core editor functionality with enhanced delete_line, new yank_line, improved paste, and extensive test coverage
crates/scriptoris/src/app.rs Application layer integration for yy command handling and corresponding tests

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

// Character-wise paste. Insert *after* the cursor.
let mut char_idx = self.line_col_to_char_idx(self.cursor_line, self.cursor_col);
if self.rope.len_chars() > 0 && self.cursor_col < self.rope.line(self.cursor_line).len_chars() {
char_idx += 1;
Copy link

Copilot AI Aug 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an extra space at the beginning of this line. It should be indented consistently with the surrounding code.

Copilot uses AI. Check for mistakes.
self.cursor_line = target_line.min(self.rope.len_lines().saturating_sub(1));
if self.cursor_line < self.rope.len_lines() {
let pasted_line = self.rope.line(self.cursor_line);
self.cursor_col = pasted_line.to_string().chars().take_while(|c| c.is_whitespace()).count();
Copy link

Copilot AI Aug 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Converting the entire line to a string just to count whitespace characters is inefficient. Consider iterating over the rope slice directly: pasted_line.chars().take_while(|c| c.is_whitespace()).count()

Suggested change
self.cursor_col = pasted_line.to_string().chars().take_while(|c| c.is_whitespace()).count();
self.cursor_col = pasted_line.chars().take_while(|c| c.is_whitespace()).count();

Copilot uses AI. Check for mistakes.
// This is the last line. If there's a preceding newline, remove it too.
if start_idx > 0 {
if self.rope.char(start_idx - 1) == '\n' {
start_idx -= 1;
Copy link

Copilot AI Aug 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check could panic if start_idx is 0 and we try to access start_idx - 1. The outer if start_idx > 0 check protects against this, but the logic is fragile. Consider restructuring for clarity.

Suggested change
start_idx -= 1;
let prev_idx = start_idx.saturating_sub(1);
if self.rope.char(prev_idx) == '\n' {
start_idx = prev_idx;

Copilot uses AI. Check for mistakes.
// Ensure line-wise yanks always end in a newline for consistent pasting behavior.
if !self.clipboard.ends_with('\n') {
self.clipboard.push('\n');
}
Copy link

Copilot AI Aug 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The get_slice method might return None for valid ranges in some rope implementations. Consider using slice(start_idx..end_idx) directly or handle the None case appropriately if this is expected behavior.

Suggested change
}
let slice = self.rope.slice(start_idx..end_idx);
self.clipboard = slice.to_string();
// Ensure line-wise yanks always end in a newline for consistent pasting behavior.
if !self.clipboard.ends_with('\n') {
self.clipboard.push('\n');

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants