Skip to content

Conversation

@mapitman
Copy link
Owner

Overview

Fixes issue #47 - Restore cursor visibility on application exit and properly handle user interruption via Ctrl+C.

Problem

When the application was interrupted with Ctrl+C during ripping operations, it would:

  1. Skip to the next track instead of exiting
  2. Leave the terminal cursor in a hidden state, making the terminal unusable
  3. Provide no feedback to the user about why the operation stopped

Solution

Added CursorManager Utility

  • New CursorManager class implements IDisposable
  • Hides cursor on initialization
  • Restores cursor visibility on disposal
  • Gracefully handles unsupported cursor operations

Enhanced Program.Main() with Signal Handlers

  1. Console.CancelKeyPress handler (Ctrl+C):

    • Restores cursor immediately
    • Displays '⚠️ Operation interrupted by user' message
    • Exits with code 130 (SIGINT signal code)
  2. AppDomain.ProcessExit handler:

    • Restores cursor for other termination signals
  3. Try/catch wrapper:

    • Catches unhandled exceptions
    • Ensures cursor restoration even on crash

Changes

  • Created src/RipSharp/Utilities/CursorManager.cs
  • Updated src/RipSharp/Core/Program.cs with cursor management and signal handlers
  • Added Spectre.Console import for styling interrupt message

Behavior Changes

✅ Ctrl+C now immediately exits the application instead of skipping tracks
✅ Cursor is always restored to visible state on exit
✅ User receives clear feedback when interrupting
✅ Exit code 130 properly indicates SIGINT termination

Testing

  • All 112 tests passing
  • Help display works normally (no interrupt message)
  • Exit code properly reflects SIGINT when Ctrl+C pressed

Closes #47

Display a styled warning message to inform the user that the operation
was interrupted when they press Ctrl+C. The message uses the warning
color from the console color scheme for consistency.

Message format: '⚠️  Operation interrupted by user'

This provides better user feedback that their interrupt was received
and explains why the operation stopped.
Copilot AI review requested due to automatic review settings January 12, 2026 01:15
Copy link
Contributor

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 addresses issue #47 by implementing cursor visibility management and proper Ctrl+C signal handling to prevent terminal cursor state issues during application interruption.

Changes:

  • Added CursorManager utility class with IDisposable pattern to manage terminal cursor visibility
  • Enhanced Program.Main() with CancelKeyPress and ProcessExit handlers for graceful shutdown
  • Integrated cursor restoration in exception handling to ensure cleanup on crash

Reviewed changes

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

File Description
src/RipSharp/Utilities/CursorManager.cs New utility class implementing IDisposable to hide cursor on initialization and restore on disposal with error handling
src/RipSharp/Core/Program.cs Added signal handlers for Ctrl+C and ProcessExit, integrated CursorManager with using statement and exception handling, added Spectre.Console import for styled warning messages

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +17 to +36
AnsiConsole.Cursor.Hide();
Console.CursorVisible = false;
}
catch
{
// Silently fail if cursor operations aren't supported
}
}

/// <summary>
/// Restores cursor visibility. Safe to call multiple times.
/// </summary>
public void RestoreCursor()
{
if (_disposed) return;

try
{
AnsiConsole.Cursor.Show();
Console.CursorVisible = true;
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

Both AnsiConsole.Cursor methods and Console.CursorVisible property are being used together to manage cursor visibility. While this dual approach provides redundancy, it may be unnecessary since Spectre.Console's AnsiConsole likely manages the underlying Console cursor state. Consider whether both approaches are needed, or document why this dual management is necessary for compatibility across different terminal environments.

Copilot uses AI. Check for mistakes.
mapitman and others added 2 commits January 11, 2026 17:25
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Added 9 test cases covering CursorManager functionality:
- Constructor successfully hides cursor
- RestoreCursor can be called multiple times safely
- Dispose properly restores cursor
- Dispose can be called multiple times
- RestoreCursor after Dispose returns early (safe)
- Using statement ensures proper disposal
- Implements IDisposable interface
- RestoreCursor is idempotent
- Gracefully handles unsupported environments

All tests verify the class handles cursor operations safely
without throwing exceptions, even in unsupported environments.

Test count increased from 112 to 121 (all passing)
@mapitman mapitman merged commit 0e32fd7 into main Jan 12, 2026
1 check passed
@mapitman mapitman deleted the bug/restore-cursor-on-exit branch January 12, 2026 01:35
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.

Restore cursor visibility on application exit

2 participants