Class: NeocitiesRed::CliDisplay

Inherits:
Object
  • Object
show all
Defined in:
lib/neocities_red/cli_display.rb

Overview

Terminal output helper for the CLI.

Wraps all user-facing output — progress indicators, success/error messages, help screens, and the ASCII art banner. Uses Pastel for colored and styled terminal output.

Every display_* method prints to stdout and may call exit (for help screens). Non-help methods return nil.

Examples:

display = NeocitiesRed::CliDisplay.new
display.display_response(result: "success", message: "Uploaded!")

See Also:

Constant Summary collapse

PENELOPE_MOUTHS =

Returns Mouth sprites for the Penelope banner cat.

Returns:

  • (Array<String>)

    Mouth sprites for the Penelope banner cat.

%w[^ o ~ - v U].freeze
PENELOPE_EYES =

Returns Eye sprites for the Penelope banner cat.

Returns:

  • (Array<String>)

    Eye sprites for the Penelope banner cat.

%w[o ~ O].freeze

Instance Method Summary collapse

Constructor Details

#initialize(io: $stdout) ⇒ CliDisplay

Creates a new display instance.

Parameters:

  • io (IO) (defaults to: $stdout)

    output stream (defaults to $stdout; inject a StringIO for testing)



31
32
33
34
# File 'lib/neocities_red/cli_display.rb', line 31

def initialize(io: $stdout)
  @io = io
  @pastel = Pastel.new(eachline: "\n")
end

Instance Method Details

#display_api_key_saved(sitename, path) ⇒ void

This method returns an undefined value.

Confirms that the API key has been saved to disk.

Parameters:

  • sitename (String)

    the site name

  • path (String)

    the config file path where the key was stored



111
112
113
# File 'lib/neocities_red/cli_display.rb', line 111

def display_api_key_saved(sitename, path)
  say "The api key for #{@pastel.bold(sitename)} has been stored in #{@pastel.bold(path)}."
end

#display_bannervoid

This method returns an undefined value.

Renders the ASCII art banner with a random Penelope cat face.



444
445
446
447
448
449
450
451
452
# File 'lib/neocities_red/cli_display.rb', line 444

def display_banner
  say <<~HERE

    |\\---/|
    | #{PENELOPE_EYES.sample}_#{PENELOPE_EYES.sample} |  #{@pastel.on_red.bold ' Neocities red '}
     \\_#{PENELOPE_MOUTHS.sample}_/

  HERE
end

#display_delete_error(resp) ⇒ void

This method returns an undefined value.

Prints an error response that occurred during file deletion.

Parameters:

  • resp (Hash)

    the API error response



148
149
150
151
# File 'lib/neocities_red/cli_display.rb', line 148

def display_delete_error(resp)
  @io.print "\n"
  display_response(resp)
end

#display_delete_help_and_exitvoid

This method returns an undefined value.

Displays the help screen for the delete command and exits.



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/neocities_red/cli_display.rb', line 284

def display_delete_help_and_exit
  display_banner

  say <<~HERE
    #{@pastel.green.bold 'delete'} - Delete files on your Neocities site

    #{@pastel.dim 'Examples:'}

    #{@pastel.green '$ neocities-red delete myfile.jpg'}               Delete myfile.jpg

    #{@pastel.green '$ neocities-red delete myfile.jpg myfile2.jpg'}   Delete myfile.jpg and myfile2.jpg

    #{@pastel.green '$ neocities-red delete mydir'}                    Deletes mydir and everything inside it (be careful!)
  HERE
  exit
end

#display_delete_progress(path) ⇒ void

This method returns an undefined value.

Prints the file deletion progress indicator (without newline).

Parameters:

  • path (String)

    remote file path being deleted



133
134
135
# File 'lib/neocities_red/cli_display.rb', line 133

def display_delete_progress(path)
  @io.print @pastel.bold("Deleting #{path} ... ")
end

#display_delete_successvoid

This method returns an undefined value.

Prints a green "SUCCESS" after a file is deleted.



140
141
142
# File 'lib/neocities_red/cli_display.rb', line 140

def display_delete_success
  @io.print "#{@pastel.green.bold('SUCCESS')}\n"
end

#display_diff_help_and_exitvoid

This method returns an undefined value.

Displays the help screen for the diff command and exits.



372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
# File 'lib/neocities_red/cli_display.rb', line 372

