dev_suite 0.2.3 → 0.2.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fde5663cbb9add03d1db18d4b31fffba0049d8d4f49e5e6bcac7d5d72c6933a2
4
- data.tar.gz: d37a1514954b871e610f07942556581f0c68ff83ce35f8f408e35adbabaeee3b
3
+ metadata.gz: 6765c4b9fa4637dafaac36da47cd8adf18652cd0d38804ddcd8641b851669f12
4
+ data.tar.gz: 3a3b27ad8b9fa4319829175995b1d6ea999e9877d537b1316b531247d6bd4b53
5
5
  SHA512:
6
- metadata.gz: 89a013a696f477509da2adc76551badd312dbe73f6ca94440c57384e6a749e0327a4d9a8d9c2262eab7da4dd0ac431656f163e5f7df1068276397c92d641d9a9
7
- data.tar.gz: 6067472079ddfdb69796f2fa34727e44dd8bc8e39c825748aaad8d138640960796bbc15262e0e0d845bfe5b53838d55a8d84208aa89bf6d685f8264e5a5dc2c8
6
+ metadata.gz: c2c9a91ccdfe89d997d66e8441d0b130dacc9edeb5fae6a3f949f1e25ff9aec09c41603597dbc7e017e9e3857c838e88182e4b670c220ea376d28934eb45c6e4
7
+ data.tar.gz: 4f2e69b97a36b68eb84d2c808ede9072b6f333aebe7f2049d16dc7c55e99592604e9e7234b36471d8d84208fec05cfa27b8ce9b942e93d566159209d7fe652d2
@@ -0,0 +1,37 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+
11
+ steps:
12
+ - name: Check out code
13
+ uses: actions/checkout@v2
14
+
15
+ - name: Set up Ruby
16
+ uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: 3.0 # Specify your project's Ruby version
19
+
20
+ - name: Install dependencies
21
+ run: bundle install
22
+
23
+ - name: Run tests
24
+ env:
25
+ CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
26
+ run: |
27
+ bundle exec rspec
28
+
29
+ - name: Upload coverage to Code Climate
30
+ env:
31
+ CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
32
+ run: |
33
+ curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
34
+ chmod +x ./cc-test-reporter
35
+ ./cc-test-reporter before-build
36
+ bundle exec rspec
37
+ ./cc-test-reporter after-build --exit-code $?
data/Gemfile CHANGED
@@ -2,11 +2,16 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- # Specify your gem's dependencies in dev_suite.gemspec
5
+ # Use the gemspec method to include dependencies specified in the gemspec file
6
6
  gemspec
7
7
 
8
- gem "rake", "~> 13.0"
9
- gem "rspec", "~> 3.9"
10
- gem "rubocop", "~> 1.65", require: false
11
- gem "rubocop-shopify", "~> 2.15", require: false
12
- gem "pry", "~> 0.14"
8
+ # Additional development tools not required as part of the gem's runtime
9
+ group :development, :test do
10
+ gem "rake", "~> 13.0"
11
+ gem "pry", "~> 0.14"
12
+ end
13
+
14
+ group :development do
15
+ gem "rubocop", "~> 1.65", require: false
16
+ gem "rubocop-shopify", "~> 2.15", require: false
17
+ end
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dev_suite (0.2.3)
4
+ dev_suite (0.2.4)
5
5
  benchmark (~> 0.1)
6
6
  get_process_mem (~> 1.0)
7
7
  thor (~> 1.1)
@@ -14,6 +14,7 @@ GEM
14
14
  bigdecimal (3.1.8)
15
15
  coderay (1.1.3)
16
16
  diff-lcs (1.5.1)
17
+ docile (1.4.1)
17
18
  ffi (1.17.0)
18
19
  ffi (1.17.0-aarch64-linux-gnu)
19
20
  ffi (1.17.0-aarch64-linux-musl)
@@ -73,6 +74,12 @@ GEM
73
74
  rubocop-shopify (2.15.1)
74
75
  rubocop (~> 1.51)
75
76
  ruby-progressbar (1.13.0)
77
+ simplecov (0.22.0)
78
+ docile (~> 1.1)
79
+ simplecov-html (~> 0.11)
80
+ simplecov_json_formatter (~> 0.1)
81
+ simplecov-html (0.12.3)
82
+ simplecov_json_formatter (0.1.4)
76
83
  strscan (3.1.0)
