dev_suite 0.1.3 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +2 -2
  4. data/lib/dev_suite/directory_tree/builder/base.rb +38 -0
  5. data/lib/dev_suite/directory_tree/builder.rb +20 -0
  6. data/lib/dev_suite/directory_tree/config.rb +18 -0
  7. data/lib/dev_suite/directory_tree/node/base.rb +13 -1
  8. data/lib/dev_suite/directory_tree/node/directory.rb +14 -4
  9. data/lib/dev_suite/directory_tree/node/file.rb +2 -4
  10. data/lib/dev_suite/directory_tree/node/permission_denied.rb +0 -2
  11. data/lib/dev_suite/directory_tree/node.rb +1 -0
  12. data/lib/dev_suite/directory_tree/renderer/base.rb +5 -24
  13. data/lib/dev_suite/directory_tree/renderer/simple.rb +57 -45
  14. data/lib/dev_suite/directory_tree/renderer.rb +12 -0
  15. data/lib/dev_suite/directory_tree/settings.rb +29 -0
  16. data/lib/dev_suite/directory_tree/visualizer.rb +11 -15
  17. data/lib/dev_suite/directory_tree.rb +7 -0
  18. data/lib/dev_suite/performance/analyzer.rb +14 -20
  19. data/lib/dev_suite/performance/config.rb +16 -0
  20. data/lib/dev_suite/performance/profiler/benchmark.rb +0 -3
  21. data/lib/dev_suite/performance/profiler/memory.rb +0 -3
  22. data/lib/dev_suite/performance/profiler.rb +1 -0
  23. data/lib/dev_suite/performance/reportor/simple.rb +52 -29
  24. data/lib/dev_suite/performance/reportor.rb +13 -1
  25. data/lib/dev_suite/performance.rb +7 -0
  26. data/lib/dev_suite/utils/color/colorizer.rb +7 -10
  27. data/lib/dev_suite/utils/config_tools/configuration.rb +41 -0
  28. data/lib/dev_suite/utils/config_tools/settings.rb +75 -0
  29. data/lib/dev_suite/utils/config_tools.rb +10 -0
  30. data/lib/dev_suite/utils/table/config.rb +8 -42
  31. data/lib/dev_suite/utils/table/renderer/base.rb +4 -2
  32. data/lib/dev_suite/utils/table/renderer/simple.rb +5 -5
  33. data/lib/dev_suite/utils/table/renderer.rb +11 -0
  34. data/lib/dev_suite/utils/table/settings.rb +34 -0
  35. data/lib/dev_suite/utils/table/table.rb +2 -8
  36. data/lib/dev_suite/utils/table.rb +1 -0
  37. data/lib/dev_suite/utils.rb +1 -0
  38. data/lib/dev_suite/version.rb +1 -1
  39. metadata +11 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 92f5e3450bc8b204f0be7e25db8a863ebd49d4d5a6990cfad7c6d336ccaf7e5e
4
- data.tar.gz: 368e6bd01867d4fc92856b8bc4825e1e5bdc2b3b978e3afa0966139f59216f28
3
+ metadata.gz: 61551856599e246df8b5d7e66bf7ada17cf7ed03147c9c846fcd1f4ed2fcaf5d
4
+ data.tar.gz: f36513a7e8afa78bd04c9a9d9cd893e9a75b79006ff2ba41f8aa0245f06cc0fa
5
5
  SHA512:
6
- metadata.gz: 973f1f20d18eab20229c5df12a304c1370ccbfc56175795c9e55fc6bc2680c0a3a3adae63472bcd3dc15ed964ba4413a5847a55d8fefc28312a119af9b0b91d5
7
- data.tar.gz: f31d767559b8cd4fbfa961cafef17a5cbbcda42a78ee5e012147a96a2652fd8b3417e1184a1e5a60925032aa21b6d256902753c799c322aa48e5240016b6f901
6
+ metadata.gz: 533af36d8beb9efbe20c5f8135d6c7255265c6e8ff7b0b2fc35f57da5572803cead32a69bcda9e672f4de5373b0a6f41e678241042c0ce16c0a06cbe681ead4d
7
+ data.tar.gz: 66729b4045f43b20029c6ad81365e51505489c3a6f99f241cfbb7acd9e31bd5951004e3faf2f0715878ac386a2c1d8108701142fdb87ebed72b63b1d7263b423
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dev_suite (0.1.3)
4
+ dev_suite (0.2.1)
5
5
  benchmark (~> 0.1)
6
6
  get_process_mem (~> 0.2)
7
7
 
data/README.md CHANGED
@@ -51,7 +51,7 @@ DevSuite::SomeUtility.do_something
51
51
  ```ruby
52
52
  require 'dev_suite'
53
53
 
54
- DevSuite::Performance::Analyzer.analyze(description: "My Code Block") do
54
+ DevSuite::Performance.analyze(description: "My Code Block") do
55
55
  sum = 0
56
56
  1_000_000.times do |i|
57
57
  sum += i
@@ -93,7 +93,7 @@ DevSuite::SomeUtility.do_something
93
93
  base_path = "/path/to/your/directory"
94
94
 
95
95
  # Perform the visualization
96
- DevSuite::DirectoryTree::Visualizer.visualize(base_path)
96
+ DevSuite::DirectoryTree.visualize(base_path)
97
97
  ```
