File: history.rb

package info (click to toggle)
ruby-byebug 11.1.3-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,252 kB
  • sloc: ruby: 8,835; ansic: 1,662; sh: 6; makefile: 4
file content (130 lines) | stat: -rw-r--r-- 2,698 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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
124
125
126
127
128
129
130
# frozen_string_literal: true

begin
  require "readline"
rescue LoadError
  warn <<-MESSAGE
    Sorry, you can't use byebug without Readline. To solve this, you need to
    rebuild Ruby with Readline support. If using Ubuntu, try `sudo apt-get
    install libreadline-dev` and then reinstall your Ruby.
  MESSAGE

  raise
end

module Byebug
  #
  # Handles byebug's history of commands.
  #
  class History
    attr_accessor :size

    def initialize
      self.size = 0
    end

    #
    # Array holding the list of commands in history
    #
    def buffer
      Readline::HISTORY.to_a
    end

    #
    # Restores history from disk.
    #
    def restore
      return unless File.exist?(Setting[:histfile])

      File.readlines(Setting[:histfile]).reverse_each { |l| push(l.chomp) }
    end

    #
    # Saves history to disk.
    #
    def save
      n_cmds = Setting[:histsize] > size ? size : Setting[:histsize]

      File.open(Setting[:histfile], "w") do |file|
        n_cmds.times { file.puts(pop) }
      end

      clear
    end

    #
    # Discards history.
    #
    def clear
      size.times { pop }
    end

    #
    # Adds a new command to Readline's history.
    #
    def push(cmd)
      return if ignore?(cmd)

      self.size += 1
      Readline::HISTORY.push(cmd)
    end

    #
    # Removes a command from Readline's history.
    #
    def pop
      self.size -= 1
      Readline::HISTORY.pop
    end

    #
    # Prints the requested numbers of history entries.
    #
    def to_s(n_cmds)
      show_size = n_cmds ? specific_max_size(n_cmds) : default_max_size

      commands = buffer.last(show_size)

      last_ids(show_size).zip(commands).map do |l|
        format("%<position>5d  %<command>s", position: l[0], command: l[1])
      end.join("\n") + "\n"
    end

    #
    # Array of ids of the last +number+ commands.
    #
    def last_ids(number)
      (1 + size - number..size).to_a
    end

    #
    # Max number of commands to be displayed when no size has been specified.
    #
    # Never more than Setting[:histsize].
    #
    def default_max_size
      [Setting[:histsize], self.size].min
    end

    #
    # Max number of commands to be displayed when a size has been specified.
    #
    # The only bound here is not showing more items than available.
    #
    def specific_max_size(number)
      [self.size, number].min
    end

    #
    # Whether a specific command should not be stored in history.
    #
    # For now, empty lines and consecutive duplicates.
    #
    def ignore?(buf)
      return true if /^\s*$/.match?(buf)
      return false if Readline::HISTORY.empty?

      buffer[Readline::HISTORY.length - 1] == buf
    end
  end
end