def display_diff_help_and_exit
  display_banner

  say <<~HERE
    #{@pastel.green.bold 'diff'} - Compare local files with remote and show differences.

    #{@pastel.dim 'Examples:'}

    #{@pastel.green '$ neocities-red diff .'}                             Compare your current path with remote

    #{@pastel.green '$ neocities-red diff ./my-website'}                  Compare ./my-website folder with remote

    #{@pastel.green '$ neocities-red diff . --ignore-dotfiles'}           Compare your current path with remote without files starting with '.'

    #{@pastel.green '$ neocities-red diff . -e file.png'}                 Compare your current path with remote without file.png
  HERE
  exit
end

#display_diff_results(added:, modified:, removed:) ⇒ void

This method returns an undefined value.

Displays the results of a diff operation.

Prints removed files in red, modified files in yellow, and added files in green. Each section is only shown if non-empty.

Parameters:

  • added (Array<String>)

    local files not present on the server

  • modified (Array<String>)

    files whose SHA1 hash differs

  • removed (Array<String>)

    server files not present locally



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/neocities_red/cli_display.rb', line 82

def display_diff_results(added:, modified:, removed:)
  if removed.any?
    say @pastel.bold.red("Removed files")
    say removed
  end

  if modified.any?
    say @pastel.bold.yellow("Modified files")
    say modified
  end

  return unless added.any?

  say @pastel.bold.green("New files")
  say added
end

#display_dry_run_noticevoid

This method returns an undefined value.

Displays a notice that the current operation is a dry run.



125
126
127
# File 'lib/neocities_red/cli_display.rb', line 125

def display_dry_run_notice
  say @pastel.green.bold("Doing a dry run, not actually pushing anything")
end

#display_gitignore_hintvoid

This method returns an undefined value.

Displays a hint that .gitignore entries are being excluded.



156
157
158
# File 'lib/neocities_red/cli_display.rb', line 156

def display_gitignore_hint
  say "Not pushing .gitignore entries (--no-gitignore to disable)"
end

#display_help_and_exitvoid

This method returns an undefined value.

Displays the main help screen listing all available subcommands and exits.



457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
# File 'lib/neocities_red/cli_display.rb', line 457

def display_help_and_exit
  display_banner
  say <<~HERE
    #{@pastel.dim 'Subcommands:'}
      delete      Delete files from your Neocities site
      diff        Compare your local directory with your Neocities site
      info        Information and stats for your site
      list        List files from your Neocities site
      logout      Remove the site api key from the config
      pizza       Order a free pizza
      pull        Get the most recent version of files from your site
      purge       Remove all files from your site
      push        Recursively upload a local directory to your site
      upload      Upload individual files to your Neocities site
      version     Unceremoniously display version and self destruct
  HERE
  exit
end

#display_info_help_and_exitvoid

This method returns an undefined value.

Displays the help screen for the info command and exits.



394
395
396
397
398
399
400
401
402
403
404
405
# File 'lib/neocities_red/cli_display.rb', line 394

def display_info_help_and_exit
  display_banner

  say <<~HERE
    #{@pastel.green.bold 'info'} - Get site info

    #{@pastel.dim 'Examples:'}

    #{@pastel.green '$ neocities-red info fauux'}   Gets info for 'fauux' site
  HERE
  exit
end

#display_list_help_and_exitvoid

This method returns an undefined value.

Displays the help screen for the list command and exits.



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/neocities_red/cli_display.rb', line 264

def display_list_help_and_exit
  display_banner

  say <<~HERE
    #{@pastel.green.bold 'list'} - List files on your Neocities site

    #{@pastel.dim 'Examples:'}

    #{@pastel.green '$ neocities-red list .'}           List files in your root directory

    #{@pastel.green '$ neocities-red list -a'}          Recursively display all files and directories

    #{@pastel.green '$ neocities-red list -d /mydir'}   Show detailed information on /mydir
  HERE
  exit
end

#display_list_table(table) ⇒ void

This method returns an undefined value.

Renders a TTY::Table to the output stream.

Parameters:

  • table (TTY::Table)

    the table to display



211
212
213
# File 'lib/neocities_red/cli_display.rb', line 211

def display_list_table(table)
  say table
end

#display_login_promptvoid

This method returns an undefined value.

Prints the interactive login prompt message.



102
103
104
# File 'lib/neocities_red/cli_display.rb', line 102

def 
  say "Please login to get your API key:"
end

#display_logout_help_and_exitvoid

This method returns an undefined value.

Displays the help screen for the logout command and exits.



410
411
412
413
414
415
416
417
418
419
420
421
# File 'lib/neocities_red/cli_display.rb', line 410

def display_logout_help_and_exit
  display_banner

  say <<~HERE
    #{@pastel.green.bold 'logout'} - Remove the site api key from the config

    #{@pastel.dim 'Examples:'}

    #{@pastel.green '$ neocities-red logout -y'}
  HERE
  exit
