Class: SergeantApp

Inherits:
Object
  • Object
show all
Includes:
Curses, Sergeant::Modals, Sergeant::Rendering, Sergeant::Utils
Defined in:
lib/sergeant.rb

Overview

Main application class for Sergeant

Constant Summary collapse

PREVIEW_LINE_LIMIT =

Side preview panel content limits

500
PREVIEW_LINE_MAX_BYTES =
2000

Constants included from Sergeant::Rendering

Sergeant::Rendering::FILE_CATEGORY_COLOR_PAIRS, Sergeant::Rendering::ICON_DIR, Sergeant::Rendering::ICON_FILE, Sergeant::Rendering::ICON_MARK, Sergeant::Rendering::ICON_SELECT, Sergeant::Rendering::MIN_PREVIEW_TOTAL_WIDTH, Sergeant::Rendering::MIN_PREVIEW_WIDTH, Sergeant::Rendering::PREVIEW_WIDTH_RATIO, Sergeant::Rendering::WINDOWS

Constants included from Sergeant::Utils

Sergeant::Utils::ARCHIVE_EXTENSIONS, Sergeant::Utils::CODE_EXTENSIONS, Sergeant::Utils::MEDIA_EXTENSIONS

Instance Method Summary collapse

Methods included from Sergeant::Rendering

#draw_item, #draw_preview_divider, #draw_preview_lines, #draw_preview_message, #draw_preview_panel, #draw_preview_title, #draw_screen, #item_attributes, #preview_placeholder_message, #truncate_for_preview

Methods included from Sergeant::Modals::Help

#show_help_modal

Methods included from Sergeant::Modals::FileOperations

#create_new_with_modal, #delete_with_modal, #edit_file, #execute_terminal_command, #get_unique_filename, #paste_with_modal, #preview_file, #rename_with_modal

Methods included from Sergeant::Modals::Dialogs

#ask_conflict_resolution, #confirm_delete_modal, #draw_progress_modal, #show_error_modal, #show_error_with_retry, #show_info_modal, #update_progress_modal

Methods included from Sergeant::Modals::Navigation

#filter_current_view, #goto_bookmark, #show_history_modal, #show_no_bookmarks_modal, #show_no_history_modal

Methods included from Sergeant::Utils

#file_category, #format_date, #format_permissions, #format_size, #fzf_available?, #get_git_branch, #get_owner_info, #glow_available?, #nano_available?, #nvim_available?, #text_file?, #vi_available?, #vim_available?

Constructor Details

#initialize(start_dir: nil, no_color: false, pwd_mode: false, restore_session: false) ⇒ SergeantApp

Returns a new instance of SergeantApp.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/sergeant.rb', line 28

def initialize(start_dir: nil, no_color: false, pwd_mode: false, restore_session: false)
  @current_dir = start_dir || Dir.pwd
  @selected_index = 0
  @scroll_offset = 0
  @show_ownership = false
  @last_show_ownership = false
  @no_color = no_color
  @pwd_mode = pwd_mode
  @config = Sergeant::Config.load_config
  @bookmarks = Sergeant::Config.load_bookmarks
  @marked_items = []
  @copied_items = []
  @cut_mode = false
  @last_refreshed_dir = nil
  @items = []
  @filter_text = ''
  @all_items = []

  # Side preview panel
  @show_preview = true
  @last_preview_path = :unset
  @preview_kind = :empty
  @preview_item = nil
  @preview_lines = []

  # Stat caching for performance
  @stat_cache = {}
  @cache_ttl = 5  # seconds
  @max_cache_entries = 5000

  # Session persistence
  @session_file = File.expand_path('~/.sgt_session')
  if restore_session && File.exist?(@session_file)
    saved_dir = File.read(@session_file).strip
    @current_dir = saved_dir if File.directory?(saved_dir)
  end

  # Recent directories history
  @history_file = File.expand_path('~/.sgt_history')
  @directory_history = load_history
  @history_max_size = 50
end

Instance Method Details

#runObject



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/sergeant.rb', line 71

def run
  init_screen

  # Only initialize colors if terminal supports them and not disabled
  if !@no_color && has_colors?
    start_color
    apply_color_theme
  end

  curs_set(0)
  noecho
  stdscr.keypad(true)

  begin
    loop do
      # Only refresh items when directory changes, not on every keystroke
      refresh_items_if_needed
      update_preview_if_needed
      draw_screen

      key = getch
      case key
      when Curses::Key::UP, 'k'
        move_selection(-1)
      when Curses::Key::DOWN, 'j'
        move_selection(1)
      when 10, 13, Curses::Key::RIGHT, 'l'
        item = @items[@selected_index]
        if item && item[:type] == :directory
          @current_dir = item[:path]
          @selected_index = 0
          @scroll_offset = 0
        elsif item && item[:type] == :file
          preview_file
        end
      when 'b'
        goto_bookmark
      when 'o'
        @show_ownership = !@show_ownership
      when 'P'
        @show_preview = !@show_preview
        @last_preview_path = :unset
      when 'e'
        edit_file
      when 'v'
        preview_file
      when 32, ' '
        toggle_mark
      when 'c'
        copy_marked_items
      when 'x'
        cut_marked_items
      when 'd'
        delete_marked_items
      when 'r'
        rename_item
      when 'p'
        paste_items
      when 'u'
        unmark_all
      when 'm'
        show_help_modal
      when 'n'
        create_new_with_modal
      when ':'
        execute_terminal_command
      when '/'
        search_files
      when 'f'
        filter_current_view
      when 'H'
        show_history_modal
      when 'R'
        # Force refresh and clear cache
        @stat_cache.clear
        force_refresh
      when 'q', 27
        close_screen
        save_session  # Save current directory for --restore
        puts @current_dir
        exit 0
      when Curses::Key::LEFT, 'h'
        parent = File.dirname(@current_dir)
        if parent != @current_dir
          @current_dir = parent
          @selected_index = 0
          @scroll_offset = 0
        end
      end
    end
  rescue Interrupt
    close_screen
    save_session
    exit 0
  rescue StandardError => e
    close_screen
    puts "Error: #{e.message}"
    puts e.backtrace
    exit 1
  end
end