98
98
 
99
99
  **Example output**
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module DirectoryTree
5
+ module Builder
6
+ class Base
7
+ #
8
+ # Recursive method to build the tree
9
+ #
10
+ def build(path)
11
+ return build_permission_denied_node(path) unless path.readable?
12
+
13
+ path.directory? ? construct_directory_node(path) : build_file_node(path)
14
+ rescue Errno::EACCES
15
+ build_permission_denied_node(path)
16
+ end
17
+
18
+ protected
19
+
20
+ def construct_directory_node(path)
21
+ directory = Node::Directory.new(path.basename.to_s)
22
+ path.children.each do |child|
23
+ directory.add_child(build(child))
24
+ end
25
+ directory
26
+ end
27
+
28
+ def build_file_node(path)
29
+ Node::File.new(path.basename.to_s)
30
+ end
31
+
32
+ def build_permission_denied_node(path)
33
+ Node::PermissionDenied.new(path.basename.to_s, path.directory?)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module DirectoryTree
5
+ module Builder
6
+ require_relative "builder/base"
7
+
8
+ class << self
9
+ def create(type)
10
+ case type
11
+ when :base
12
+ Base.new
13
+ else
14
+ raise ArgumentError, "Unknown renderer type: #{type}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module DirectoryTree
5
+ class Config
6
+ include Utils::ConfigTools::Configuration
7
+
8
+ attr_reader :settings, :builder, :renderer
9
+
10
+ def initialize(settings: {}, builder: :base, renderer: :simple)
11
+ @settings = Settings.new(settings)
12
+ @builder = Builder.create(builder)
13
+ @renderer = Renderer.create(renderer)
14
+ freeze # Make the instance of this class immutable as well
15
+ end
16
+ end
17
+ end
18
+ end
@@ -11,7 +11,19 @@ module DevSuite
11
11
  end
12
12
 
13
13
  def directory?
14
- raise NotImplementedError, "Must implement in subclass"
14
+ false
15
+ end
16
+
17
+ def file?
18
+ false
19
+ end
20
+
21
+ def children
22
+ []
23
+ end
24
+
25
+ def hidden?
26
+ @name.start_with?(".")
15
27
  end
16
28
  end
17
29
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "base"
4
-
5
3
  module DevSuite
6
4
  module DirectoryTree
7
5
  module Node
@@ -17,8 +15,20 @@ module DevSuite
17
15
  true
18
16
  end
19
17
 
20
- def add_child(child)
21
- @children << child
18
+ def add_child(node)
19
+ @children << node
20
+ sort_children!
21
+ end
22
+
23
+ private
24
+
25
+ def sort_children!
26
+ @children.sort_by! do |node|
27
+ [
28
+ node.hidden? ? 1 : 0, # Hidden nodes should be at the end
29
+ node.name.downcase, # Alphabetical order
30
+ ]
31
+ end
22
32
  end
23
33
  end
24
34
  end
@@ -1,13 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "base"
4
-
5
3
  module DevSuite
6
4
  module DirectoryTree
7
5
  module Node
8
6
  class File < Base
9
- def directory?
10
- false
7
+ def file?
8
+ true
11
9
  end
12
10
  end
13
11
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "base"
4
-
5
3
  module DevSuite
6
4
  module DirectoryTree
7
5
  module Node
@@ -3,6 +3,7 @@
3
3
  module DevSuite
4
4
  module DirectoryTree
5
5
  module Node
6
+ require_relative "node/base"
6
7
  require_relative "node/file"
7
8
  require_relative "node/directory"
8
9
  require_relative "node/permission_denied"
@@ -1,36 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "pathname"
4
-
5
3
  module DevSuite
6
4
  module DirectoryTree
7
5
  module Renderer
8
6
  class Base
9
- def initialize(base_path)
10
- @base_path = Pathname.new(base_path)
11
- end
7
+ attr_reader :settings
12
8
 
13
- def render
14
- root = build_tree(@base_path)
15
- render_node(root, "", true)
9
+ def initialize(settings: Settings.new)
10
+ @settings = settings
16
11
  end
17
12
 
18
- private
19
-
20
- # Builds the tree structure
21
- # @param path [Pathname] The path to build the tree from
22
- # @return [Node::Base] The root node of the tree
23
- def build_tree(path)
24
- raise NotImplementedError, "You must implement the build_tree method"
25
- end
26
-
27
- # Renders a node in the tree
28
- # @param node [Node::Base] The node to render
29
- # @param prefix [String] The prefix to add to the node
30
- # @param is_last [Boolean] Whether this is the last node in the list
31
- # @return [String] The rendered node
32
- def render_node(node, prefix, is_last)
33
- raise NotImplementedError, "You must implement the render_node method"
13
+ def render
14
+ raise NotImplementedError
34
15
  end
