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 +4 -4
- data/.github/workflows/ci.yml +37 -0
- data/Gemfile +11 -6
- data/Gemfile.lock +9 -1
- data/README.md +13 -2
- data/dev_suite.gemspec +5 -0
- data/lib/dev_suite/cli/commands/base.rb +1 -29
- data/lib/dev_suite/cli/commands/tree.rb +29 -8
- data/lib/dev_suite/cli/commands/version.rb +1 -1
- data/lib/dev_suite/cli/main.rb +12 -9
- data/lib/dev_suite/directory_tree/config.rb +31 -6
- data/lib/dev_suite/directory_tree/directory_tree.rb +21 -0
- data/lib/dev_suite/directory_tree/renderer/simple.rb +3 -3
- data/lib/dev_suite/directory_tree/settings.rb +1 -12
- data/lib/dev_suite/directory_tree/visualizer/base.rb +13 -0
- data/lib/dev_suite/directory_tree/visualizer/tree.rb +50 -0
- data/lib/dev_suite/directory_tree/visualizer.rb +14 -13
- data/lib/dev_suite/directory_tree.rb +1 -8
- data/lib/dev_suite/emoji.rb +33 -0
- data/lib/dev_suite/error_handler.rb +22 -0
- data/lib/dev_suite/logger.rb +56 -0
- data/lib/dev_suite/performance/config.rb +25 -5
- data/lib/dev_suite/utils/config_tools/configuration.rb +103 -10
- data/lib/dev_suite/utils/config_tools/settings.rb +0 -8
- data/lib/dev_suite/version.rb +1 -1
- data/lib/dev_suite.rb +4 -2
- metadata +37 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6765c4b9fa4637dafaac36da47cd8adf18652cd0d38804ddcd8641b851669f12
|
4
|
+
data.tar.gz: 3a3b27ad8b9fa4319829175995b1d6ea999e9877d537b1316b531247d6bd4b53
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
#
|
5
|
+
# Use the gemspec method to include dependencies specified in the gemspec file
|
6
6
|
gemspec
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
gem "
|
11
|
-
gem "
|
12
|
-
|
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.
|
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
|
-
[![
|
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
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
data/lib/dev_suite/cli/main.rb
CHANGED
@@ -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
|
-
|
8
|
-
|
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
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
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,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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
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
|
-
|
8
|
+
# Define configuration attributes
|
9
|
+
config_attr :profilers, default_value: [:execution_time, :memory]
|
10
|
+
config_attr :reportor, default_value: :simple
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
#
|
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
|
-
#
|
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
|
-
|
29
|
-
|
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
|
-
|
35
|
-
|
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
|
data/lib/dev_suite/version.rb
CHANGED
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/
|
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.
|
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-
|
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
|