end

#display_logout_successvoid

This method returns an undefined value.

Displays a logout success message.



118
119
120
# File 'lib/neocities_red/cli_display.rb', line 118

def display_logout_success
  say @pastel.bold("Your api key has been removed.")
end

#display_pizza_help_and_exitvoid

This method returns an undefined value.

Displays the pizza easter egg help screen and exits.



256
257
258
259
# File 'lib/neocities_red/cli_display.rb', line 256

def display_pizza_help_and_exit
  say Services::Common::Pizza.new.make_order
  exit
end

#display_pull_failurevoid

This method returns an undefined value.

Prints a red "FAIL" when a file pull fails.



240
241
242
# File 'lib/neocities_red/cli_display.rb', line 240

def display_pull_failure
  @io.print "#{@pastel.red.bold('FAIL')}\n"
end

#display_pull_help_and_exitvoid

This method returns an undefined value.

Displays the help screen for the pull command and exits.



332
333
334
335
336
337
338
339
# File 'lib/neocities_red/cli_display.rb', line 332

def display_pull_help_and_exit
  display_banner

  say <<~HERE
    #{@pastel.magenta.bold 'pull'} - Get the most recent version of files from your site, does not download if files haven't changed
  HERE
  exit
end

#display_pull_no_updatesvoid

This method returns an undefined value.

Prints "NO NEW UPDATES" in yellow for files skipped during pull.



226
227
228
# File 'lib/neocities_red/cli_display.rb', line 226

def display_pull_no_updates
  @io.print "#{@pastel.yellow.bold('NO NEW UPDATES')}\n"
end

#display_pull_progress(path) ⇒ void

This method returns an undefined value.

Prints the file pull progress indicator (without newline).

Parameters:

  • path (String)

    remote file path being pulled



219
220
221
# File 'lib/neocities_red/cli_display.rb', line 219

def display_pull_progress(path)
  @io.print @pastel.bold("Pulling #{path} ... ")
end

#display_pull_stats(success_loaded, total_time) ⇒ void

This method returns an undefined value.

Displays a summary of pull statistics.

Parameters:

  • success_loaded (Integer)

    number of files successfully downloaded

  • total_time (Float)

    total elapsed time in seconds



249
250
251
# File 'lib/neocities_red/cli_display.rb', line 249

def display_pull_stats(success_loaded, total_time)
  say @pastel.green "\nSuccessfully fetched #{success_loaded} files in #{total_time.round(2)} seconds"
end

#display_pull_successvoid

This method returns an undefined value.

Prints a green "SUCCESS" after a file is pulled.



233
234
235
# File 'lib/neocities_red/cli_display.rb', line 233

def display_pull_success
  @io.print "#{@pastel.green.bold('SUCCESS')}\n"
end

#display_purge_help_and_exitvoid

This method returns an undefined value.

Displays the help screen for the purge command and exits.



426
427
428
429
430
431
432
433
434
435
436
437
438
439
# File 'lib/neocities_red/cli_display.rb', line 426

def display_purge_help_and_exit
  display_banner

  say <<~HERE
    #{@pastel.green.bold 'purge'} - Remove all files from your site

    #{@pastel.dim 'Examples:'}

    #{@pastel.green '$ neocities-red purge -y'}                Delete all files from your site

    #{@pastel.green '$ neocities-red purge -y --dry-run'}      Show what would be deleted
  HERE
  exit
end

#display_push_help_and_exitvoid

This method returns an undefined value.

Displays the help screen for the push command and exits.



344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/neocities_red/cli_display.rb', line 344

def display_push_help_and_exit
  display_banner

  say <<~HERE
    #{@pastel.green.bold 'push'} - Recursively upload a local directory to your Neocities site

    #{@pastel.dim 'Examples:'}

    #{@pastel.green '$ neocities-red push .'}                                 Recursively upload current directory.

    #{@pastel.green '$ neocities-red push . -e node_modules -e secret.txt'}   Exclude certain files from push

    #{@pastel.green '$ neocities-red push . --no-gitignore'}                  Don't use .gitignore to exclude files

    #{@pastel.green '$ neocities-red push . --ignore-dotfiles'}               Ignore files with '.' at the beginning (for example, '.git/')

    #{@pastel.green '$ neocities-red push . --dry-run'}                       Just show what would be uploaded

    #{@pastel.green '$ neocities-red push . --optimized'}                     Do not upload unchanged files.

    #{@pastel.green '$ neocities-red push . --prune'}                         Delete site files not in dir (be careful!)
  HERE
  exit