35
16
  end
36
17
  end
@@ -1,75 +1,87 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "base"
4
- require_relative "../node"
5
-
6
3
  module DevSuite
7
4
  module DirectoryTree
8
5
  module Renderer
9
6
  class Simple < Base
10
- private
11
-
12
- def build_tree(path)
13
- return permission_denied_node(path) unless path.readable?
14
-
15
- path.directory? ? directory_node(path) : file_node(path)
16
- rescue Errno::EACCES
17
- permission_denied_node(path)
18
- end
19
-
20
- def render_node(node, prefix = "", is_last = true)
21
- is_root = prefix.empty?
22
- connector = determine_connector(is_root, is_last)
23
- new_prefix = update_prefix(prefix, is_last)
24
-
25
- output = construct_output(node, prefix, connector)
26
- output += node_suffix(node)
27
-
7
+ # The characters are used to draw the tree structure
8
+ #
9
+ # (U+2514) is the L-shaped corner character
10
+ # (U+251C) is the L-shaped corner character
11
+ # │ (U+2502) is the vertical line character
12
+ # (U+2500) is the horizontal line character
13
+ #   (U+00A0) is the non-breaking space character
14
+ # | (U+007C) is the vertical line character
15
+ # (U+0020) is the space character
16
+ LAST_NODE_CONNECTOR = "└── "
17
+ NODE_CONNECTOR = "├── "
18
+ INDENT = " "
19
+ PIPE = "│ "
20
+
21
+ def render(node:, prefix: "", is_last: true, depth: 0)
22
+ return "" if skip_node?(node) || exceeds_max_depth?(depth)
23
+
24
+ output = node_line(node: node, prefix: prefix, is_last: is_last)
28
25
  if node.directory? && node.children.any?
29
- node.children.each_with_index do |child, index|
30
- output += render_node(child, new_prefix, index == node.children.size - 1)
31
- end
26
+ output += render_children(node: node, prefix: prefix, is_last: is_last, depth: depth)
32
27
  end
33
28
 
34
29
  output
35
30
  end
36
31
 
37
- def determine_connector(is_root, is_last)
38
- return "" if is_root
32
+ private
39
33
 
40
- is_last ? "└── " : "├── "
34
+ def settings
35
+ Config.configuration.settings
41
36
  end
42
37
 
43
- def update_prefix(prefix, is_last)
44
- "#{prefix}#{is_last ? " " : "| "}"
38
+ def skip_node?(node)
39
+ hidden_file_skipped?(node) || filetype_skipped?(node)
45
40
  end
46
41
 
47
- def construct_output(node, prefix, connector)
48
- "#{prefix}#{connector}#{node.name}"
42
+ def hidden_file_skipped?(node)
43
+ settings.skip_hidden? && node.hidden?
49
44
  end
50
45
 
51
- def node_suffix(node)
52
- node.directory? ? "/\n" : "\n"
46
+ def filetype_skipped?(node)
47
+ node.file? && settings.skip_types.include?(::File.extname(node.name))
53
48
  end
54
49
 
55
- def directory_node(path)
56
- dir = Node::Directory.new(path.basename.to_s)
57
- sorted_children(path).each do |child|
58
- dir.add_child(build_tree(child))
59
- end
60
- dir
50
+ def exceeds_max_depth?(depth)
51
+ max_depth = settings.max_depth
52
+ max_depth && depth > max_depth
61
53
  end
62
54
 
63
- def file_node(path)
64
- Node::File.new(path.basename.to_s)
55
+ def node_line(node:, prefix:, is_last:)
56
+ connector = determine_connector(is_root: prefix.empty?, is_last: is_last)
57
+ "#{prefix}#{connector}#{node.name}#{suffix_for(node)}"
58
+ end
59
+
60
+ def determine_connector(is_root:, is_last:)
61
+ return "" if is_root
62
+
63
+ is_last ? LAST_NODE_CONNECTOR : NODE_CONNECTOR
64
+ end
65
+
66
+ def suffix_for(node)
67
+ node.directory? ? "/\n" : "\n"
65
68
  end
66
69
 
67
- def permission_denied_node(path)
68
- Node::PermissionDenied.new(path.basename.to_s, path.directory?)
70
+ def render_children(node:, prefix:, is_last:, depth:)
71
+ new_prefix = updated_prefix(prefix: prefix, is_last: is_last)
72
+ visible_children = node.children.reject { |child| skip_node?(child) }
73
+ visible_children.each_with_index.map do |child, index|
74
+ render(
75
+ node: child,
76
+ prefix: new_prefix,
77
+ is_last: index == visible_children.size - 1,
78
+ depth: depth + 1,
79
+ )
80
+ end.join
69
81
  end
70
82
 
71
- def sorted_children(path)
72
- path.children.sort_by { |child| child.basename.to_s.downcase }
83
+ def updated_prefix(prefix:, is_last:)
84
+ "#{prefix}#{is_last ? INDENT : PIPE}"
73
85
  end
