ruby-shell 2.9.1 → 2.10.0

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 (3) hide show
  1. checksums.yaml +4 -4
  2. data/bin/rsh +148 -14
  3. metadata +6 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ceae5891b4b0deebdf2e2876232999e8c64374f4730ab4d5e8ef09ff2dc3835
4
- data.tar.gz: bee38e735fb5f9eb1b4b133471ea649faec9531c7138ef035c6c9a089db87f06
3
+ metadata.gz: 5f20098ee7a4e00745916fb1830834273a00dbc5e92bea6b5f1cbd0f66b48639
4
+ data.tar.gz: 135135d2f788b75eb9e51cebd3dd3d680c4f07717819bf6fc9232bf8b4a32943
5
5
  SHA512:
6
- metadata.gz: 7e586a0d583b1d3c33f441ce1dcabf001dc1a12d3a375581ad2337db8cab2822850455cf599b5a5e7ba21a31d750f2133c10b0a71c3e9bdc6ff62454c98296ee
7
- data.tar.gz: 8b7ae87743f8fe9f0414dda5ae607f632ece3f8289131519d21d8ebc20d54d13d7d7361364b8eeef7d9c68d6af9006731790decbee4eb0862a159997af0f306c
6
+ metadata.gz: c3494e59f58963262f8142850dbda9a76c50e6367a681389cd921a8db1bc47d2e68a6490799696c8b8e3437234934070364194f3aa81568a1f8bfdcfc61d9c0d
7
+ data.tar.gz: 8586e7cda13c597863e1d93cb978f0e5815b554a177b6977e41e0f2bc0f1d5a6017e0c04dbf32e45369a2a16180eface4bd67831f8be74b6dc7129f5664e63ed
data/bin/rsh CHANGED
@@ -32,15 +32,20 @@ module Cursor # Terminal cursor movement ANSI codes (thanks to https://github.co
32
32
  end
33
33
  def pos # Query cursor current position
34
34
  res = ''
35
- $stdin.raw do |stdin|
36
- $stdout << CSI + '6n' # Tha actual ANSI get-position
37
- $stdout.flush
38
- while (c = stdin.getc) != 'R'
39
- res << c if c
35
+ begin
36
+ $stdin.raw do |stdin|
37
+ $stdout << CSI + '6n' # Tha actual ANSI get-position
38
+ $stdout.flush
39
+ while (c = stdin.getc) != 'R'
40
+ res << c if c
41
+ end
40
42
  end
43
+ rescue Errno::ENOTTY
44
+ # Not a TTY, return default values
45
+ return 25, 80
41
46
  end
42
47
  m = res.match /(?<row>\d+);(?<col>\d+)/
43
- return m[:row].to_i, m[:col].to_i
48
+ return m ? [m[:row].to_i, m[:col].to_i] : [25, 80]
44
49
  end
45
50
  def rowget
46
51
  row, col = self.pos
@@ -596,12 +601,19 @@ def rshrc # Write updates to .rshrc
596
601
  else
597
602
  conf = ""
598
603
  end
599
- conf.sub!(/^@nick.*\n/, "")
604
+ conf.sub!(/^@nick.*\n/, "")
600
605
  conf += "@nick = #{@nick}\n"
601
- conf.sub!(/^@gnick.*\n/, "")
606
+ conf.sub!(/^@gnick.*\n/, "")
602
607
  conf += "@gnick = #{@gnick}\n"
603
- conf.sub!(/^@history.*\n/, "")
604
- conf += "@history = #{@history.last(@histsize)}\n"
608
+ conf.sub!(/^@history.*\n/, "")
609
+ # Ensure history is properly formatted as valid Ruby array
610
+ begin
611
+ history_str = @history.last(@histsize).inspect
612
+ conf += "@history = #{history_str}\n"
613
+ rescue => e
614
+ conf += "@history = []\n"
615
+ puts "Warning: Error saving history: #{e.message}"
616
+ end
605
617
  File.write(Dir.home+'/.rshrc', conf)
606
618
  puts "\n.rshrc updated"
607
619
  end
