irb 1.14.0 → 1.14.2

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.
data/lib/irb/history.rb CHANGED
@@ -1,6 +1,32 @@
1
1
  require "pathname"
2
2
 
3
3
  module IRB
4
+ module History
5
+ class << self
6
+ # Integer representation of <code>IRB.conf[:HISTORY_FILE]</code>.
7
+ def save_history
8
+ IRB.conf[:SAVE_HISTORY].to_i
9
+ end
10
+
11
+ def save_history?
12
+ !save_history.zero?
13
+ end
14
+
15
+ def infinite?
16
+ save_history.negative?
17
+ end
18
+
19
+ # Might be nil when HOME and XDG_CONFIG_HOME are not available.
20
+ def history_file
21
+ if (history_file = IRB.conf[:HISTORY_FILE])
22
+ File.expand_path(history_file)
23
+ else
24
+ IRB.rc_file("_history")
25
+ end
26
+ end
27
+ end
28
+ end
29
+
4
30
  module HistorySavingAbility # :nodoc:
5
31
  def support_history_saving?
6
32
  true
@@ -11,76 +37,75 @@ module IRB
11
37
  end
12
38
 
13
39
  def load_history
40
+ history_file = History.history_file
41
+ return unless File.exist?(history_file.to_s)
42
+
14
43
  history = self.class::HISTORY
15
44
 
16
- if history_file = IRB.conf[:HISTORY_FILE]
17
- history_file = File.expand_path(history_file)
18
- end
19
- history_file = IRB.rc_file("_history") unless history_file
20
- if history_file && File.exist?(history_file)
21
- File.open(history_file, "r:#{IRB.conf[:LC_MESSAGES].encoding}") do |f|
22
- f.each { |l|
23
- l = l.chomp
24
- if self.class == RelineInputMethod and history.last&.end_with?("\\")
25
- history.last.delete_suffix!("\\")
26
- history.last << "\n" << l
27
- else
28
- history << l
29
- end
30
- }
31
- end
32
- @loaded_history_lines = history.size
33
- @loaded_history_mtime = File.mtime(history_file)
45
+ File.open(history_file, "r:#{IRB.conf[:LC_MESSAGES].encoding}") do |f|
46
+ f.each { |l|
47
+ l = l.chomp
48
+ if self.class == RelineInputMethod and history.last&.end_with?("\\")
49
+ history.last.delete_suffix!("\\")
50
+ history.last << "\n" << l
51
+ else
52
+ history << l
53
+ end
54
+ }
34
55
  end
56
+ @loaded_history_lines = history.size
57
+ @loaded_history_mtime = File.mtime(history_file)
35
58
  end
36
59
 
37
60
  def save_history
61
+ return unless History.save_history?
62
+ return unless (history_file = History.history_file)
63
+ unless ensure_history_file_writable(history_file)
64
+ warn <<~WARN
65
+ Can't write history to #{History.history_file.inspect} due to insufficient permissions.
66
+ Please verify the value of `IRB.conf[:HISTORY_FILE]`. Ensure the folder exists and that both the folder and file (if it exists) are writable.
67
+ WARN
68
+ return
69
+ end
70
+
38
71
  history = self.class::HISTORY.to_a
39
72
 
40
- if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) != 0
41
- if history_file = IRB.conf[:HISTORY_FILE]
42
- history_file = File.expand_path(history_file)
43
- end
44
- history_file = IRB.rc_file("_history") unless history_file
73
+ if File.exist?(history_file) &&
74
+ File.mtime(history_file) != @loaded_history_mtime
75
+ history = history[@loaded_history_lines..-1] if @loaded_history_lines
76
+ append_history = true
77
+ end
45
78
 
46
- # When HOME and XDG_CONFIG_HOME are not available, history_file might be nil
47
- return unless history_file
79
+ File.open(history_file, (append_history ? "a" : "w"), 0o600, encoding: IRB.conf[:LC_MESSAGES]&.encoding) do |f|
80
+ hist = history.map { |l| l.scrub.split("\n").join("\\\n") }
48
81
 
49
- # Change the permission of a file that already exists[BUG #7694]
50
- begin
51
- if File.stat(history_file).mode & 066 != 0
52
- File.chmod(0600, history_file)
53
- end
54
- rescue Errno::ENOENT
55
- rescue Errno::EPERM
56
- return
57
- rescue
58
- raise
82
+ unless append_history || History.infinite?
83
+ # Check size before slicing because array.last(huge_number) raises RangeError.
84
+ hist = hist.last(History.save_history) if hist.size > History.save_history
59
85
  end
60
86
 
61
- if File.exist?(history_file) &&
62
- File.mtime(history_file) != @loaded_history_mtime
63
- history = history[@loaded_history_lines..-1] if @loaded_history_lines
64
- append_history = true
65
- end
87
+ f.puts(hist)
88
+ end
89
+ end
66
90
 