74
86
  end
75
87
  end
@@ -3,7 +3,19 @@
3
3
  module DevSuite
4
4
  module DirectoryTree
5
5
  module Renderer
6
+ require_relative "renderer/base"
6
7
  require_relative "renderer/simple"
8
+
9
+ class << self
10
+ def create(type)
11
+ case type
12
+ when :simple
13
+ Simple.new
14
+ else
15
+ raise ArgumentError, "Unknown renderer type: #{type}"
16
+ end
17
+ end
18
+ end
7
19
  end
8
20
  end
9
21
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module DirectoryTree
5
+ class Settings
6
+ include Utils::ConfigTools::Settings
7
+
8
+ def default_settings
9
+ {
10
+ skip_hidden: false,
11
+ skip_types: [],
12
+ max_depth: nil,
13
+ }
14
+ end
15
+
16
+ def skip_hidden?
17
+ get(:skip_hidden)
18
+ end
19
+
20
+ def skip_types
21
+ get(:skip_types)
22
+ end
23
+
24
+ def max_depth
25
+ get(:max_depth)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,25 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "pathname"
4
- require_relative "renderer"
5
-
6
3
  module DevSuite
7
4
  module DirectoryTree
8
5
  class Visualizer
9
- class << self
10
- # Visualizes the directory tree
11
- # @param base_path [String] The base path of the directory
12
- def visualize(base_path)
13
- new(base_path).visualize
14
- end
15
- end
16
-
17
- def initialize(base_path, renderer: Renderer::Simple.new(base_path))
18
- @renderer = renderer
6
+ # Visualizes the directory tree
7
+ # @param path [String] The base path of the directory
8
+ def visualize(path)
9
+ root = Config.configuration.builder.build(Pathname.new(path))
10
+ renderer = Config.configuration.renderer
11
+ puts renderer.render(node: root)
19
12
  end
13
+ end
20
14
 
21
- def visualize
22
- puts @renderer.render
15
+ class << self
16
+ def visualize(path)
17
+ visualizer = Visualizer.new
18
+ visualizer.visualize(path)
23
19
  end
24
20
  end
25
21
  end
@@ -2,6 +2,13 @@
2
2
 
3
3
  module DevSuite
4
4
  module DirectoryTree
5
+ require "pathname"
6
+
7
+ require_relative "directory_tree/node"
8
+ require_relative "directory_tree/config"
9
+ require_relative "directory_tree/settings"
10
+ require_relative "directory_tree/renderer"
11
+ require_relative "directory_tree/builder"
5
12
  require_relative "directory_tree/visualizer"
6
13
  end
7
14
  end
@@ -1,25 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "reportor"
4
- require_relative "profiler"
5
-
6
3
  module DevSuite
7
4
  module Performance
8
5
  class Analyzer
9
- class << self
10
- # Generates a performance report
11
- # @param benchmark_result [Benchmark::Tms] The benchmark result
12
- # @param memory_stats [Hash] The memory statistics
13
- def analyze(description: "Block", &block)
14
- raise ArgumentError, "No block given" unless block_given?
15
-
16
- analyzer = new(description: description)
17
- analyzer.analyze(&block)
18
- end
19
- end
20
-
21
6
  def initialize(description: "Block")
22
7
  @description = description
8
+
23
9
  @benchmark_profiler = Profiler::Benchmark.new
24
10
  @memory_profiler = Profiler::Memory.new
25
11
  @memory_usage = Data::MemoryUsage.new
@@ -29,6 +15,8 @@ module DevSuite
29
15
  # @param block [Proc] The block to be analyzed
30
16
  # @raise [ArgumentError] If no block is given
31
17
  def analyze(&block)
18
+ raise ArgumentError, "No block given" unless block_given?
19
+
32
20
  memory_before = @memory_usage.current
33
21
  benchmark_result = profile_benchmark(&block)
34
22
  memory_after = @memory_usage.current
@@ -53,12 +41,18 @@ module DevSuite
53
41
  # @param benchmark_result [Benchmark::Tms] The benchmark result
54
42
  # @param memory_stats [Hash] The memory statistics
55
43
  def generate_report(benchmark_result, memory_stats)
