irb 1.14.0 → 1.14.2

Sign up to get free protection for your applications and to get access to all the features.
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
  インエディタは使わなくなる.