dev_suite 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
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