77
84
  thor (1.3.1)
78
85
  unicode-display_width (2.5.0)
@@ -97,6 +104,7 @@ DEPENDENCIES
97
104
  rspec (~> 3.9)
98
105
  rubocop (~> 1.65)
99
106
  rubocop-shopify (~> 2.15)
107
+ simplecov (~> 0.21)
100
108
 
101
109
  BUNDLED WITH
102
110
  2.5.17
data/README.md CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  [![Gem Version](https://img.shields.io/gem/v/dev_suite?color=blue)](https://rubygems.org/gems/dev_suite)
4
4
  [![Gem Downloads](https://img.shields.io/gem/dt/dev_suite?color=blue)](https://rubygems.org/gems/dev_suite)
5
- [![Code Climate](https://codeclimate.com/github/patrick204nqh/dev_suite/badges/gpa.svg)](https://codeclimate.com/github/patrick204nqh/dev_suite)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/fd83689d39e0f24663fa/maintainability)](https://codeclimate.com/github/patrick204nqh/dev_suite/maintainability)
6
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/fd83689d39e0f24663fa/test_coverage)](https://codeclimate.com/github/patrick204nqh/dev_suite/test_coverage)
6
7
  [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=patrick204nqh_dev_suite&metric=alert_status)](https://sonarcloud.io/summary/overall?id=patrick204nqh_dev_suite)
7
8
  [![Dependencies Status](https://badges.depfu.com/badges/84fefb47a5b99ea19afd20a2aae22e3e/overview.svg)](https://depfu.com/github/patrick204nqh/dev_suite?project_id=44065)
8
9
  [![Known Vulnerabilities](https://snyk.io/test/github/patrick204nqh/dev_suite/badge.svg)](https://snyk.io/test/github/patrick204nqh/dev_suite)
@@ -107,9 +108,19 @@ DevSuite also provides a command-line interface for various utilities. Below are
107
108
  DevSuite also provides a command-line interface for directory tree visualization. Use the following command to print the directory tree of the specified path:
108
109
 
109
110
  ```sh
110
- $ devsuite tree [PATH]
111
+ $ devsuite tree [PATH] [OPTIONS]
111
112
  ```
112
113
 
114
+ **CLI Options**:
115
+
116
+ Below is a table describing the available options for the `devsuite tree` command:
117
+
118
+ | Option | Description | Example Usage |
119
+ |-----------------|--------------------------------------------------|------------------------------------------------|
120
+ | `--depth`, `-d` | Limit the depth of the directory tree displayed. | `$ devsuite tree /path --depth 2` |
121
+ | `--skip-hidden` | Skip hidden files and directories. | `$ devsuite tree /path --skip-hidden` |
122
+ | `--skip-types` | Exclude files of specific types. | `$ devsuite tree /path --skip-types .log .tmp` |
123
+
113
124
  **Configuration Guide**:
114
125
  Customize the visualization by setting configuration options:
115
126
  ```ruby
data/dev_suite.gemspec CHANGED
@@ -29,7 +29,12 @@ Gem::Specification.new do |spec|
29
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
30
  spec.require_paths = ["lib"]
31
31
 
32
+ # Runtime dependencies
32
33
  spec.add_dependency("benchmark", "~> 0.1")
33
34
  spec.add_dependency("get_process_mem", "~> 1.0")
34
35
  spec.add_dependency("thor", "~> 1.1")
36
+
37
+ # Development dependencies
38
+ spec.add_development_dependency("rspec", "~> 3.9")
39
+ spec.add_development_dependency("simplecov", "~> 0.21")
35
40
  end
@@ -4,35 +4,7 @@ module DevSuite
4
4
  module CLI
5
5
  module Commands
6
6
  class Base < Thor
7
- no_commands do
8
- # Log message to console
9
- def log(message, level: :info)
10
- case level
11
- when :info
12
- puts "[INFO] #{message}"
13
- when :warn
14
- puts "[WARNING] #{message}"
15
- when :error
16
- puts "[ERROR] #{message}"
17
- when :debug
18
- puts "[DEBUG] #{message}" if ENV["DEBUG_MODE"]
19
- end
20
- end
21
-
22
- # Handle common errors
23
- def handle_error(error)
24
- log("Error: #{error.message}", level: :error)
25
- exit(1)
26
- end
27
-
28
- # Default method to load configuration
29
- def load_config(file)
30
- YAML.load_file(file)
31
- rescue Errno::ENOENT
32
- log("Configuration file not found: #{file}", level: :error)
33
- exit(1)
34
- end
35
- end
7
+ include ErrorHandler
36
8
 
37
9
  desc "execute", "Execute the command"
38
10
  def execute
@@ -5,14 +5,35 @@ module DevSuite
5
5
  module Commands
6
6
  class Tree < Base
7
7
  desc "visualize PATH", "Visualize the directory structure at given PATH"
8
- def execute(path)
9
- log("Starting visualization for: #{path}")
10
- begin
11
- # Assume visualize_path is a method that can raise exceptions
12
- DirectoryTree.visualize(path)
13
- log("Visualization complete.")
14
- rescue StandardError => e
15
- handle_error(e)
8
+ def execute(path, options: {})
9
+ Logger.log("Starting visualization for: #{path}", emoji: :start)
10
+
11
+ apply_configure(options)
12
+ visualize(path)
13
+
14
+ Logger.log("Visualization complete!", emoji: :success)
15
+ rescue StandardError => e
16
+ ErrorHandler.handle_error(e)
17
+ end
18
+
19
+ private
20
+
21
+ def visualize(path)
22
+ DirectoryTree.visualize(path)
23
+ end
24
+
25
+ def apply_configure(options)
26
+ option_config_mapping = {
27
+ depth: :max_depth,
28
+ skip_hidden: :skip_hidden,
29
+ skip_types: :skip_types,
30
+ }
31
+
32
+ DirectoryTree::Config.configure do |config|
33
+ option_config_mapping.each do |option_key, config_key|
34
+ value = options[option_key]
35
+ config.settings.set(config_key, value) if value
36
+ end
16
37
  end
17
38
  end
18
39
  end
@@ -5,7 +5,7 @@ module DevSuite
5
5
  module Commands
6
6
  class Version < Base
7
7
  def execute
8
- log("DevSuite version: #{DevSuite::VERSION}")
8
+ Logger.log("DevSuite version: #{DevSuite::VERSION} is live!", emoji: :start)
9
9
  end
10
10
  end
11
11
  end
@@ -4,8 +4,15 @@ module DevSuite
4
4
  module CLI
5
5
  class Main < Thor
6
6
  desc "tree DIRECTORY", "Prints the directory tree"
7
- def tree(directory)
8
- execute_command(Commands::Tree, directory)
7
+ method_option :depth, aliases: "-d", type: :numeric, desc: "Limit the depth of the directory tree displayed"
8
+ method_option :skip_hidden, type: :boolean, default: false, desc: "Skip hidden files and directories"
9
+ method_option :skip_types,
10
+ type: :array,
11
+ default: [],
12
+ banner: "TYPE1 TYPE2",
13
+ desc: "Exclude files of specific types"
14
+ def tree(path = ".")
15
+ execute_command(Commands::Tree, path, options: options)
9
16
  end
10
17
 
11
18
  desc "version", "Displays the version of the dev_suite gem"
@@ -15,14 +22,10 @@ module DevSuite
15
22
 
16
23
  private
17
24
 
18
- def execute_command(command_class, *args)
19
- command_class.new.execute(*args)
25
+ def execute_command(command_class, *args, **kargs)
26
+ command_class.new.execute(*args, **kargs)
20
27
  rescue StandardError => e
21
- handle_error(e)
22
- end
23
-
24
- def handle_error(error)
25
- puts "An error occurred: #{error.message}"
28
+ ErrorHandler.handle_error(e)
26
29
  end
27
30
  end
28
31
  end
@@ -5,13 +5,38 @@ module DevSuite
5
5
  class Config
6
6
  include Utils::ConfigTools::Configuration
7
7
 
8
- attr_reader :settings, :builder, :renderer
8
+ # Define configuration attributes
9
+ config_attr :settings, default_value: {}
10
+ config_attr :builder, default_value: :base
11
+ config_attr :renderer, default_value: :simple
12
+ config_attr :visualizer, default_value: :tree
9
13
 
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
14
+ private
15
+
16
+ def validate_attr!(attr, value)
17
+ case attr
18
+ when :settings
19
+ validate_hash!(attr, value)
20
+ when :builder, :renderer, :visualizer
21
+ validate_symbol!(attr, value)
22
+ else
23
+ raise ArgumentError, "Invalid attribute: #{attr}"
24
+ end
25
+ end
26
+
27
+ def resolve_attr(attr, value)
28
+ case attr
29
+ when :settings
30
+ Settings.new(value)
31
+ when :builder
32
+ Builder.create(value)
33
+ when :renderer
34
+ Renderer.create(value)
35
+ when :visualizer
36
+ Visualizer.create(value)
37
+ else
38
+ super # Return the value directly if no special resolution is needed
39
+ end
15
40
  end
16
41
  end
17
42
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module DirectoryTree
5
+ require "pathname"
6
+
7
+ require_relative "node"
8
+ require_relative "config"
9
+ require_relative "settings"
10
+ require_relative "renderer"
11
+ require_relative "builder"
12
+ require_relative "visualizer"
13
+
14
+ class << self
15
+ def visualize(path)
16
+ visualizer = Config.configuration.visualizer
17
+ visualizer.visualize(path)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -40,15 +40,15 @@ module DevSuite
40
40
  end
41
41
 
42
42
  def hidden_file_skipped?(node)
43
- settings.skip_hidden? && node.hidden?
43
+ settings.get(:skip_hidden) && node.hidden?
44
44
  end
45
45
 
46
46
  def filetype_skipped?(node)
47
- node.file? && settings.skip_types.include?(::File.extname(node.name))
47
+ node.file? && settings.get(:skip_types).include?(::File.extname(node.name))
48
48
  end
49
49
 
50
50
  def exceeds_max_depth?(depth)
51
- max_depth = settings.max_depth
51
+ max_depth = settings.get(:max_depth)
52
52
  max_depth && depth > max_depth
53
53
  end
54
54
 
@@ -10,20 +10,9 @@ module DevSuite
10
10
  skip_hidden: false,
11
11
  skip_types: [],
12
12
  max_depth: nil,
13
+ max_size: 100 * 1024 * 1024, # 100 MB
13
14
  }
14
15
  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
16
  end
28
17
  end
29
18
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module DirectoryTree
5
+ module Visualizer
6
+ class Base
7
+ def visualize(path)
8
+ raise NotImplementedError, "You must implement #{self.class}##{__method}"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module DirectoryTree
5
+ module Visualizer
6
+ class Tree < Base
7
+ # Visualizes the directory tree
8
+ # @param path [String] The base path of the directory
9
+ def visualize(path)
10
+ path = Pathname.new(path)
11
+ validate_path!(path)
12
+ validate_size!(path)
13
+
14
+ root = build_root_node(path)
15
+ output = render_output(root)
16
+
17
+ puts output
18
+ end
19
+
20
+ private
21
+
22
+ def validate_path!(path)
23
+ raise ArgumentError, "Invalid path" unless path.exist?
24
+ end
25
+
26
+ def validate_size!(path)
27
+ config = Config.configuration
28
+ max_size = config.settings.get(:max_size)
29
+ raise ArgumentError, "Directory too large to render" if directory_size(path) > max_size
30
+ end
31
+
32
+ def directory_size(path)
33
+ path.children.reduce(0) do |size, child|
34
+ size + (child.directory? ? directory_size(child) : child.size)
35
+ end
36
+ end
37
+
38
+ def build_root_node(path)
39
+ config = Config.configuration
40
+ config.builder.build(path)
41
+ end
42
+
43
+ def render_output(root)
44
+ config = Config.configuration
45
+ config.renderer.render(node: root)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -2,20 +2,21 @@
2
2
 
3
3
  module DevSuite
4
4
  module DirectoryTree
5
- class Visualizer
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)
12
- end
13
- end
5
+ module Visualizer
6
+ require "pathname"
7
+
8
+ require_relative "visualizer/base"
9
+ require_relative "visualizer/tree"
14
10
 
15
- class << self
16
- def visualize(path)
17
- visualizer = Visualizer.new
18
- visualizer.visualize(path)
11
+ class << self
12
+ def create(type)
13
+ case type
14
+ when :tree
15
+ Tree.new
16
+ else
17
+ raise ArgumentError, "Unknown renderer type: #{type}"
18
+ end
19
+ end
19
20
  end
20
21
  end
21
22
  end
@@ -2,13 +2,6 @@
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"
12
- require_relative "directory_tree/visualizer"
5
+ require_relative "directory_tree/directory_tree"
13
6
  end
14
7
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module Emoji
5
+ # A frozen hash that contains all the emojis used in the application.
6
+ EMOJIS = {
7
+ start: "🚀",
8
+ success: "✅",
9
+ error: "🚨❌",
10
+ retry: "💥",
11
+ info: "ℹ️",
12
+ warning: "⚠️",
13
+ note: "📝", # For notes or annotations
14
+ tip: "💡", # For tips or helpful hints
15
+ important: "❗", # For important information
16
+ caution: "⚠️", # For warnings or cautions
17
+ document: "📄", # For representing documents or files
18
+ code: "💻", # For code or technical content
19
+ update: "🔄", # For updates or changes
20
+ bug: "🐞", # For bugs or issues
21
+ fix: "🔧", # For fixes or repairs
22
+ }.freeze
23
+
24
+ class << self
25
+ # Returns the emoji corresponding to the given key.
26
+ # @param key [Symbol] the key to look up the emoji
27
+ # @return [String] the corresponding emoji or an empty string if not found
28
+ def get(key)
29
+ EMOJIS[key] || ""
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module ErrorHandler
5
+ extend self # This makes all instance methods behave like class methods
6
+
7
+ def handle_error(error)
8
+ Logger.log(
9
+ "Oops! An error occurred: #{error.message}",
10
+ level: :error,
11
+ emoji: :error,
12
+ )
13
+ Logger.log(
14
+ "For more information, please refer to the README: " \
15
+ "https://github.com/patrick204nqh/dev_suite",
16
+ level: :error,
17
+ emoji: :document,
18
+ )
19
+ # exit(1)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSuite
4
+ module Logger
5
+ LOG_DETAILS = {
6
+ info: { prefix: "[INFO]", color: :green },
7
+ warn: { prefix: "[WARNING]", color: :yellow },
8
+ error: { prefix: "[ERROR]", color: :red },
9
+ debug: { prefix: "[DEBUG]", color: :blue },
10
+ }.freeze
11
+
12
+ class << self
13
+ # Logs a message with an optional emoji and specified log level.
14
+ #
15
+ # @param message [String] The message to log.
16
+ # @param level [Symbol] The log level (:info, :warn, :error, :debug).
17
+ # @param emoji [String, Symbol] Optional emoji to prepend to the message.
18
+ def log(message, level: :info, emoji: nil)
19
+ emoji_icon = resolve_emoji(emoji)
20
+ formatted_message = format_message("#{emoji_icon} #{message}", level)
21
+ output_log(formatted_message)
22
+ end
23
+
24
+ private
25
+
26
+ # Resolves the emoji, either from a symbol or directly as a string.
27
+ #
28
+ # @param emoji [String, Symbol, nil] The emoji or its symbol key.
29
+ # @return [String] The resolved emoji or an empty string if none is provided.
30
+ def resolve_emoji(emoji)
31
+ return "" unless emoji
32
+
33
+ emoji.is_a?(Symbol) ? Emoji.get(emoji) : emoji
34
+ end
35
+
36
+ # Formats the log message with the appropriate prefix and color.
37
+ #
38
+ # @param message [String] The message to format.
39
+ # @param level [Symbol] The log level (:info, :warn, :error, :debug).
40
+ # @return [String] The formatted log message.
41
+ def format_message(message, level)
42
+ details = LOG_DETAILS[level]
43
+ raise ArgumentError, "Invalid log level: #{level}" unless details
44
+
45
+ Utils::Color.colorize("#{details[:prefix]} #{message}", color: details[:color])
46
+ end
47
+
48
+ # Outputs the formatted log message to the console.
49
+ #
50
+ # @param formatted_message [String] The message to output.
51
+ def output_log(formatted_message)
52
+ puts formatted_message if formatted_message
53
+ end
54
+ end
55
+ end
56
+ end
@@ -5,12 +5,32 @@ module DevSuite
5
5
  class Config
6
6
  include Utils::ConfigTools::Configuration
7
7
 
8
- attr_reader :profilers, :reportor
8
+ # Define configuration attributes
9
+ config_attr :profilers, default_value: [:execution_time, :memory]
10
+ config_attr :reportor, default_value: :simple
9
11
 
10
- def initialize(profilers: [:execution_time, :memory], reportor: :simple)
11
- @profilers = Profiler.create_multiple(profilers)
12
- @reportor = Reportor.create(reportor)
13
- freeze # Make the instance of this class immutable
12
+ private
13
+
14
+ def validate_attr!(attr, value)
15
+ case attr
16
+ when :profilers
17
+ validate_array!(attr, value)
18
+ when :reportor
19
+ validate_symbol!(attr, value)
20
+ else
21
+ raise ArgumentError, "Invalid attribute: #{attr}"
22
+ end
23
+ end
24
+
25
+ def resolve_attr(attr, value)
26
+ case attr
27
+ when :profilers
28
+ Profiler.create_multiple(value)
29
+ when :reportor
30
+ Reportor.create(value)
31
+ else
32
+ value
33
+ end
14
34
  end
15
35
  end
16
36
  end
@@ -8,31 +8,124 @@ module DevSuite
8
8
  class << self
9
9
  def included(base)
10
10
  base.extend(ClassMethods)
11
+ base.include(InstanceMethods)
11
12
  end
12
13
  end
13
14
 
14
15
  module ClassMethods
15
- #
16
- # Provide global access to a single instance of Config
17
- #
16
+ # Provides global access to a single instance of the configuration class
17
+ # @return [Object] The singleton configuration instance
18
18
  def configuration
19
19
  @configuration ||= new
20
20
  end
21
21
 
22
- #
23
- # Allow block-based configuration
24
- #
22
+ # Allows block-based configuration
23
+ # Example usage:
24
+ # ConfigClass.configure do |config|
25
+ # config.attr_name = value
26
+ # end
25
27
  def configure
26
28
  yield(configuration)
27
29
  rescue StandardError => e
28
- handle_configuration_error(e)
29
- raise
30
+ ErrorHandler.handle_error(e)
31
+ end
32
+
33
+ # Defines a configuration attribute with an optional default value
34
+ # This method automatically creates getter and setter methods for the attribute
35
+ #
36
+ # @param attr_name [Symbol] The name of the attribute
37
+ # @param default_value [Object] The default value for the attribute
38
+ def config_attr(attr_name, default_value: nil)
39
+ config_attrs[attr_name] = default_value
40
+
41
+ # Getter method for the attribute
42
+ define_method(attr_name) do
43
+ instance_variable_get("@#{attr_name}")
44
+ end
45
+
46
+ # Setter method for the attribute with validation and resolution
47
+ define_method("#{attr_name}=") do |value|
48
+ validate_attr!(attr_name, value)
49
+ instance_variable_set("@#{attr_name}", resolve_attr(attr_name, value))
50
+ end
30
51
  end
31
52
 
53
+ # Stores configuration attributes and their default values
54
+ # @return [Hash] A hash of attribute names and their default values
55
+ def config_attrs
56
+ @config_attrs ||= {}
57
+ end
58
+ end
59
+
60
+ # Module for instance-level methods
61
+ module InstanceMethods
32
62
  private
33
63
 
34
- def handle_configuration_error(error)
35
- puts "Configuration error: #{error.message}"
64
+ # Initializes configuration attributes with provided or default values
65
+ # This method is called automatically during object initialization
66
+ #
67
+ # @param options [Hash] A hash of attribute names and their values
68
+ def initialize(**options)
69
+ initialize_attributes(options)
70
+ end
71
+
72
+ # Sets up each attribute with either the provided value or the default value
73
+ #
74
+ # @param options [Hash] A hash of attribute names and their values
75
+ def initialize_attributes(options)
76
+ self.class.config_attrs.each do |attr_name, default_value|
77
+ value = options.fetch(attr_name, default_value)
78
+ send("#{attr_name}=", value)
79
+ end
80
+ end
81
+
82
+ # Validates an attribute's value based on its type
83
+ # Override this method in the including class to add custom validation logic
84
+ #
85
+ # @param attr [Symbol] The name of the attribute
86
+ # @param value [Object] The value to validate
87
+ def validate_attr!(attr, value)
88
+ raise ArgumentError, "Unknown attribute: #{attr}" unless self.class.config_attrs.key?(attr)
89
+ raise ArgumentError, "Invalid #{attr} value: #{value}" if value.nil?
90
+
91
+ # Override in including class to add custom validation logic
92
+ end
93
+
94
+ # Validates that an attribute's value is a Hash
95
+ #
96
+ # @param attr [Symbol] The name of the attribute
97
+ # @param value [Object] The value to validate
98
+ def validate_hash!(attr, value)
99
+ raise ArgumentError, "Invalid #{attr} value: expected a Hash" unless value.is_a?(Hash)
100
+ end
101
+
102
+ # Validates that an attribute's value is a Symbol
103
+ #
104
+ # @param attr [Symbol] The name of the attribute
105
+ # @param value [Object] The value to validate
106
+ def validate_symbol!(attr, value)
107
+ raise ArgumentError, "Invalid #{attr} value: expected a Symbol" unless value.is_a?(Symbol)
108
+ end
109
+
110
+ # Validates that an attribute's value is an Array
111
+ #
112
+ # @param attr [Symbol] The name of the attribute
113
+ # @param value [Object] The value to validate
114
+ def validate_array!(attr, value)
115
+ raise ArgumentError, "Invalid #{attr} value: expected an Array" unless value.is_a?(Array)
116
+ end
117
+
118
+ # Resolves the value of an attribute, especially if it requires
119
+ # converting a symbol to an object. Override in the including class.
120
+ #
121
+ # @param _attr [Symbol] The name of the attribute
122
+ # @param value [Object] The value to resolve
123
+ # @return [Object] The resolved value
124
+ def resolve_attr(attr, value)
125
+ raise ArgumentError, "Unknown attribute: #{attr}" unless self.class.config_attrs.key?(attr)
126
+
127
+ # Override in including class to resolve symbols to objects
128
+ value
36
129
  end
37
130
  end
38
131
  end
@@ -32,14 +32,6 @@ module DevSuite
32
32
  end
33
33
  end
34
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
35
  def reset!
44
36
  @settings = default_settings
45
37
  end
@@ -1,3 +1,3 @@
1
1
  module DevSuite
2
- VERSION = "0.2.3"
2
+ VERSION = "0.2.4"
3
3
  end
data/lib/dev_suite.rb CHANGED
@@ -2,11 +2,13 @@
2
2
 
3
3
  module DevSuite
4
4
  require_relative "dev_suite/version"
5
- require_relative "dev_suite/cli"
5
+ require_relative "dev_suite/emoji"
6
+ require_relative "dev_suite/logger"
7
+ require_relative "dev_suite/error_handler"
6
8
  require_relative "dev_suite/utils"
9
+ require_relative "dev_suite/cli"
7
10
  require_relative "dev_suite/performance"
8
11
  require_relative "dev_suite/directory_tree"
9
12
 
10
13
  class Error < StandardError; end
11
- # Your code goes here...
12
14
  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.2.3
4
+ version: 0.2.4
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-12 00:00:00.000000000 Z
11
+ date: 2024-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.9'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.9'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.21'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.21'
55
83
  description: This gem provides a suite of utilities for developers to enhance their
56
84
  productivity.
57
85
  email:
@@ -61,6 +89,7 @@ executables:
61
89
  extensions: []
62
90
  extra_rdoc_files: []
63
91
  files:
92
+ - ".github/workflows/ci.yml"
64
93
  - ".gitignore"
65
94
  - ".rspec"
66
95
  - ".rubocop.yml"
@@ -87,6 +116,7 @@ files:
87
116
  - lib/dev_suite/directory_tree/builder.rb
88
117
  - lib/dev_suite/directory_tree/builder/base.rb
89
118
  - lib/dev_suite/directory_tree/config.rb
119
+ - lib/dev_suite/directory_tree/directory_tree.rb
90
120
  - lib/dev_suite/directory_tree/node.rb
91
121
  - lib/dev_suite/directory_tree/node/base.rb
92
122
  - lib/dev_suite/directory_tree/node/directory.rb
@@ -97,6 +127,11 @@ files:
97
127
  - lib/dev_suite/directory_tree/renderer/simple.rb
98
128
  - lib/dev_suite/directory_tree/settings.rb
99
129
  - lib/dev_suite/directory_tree/visualizer.rb
130
+ - lib/dev_suite/directory_tree/visualizer/base.rb
131
+ - lib/dev_suite/directory_tree/visualizer/tree.rb
132
+ - lib/dev_suite/emoji.rb
133
+ - lib/dev_suite/error_handler.rb
134
+ - lib/dev_suite/logger.rb
100
135
  - lib/dev_suite/performance.rb
101
136
  - lib/dev_suite/performance/analyzer.rb
102
137
  - lib/dev_suite/performance/config.rb