File: truncator.rb

package info (click to toggle)
ruby-tty-command 0.10.1-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 452 kB
  • sloc: ruby: 1,990; makefile: 4; sh: 4
file content (106 lines) | stat: -rw-r--r-- 2,591 bytes parent folder | download
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
# frozen_string_literal: true

module TTY
  class Command
    # Retains the first N bytes and the last N bytes from written content
    #
    # @api private
    class Truncator
      # Default maximum byte size for prefix & suffix
      DEFAULT_SIZE = 32 << 10

      # Create a Truncator
      #
      # @param [Hash] options
      # @option options [Number] max_size
      #
      # @api public
      def initialize(options = {})
        @max_size = options.fetch(:max_size) { DEFAULT_SIZE }
        @prefix   = ""
        @suffix   = ""
        @skipped  = 0
      end

      # Write content
      #
      # @param [String] content
      #   the content to write
      #
      # @return [nil]
      #
      # @api public
      def write(content)
        content = content.to_s.dup

        content, @prefix = append(content, @prefix)

        if (over = (content.bytesize - @max_size)) > 0
          content = content.byteslice(over..-1)
          @skipped += over
        end

        content, @suffix = append(content, @suffix)

        # suffix is full but we still have content to write
        while content.bytesize > 0
          content = copy(content, @suffix)
        end
      end
      alias << write

      # Truncated representation of the content
      #
      # @return [String]
      #
      # @api public
      def read
        return @prefix if @suffix.empty?

        if @skipped.zero?
          return @prefix << @suffix
        end

        @prefix + "\n... omitting #{@skipped} bytes ...\n" + @suffix
      end
      alias to_s read

      private

      # Copy minimum bytes from source to destination
      #
      # @return [String]
      #   the remaining content
      #
      # @api private
      def copy(value, dest)
        bytes = value.bytesize
        n = bytes < dest.bytesize ? bytes : dest.bytesize

        head, tail = dest.byteslice(0...n), dest.byteslice(n..-1)
        dest.replace("#{tail}#{value[0...n]}")
        @skipped += head.bytesize
        value.byteslice(n..-1)
      end

      # Append value to destination
      #
      # @param [String] value
      #
      # @param [String] dst
      #
      # @api private
      def append(value, dst)
        remain    = @max_size - dst.bytesize
        remaining = ""
        if remain > 0
          value_bytes = value.to_s.bytesize
          offset = value_bytes < remain ? value_bytes : remain
          remaining = value.byteslice(0...offset)
          value = value.byteslice(offset..-1)
        end
        [value, dst + remaining]
      end
    end # Truncator
  end # Command
end # TTY