dev_suite 0.1.3 → 0.2.1

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.
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