67
- pathname = Pathname.new(history_file)
68
- unless Dir.exist?(pathname.dirname)
69
- warn "Warning: The directory to save IRB's history file does not exist. Please double check `IRB.conf[:HISTORY_FILE]`'s value."
70
- return
71
- end
91
+ private
72
92
 
73
- File.open(history_file, (append_history ? 'a' : 'w'), 0o600, encoding: IRB.conf[:LC_MESSAGES]&.encoding) do |f|
74
- hist = history.map{ |l| l.scrub.split("\n").join("\\\n") }
75
- unless append_history
76
- begin
77
- hist = hist.last(num) if hist.size > num and num > 0
78
- rescue RangeError # bignum too big to convert into `long'
79
- # Do nothing because the bignum should be treated as infinity
80
- end
81
- end
82
- f.puts(hist)
93
+ # Returns boolean whether writing to +history_file+ will be possible.
94
+ # Permissions of already existing +history_file+ are changed to
95
+ # owner-only-readable if necessary [BUG #7694].
96
+ def ensure_history_file_writable(history_file)
97
+ history_file = Pathname.new(history_file)
98
+
99
+ return false unless history_file.dirname.writable?
100
+ return true unless history_file.exist?
101
+
102
+ begin
103
+ if history_file.stat.mode & 0o66 != 0
104
+ history_file.chmod 0o600
83
105
  end
106
+ true
107
+ rescue Errno::EPERM # no permissions
108
+ false
84
109
  end
85
110
  end
86
111
  end
data/lib/irb/init.rb CHANGED
@@ -80,7 +80,7 @@ module IRB # :nodoc:
80
80
  @CONF[:USE_SINGLELINE] = false unless defined?(ReadlineInputMethod)
81
81
  @CONF[:USE_COLORIZE] = (nc = ENV['NO_COLOR']).nil? || nc.empty?
82
82
  @CONF[:USE_AUTOCOMPLETE] = ENV.fetch("IRB_USE_AUTOCOMPLETE", "true") != "false"
83
- @CONF[:COMPLETOR] = ENV.fetch("IRB_COMPLETOR", "regexp").to_sym
83
+ @CONF[:COMPLETOR] = ENV["IRB_COMPLETOR"]&.to_sym
84
84
  @CONF[:INSPECT_MODE] = true
85
85
  @CONF[:USE_TRACER] = false
86
86
  @CONF[:USE_LOADER] = false
@@ -67,7 +67,9 @@ module IRB
67
67
  #
68
68
  # See IO#gets for more information.
69
69
  def gets
70
- puts if @stdout.tty? # workaround for debug compatibility test
70
+ # Workaround for debug compatibility test https://github.com/ruby/debug/pull/1100
71
+ puts if ENV['RUBY_DEBUG_TEST_UI']
72
+
71
73
  print @prompt
72
74
  line = @stdin.gets
73
75
  @line[@line_no += 1] = line
@@ -171,11 +173,13 @@ module IRB
171
173
  end
172
174
 
173
175
  class ReadlineInputMethod < StdioInputMethod
174
- def self.initialize_readline
175
- require "readline"
176
- rescue LoadError
177
- else
178
- include ::Readline
176
+ class << self
177
+ def initialize_readline
178
+ require "readline"
179
+ rescue LoadError
180
+ else
181
+ include ::Readline
182
+ end
179
183
  end
180
184
 
181
185
  include HistorySavingAbility
@@ -263,18 +267,9 @@ module IRB
263
267
  @completion_params = [preposing, target, postposing, bind]
264
268
  @completor.completion_candidates(preposing, target, postposing, bind: bind)
265
269
  }
266
- Reline.output_modifier_proc =
267
- if IRB.conf[:USE_COLORIZE]
268
- proc do |output, complete: |
269
- next unless IRB::Color.colorable?
270
- lvars = IRB.CurrentContext&.local_variables || []
271
- IRB::Color.colorize_code(output, complete: complete, local_variables: lvars)
272
- end
273
- else
274
- proc do |output|
275
- Reline::Unicode.escape_for_print(output)
276
- end
277
- end
270
+ Reline.output_modifier_proc = proc do |input, complete:|
271
+ IRB.CurrentContext.colorize_input(input, complete: complete)
272
+ end
278
273
  Reline.dig_perfect_match_proc = ->(matched) { display_document(matched) }
279
274
  Reline.autocompletion = IRB.conf[:USE_AUTOCOMPLETE]
280
275
 
@@ -353,9 +348,15 @@ module IRB
353
348
  if show_easter_egg
354
349
  IRB.__send__(:easter_egg)
355
350
  else
351
+ # RDoc::RI::Driver#display_names uses pager command internally.
352
+ # Some pager command like `more` doesn't use alternate screen
353
+ # so we need to turn on and off alternate screen manually.
356
354
  begin