end

#display_response(resp) ⇒ void

This method returns an undefined value.

Displays an API response with appropriate coloring.

Handles three response shapes:

  • Exception — prints the error message in red and exits
  • :result == "success" — prints in green
  • :result == "error" && :error_type == "file_exists" — prints in yellow
  • All other errors — prints in red

Parameters:

  • resp (Hash, Exception)

    API response or exception



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/neocities_red/cli_display.rb', line 54

def display_response(resp)
  if resp.is_a?(Exception)
    say "#{@pastel.red.bold('ERROR:')} #{resp.detailed_message}"
    exit
  end

  if resp[:result] == "success"
    say "#{@pastel.green.bold('SUCCESS:')} #{resp[:message]}"
  elsif resp[:result] == "error" && resp[:error_type] == "file_exists"
    out = "#{@pastel.yellow.bold('EXISTS:')} #{resp[:message]}"
    out += " (#{resp[:error_type]})" if resp[:error_type]
    say out
  else
    out = "#{@pastel.red.bold('ERROR:')} #{resp[:message]}"
    out += " (#{resp[:error_type]})" if resp[:error_type]
    say out
  end
end

#display_skip_directory(path) ⇒ void

This method returns an undefined value.

Displays a message that a directory path is being skipped.

Parameters:

  • path (String)

    the directory path that was skipped



187
188
189
# File 'lib/neocities_red/cli_display.rb', line 187

def display_skip_directory(path)
  say @pastel.bold("#{path} is a directory, skipping")
end

#display_skip_file(path) ⇒ void

This method returns an undefined value.

Displays a message that a non-directory path is being skipped (during folder upload).

Parameters:

  • path (String)

    the file path that was skipped



196
197
198
# File 'lib/neocities_red/cli_display.rb', line 196

def display_skip_file(path)
  say @pastel.bold("#{path} is not a directory, skipping")
end

#display_upload_completevoid

This method returns an undefined value.

Displays a message that all file uploads are complete.



203
204
205
# File 'lib/neocities_red/cli_display.rb', line 203

def display_upload_complete
  say "All files uploaded."
end

#display_upload_existsvoid

This method returns an undefined value.

Prints a yellow "EXISTS" when the uploaded file already matches remotely.



179
180
181
# File 'lib/neocities_red/cli_display.rb', line 179

def display_upload_exists
  @io.print "#{@pastel.yellow.bold('EXISTS')}\n"
end

#display_upload_help_and_exitvoid

This method returns an undefined value.

Displays the help screen for the upload command and exits.



304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
# File 'lib/neocities_red/cli_display.rb', line 304

def display_upload_help_and_exit
  display_banner

  say <<~HERE
    #{@pastel.green.bold 'upload'} - Upload a file/folder to a path on your Neocities site

    #{@pastel.dim 'Usage:'}

        neocities-red upload LOCAL_PATH [REMOTE_PATH]

    REMOTE_PATH defaults to the basename of LOCAL_PATH when omitted.

    #{@pastel.dim 'Examples:'}

    #{@pastel.green '$ neocities-red upload foo.html'}             Uploads foo.html as /foo.html

    #{@pastel.green '$ neocities-red upload images/'}              Uploads images/ contents to /images/

    #{@pastel.green '$ neocities-red upload images/ assets/'}      Uploads images/ contents to /assets/

    #{@pastel.green '$ neocities-red upload ./img.jpg /images/'}   Uploads img.jpg to /images/img.jpg
  HERE
  exit
end

#display_upload_progress(path, remote_path) ⇒ void

This method returns an undefined value.

Prints the file upload progress indicator (without newline).

Parameters:

  • path (String)

    local file path being uploaded

  • remote_path (String)

    remote destination path



165
166
167
# File 'lib/neocities_red/cli_display.rb', line 165

def display_upload_progress(path, remote_path)
  @io.print @pastel.bold("Uploading #{path} to #{remote_path} ... ")
end

#display_upload_successvoid

This method returns an undefined value.

Prints a green "SUCCESS" after a file is uploaded.



172
173
174
# File 'lib/neocities_red/cli_display.rb', line 172

def display_upload_success
  @io.print "#{@pastel.green.bold('SUCCESS')}\n"
end

#say(message = "") ⇒ void

This method returns an undefined value.

Prints a message followed by a newline.

Parameters:

  • message (String) (defaults to: "")

    text to print



40
41
42
# File 'lib/neocities_red/cli_display.rb', line 40

def say(message = "")
  @io.puts(message)
end