@@ -1104,18 +1116,140 @@ def ai_setup_help
1104
1116
  end
1105
1117
 
1106
1118
  # INITIAL SETUP
1119
+ def load_rshrc_safe
1120
+ return unless File.exist?(Dir.home+'/.rshrc')
1121
+
1122
+ begin
1123
+ # Try to load the .rshrc file
1124
+ load(Dir.home+'/.rshrc')
1125
+
1126
+ # Validate critical variables
1127
+ @history = [] unless @history.is_a?(Array)
1128
+ @nick = {} unless @nick.is_a?(Hash)
1129
+ @gnick = {} unless @gnick.is_a?(Hash)
1130
+
1131
+ rescue SyntaxError => e
1132
+ puts "\n\033[31mERROR: Syntax error in .rshrc:\033[0m"
1133
+ puts e.message
1134
+ puts "\n\033[33mAttempting to auto-heal .rshrc...\033[0m\n"
1135
+
1136
+ if auto_heal_rshrc
1137
+ puts "\033[32m.rshrc has been healed! Retrying...\033[0m\n"
1138
+ begin
1139
+ load(Dir.home+'/.rshrc')
1140
+ rescue => e2
1141
+ puts "\033[31mAuto-heal failed. Loading with defaults.\033[0m"
1142
+ load_defaults
1143
+ end
1144
+ else
1145
+ puts "\033[31mAuto-heal failed. Loading with defaults.\033[0m"
1146
+ load_defaults
1147
+ end
1148
+
1149
+ rescue => e
1150
+ puts "\n\033[31mERROR loading .rshrc: #{e.message}\033[0m"
1151
+ puts "\033[33mLoading with defaults...\033[0m\n"
1152
+ load_defaults
1153
+ end
1154
+ end
1155
+
1156
+ def auto_heal_rshrc
1157
+ begin
1158
+ rshrc_path = Dir.home + '/.rshrc'
1159
+ return false unless File.exist?(rshrc_path)
1160
+
1161
+ # Backup the corrupted file
1162
+ backup_path = rshrc_path + '.backup.' + Time.now.strftime('%Y%m%d_%H%M%S')
1163
+ File.write(backup_path, File.read(rshrc_path))
1164
+ puts "Backed up corrupted .rshrc to #{backup_path}"
1165
+
1166
+ content = File.read(rshrc_path)
1167
+ original_content = content.dup
1168
+ healed = false
1169
+
1170
+ # Fix common history array issues
1171
+ if content =~ /^@history\s*=\s*\[.*\]\s*\n\s*,/m
1172
+ # Fix case where array ends with ] followed by comma on next line
1173
+ content.gsub!(/^(@history\s*=\s*\[.*\])\s*\n\s*,(.*)$/m) do |match|
1174
+ # Remove the extra closing bracket and merge the lines
1175
+ history_line = $1
1176
+ continuation = $2
1177
+ # Remove trailing ] from first part
1178
+ history_line = history_line.sub(/\]\s*$/, '')
1179
+ # Combine and close properly
1180
+ "#{history_line}, #{continuation}]"
1181
+ end
1182
+ healed = true
1183
+ end
1184
+
1185
+ # Fix unclosed arrays
1186
+ ['@history', '@nick', '@gnick'].each do |var|
1187
+ if content =~ /^#{var}\s*=\s*[[{](?!.*[}\]]\s*$)/m
1188
+ content.sub!(/^(#{var}\s*=\s*)(\[.*?)$/m) { "#{$1}#{$2}]" }
1189
+ content.sub!(/^(#{var}\s*=\s*)({.*?)$/m) { "#{$1}#{$2}}" }
1190
+ healed = true
1191
+ end
1192
+ end
1193
+
1194
+ # Validate Ruby syntax of the healed content
1195
+ begin
1196
+ # Try to parse the content
1197
+ eval("BEGIN {return true}\n" + content)
1198
+ rescue SyntaxError => e
1199
+ # If still has syntax errors, extract only valid parts
1200
+ new_content = ""
1201
+
1202
+ # Extract valid variable assignments
1203
+ content.each_line do |line|
1204
+ if line =~ /^(@\w+|\w+)\s*=\s*.+$/
1205
+ begin
1206
+ eval(line)
1207
+ new_content += line
1208
+ rescue
1209
+ # Skip invalid lines
1210
+ end
1211
+ elsif line =~ /^(def|class|module|end|if|else|elsif|when|case|begin|rescue)/
1212
+ new_content += line
1213
+ elsif line.strip.start_with?('#') || line.strip.empty?
1214
+ new_content += line
1215
+ end
1216
+ end
1217
+
1218
+ content = new_content
1219
+ healed = true
1220
+ end
1221
+
1222
+ if healed && content != original_content
1223
+ File.write(rshrc_path, content)
1224
+ return true
1225
+ end
1226
+
1227
+ false
1228
+ rescue => e
1229
+ puts "Error during auto-heal: #{e.message}"
1230
+ false
1231
+ end
1232
+ end
1233
+
1234
+ def load_defaults
1235
+ @history ||= []
1236
+ @nick ||= {"ls" => "ls --color -F"}
1237
+ @gnick ||= {}
1238
+ puts "Loaded with default configuration."
1239
+ end
1240
+
1107
1241
  begin # Load .rshrc and populate @history
1108
1242
  trap "SIGINT" do end
1109
- trap "SIGHUP" do
1243
+ trap "SIGHUP" do
1110
1244
  rshrc
1111
1245
  exit
1112
1246
  end
1113
- trap "SIGTERM" do
1247
+ trap "SIGTERM" do
1114
1248
  rshrc
1115
1249
  exit
1116
1250
  end
1117
1251
  firstrun unless File.exist?(Dir.home+'/.rshrc') # Initial loading - to get history
1118
- load(Dir.home+'/.rshrc')
1252
+ load_rshrc_safe
1119
1253
  # Load login shell files if rsh is running as login shell
1120
1254
  if ENV['LOGIN_SHELL'] or $0 == "-rsh" or ARGV.include?('-l') or ARGV.include?('--login')
1121
1255
  ['/etc/profile', Dir.home+'/.profile', Dir.home+'/.bash_profile', Dir.home+'/.bashrc'].each do |f|
@@ -1159,7 +1293,7 @@ loop do
1159
1293
  begin
1160
1294
  @user = Etc.getpwuid(Process.euid).name # For use in @prompt
1161
1295
  @node = Etc.uname[:nodename] # For use in @prompt
1162
- h = @history; load(Dir.home+'/.rshrc') if File.exist?(Dir.home+'/.rshrc'); @history = h # reload prompt but not history
1296
+ h = @history; load_rshrc_safe; @history = h # reload prompt but not history safely
1163
1297
  @prompt.gsub!(/#{Dir.home}/, '~') # Simplify path in prompt
1164
1298
  system("printf \"\033]0;rsh: #{Dir.pwd}\007\"") # Set Window title to path
1165
1299
  @history[0] = "" unless @history[0]
metadata CHANGED
@@ -1,21 +1,21 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-shell
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.1
4
+ version: 2.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geir Isene
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-09-13 00:00:00.000000000 Z
11
+ date: 2025-09-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: 'A shell written in Ruby with extensive tab completions, aliases/nicks,
14
14
  history, syntax highlighting, theming, auto-cd, auto-opening files and more. UPDATE
15
- v2.9.0: AI integration! Use @ for AI text responses and @@ for AI command suggestions.
16
- Works with local Ollama or external providers like OpenAI. v2.8.0: Enhanced help
17
- system, :info command, and easier nick management. v2.7.0: Ruby Functions, job control,
18
- command substitution, and more.'
15
+ v2.10.0: Auto-healing for corrupted .rshrc files and robust error handling. v2.9.0:
16
+ AI integration! Use @ for AI text responses and @@ for AI command suggestions. Works
17
+ with local Ollama or external providers like OpenAI. v2.8.0: Enhanced help system,
18
+ :info command, and easier nick management.'
19
19
  email: g@isene.com
20
20
  executables:
21
21
  - rsh