56
- reportor = Reportor::Simple.new(
57
- @description,
58
- benchmark_result,
59
- memory_stats,
44
+ Config.configuration.reportor.generate(
45
+ description: @description,
46
+ benchmark_result: benchmark_result,
47
+ memory_stats: memory_stats,
60
48
  )
61
- reportor.generate
49
+ end
50
+ end
51
+
52
+ class << self
53
+ def analyze(description: "Block", &block)
54
+ analyzer = Analyzer.new(description: description)
55
+ analyzer.analyze(&block)
62
56
  end
63
57
  end
64
58
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module Performance
5
+ class Config
6
+ include Utils::ConfigTools::Configuration
7
+
8
+ attr_reader :reportor
9
+
10
+ def initialize(reportor: :simple)
11
+ @reportor = Reportor.create(reportor)
12
+ freeze # Make the instance of this class immutable
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "benchmark"
4
- require_relative "base"
5
-
6
3
  module DevSuite
7
4
  module Performance
8
5
  module Profiler
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "base"
4
- require_relative "../data/memory_usage"
5
-
6
3
  module DevSuite
7
4
  module Performance
8
5
  module Profiler
@@ -3,6 +3,7 @@
3
3
  module DevSuite
4
4
  module Performance
5
5
  module Profiler
6
+ require_relative "profiler/base"
6
7
  require_relative "profiler/benchmark"
7
8
  require_relative "profiler/memory"
8
9
  end
@@ -1,22 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "base"
4
-
5
3
  module DevSuite
6
4
  module Performance
7
5
  module Reportor
8
6
  class Simple < Base
9
- def initialize(description, benchmark_result, memory_stats)
10
- super()
11
- @description = description
12
- @benchmark_result = benchmark_result
13
- @memory_stats = memory_stats
14
- end
15
-
7
+ #
16
8
  # Generates the performance report
17
- def generate
9
+ #
10
+ def generate(description:, benchmark_result:, memory_stats:)
18
11
  table = create_table
19
- populate_table(table)
12
+ populate_table(
13
+ table,
14
+ description: description,
15
+ benchmark_result: benchmark_result,
16
+ memory_stats: memory_stats,
17
+ )
20
18
  render_table(table)
21
19
  end
22
20
 
@@ -26,36 +24,61 @@ module DevSuite
26
24
  # Creates a new table with the specified configuration
27
25
  #
28
26
  def create_table
29
- config = Utils::Table::Config.new
30
- Utils::Table::Table.new(config).tap do |table|
31
- table.title = "Performance Analysis"
32
- table.add_columns("Metric", "Value")
27
+ table = Utils::Table::Table.new
28
+ table.tap do |t|
29
+ t.title = "Performance Analysis"
30
+ t.add_columns("Metric", "Value")
33
31
  end
34
32
  end
35
33
 
36
34
  #
37
35
  # Populates the table with benchmark and memory statistics
38
36
  #
39
- def populate_table(table)
40
- table.add_row(["Description", @description])
41
- table.add_row(["Total Time (s)", format("%.6f", @benchmark_result.real)])
42
- table.add_row(["User CPU Time (s)", format("%.6f", @benchmark_result.utime)])
43
- table.add_row(["System CPU Time (s)", format("%.6f", @benchmark_result.stime)])
44
- table.add_row(["User + System CPU Time (s)", format("%.6f", @benchmark_result.total)])
45
- table.add_row(["Memory Before (MB)", format("%.2f", @memory_stats[:before])])
46
- table.add_row(["Memory After (MB)", format("%.2f", @memory_stats[:after])])
47
- table.add_row(["Memory Used (MB)", format("%.2f", @memory_stats[:used])])
48
- table.add_row(["Max Memory Used (MB)", format("%.2f", @memory_stats[:max])])
49
- table.add_row(["Min Memory Used (MB)", format("%.2f", @memory_stats[:min])])
50
- table.add_row(["Avg Memory Used (MB)", format("%.2f", @memory_stats[:avg])])
37
+ def populate_table(table, description: "", benchmark_result: nil, memory_stats: {})
38
+ validate_benchmark_result(benchmark_result)
39
+ validate_memory_stats(memory_stats)
40
+
41
+ table.add_row(["Description", description])
42
+ table.add_row(["Total Time (s)", format("%.6f", benchmark_result.real)])
43
+ table.add_row(["User CPU Time (s)", format("%.6f", benchmark_result.utime)])
44
+ table.add_row(["System CPU Time (s)", format("%.6f", benchmark_result.stime)])
45
+ table.add_row(["User + System CPU Time (s)", format("%.6f", benchmark_result.total)])
46
+ table.add_row(["Memory Before (MB)", format("%.2f", memory_stats[:before])])
47
+ table.add_row(["Memory After (MB)", format("%.2f", memory_stats[:after])])
48
+ table.add_row(["Memory Used (MB)", format("%.2f", memory_stats[:used])])
49
+ table.add_row(["Max Memory Used (MB)", format("%.2f", memory_stats[:max])])
50
+ table.add_row(["Min Memory Used (MB)", format("%.2f", memory_stats[:min])])
51
+ table.add_row(["Avg Memory Used (MB)", format("%.2f", memory_stats[:avg])])
51
52
  end
52
53
 
53
54
  #
54
55
  # Renders the table using the specified renderer
55
56
  #
56
57
  def render_table(table)
57
- renderer = Utils::Table::Renderer::Simple.new
58
- puts table.render(renderer: renderer)
58
+ renderer = Utils::Table::Config.configuration.renderer
59
+ puts renderer.render(table)
60
+ end
61
+
62
+ #
63
+ # Validates the benchmark_result object
64
+ #
65
+ def validate_benchmark_result(benchmark_result)
66
+ required_methods = [:real, :utime, :stime, :total]
67
+ missing_methods = required_methods.reject { |method| benchmark_result.respond_to?(method) }
68
+ unless missing_methods.empty?
69
+ raise ArgumentError, "benchmark_result is missing required methods: #{missing_methods.join(", ")}"
70
+ end
71
+ end
72
+
73
+ #
74
+ # Validates the memory_stats hash
75
+ #
76
+ def validate_memory_stats(memory_stats)
77
+ required_keys = [:before, :after, :used, :max, :min, :avg]
78
+ missing_keys = required_keys.reject { |key| memory_stats.key?(key) }
79
+ unless missing_keys.empty?
80
+ raise ArgumentError, "memory_stats is missing required keys: #{missing_keys.join(", ")}"
81
+ end
59
82
  end
60
83
  end
61
84
  end
@@ -2,8 +2,20 @@
2
2
 
3
3
  module DevSuite
4
4
  module Performance
5
- module Reporting
5
+ module Reportor
6
+ require_relative "reportor/base"
6
7
  require_relative "reportor/simple"
8
+
9
+ class << self
10
+ def create(reportor)
11
+ case reportor
12
+ when :simple
13
+ Simple.new
14
+ else
15
+ raise ArgumentError, "Invalid reportor: #{reportor}"
16
+ end
17
+ end
18
+ end
7
19
  end
8
20
  end
9
21
  end
@@ -2,6 +2,13 @@
2
2
 
3
3
  module DevSuite
4
4
  module Performance
5
+ require "benchmark"
6
+ require "get_process_mem"
7
+
8
+ require_relative "performance/data"
9
+ require_relative "performance/profiler"
10
+ require_relative "performance/reportor"
5
11
  require_relative "performance/analyzer"
12
+ require_relative "performance/config"
6
13
  end
7
14
  end
@@ -3,21 +3,18 @@
3
3
  module DevSuite
4
4
  module Utils
5
5
  module Color
6
- class << self
6
+ class Colorizer
7
7
  def colorize(text, **kargs)
8
- Colorizer.new(Config.configuration).colorize(text, **kargs)
8
+ puts Config.configuration.strategy.colorize(text, **kargs)
9
9
  end
10
10
  end
11
11
 
12
- class Colorizer
13
- attr_reader :config
14
-
15
- def initialize(config = Config.configuration)
16
- @config = config
17
- end
18
-
12
+ class << self
19
13
  def colorize(text, **kargs)
20
- puts @config.strategy.colorize(text, **kargs)
14
+ raise ArgumentError, "Text to colorize must be a string" unless text.is_a?(String)
15
+
16
+ colorizer = Colorizer.new
17
+ colorizer.colorize(text, **kargs)
21
18
  end
22
19
  end
23
20
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module Utils
5
+ module ConfigTools
6
+ module Configuration
7
+ # Module for global configuration
8
+ class << self
9
+ def included(base)
10
+ base.extend(ClassMethods)
11
+ end
12
+ end
13
+
14
+ module ClassMethods
15
+ #
16
+ # Provide global access to a single instance of Config
17
+ #
18
+ def configuration
19
+ @configuration ||= new
20
+ end
21
+
22
+ #
23
+ # Allow block-based configuration
24
+ #
25
+ def configure
26
+ yield(configuration)
27
+ rescue StandardError => e
28
+ handle_configuration_error(e)
29
+ raise
30
+ end
31
+
32
+ private
33
+
34
+ def handle_configuration_error(error)
35
+ puts "Configuration error: #{error.message}"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module Utils
5
+ module ConfigTools
6
+ # Module for managing instance settings
7
+ module Settings
8
+ class << self
9
+ def included(base)
10
+ base.include(InstanceMethods)
11
+ end
12
+ end
13
+
14
+ module InstanceMethods
15
+ def initialize(settings = {})
16
+ @settings = merge_settings(default_settings, settings)
17
+ end
18
+
19
+ def set(*keys, value)
20
+ key_path = normalize_keys(keys)
21
+ last_key = key_path.pop
22
+ target = key_path.each_with_object(@settings) do |key, nested|
23
+ nested[key] ||= {}
24
+ end
25
+ target[last_key] = value
26
+ end
27
+
28
+ def get(*keys)
29
+ key_path = normalize_keys(keys)
30
+ key_path.reduce(@settings) do |nested, key|
31
+ nested.is_a?(Hash) ? nested[key] : nil
32
+ end
33
+ end
34
+
35
+ def apply
36
+ #
37
+ # Implement logic to apply settings in the including class
38
+ # TODO: need to review this method
39
+ #
40
+ raise NotImplementedError, "#{self.class} must implement the #apply method"
41
+ end
42
+
43
+ def reset!
44
+ @settings = default_settings
45
+ end
46
+
47
+ def default_settings
48
+ raise NotImplementedError, "#{self.class} must implement the #default_settings method"
49
+ end
50
+
51
+ private
52
+
53
+ def normalize_keys(keys)
54
+ key_path = keys.flatten
55
+ if key_path.size == 1 && key_path.first.is_a?(String)
56
+ key_path.first.to_s.split(".").map(&:to_sym)
57
+ else
58
+ key_path.map(&:to_sym)
59
+ end
60
+ end
61
+
62
+ def merge_settings(defaults, overrides)
63
+ defaults.merge(overrides) do |_key, oldval, newval|
64
+ if oldval.is_a?(Hash) && newval.is_a?(Hash)
65
+ merge_settings(oldval, newval)
66
+ else
67
+ newval
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module Utils
5
+ module ConfigTools
6
+ require_relative "config_tools/configuration"
7
+ require_relative "config_tools/settings"
8
+ end
9
+ end
10
+ end
@@ -4,7 +4,9 @@ module DevSuite
4
4
  module Utils
5
5
  module Table
6
6
  class Config
7
- DEFAULTS = {
7
+ include ConfigTools::Configuration
8
+
9
+ DEFAULT_SETTING = {
8
10
  colors: {
9
11
  title: :cyan,
10
12
  column: :yellow,
@@ -17,48 +19,12 @@ module DevSuite
17
19
  },
18
20
  }.freeze
19
21
 
20
- attr_reader :settings
21
-
22
- def initialize(settings = {})
23
- @settings = deep_merge(DEFAULTS, settings)
24
- end
25
-
26
- class << self
27
- #
28
- # Provide global access to a single instance of Config
29
- #
30
- def configuration
31
- @configuration ||= new
32
- end
33
-
34
- # Allow block-based configuration
35
- def configure
36
- yield(configuration)
37
- rescue StandardError => e
38
- handle_configuration_error(e)
39
- end
40
-
41
- private
42
-
43
- def handle_configuration_error(error)
44
- puts "Configuration error: #{error.message}"
45
- end
46
- end
47
-
48
- def color_for(key)
49
- @settings[:colors][key] || DEFAULTS[:colors][:row]
50
- end
51
-
52
- def alignment_for(key)
53
- @settings[:alignments][key] || :left
54
- end
55
-
56
- private
22
+ attr_reader :settings, :renderer
57
23
 
58
- def deep_merge(original, override)
59
- original.merge(override) do |_key, oldval, newval|
60
- oldval.is_a?(Hash) ? deep_merge(oldval, newval) : newval
61
- end
24
+ def initialize(settings: {}, renderer: :simple)
25
+ @settings = Settings.new(settings)
26
+ @renderer = Renderer.create(renderer, settings: @settings)
27
+ freeze
62
28
  end
63
29
  end
64
30
  end
@@ -5,8 +5,10 @@ module DevSuite
5
5
  module Table
6
6
  module Renderer
7
7
  class Base
8
- def initialize(config = Config.new)
9
- @config = config
8
+ attr_reader :settings
9
+
10
+ def initialize(settings: Settings.new)
11
+ @settings = settings
10
12
  end
11
13
 
12
14
  def render(table)
@@ -45,7 +45,7 @@ module DevSuite
45
45
 
46
46
  total_width = column_widths.sum + column_widths.size * 3 - 1
47
47
  title_str = "| #{table.title.center(total_width - 2)} |"
48
- colorize(title_str, @config.color_for(:title))
48
+ colorize(title_str, settings.color_for(:title))
49
49
  end
50
50
 
51
51
  def render_header(table, column_widths)
@@ -55,13 +55,13 @@ module DevSuite
55
55
  text_align(column.name, column_widths[index])
56
56
  end
57
57
  header_str = "| #{header.join(" | ")} |"
58
- colorize(header_str, @config.color_for(:column))
58
+ colorize(header_str, settings.color_for(:column))
59
59
  end
60
60
 
61
61
  def render_separator(column_widths)
62
62
  separator = column_widths.map { |width| "-" * width }.join("-+-")
63
63
  separator_str = "+-#{separator}-+"
64
- colorize(separator_str, @config.color_for(:border))
64
+ colorize(separator_str, settings.color_for(:border))
65
65
  end
66
66
 
67
67
  def render_rows(table, column_widths)
@@ -69,7 +69,7 @@ module DevSuite
69
69
  render_row(row, column_widths)
70
70
  end
71
71
  cells_str = cells.join("\n")
72
- colorize(cells_str, @config.color_for(:row))
72
+ colorize(cells_str, settings.color_for(:row))
73
73
  end
74
74
 
75
75
  def render_row(row, column_widths)
@@ -77,7 +77,7 @@ module DevSuite
77
77
  text_align(cell.to_s, column_widths[index])
78
78
  end
79
79
  cell_str = "| #{cell.join(" | ")} |"
80
- colorize(cell_str, @config.color_for(:row))
80
+ colorize(cell_str, settings.color_for(:row))
81
81
  end
82
82
  end
83
83
  end
@@ -6,6 +6,17 @@ module DevSuite
6
6
  module Renderer
7
7
  require_relative "renderer/base"
8
8
  require_relative "renderer/simple"
9
+
10
+ class << self
11
+ def create(type, settings: Settings.new)
12
+ case type
13
+ when :simple
14
+ Simple.new(settings: settings)
15
+ else
16
+ raise ArgumentError, "Unknown renderer type: #{type}"
17
+ end
18
+ end
19
+ end
9
20
  end
10
21
  end
11
22
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module Utils
5
+ module Table
6
+ class Settings
7
+ include ConfigTools::Settings
8
+
9
+ def default_settings
10
+ {
11
+ colors: {
12
+ title: :cyan,
13
+ column: :yellow,
14
+ row: :default,
15
+ border: :blue,
16
+ },
17
+ alignments: {
18
+ column: :left,
19
+ row: :left,
20
+ },
21
+ }
22
+ end
23
+
24
+ def color_for(key)
25
+ get(:colors, key)
26
+ end
27
+
28
+ def alignment_for(key)
29
+ get(:alignments, key)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -5,13 +5,11 @@ module DevSuite
5
5
  module Table
6
6
  class Table
7
7
  attr_accessor :title
8
- attr_reader :columns, :rows, :config
8
+ attr_reader :columns, :rows
9
9
 
10
- def initialize(config = Config.new)
10
+ def initialize
11
11
  @columns = []
12
12
  @rows = []
13
- @title = ""
14
- @config = config
15
13
  end
16
14
 
17
15
  def add_columns(*names)
@@ -25,10 +23,6 @@ module DevSuite
25
23
  def add_row(data)
26
24
  @rows << Row.new(data)
27
25
  end
28
-
29
- def render(renderer: Renderer::Simple.new(config))
30
- renderer.render(self)
31
- end
32
26
  end
33
27
  end
34
28
  end
@@ -7,6 +7,7 @@ module DevSuite
7
7
  require_relative "table/column"
8
8
  require_relative "table/row"
9
9
  require_relative "table/config"
10
+ require_relative "table/settings"
10
11
  require_relative "table/formatter"
11
12
  require_relative "table/renderer"
12
13
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module DevSuite
4
4
  module Utils
5
+ require_relative "utils/config_tools"
5
6
  require_relative "utils/color"
6
7
  require_relative "utils/table"
7
8
  end
@@ -1,3 +1,3 @@
1
1
  module DevSuite
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dev_suite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Huy Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-08-10 00:00:00.000000000 Z
11
+ date: 2024-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark
@@ -62,6 +62,9 @@ files:
62
62
  - dev_suite.gemspec
63
63
  - lib/dev_suite.rb
64
64
  - lib/dev_suite/directory_tree.rb
65
+ - lib/dev_suite/directory_tree/builder.rb
66
+ - lib/dev_suite/directory_tree/builder/base.rb
67
+ - lib/dev_suite/directory_tree/config.rb
65
68
  - lib/dev_suite/directory_tree/node.rb
66
69
  - lib/dev_suite/directory_tree/node/base.rb
67
70
  - lib/dev_suite/directory_tree/node/directory.rb
@@ -70,9 +73,11 @@ files:
70
73
  - lib/dev_suite/directory_tree/renderer.rb
71
74
  - lib/dev_suite/directory_tree/renderer/base.rb
72
75
  - lib/dev_suite/directory_tree/renderer/simple.rb
76
+ - lib/dev_suite/directory_tree/settings.rb
73
77
  - lib/dev_suite/directory_tree/visualizer.rb
74
78
  - lib/dev_suite/performance.rb
75
79
  - lib/dev_suite/performance/analyzer.rb
80
+ - lib/dev_suite/performance/config.rb
76
81
  - lib/dev_suite/performance/data.rb
77
82
  - lib/dev_suite/performance/data/memory_usage.rb
78
83
  - lib/dev_suite/performance/profiler.rb
@@ -94,6 +99,9 @@ files:
94
99
  - lib/dev_suite/utils/color/strategy/basic.rb
95
100
  - lib/dev_suite/utils/color/strategy/rgb.rb
96
101
  - lib/dev_suite/utils/color/strategy/theme.rb
102
+ - lib/dev_suite/utils/config_tools.rb
103
+ - lib/dev_suite/utils/config_tools/configuration.rb
104
+ - lib/dev_suite/utils/config_tools/settings.rb
97
105
  - lib/dev_suite/utils/table.rb
98
106
  - lib/dev_suite/utils/table/column.rb
99
107
  - lib/dev_suite/utils/table/config.rb
@@ -104,6 +112,7 @@ files:
104
112
  - lib/dev_suite/utils/table/renderer/base.rb
105
113
  - lib/dev_suite/utils/table/renderer/simple.rb
106
114
  - lib/dev_suite/utils/table/row.rb
115
+ - lib/dev_suite/utils/table/settings.rb
107
116
  - lib/dev_suite/utils/table/table.rb
108
117
  - lib/dev_suite/version.rb
109
118
  homepage: https://patrick204nqh.github.io