drakkon 0.0.3

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.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +50 -0
  3. data/bin/drakkon +16 -0
  4. data/lib/drakkon/build.rb +126 -0
  5. data/lib/drakkon/cli.rb +64 -0
  6. data/lib/drakkon/gem/bundle.rb +116 -0
  7. data/lib/drakkon/gem/cli.rb +46 -0
  8. data/lib/drakkon/gem/configure.rb +73 -0
  9. data/lib/drakkon/gem/gem.rb +56 -0
  10. data/lib/drakkon/gem/helpers/check.rb +110 -0
  11. data/lib/drakkon/gem/helpers/files.rb +57 -0
  12. data/lib/drakkon/gem/helpers/general.rb +21 -0
  13. data/lib/drakkon/gem/helpers/modules.rb +51 -0
  14. data/lib/drakkon/gem/helpers/source.rb +43 -0
  15. data/lib/drakkon/gem/install.rb +24 -0
  16. data/lib/drakkon/init.rb +85 -0
  17. data/lib/drakkon/lib/hub.rb +112 -0
  18. data/lib/drakkon/lib/images/biggest.rb +43 -0
  19. data/lib/drakkon/lib/images/blur.rb +76 -0
  20. data/lib/drakkon/lib/images/bulk_rename.rb +86 -0
  21. data/lib/drakkon/lib/images/canvas.rb +74 -0
  22. data/lib/drakkon/lib/images/cli.rb +78 -0
  23. data/lib/drakkon/lib/images/desaturate.rb +58 -0
  24. data/lib/drakkon/lib/images/flip_flop.rb +76 -0
  25. data/lib/drakkon/lib/images/gif.rb +61 -0
  26. data/lib/drakkon/lib/images/index.rb +185 -0
  27. data/lib/drakkon/lib/images/list.rb +56 -0
  28. data/lib/drakkon/lib/images/modulate.rb +69 -0
  29. data/lib/drakkon/lib/images/resize.rb +83 -0
  30. data/lib/drakkon/lib/images/roll.rb +68 -0
  31. data/lib/drakkon/lib/images/rotate.rb +60 -0
  32. data/lib/drakkon/lib/images/scale.rb +86 -0
  33. data/lib/drakkon/lib/images/sepia.rb +64 -0
  34. data/lib/drakkon/lib/images/shift.rb +89 -0
  35. data/lib/drakkon/lib/images/split.rb +93 -0
  36. data/lib/drakkon/lib/images/spritesheet.rb +85 -0
  37. data/lib/drakkon/lib/images/trim.rb +56 -0
  38. data/lib/drakkon/lib/images/white.rb +56 -0
  39. data/lib/drakkon/lib/logbot.rb +86 -0
  40. data/lib/drakkon/lib/manifest.rb +74 -0
  41. data/lib/drakkon/lib/pastel.rb +49 -0
  42. data/lib/drakkon/lib/settings.rb +130 -0
  43. data/lib/drakkon/lib/shims.rb +8 -0
  44. data/lib/drakkon/lib/version.rb +79 -0
  45. data/lib/drakkon/release.rb +3 -0
  46. data/lib/drakkon/run/commands/images.rb +14 -0
  47. data/lib/drakkon/run/commands/log.rb +57 -0
  48. data/lib/drakkon/run/commands/restart.rb +14 -0
  49. data/lib/drakkon/run/helpers.rb +60 -0
  50. data/lib/drakkon/run/reader_shim.rb +110 -0
  51. data/lib/drakkon/run/tty.rb +119 -0
  52. data/lib/drakkon/run.rb +80 -0
  53. data/lib/drakkon/setup.rb +31 -0
  54. data/lib/drakkon/skeleton/cli.rb +46 -0
  55. data/lib/drakkon/skeleton/deploy.rb +105 -0
  56. data/lib/drakkon/skeleton/helpers/check.rb +143 -0
  57. data/lib/drakkon/skeleton/helpers/general.rb +21 -0
  58. data/lib/drakkon/skeleton/helpers/source.rb +43 -0
  59. data/lib/drakkon/skeleton/install.rb +31 -0
  60. data/lib/drakkon/skeleton/template.rb +14 -0
  61. data/lib/drakkon/web.rb +68 -0
  62. data/lib/drakkon.rb +43 -0
  63. metadata +302 -0
