Module: Howzit::ScriptSupport
- Defined in:
- lib/howzit/script_support.rb
Overview
Script Support module Handles helper script installation and injection for run blocks rubocop:disable Metrics/ModuleLength
Constant Summary collapse
- LEGACY_SUPPORT_DIR =
Prefer XDG_CONFIG_HOME/howzit/support if set, otherwise ~/.config/howzit/support. For backwards compatibility, we detect an existing ~/.local/share/howzit directory and can optionally migrate it to the new location.
File.join(Dir.home, '.local', 'share', 'howzit')
- SUPPORT_DIR =
if ENV['XDG_CONFIG_HOME'] && !ENV['XDG_CONFIG_HOME'].empty? File.join(ENV['XDG_CONFIG_HOME'], 'howzit', 'support') else File.join(Dir.home, '.config', 'howzit', 'support') end
Class Method Summary collapse
-
.detect_interpreter(script_content) ⇒ Symbol?
Detect interpreter from hashbang line.
-
.ensure_support_dir ⇒ Object
Ensure support directory exists and is populated.
-
.execution_command_for(script_path, interpreter) ⇒ String
Get the command to execute a script based on interpreter.
-
.inject_helper(script_content) ⇒ Array
Inject helper script loading into script content.
-
.injection_line_for(interpreter) ⇒ String?
Get the injection line for a given interpreter.
-
.install_helper_scripts ⇒ Object
Install all helper scripts.
-
.migrate_legacy_support(early_init: false) ⇒ Object
Migrate legacy ~/.local/share/howzit directory into the new config root, merging contents and removing the legacy directory when complete.
-
.simple_yn_prompt(prompt, default: true) ⇒ Object
Simple Y/N prompt that doesn’t depend on Howzit.options (for use during early config initialization).
-
.support_dir ⇒ String
Get the support directory path.
Class Method Details
.detect_interpreter(script_content) ⇒ Symbol?
Detect interpreter from hashbang line
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/howzit/script_support.rb', line 132 def detect_interpreter(script_content) first_line = script_content.lines.first&.strip return nil unless first_line&.start_with?('#!') shebang = first_line.sub(/^#!/, '').strip case shebang when %r{/bin/bash}, %r{/usr/bin/env bash} :bash when %r{/bin/zsh}, %r{/usr/bin/env zsh} :zsh when %r{/bin/fish}, %r{/usr/bin/env fish} :fish when %r{/usr/bin/env ruby}, %r{/usr/bin/ruby}, %r{/usr/local/bin/ruby} :ruby when %r{/usr/bin/env python3?}, %r{/usr/bin/python3?}, %r{/usr/local/bin/python3?} :python when %r{/usr/bin/env perl}, %r{/usr/bin/perl} :perl when %r{/usr/bin/env node}, %r{/usr/bin/node} :node end end |
.ensure_support_dir ⇒ Object
Ensure support directory exists and is populated
34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/howzit/script_support.rb', line 34 def ensure_support_dir dir = support_dir legacy_dir = File.(LEGACY_SUPPORT_DIR) File.(File.join(SUPPORT_DIR, '..')) # If legacy files exist, always offer to migrate them before proceeding. # Use early_init=false here since config is already loaded by the time we reach this point migrate_legacy_support(early_init: false) if File.directory?(legacy_dir) FileUtils.mkdir_p(dir) unless File.directory?(dir) install_helper_scripts dir end |
.execution_command_for(script_path, interpreter) ⇒ String
Get the command to execute a script based on interpreter
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/howzit/script_support.rb', line 219 def execution_command_for(script_path, interpreter) cmd = case interpreter when :bash "/bin/bash #{Shellwords.escape(script_path)}" when :zsh "/bin/zsh #{Shellwords.escape(script_path)}" when :fish "/usr/bin/env fish #{Shellwords.escape(script_path)}" when :ruby "/usr/bin/env ruby #{Shellwords.escape(script_path)}" when :python "/usr/bin/env python3 #{Shellwords.escape(script_path)}" when :perl "/usr/bin/env perl #{Shellwords.escape(script_path)}" when :node "/usr/bin/env node #{Shellwords.escape(script_path)}" end # Fallback to direct execution if interpreter not recognized cmd || script_path end |
.inject_helper(script_content) ⇒ Array
Inject helper script loading into script content
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/howzit/script_support.rb', line 188 def inject_helper(script_content) interpreter = detect_interpreter(script_content) return [script_content, nil] unless interpreter injection = injection_line_for(interpreter) return [script_content, interpreter] unless injection lines = script_content.lines injection_lines = injection.split("\n").map { |l| "#{l}\n" } # Find the hashbang line if lines.first&.strip&.start_with?('#!') # Insert after hashbang injection_lines.each_with_index do |line, idx| lines.insert(1 + idx, line) end else # No hashbang, prepend lines = injection_lines + lines end [lines.join, interpreter] end |
.injection_line_for(interpreter) ⇒ String?
Get the injection line for a given interpreter
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/howzit/script_support.rb', line 163 def injection_line_for(interpreter) support_path = support_dir case interpreter when :bash, :zsh "source \"#{support_path}/howzit.sh\"" when :fish "source \"#{support_path}/howzit.fish\"" when :ruby "require '#{support_path}/howzit.rb'" when :python "import sys\nsys.path.insert(0, '#{support_path}')\nimport howzit" when :perl "require '#{support_path}/howzit.pl'" when :node "require('#{support_path}/howzit.js')" end end |
.install_helper_scripts ⇒ Object
Install all helper scripts
243 244 245 246 247 248 249 250 251 252 253 |
# File 'lib/howzit/script_support.rb', line 243 def install_helper_scripts dir = support_dir FileUtils.mkdir_p(dir) install_bash_helper(dir) install_fish_helper(dir) install_ruby_helper(dir) install_python_helper(dir) install_perl_helper(dir) install_node_helper(dir) end |
.migrate_legacy_support(early_init: false) ⇒ Object
Migrate legacy ~/.local/share/howzit directory into the new config root, merging contents and removing the legacy directory when complete.
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 |
# File 'lib/howzit/script_support.rb', line 72 def migrate_legacy_support(early_init: false) legacy_dir = File.(LEGACY_SUPPORT_DIR) new_root = File.(File.join(SUPPORT_DIR, '..')) unless File.directory?(legacy_dir) return if early_init Howzit.console.info "No legacy Howzit directory found at #{legacy_dir}; nothing to migrate." return end prompt = "Migrate Howzit files from #{legacy_dir} to #{new_root}? This will overwrite files in the new location with legacy versions, " \ 'add new files, and leave any extra files in the new location in place.' if early_init unless simple_yn_prompt(prompt, default: true) warn 'Migration cancelled; no changes made.' return end else unless Prompt.yn(prompt, default: true) Howzit.console.info 'Migration cancelled; no changes made.' return end end FileUtils.mkdir_p(new_root) unless File.directory?(new_root) # Merge legacy into new_root: # - overwrite files in new_root with versions from legacy # - add files that do not yet exist # - leave files that exist only in new_root untouched Dir.children(legacy_dir).each do |entry| src = File.join(legacy_dir, entry) dest = File.join(new_root, entry) if File.directory?(src) FileUtils.mkdir_p(dest) FileUtils.cp_r(File.join(src, '.'), dest) else FileUtils.cp(src, dest) end end FileUtils.rm_rf(legacy_dir) if early_init warn "Migrated Howzit files from #{legacy_dir} to #{new_root}." else Howzit.console.info "Migrated Howzit files from #{legacy_dir} to #{new_root}." end end |
.simple_yn_prompt(prompt, default: true) ⇒ Object
Simple Y/N prompt that doesn’t depend on Howzit.options (for use during early config initialization)
51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/howzit/script_support.rb', line 51 def simple_yn_prompt(prompt, default: true) return default unless $stdout.isatty tty_state = `stty -g` yn = default ? '[Y/n]' : '[y/N]' $stdout.syswrite "\e[1;37m#{prompt} #{yn}\e[1;37m? \e[0m" system 'stty raw -echo cbreak isig' res = $stdin.sysread 1 res.chomp! puts system 'stty cooked' system "stty #{tty_state}" res.empty? ? default : res =~ /y/i end |
.support_dir ⇒ String
Get the support directory path
27 28 29 |
# File 'lib/howzit/script_support.rb', line 27 def support_dir File.(SUPPORT_DIR) end |