355
+ print "\e[?1049h"
357
356
  driver.display_names([name])
358
357
  rescue RDoc::RI::Driver::NotFoundError
358
+ ensure
359
+ print "\e[?1049l"
359
360
  end
360
361
  end
361
362
  end
data/lib/irb/inspector.rb CHANGED
@@ -6,7 +6,6 @@
6
6
 
7
7
  module IRB # :nodoc:
8
8
 
9
-
10
9
  # Convenience method to create a new Inspector, using the given +inspect+
11
10
  # proc, and optional +init+ proc and passes them to Inspector.new
12
11
  #
@@ -43,38 +42,40 @@ module IRB # :nodoc:
43
42
  # +:marshal+:: Using Marshal.dump
44
43
  INSPECTORS = {}
45
44
 
46
- # Determines the inspector to use where +inspector+ is one of the keys passed
47
- # during inspector definition.
48
- def self.keys_with_inspector(inspector)
49
- INSPECTORS.select{|k, v| v == inspector}.collect{|k, v| k}
50
- end
51
-
52
- # Example
53
- #
54
- # Inspector.def_inspector(key, init_p=nil){|v| v.inspect}
55
- # Inspector.def_inspector([key1,..], init_p=nil){|v| v.inspect}
56
- # Inspector.def_inspector(key, inspector)
57
- # Inspector.def_inspector([key1,...], inspector)
58
- def self.def_inspector(key, arg=nil, &block)
59
- if block_given?
60
- inspector = IRB::Inspector(block, arg)
61
- else
62
- inspector = arg
45
+ class << self
46
+ # Determines the inspector to use where +inspector+ is one of the keys passed
47
+ # during inspector definition.
48
+ def keys_with_inspector(inspector)
49
+ INSPECTORS.select{|k, v| v == inspector}.collect{|k, v| k}
63
50
  end
64
51
 
65
- case key
66
- when Array
67
- for k in key
68
- def_inspector(k, inspector)
52
+ # Example
53
+ #
54
+ # Inspector.def_inspector(key, init_p=nil){|v| v.inspect}
55
+ # Inspector.def_inspector([key1,..], init_p=nil){|v| v.inspect}
56
+ # Inspector.def_inspector(key, inspector)
57
+ # Inspector.def_inspector([key1,...], inspector)
58
+ def def_inspector(key, arg=nil, &block)
59
+ if block_given?
60
+ inspector = IRB::Inspector(block, arg)
61
+ else
62
+ inspector = arg
63
+ end
64
+
65
+ case key
66
+ when Array
67
+ for k in key
68
+ def_inspector(k, inspector)
69
+ end
70
+ when Symbol
71
+ INSPECTORS[key] = inspector
72
+ INSPECTORS[key.to_s] = inspector
73
+ when String
74
+ INSPECTORS[key] = inspector
75
+ INSPECTORS[key.intern] = inspector
76
+ else
77
+ INSPECTORS[key] = inspector
69
78
  end
70
- when Symbol
71
- INSPECTORS[key] = inspector
72
- INSPECTORS[key.to_s] = inspector
73
- when String
74
- INSPECTORS[key] = inspector
75
- INSPECTORS[key.intern] = inspector
76
- else
77
- INSPECTORS[key] = inspector
78
79
  end
79
80
  end
80
81
 
@@ -8,7 +8,7 @@ Usage: irb.rb [options] [programfile] [arguments]
8
8
  -w ruby -w と同じ.
9
9
  -W[level=2] ruby -W と同じ.
10
10
  --context-mode n 新しいワークスペースを作成した時に関連する Binding
11
- オブジェクトの作成方法を 0 から 3 のいずれかに設定する.
11
+ オブジェクトの作成方法を 0 から 4 のいずれかに設定する.
12
12
  --extra-doc-dir 指定したディレクトリのドキュメントを追加で読み込む.
13
13
  --echo 実行結果を表示する(デフォルト).
14
14
  --noecho 実行結果を表示しない.
@@ -33,9 +33,9 @@ Usage: irb.rb [options] [programfile] [arguments]
33
33
  補完に正規表現を利用する.
34
34
  --type-completor 補完に型情報を利用する.
35
35
  --prompt prompt-mode/--prompt-mode prompt-mode
36
- プロンプトモードを切替えます. 現在定義されているプ
37
- ロンプトモードは, default, simple, xmp, inf-rubyが
38
- 用意されています.
36
+ プロンプトモードを切り替える.
37
+ 現在定義されているプロンプトモードは,
38
+ default, classic, simple, inf-ruby, xmp, null.
39
39
  --inf-ruby-mode emacsのinf-ruby-mode用のプロンプト表示を行なう. 特
40
40
  に指定がない限り, シングルラインエディタとマルチラ
41
41
  インエディタは使わなくなる.