@@ -0,0 +1,86 @@
1
+ # Log Helper
2
+ module LogBot
3
+ # For Amazing Print
4
+ def self.settings
5
+ { ruby19_syntax: true, multiline: false }
6
+ end
7
+
8
+ def self.output(name, message, level, duration = nil)
9
+ time = Time.now.strftime('%I:%M:%S').pastel(:bright_black)
10
+ output = time
11
+ output += " #{color_level(level)}"
12
+ output += " - #{name.to_s.pastel(:bright_blue)} "
13
+ output += "(#{duration.round(2)}) ".pastel(:magenta) if duration
14
+
15
+ output += ' '
16
+ if message
17
+ output += case message
18
+ when String then message
19
+ else
20
+ message.ai(settings)
21
+ end
22
+ end
23
+
24
+ puts output unless ENV['TESTING']
25
+ end
26
+
27
+ def self.color_level(level)
28
+ case level
29
+ when :debug
30
+ level.to_s.upcase.pastel(:bright_cyan)
31
+ when :info
32
+ level.to_s.upcase.pastel(:cyan)
33
+ when :warn
34
+ level.to_s.upcase.pastel(:yellow)
35
+ when :error
36
+ level.to_s.upcase.pastel(:bright_red)
37
+ when :fatal
38
+ level.to_s.upcase.pastel(:red)
39
+ end
40
+ end
41
+
42
+ def self.info(name, message = nil, level = :info)
43
+ output(name, message, level)
44
+ end
45
+
46
+ def self.debug(name, message = nil, level = :debug)
47
+ output(name, message, level)
48
+ end
49
+
50
+ def self.warn(name, message = nil, level = :warn)
51
+ output(name, message, level)
52
+ end
53
+
54
+ def self.error(name, message = nil, level = :error)
55
+ output(name, message, level)
56
+ end
57
+
58
+ def self.fatal(name, message = nil, level = :fatal)
59
+ output(name, message, level)
60
+ end
61
+
62
+ def self.do(name, message = nil, level = nil)
63
+ began_at = clock_time
64
+
65
+ level ||= :info
66
+ result = yield
67
+
68
+ duration = (clock_time - began_at).round(3)
69
+
70
+ output(name, message, level, duration)
71
+
72
+ result
73
+ end
74
+
75
+ def self.measure
76
+ began_at = clock_time
77
+ result = yield
78
+ duration = (clock_time - began_at).round(3)
79
+ [result, duration]
80
+ end
81
+
82
+ # From Rack Time
83
+ def self.clock_time
84
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
85
+ end
86
+ end
@@ -0,0 +1,74 @@
1
+ # ======================
2
+ # Debug Helpers
3
+ # ======================
4
+ # Manifest.list
5
+ # Manifest.search('app')
6
+ # ======================
7
+
8
+ module Drakkon
9
+ # Helper to Generate Manifest
10
+ module Manifest
11
+ def self.root_directory
12
+ "#{Dir.pwd}/"
13
+ end
14
+
15
+ def self.run!(force: false)
16
+ list
17
+ search("#{Dir.pwd}/app")
18
+
19
+ # No Dupes please
20
+ list.reject! { |x| x.include? 'app/drakkon/manifest.rb' }
21
+
22
+ list.map! do |file|
23
+ file.gsub(root_directory, '')
24
+ end
25
+
26
+ if Settings.config[:manifest_digest] == digest
27
+ LogBot.info('Manifest', 'Nothing New')
28
+ return unless force
29
+ end
30
+
31
+ Settings.update(:manifest_digest, digest)
32
+
33
+ LogBot.info('Manifest', 'Saved!')
34
+
35
+ # Make Directory `app/drakkon` if it doesn't exist
36
+ FileUtils.mkdir_p('app/drakkon') unless File.directory?('app/drakkon')
37
+
38
+ File.write('app/drakkon/manifest.rb', required)
39
+ end
40
+
41
+ def self.digest
42
+ Digest::MD5.hexdigest(list.map { |x| Digest::MD5.file(x).hexdigest }.join)
43
+ end
44
+
45
+ def self.list
46
+ @list ||= []
47
+
48
+ @list
49
+ end
50
+
51
+ def self.search(dir)
52
+ @list.concat Dir["#{dir}/*.rb"]
53
+
54
+ Dir["#{dir}/*"].each do |file|
55
+ next unless File.directory?(file)
56
+
57
+ Manifest.search(file)
58
+ end
59
+ end
60
+
61
+ # Generate Require Statements
62
+ # Sure there gonna be plenty of opinions on this bad boi
63
+ def self.required
64
+ <<~TEMPLATE
65
+ #{Manifest.list.reverse.inspect}.each do |file|
66
+ require file
67
+ end
68
+ TEMPLATE
69
+ end
70
+
71
+ # ----------------------
72
+ end
73
+ # ----------------------
74
+ end
@@ -0,0 +1,49 @@
1
+ # Top level namespace
2
+ module Drakkon
3
+ # Replace Colorize with Pastel Monkey Patch String Shim
4
+ # https://github.com/piotrmurach/pastel#features
5
+
6
+ # Looping in GreenHat to allow disabling of Color
7
+ module Color
8
+ def self.pastel
9
+ @pastel ||= Pastel.new
10
+ end
11
+
12
+ def self.decorate(args)
13
+ pastel.decorate(*args)
14
+ end
15
+ end
16
+ end
17
+
18
+ # Monkey Patch
19
+ class String
20
+ def pastel(*args)
21
+ Drakkon::Color.decorate(args.unshift(self))
22
+ end
23
+
24
+ def unpastel
25
+ Drakkon::Color.pastel.strip self
26
+ end
27
+
28
+ def snake_case
29
+ return downcase if match(/\A[A-Z]+\z/)
30
+
31
+ gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
32
+ .gsub(/([a-z])([A-Z])/, '\1_\2')
33
+ .downcase
34
+ end
35
+ end
36
+
37
+ # Monkey Patch
38
+ class Symbol
39
+ def pastel(*args)
40
+ Drakkon::Color.decorate(args.unshift(to_s))
41
+ end
42
+ end
43
+
44
+ # Monkey Patch
45
+ class Array
46
+ def pastel(*args)
47
+ Drakkon::Color.decorate(args.unshift(to_s))
48
+ end
49
+ end
@@ -0,0 +1,130 @@
1
+ module Drakkon
2
+ # Project Specific Config Settings
3
+ module Settings
4
+ def self.init?
5
+ if File.directory?(config_file)
6
+ LogBot.fatal('Settings', "Conflicting Config / Directory #{config_file}")
7
+ exit 0
8
+ end
9
+
10
+ File.exist?(config_file)
11
+ end
12
+
13
+ # Helper to exit if project isn't ready for drakkon usage
14
+ def self.ready?
15
+ return if init?
16
+
17
+ LogBot.warn('Setup', "Drakkon not configured. Run #{'init'.pastel(:green)} first")
18
+
19
+ exit 1
20
+ end
21
+
22
+ def self.prompt
23
+ TTY::Prompt.new(active_color: :cyan)
24
+ end
25
+
26
+ def self.version
27
+ config.version
28
+ end
29
+
30
+ def self.gems
31
+ config[:gems]
32
+ end
33
+
34
+ def self.platforms?
35
+ !config[:platforms].empty?
36
+ end
37
+
38
+ def self.platforms
39
+ config[:platforms]
40
+ end
41
+
42
+ def self.app_dir
43
+ "#{Dir.pwd}/app"
44
+ end
45
+
46
+ def self.drakkon_dir
47
+ "#{Dir.pwd}/app/drakkon"
48
+ end
49
+
50
+ def self.image_index?
51
+ config[:image_index]
52
+ end
53
+
54
+ def self.manifest?
55
+ config[:manifest]
56
+ end
57
+
58
+ def self.config_file
59
+ "#{Dir.pwd}/.drakkon"
60
+ end
61
+
62
+ def self.config_defaults
63
+ # Defaults
64
+ @config[:platforms] ||= []
65
+ @config[:version] ||= Hub.version_latest
66
+ @config[:image_index] ||= true
67
+ @config[:manifest] ||= true
68
+ @config[:gems] ||= {}
69
+ end
70
+
71
+ def self.config
72
+ # Write Default
73
+ File.write(config_file, JSON.pretty_generate({})) unless File.exist?(config_file)
74
+
75
+ if @config.nil?
76
+ @config ||= JSON.parse(File.read(config_file), { symbolize_names: true })
77
+ # @config ||= Oj.load File.read(config_file)
78
+ config_defaults
79
+ end
80
+
81
+ @config
82
+ end
83
+
84
+ def self.update(key, value)
85
+ config[key] = value
86
+ write
87
+ end
88
+
89
+ def self.delete(key)
90
+ config.delete key
91
+ write
92
+ end
93
+
94
+ def self.write
95
+ # LogBot.debug('Settings', "Writing Config: #{config_file}")
96
+ File.write(config_file, JSON.pretty_generate(config))
97
+ # File.write(config_file, Oj.dump(config))
98
+ end
99
+
100
+ def self.menu
101
+ prompt.select('Change Settings:', filter: true) do |menu|
102
+ menu.choice name: 'platforms', value: :platforms
103
+ menu.choice name: 'version', value: :version
104
+ menu.choice name: 'image_index', value: :image_index
105
+ menu.choice name: 'manifest', value: :manifest
106
+ menu.choice name: 'exit', value: :exit
107
+ end
108
+ rescue TTY::Reader::InputInterrupt
109
+ exit 0
110
+ end
111
+
112
+ def self.menu_do(arg)
113
+ case arg
114
+ when :platforms
115
+ Settings.update(:platforms, Build.platform_setup)
116
+ when :version
117
+ Version.set
118
+ when :image_index
119
+ Settings.update(:image_index, prompt.yes?("Index Images? (Enabled: #{image_index?})"))
120
+ when :manifest
121
+ Settings.update(:image_index, prompt.yes?("Write Manifest? (Enabled: #{manifest?})"))
122
+ when :exit
123
+ exit 0
124
+ end
125
+ end
126
+
127
+ # ======================================================================
128
+ end
129
+ # ======================================================================
130
+ end
@@ -0,0 +1,8 @@
1
+ # Make it easier to check for animations
2
+ class String
3
+ def numeric?
4
+ !Float(self).nil?
5
+ rescue StandardError
6
+ false
7
+ end
8
+ end
@@ -0,0 +1,79 @@
1
+ module Drakkon
2
+ # Run Command for CLI
3
+ module Version
4
+ def self.args(raw = nil)
5
+ @args ||= raw
6
+
7
+ @args
8
+ end
9
+
10
+ def self.list
11
+ LogBot.info('Versions', Hub.versions.join(', '))
12
+ end
13
+
14
+ def self.set
15
+ current = "(Current: #{Settings.version.pastel(:bright_blue)})"
16
+ version = prompt.select("Select version #{current}", Hub.versions_sorted, filter: true)
17
+
18
+ Settings.update(:version, version)
19
+ end
20
+
21
+ # General Run
22
+ def self.install!(raw)
23
+ zip = raw.first
24
+ if File.extname(zip) != '.zip'
25
+ LogBot.fatal('Version', "Invalid Argument! Must be a zip file! '#{zip}'")
26
+ exit(1)
27
+ end
28
+
29
+ Dir.mktmpdir('drakkon-sauce-') do |tmp|
30
+ # full_path = "#{Dir.pwd}/#{zip}"
31
+
32
+ # Execut Unzip / Better Way to do this?
33
+ system("unzip -q -d #{tmp} #{zip}")
34
+
35
+ # Find Dir
36
+ dr_dir = Dir["#{tmp}/*"].first
37
+ unless dr_dir.include?('dragonruby-')
38
+ LogBot.fatal('Version', "Valid Zip? Not finding DragonRuby Directory, #{dr_dir}")
39
+ exit(2)
40
+ end
41
+
42
+ # Find Version
43
+ unless File.exist?("#{dr_dir}/CHANGELOG-CURR.txt")
44
+ LogBot.fatal('Version', "Version File Missing! #{"#{dr_dir}/CHANGELOG-CURR.txt"}")
45
+ exit(2)
46
+ end
47
+
48
+ # Collect Version
49
+ dr_version = File.open("#{dr_dir}/CHANGELOG-CURR.txt", &:readline)&.chomp&.split(' ', 2)&.last
50
+ if dr_version.nil?
51
+ LogBot.fatal('Version', "Unable to find DragonRuby Version!, #{dr_version}")
52
+ exit(2)
53
+ end
54
+
55
+ # TODO: add overwrite
56
+ if Hub.version?(dr_version)
57
+ LogBot.fatal('Version', "Version already exists!, #{dr_version}")
58
+ exit(3)
59
+ end
60
+
61
+ # Copy
62
+ FileUtils.cp_r(dr_dir, "#{Hub.dir}/#{dr_version}/")
63
+
64
+ # Save
65
+ Hub.version_add(dr_version)
66
+
67
+ # Finish
68
+ LogBot.info('Version', "#{dr_version} Installed!")
69
+ end
70
+ end
71
+
72
+ def self.prompt
73
+ TTY::Prompt.new(active_color: :cyan)
74
+ end
75
+
76
+ #=======================================================
77
+ end
78
+ #=======================================================
79
+ end
@@ -0,0 +1,3 @@
1
+ module Drakkon
2
+ VERSION = '0.0.3'.freeze
3
+ end
@@ -0,0 +1,14 @@
1
+ module Drakkon
2
+ # Run Command for CLI
3
+ module Run
4
+ # Runnable Terminal Commands
5
+ module Commands
6
+ def self.cmd_images(_args)
7
+ Images::Index.run!(force: true, dir: Run.context)
8
+ end
9
+
10
+ # ========================================================================
11
+ end
12
+ # ==========================================================================
13
+ end
14
+ end
@@ -0,0 +1,57 @@
1
+ module Drakkon
2
+ # Run Command for CLI
3
+ module Run
4
+ # Runnable Terminal Commands
5
+ module Commands
6
+ def self.cmd_logs(_args)
7
+ TTY::Pager.page(command: 'less +G') do |pager|
8
+ Run.logs.each do |line|
9
+ pager.write line
10
+ end
11
+ end
12
+ end
13
+
14
+ def self.cmd_tail(_args)
15
+ loop do
16
+ if Run.dragonruby.ready?
17
+ $stdin.cooked!
18
+ line = Run.dragonruby.readline
19
+ Run.logs.push line # Store
20
+ puts line
21
+ elsif key_pressed?
22
+ key = $stdin.readchar
23
+ if key.ord >= 32 && key.ord <= 126
24
+ break
25
+ else
26
+ break if key == "\u0003" # 'CTRL C'
27
+ break if key == "\u0004" # 'CTRL D'
28
+
29
+ $stdin.cooked!
30
+ puts "any key to stop following: #{key.inspect}".pastel(:green)
31
+ end
32
+
33
+ else
34
+ $stdin.raw!
35
+ sleep 0.1
36
+ end
37
+ end
38
+
39
+ # Restore the previous raw mode
40
+ $stdin.cooked!
41
+ rescue EOFError
42
+ :ignore
43
+ end
44
+
45
+ def self.key_pressed?
46
+ # Set raw mode to ensure immediate input
47
+ $stdin.raw(&:ready?)
48
+ ensure
49
+ # Restore the previous raw mode
50
+ $stdin.cooked!
51
+ end
52
+
53
+ # ========================================================================
54
+ end
55
+ # ==========================================================================
56
+ end
57
+ end
@@ -0,0 +1,14 @@
1
+ module Drakkon
2
+ # Run Command for CLI
3
+ module Run
4
+ # Runnable Terminal Commands
5
+ module Commands
6
+ def self.cmd_restart(_args)
7
+ Run.restart
8
+ end
9
+
10
+ # ========================================================================
11
+ end
12
+ # ==========================================================================
13
+ end
14
+ end
@@ -0,0 +1,60 @@
1
+ module Drakkon
2
+ # Run Command for CLI
3
+ module Run
4
+ def self.index
5
+ @index ||= build_index
6
+ @index
7
+ end
8
+
9
+ def self.build_index
10
+ Commands.public_methods.select { |x| x.to_s[0..3] == 'cmd_' }.map do |cmd|
11
+ cmd.to_s.gsub('cmd_', '')
12
+ end
13
+ end
14
+
15
+ def self.readline_notch
16
+ "#{'drakkon'.pastel(:bright_black)} » "
17
+ end
18
+
19
+ # Exec skips the weird shell stuff
20
+ def self.run_cmd
21
+ "PATH=#{version_dir}:$PATH exec dragonruby #{@context}"
22
+ # "PATH=#{version_dir}:$PATH exec dragonruby #{@context} > #{log_file}"
23
+ end
24
+
25
+ def self.log_file
26
+ "#{Hub.dir}/log.txt"
27
+ end
28
+
29
+ def self.dragonruby(value = nil)
30
+ @dragonruby ||= value
31
+
32
+ @dragonruby
33
+ end
34
+
35
+ def self.args(raw = [])
36
+ @args ||= raw
37
+
38
+ @args
39
+ end
40
+
41
+ def self.version_dir
42
+ "#{Hub.dir}/#{Settings.version}"
43
+ end
44
+
45
+ def self.force_images?
46
+ args.include?('images')
47
+ end
48
+
49
+ def self.force_manifest?
50
+ args.include?('manifest')
51
+ end
52
+
53
+ def self.prompt
54
+ TTY::Prompt.new(active_color: :cyan)
55
+ end
56
+
57
+ #=======================================================
58
+ end
59
+ #=======================================================
60
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https :/ / github.com / piotrmurach / tty - reader / blob / master / lib / tty / reader.rb
4
+
5
+ # Disabling Since this is a Shim
6
+ # rubocop:disable all
7
+
8
+ module TTY
9
+ # A class responsible for reading character input from STDIN
10
+ #
11
+ # Used internally to provide key and line reading functionality
12
+ #
13
+ # @api public
14
+ class Reader
15
+ attr_accessor :line, :breaker
16
+
17
+ def read_line(prompt = '', value: '', echo: true, raw: true, nonblock: false)
18
+ # Greenhat Shim:: Store Line
19
+ self.breaker = false
20
+ self.line = Line.new(value, prompt: prompt)
21
+ screen_width = TTY::Screen.width
22
+ buffer = ''
23
+
24
+ output.print(line)
25
+
26
+ while (codes = get_codes(echo: echo, raw: raw, nonblock: nonblock)) &&
27
+ (code = codes[0])
28
+ char = codes.pack('U*')
29
+
30
+ # GreenHat Shim / Back Tab Down Submodule
31
+ if [:back_tab, :ctrl_c].include? console.keys[char]
32
+ clear_display(line, screen_width)
33
+ trigger_key_event(char, line: line.to_s)
34
+ break
35
+ end
36
+
37
+ # Greenhat Shim
38
+ if EXIT_KEYS.include?(console.keys[char])
39
+ trigger_key_event(char, line: line.to_s)
40
+ raise Interrupt
41
+ end
42
+
43
+ clear_display(line, screen_width) if raw && echo
44
+
45
+ if console.keys[char] == :backspace || code == BACKSPACE
46
+ unless line.start?
47
+ line.left
48
+ line.delete
49
+ end
50
+ elsif console.keys[char] == :delete || code == DELETE
51
+ line.delete
52
+ elsif console.keys[char].to_s =~ /ctrl_/
53
+ # skip
54
+ elsif console.keys[char] == :up
55
+ line.replace(history_previous) if history_previous?
56
+ elsif console.keys[char] == :down
57
+ line.replace(history_next? ? history_next : buffer) if track_history?
58
+ elsif console.keys[char] == :left
59
+ line.left
60
+ elsif console.keys[char] == :right
61
+ line.right
62
+ elsif console.keys[char] == :home
63
+ line.move_to_start
64
+ elsif console.keys[char] == :end
65
+ line.move_to_end
66
+ else
67
+ if raw && [CARRIAGE_RETURN, NEWLINE].include?(code)
68
+ char = "\n"
69
+ line.move_to_end
70
+ end
71
+ line.insert(char)
72
+ buffer = line.text
73
+ end
74
+
75
+ if (console.keys[char] == :backspace || code == BACKSPACE) && echo
76
+ if raw
77
+ output.print("\e[1X") unless line.start?
78
+ else
79
+ output.print("\s" + (line.start? ? '' : "\b"))
80
+ end
81
+ end
82
+
83
+ # trigger before line is printed to allow for line changes
84
+ trigger_key_event(char, line: line.to_s)
85
+
86
+ if raw && echo
87
+ output.print(line.to_s)
88
+ if char == "\n"
89
+ line.move_to_start
90
+ elsif !line.end? # readjust cursor position
91
+ output.print(cursor.backward(line.text_size - line.cursor))
92
+ end
93
+ end
94
+
95
+ # Greenhat Shim do things
96
+ next unless [CARRIAGE_RETURN, NEWLINE].include?(code) || breaker
97
+
98
+ buffer = ''
99
+ output.puts unless echo
100
+ break
101
+ end
102
+
103
+ add_to_history(line.text.rstrip) if track_history? && echo
104
+
105
+ line.text
106
+ end
107
+ end
108
+ end
109
+
110
+ # rubocop:enable all