utils 0.68.0 → 0.69.0

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +251 -18
  3. data/bin/ascii7 +28 -0
  4. data/bin/blameline +17 -0
  5. data/bin/changes +69 -5
  6. data/bin/classify +128 -7
  7. data/bin/code_comment +102 -104
  8. data/bin/commit_message +26 -2
  9. data/bin/create_cstags +18 -0
  10. data/bin/create_tags +10 -0
  11. data/bin/discover +38 -1
  12. data/bin/edit +14 -1
  13. data/bin/edit_wait +14 -0
  14. data/bin/enum +139 -15
  15. data/bin/git-empty +50 -0
  16. data/bin/git-versions +20 -0
  17. data/bin/json_check +15 -1
  18. data/bin/long_lines +11 -2
  19. data/bin/myex +38 -0
  20. data/bin/on_change +22 -0
  21. data/bin/path +21 -0
  22. data/bin/print_method +29 -1
  23. data/bin/probe +52 -4
  24. data/bin/rainbow +52 -0
  25. data/bin/rd2md +15 -0
  26. data/bin/search +83 -1
  27. data/bin/sedit +6 -0
  28. data/bin/serve +18 -3
  29. data/bin/ssh-tunnel +14 -2
  30. data/bin/strip_spaces +17 -9
  31. data/bin/sync_dir +48 -1
  32. data/bin/untest +19 -1
  33. data/bin/utils-utilsrc +42 -6
  34. data/bin/vcf2alias +33 -0
  35. data/bin/yaml_check +24 -2
  36. data/lib/utils/config_dir.rb +127 -0
  37. data/lib/utils/config_file.rb +445 -1
  38. data/lib/utils/editor.rb +215 -3
  39. data/lib/utils/finder.rb +127 -16
  40. data/lib/utils/grepper.rb +90 -1
  41. data/lib/utils/irb.rb +387 -39
  42. data/lib/utils/line_blamer.rb +28 -0
  43. data/lib/utils/line_formatter.rb +198 -0
  44. data/lib/utils/md5.rb +14 -0
  45. data/lib/utils/patterns.rb +77 -3
  46. data/lib/utils/probe_server.rb +302 -23
  47. data/lib/utils/ssh_tunnel_specification.rb +58 -0
  48. data/lib/utils/version.rb +1 -1
  49. data/lib/utils/xt/source_location_extension.rb +18 -6
  50. data/lib/utils.rb +3 -1
  51. data/tests/utils_test.rb +7 -1
  52. data/utils.gemspec +5 -5
  53. metadata +4 -6
  54. data/bin/number_files +0 -26
  55. data/lib/utils/xdg_config.rb +0 -10
  56. /data/{COPYING → LICENSE} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9614b9a971f130099440edb6a8a73621898e9e7a4ce8d97c79350fef531db772
4
- data.tar.gz: 8cb380f6c71ac83d9dfa4e6a7a4d1423db5191f7ee73b1e3460c44bf030b778c
3
+ metadata.gz: 85f412311ef245615fb822299605146a2b1fe3c6a678b7c4826bfda8c7f80e78
4
+ data.tar.gz: 0af45f306f2115ccb6b2a508d7d206a19d8433305d88e9d4b36da3d362edbae3
5
5
  SHA512:
6
- metadata.gz: ce20e8f6e063c20a46d49ddffa09c42a4bc79f1bdec21c3e384d94a4bceaf097119737fafa7fde02a295412e80622e6c17f8161a0258d64697a4d9f377c73189
7
- data.tar.gz: f68fbe751a246b259ebedba01efad3e6cb0c729e5f75cb80fa93a1e758c1df20d00ab3275b414b90ca236d5cff5a1ef3a9f8676a0bc1b29c5855b362e861d3ab
6
+ metadata.gz: 5b72e6f84ed6945c7dcc29ce430385c29fe5f91ff27a5ddeff394e09a0c43324845677a775311cd67059507918a3080699b78d9c1828c132d439a4055103881e
7
+ data.tar.gz: 26f68d486605ae78883a3dd6589517e80351f186efb17e4be12946b18d2fbdbd870276f89ee68e08f8eb1f21ff0958cc7ff7b100ab709ae7a128ac475ca0208a
data/README.md CHANGED
@@ -1,27 +1,260 @@
1
- # Utils - Some useful command line utilities
1
+ # 📦 Utils - Developer Productivity Command-Line Utilities
2
2
 
3
- ## Description
3
+ ## 📝 Description
4
4
 
5
- This ruby gem provides some useful command line utilities.
5
+ This Ruby gem delivers a curated collection of command-line utilities designed
6
+ to streamline software development workflows and automate repetitive tasks. The
7
+ toolkit spans multiple domains including code analysis, testing automation,
8
+ file manipulation, and system administration.
6
9
 
7
- ## Author
10
+ ### Key Features
8
11
 
9
- Florian Frank <mailto:flori@ping.de>
12
+ - **Ruby-Centric Approach**: Built leveraging Ruby's expressive syntax,
13
+ metaprogramming capabilities, and dynamic nature
14
+ - **Multi-Functional Tools**: From simple CLI interfaces to sophisticated
15
+ automation workflows
16
+ - **Modern Integration**: Seamlessly integrates with popular development
17
+ frameworks, external services (including LLMs via Ollama), and system tools
18
+ - **Modular Architecture**: Lightweight design allowing selective tool usage
19
+ without heavy dependencies
20
+ - **Composability**: Tools designed to work together or independently
10
21
 
11
- ## License
22
+ ### Technical Approach
12
23
 
13
- This is free software; you can redistribute it and/or modify it under the
14
- terms of the GNU General Public License Version 2 as published by the Free
15
- Software Foundation: www.gnu.org/copyleft/gpl.html
24
+ The utilities embrace Ruby's strengths through:
25
+ - Dynamic method dispatch and metaprogramming techniques
26
+ - Expressive DSLs for configuration and tool definition
27
+ - Seamless integration with Git, vim, SSH, and terminal multiplexers
28
+ - Performance-conscious design with pattern matching for pruning operations
16
29
 
17
- ## TODO
30
+ ## 🛠️ Installation
18
31
 
19
- - add script to fetch ci spec failures and create an error list
20
- - improve backup mechanism for new configuration, interactivity?
32
+ Add this gem to your Gemfile:
21
33
 
22
- _CHECK_
23
- - When finding many places in the same file only jump to the first occurence if
24
- a cli option is given.
25
- - Make it configurable to find the same file many times via different symlinks
26
- or to find it only once.
27
- - Stop finder from going in infinite symlink circles
34
+ ```ruby
35
+ gem 'utils'
36
+ ```
37
+
38
+ And install it using Bundler:
39
+
40
+ ```bash
41
+ bundle install
42
+ ```
43
+
44
+ Or install the gem directly:
45
+
46
+ ```bash
47
+ gem install utils
48
+ ```
49
+
50
+ ## 🧰 Utilities
51
+
52
+ ### 🔍 Searching
53
+
54
+ - **`blameline`** - Show git blame line for a file and line number
55
+ - **`create_cstags`** - Create cscope tags file for current directory
56
+ - **`create_tags`** - Create ctags tags file for current directory
57
+ - **`discover`** - Find files with specific content patterns
58
+ - **`git-versions`** - Show git versions of files and directories
59
+ - **`long_lines`** - Finds long lines with author attribution
60
+ - **`search`** - Search for text in files recursively
61
+
62
+ ### ✍️ Editing
63
+
64
+ - **`classify`** - Classify files by type using file command
65
+ - **`edit_wait`** - Edit a file and wait for changes to be saved
66
+ - **`edit`** - Edit a file using default editor
67
+ - **`print_method`** - Extracts complete method definitions from Ruby source
68
+ files
69
+ - **`sedit`** - Edit a file with sed commands
70
+ - **`strip_spaces`** - Removes trailing whitespace with tab conversion options
71
+ - **`sync_dir`** - Sync directories with rsync
72
+ - **`untest`** - Remove test files from current directory
73
+
74
+ ### 🧪 Testing
75
+
76
+ - **`json_check`** - Validate JSON syntax in files
77
+ - **`on_change`** - Monitors files for changes and executes commands
78
+ - **`probe`** - Test runner supporting RSpec, Test::Unit, Cucumber with
79
+ server/client functionality
80
+ - **`yaml_check`** - Validate YAML syntax in files
81
+
82
+ ### 📚 Documenting
83
+
84
+ - **`changes`** - Generate changelogs using Git history and LLM summaries
85
+ - **`code_comment`** - Generates YARD documentation using LLM assistance
86
+ - **`commit_message`** - Generate commit messages via LLM from git diff
87
+ - **`rd2md`** - Convert RDoc to Markdown
88
+
89
+ ### ⚙️ Configuring
90
+
91
+ - **`git-empty`** - Create empty git repository with default files
92
+ - **`myex`** - Processes MySQL dump files (list, create, truncate, insert,
93
+ search)
94
+ - **`path`** - Show or modify PATH environment variable
95
+ - **`utils-utilsrc`** - Manages `~/.utilsrc` configuration file with
96
+ show/diff/edit capabilities
97
+ - **`vcf2alias`** - Converts VCard contacts to Mutt email aliases
98
+
99
+ ### 🌐 Networking
100
+
101
+ - **`serve`** - Simple HTTP server launcher
102
+ - **`ssh-tunnel`** - Create SSH tunnel to remote host
103
+
104
+ ### 🎨 Slacking
105
+
106
+ - **`ascii7`** - Generate ASCII art from text
107
+ - **`enum`** - Enumerate files and directories with line counts
108
+ - **`rainbow`** - Display rainbow-colored banner text
109
+
110
+ ## ⚙️ Configuration
111
+
112
+ The `~/.utilsrc` configuration file uses Ruby syntax to define settings for
113
+ various utility components. This file allows you to customize the behavior of
114
+ different utilities without modifying their source code.
115
+
116
+ Each configuration block corresponds to a specific utility or category of
117
+ utilities. The settings within each block control how those utilities behave
118
+ during execution. The configuration system supports:
119
+
120
+ - **Pattern matching**: Regular expressions for including/excluding files and
121
+ directories
122
+ - **Performance optimization**: Caching mechanisms and pruning rules to avoid
123
+ unnecessary processing
124
+ - **Integration capabilities**: Settings for connecting with external tools
125
+ like SSH, vim, and terminal multiplexers
126
+ - **Environment customization**: Ability to set environment variables and
127
+ default paths
128
+
129
+ The configuration is loaded at runtime and can be modified without requiring a
130
+ restart of the utilities. Changes take effect immediately for subsequent
131
+ operations.
132
+
133
+ ⚠️ **Important Note**: Since this is Ruby syntax, you have access to full Ruby
134
+ capabilities within the configuration blocks. You can use variables, methods,
135
+ conditional logic, and other Ruby features to create dynamic configurations
136
+ when needed.
137
+
138
+ ```ruby
139
+ # vim: set ft=ruby:
140
+
141
+ # ~/.utilsrc - Utility configuration file
142
+ # This file contains configuration settings for various utility components
143
+
144
+ ## Search Configuration
145
+ search do
146
+ # Directories to prune during search operations
147
+ # These are excluded from the search scope to improve performance
148
+ prune_dirs /\A(\.svn|\.git|\.terraform|CVS|tmp|coverage|corpus|pkg|\.yardoc)\z/
149
+
150
+ # Files to skip during search operations
151
+ # Excludes temporary files, log files, and system files
152
+ skip_files /(\A\.|\.sw[pon]\z|\.(log|fnm|jpg|jpeg|png|pdf|svg)\z|\Atags\z|~\z)/i
153
+ end
154
+
155
+ ## Discovery Configuration
156
+ discover do
157
+ # Directories to prune during discovery operations
158
+ # Excludes version control systems, temporary directories, and build artifacts
159
+ prune_dirs /\A(\.svn|\.git|\.terraform|\.yardoc|CVS|tmp|coverage|corpus|pkg|\.yardoc)\z/
160
+
161
+ # Files to skip during discovery operations
162
+ # Excludes hidden files, swap files, and log files
163
+ skip_files /(\A\.|\.sw[pon]\z|\.log\z|~\z)/
164
+
165
+ # Cache index expiration time in seconds (1 hour = 3600 seconds)
166
+ index_expire_after 3_600
167
+
168
+ # Maximum number of matches to return (0 = no limit)
169
+ # Prevents overwhelming output when many files match the search criteria
170
+ max_matches 10
171
+ end
172
+
173
+ ## Space Stripping Configuration
174
+ strip_spaces do
175
+ # Directories to prune during space stripping operations
176
+ # Excludes hidden directories and system directories
177
+ prune_dirs /\A(\..*|CVS|pkg|\.yardoc)\z/
178
+
179
+ # Files to skip during space stripping operations
180
+ # Excludes hidden files, swap files, and log files
181
+ skip_files /(\A\.|\.sw[pon]\z|\.log\z|~\z)/
182
+ end
183
+
184
+ ## Probe Configuration
185
+ probe do
186
+ # Test framework to use for probing
187
+ test_framework :'test-unit'
188
+
189
+ # Directories to include in probe operations
190
+ # Specifies where to look for test files and source code
191
+ include_dirs %w[lib test tests ext spec]
192
+ end
193
+
194
+ ## SSH Tunnel Configuration
195
+ ssh_tunnel do
196
+ # Terminal multiplexer to use (supports :tmux or other terminal managers)
197
+ terminal_multiplexer :tmux
198
+
199
+ # Login session path for SSH connections
200
+ login_session "/home/#{ENV['USER']}"
201
+
202
+ # Environment variables to set for the tunnel
203
+ env(
204
+ FOO: 'test' # Example environment variable - adjust as needed
205
+ )
206
+
207
+ # Enable or disable copy/paste functionality
208
+ copy_paste true do
209
+ # Bind address for the tunnel
210
+ bind_address 'localhost'
211
+
212
+ # Port number for the tunnel
213
+ port 6166
214
+
215
+ # Host for the tunnel
216
+ host 'localhost'
217
+
218
+ # Host port for the tunnel
219
+ host_port 6166
220
+ end
221
+ end
222
+
223
+ ## Classification Configuration
224
+ classify do
225
+ # Default path shifting value (1 = shift by one directory level)
226
+ shift_path_by_default 1
227
+
228
+ # Path prefixes to check in order for classification
229
+ # Used to determine how paths should be shifted or categorized
230
+ shift_path_for_prefix [ # prefixes checked in order
231
+ 'a/b',
232
+ 'c/d/e',
233
+ ]
234
+ end
235
+
236
+ ## Sync Directory Configuration
237
+ sync_dir do
238
+ # Paths to skip during sync operations
239
+ # Uses regex pattern to exclude certain directory patterns
240
+ skip_path %r((\A|/)\.\w)
241
+ end
242
+
243
+ ## Edit Configuration
244
+ edit do
245
+ # Path to vim executable
246
+ # Uses shell command to find vim in PATH
247
+ vim_path `which vim`.chomp
248
+
249
+ # Default arguments for vim (nil = no default args)
250
+ vim_default_args nil
251
+ end
252
+ ```
253
+
254
+ ## 👨‍💻 Author
255
+
256
+ [Florian Frank](mailto:flori@ping.de)
257
+
258
+ ## 📄 License
259
+
260
+ GPLv2 [LICENSE](./LICENSE)
data/bin/ascii7 CHANGED
@@ -1,4 +1,32 @@
1
1
  #!/usr/bin/env ruby
2
+ #
3
+ # This script generates a visual representation of how 7-bit ASCII characters #
4
+ # are interpreted when the upper 2 bits (prefix) are varied while keeping the
5
+ # lower 5 bits constant. It demonstrates the relationship between binary
6
+ # patterns and character representations in classic ASCII encoding.
7
+ #
8
+ # The output shows:
9
+ # - First column: Lower 5 bits of ASCII values (0-31 in binary)
10
+ # - Remaining columns: Character names for each prefix combination (00, 01, 10, 11)
11
+ # where prefix + lower_bits = full 7-bit ASCII value
12
+ #
13
+ # This reveals how early computer systems treated the same bit patterns differently
14
+ # depending on context or system interpretation, and illustrates the evolution
15
+ # from control characters to printable ASCII ranges.
16
+ #
17
+ # The script uses bit manipulation: (prefix << 5) | lower_bits
18
+ # to generate all 32 combinations of the lower 5 bits with 4 possible prefixes.
19
+ #
20
+ # This demonstrates fundamental concepts in computer science:
21
+ # - Bit-level character encoding
22
+ # - Historical ASCII design principles
23
+ # - Binary representation and manipulation
24
+ # - Control character vs printable character distinctions
25
+ #
26
+ # References:
27
+ # - Original 7-bit ASCII standard
28
+ # - Early computer system character set conventions
29
+ # - Bit manipulation in low-level programming
2
30
 
3
31
  map = Hash.new { |h, k| h[k] = k }.merge(
4
32
  " " => "Spc",
data/bin/blameline CHANGED
@@ -1,4 +1,21 @@
1
1
  #!/usr/bin/env ruby
2
+ #
3
+ # Line blamer - Show Git blame information for lines or files
4
+ #
5
+ # Usage: blameline [OPTIONS] [LINES|FILES]
6
+ #
7
+ # Displays Git blame information for specified lines or files.
8
+ #
9
+ # Options:
10
+ # -s Read lines from stdin instead of command-line arguments
11
+ # -h Show this help message
12
+ #
13
+ # Examples:
14
+ # blameline file.rb:23 # Blame all lines in file
15
+ # blameline -s < lines.txt # Blame lines from stdin
16
+ # echo some/code:23 | blameline -s # Blame single line from stdin
17
+ #
18
+ # Shows author, commit hash, and date for each line of code.
2
19
 
3
20
  require 'tins/go'
4
21
  include Tins::GO
data/bin/changes CHANGED
@@ -1,17 +1,62 @@
1
1
  #!/usr/bin/env ruby
2
+ #
3
+ # Generate changelogs using Git history and LLM summaries
4
+ #
5
+ # Usage:
6
+ # changes pending # Show changes since last version
7
+ # changes current # Show changes between two latest versions
8
+ # changes range v1.0.0..v1.2.0 # Show changes in a specific range
9
+ # changes full # Generate full changelog from first tag
10
+ # changes add CHANGELOG.md # Append new entries to existing file
11
+ #
12
+ # Requires:
13
+ # - Git repository with version tags (vX.Y.Z format)
14
+ # - Ollama server running locally or accessible via OLLAMA_URL / OLLAMA_HOST
15
+ # - Configuration files in ~/.config/changes/
16
+ # - system.txt: System prompt for LLM
17
+ # - prompt.txt: Template for changelog generation
18
+ # - client.json: Ollama client settings
19
+ # - options.json: Generation options (temperature, etc.)
20
+ #
21
+ # Environment variables:
22
+ # OLLAMA_URL: Base URL of Ollama server OR
23
+ # OLLAMA_HOST: Host of Ollama server
24
+ # OLLAMA_MODEL: Model to use (default: llama3.1)
25
+ # XDG_CONFIG_HOME: Custom config directory location
26
+ # DEBUG: Set to 1 for verbose output
2
27
 
3
28
  require 'ollama'
4
29
  include Ollama
5
- require 'tins/xt'
6
30
  require 'utils'
7
- include Utils::XDGConfig
8
31
 
32
+ # Executes a shell command and returns its output.
33
+ #
34
+ # This method runs the provided command in a shell environment and captures its
35
+ # standard output. If the command fails (returns a non-zero exit status), it
36
+ # raises an exception with details about the failure.
37
+ #
38
+ # @param cmd [ String ] the shell command to be executed
39
+ #
40
+ # @return [ String ] the standard output of the executed command
41
+ #
42
+ # @raise [ RuntimeError ] if the executed command returns a non-zero exit status
9
43
  def x(cmd)
10
44
  output = `#{cmd}`
11
45
  $?.success? or fail "failed to execute #{cmd.inspect}"
12
46
  output
13
47
  end
14
48
 
49
+ # Finds the highest version tag from a CHANGES file by parsing version strings
50
+ # in YYYY-MM-DD vMAJOR.MINOR.PATCH format.
51
+ #
52
+ # This method reads through the specified file line by line, extracting version
53
+ # tags that match the pattern "## YYYY-MM-DD vMAJOR.MINOR.PATCH" and determines
54
+ # the highest version number among them.
55
+ #
56
+ # @param filename [ String ] the path to the file containing version tags
57
+ #
58
+ # @return [ String, nil ] the highest version string found in the file, or nil
59
+ # if no valid version tags are present
15
60
  def find_highest_version_tag(filename)
16
61
  File.open(filename, ?r) do |input|
17
62
  tags = []
@@ -24,6 +69,17 @@ def find_highest_version_tag(filename)
24
69
  end
25
70
  end
26
71
 
72
+ # The compute_change method generates a changelog entry by processing Git log
73
+ # information and using an LLM to create a formatted summary.
74
+ #
75
+ # This method takes two range parameters, computes the Git log between them,
76
+ # retrieves the commit date, and then uses an LLM to generate a human-readable
77
+ # changelog entry based on configuration files and prompt templates.
78
+ #
79
+ # @param range_from [ Object ] the starting point of the Git log range
80
+ # @param range_to [ Object ] the ending point of the Git log range
81
+ #
82
+ # @return [ String ] a formatted changelog entry including the date and LLM-generated content
27
83
  def compute_change(range_from, range_to)
28
84
  range_from = range_from.to_s.sub(/\Av?/, ?v)
29
85
  if range_to.to_s == 'HEAD'
@@ -45,7 +101,7 @@ def compute_change(range_from, range_to)
45
101
  EOT
46
102
  end
47
103
 
48
- config = xdg_config('changes')
104
+ config = Utils::ConfigDir.new('changes', env_var: 'XDG_CONFIG_HOME')
49
105
 
50
106
  base_url = ENV['OLLAMA_URL'] || 'http://%s' % ENV.fetch('OLLAMA_HOST')
51
107
  model = ENV.fetch('OLLAMA_MODEL', 'llama3.1')
@@ -156,7 +212,15 @@ when 'full', 'add'
156
212
  end
157
213
  end
158
214
  else
159
- puts <<~end
215
+ puts <<~EOT
160
216
  Usage: #{File.basename($0)} help|range|full|add|pending
161
- end
217
+
218
+ Commands:
219
+ pending Show changes since last version tag
220
+ current Show changes between two latest version tags
221
+ range <range> Show changes for a specific Git range (e.g., v1.0.0..v1.2.0)
222
+ full Generate complete changelog from first tag
223
+ add <file> Append new entries to existing changelog file
224
+
225
+ EOT
162
226
  end
data/bin/classify CHANGED
@@ -1,11 +1,35 @@
1
1
  #!/usr/bin/env ruby
2
+ #
3
+ # Ruby module name to file path converter
4
+ #
5
+ # This tool helps map between Ruby module naming conventions and filesystem
6
+ # paths, which is essential for Ruby development, code generation, and
7
+ # refactoring. It converts between Foo::BarBaz (module names) and foo/bar_baz
8
+ # (file paths) while supporting various formatting options and project-specific
9
+ # path shifting.
10
+ #
11
+ # Common use cases:
12
+ # - Converting controller names to file paths in Rails
13
+ # - Refactoring code by mapping between naming conventions
14
+ # - Can be used in editor functions for easy access
15
+ #
16
+ # Run 'classify -h' for detailed help and examples
2
17
 
3
18
  require 'utils'
4
- require 'tins/go'
5
19
  include Tins::GO
6
- require 'tins/xt/string'
7
20
  require 'term/ansicolor'
8
21
 
22
+ # The path_shifter method processes a string path by splitting it using the
23
+ # specified separator and then either removing the first n elements or taking a
24
+ # slice from the end, depending on whether n is positive or negative.
25
+ #
26
+ # @param string [ String ] the path string to be processed
27
+ # @param separator [ String ] the character used to split the path string,
28
+ # defaults to '/'
29
+ # @param n [ Integer, nil ] the number of elements to remove from the beginning
30
+ # of the path if positive, or take from the end if negative
31
+ #
32
+ # @return [ String ] the resulting path string after processing
9
33
  def path_shifter(string, separator: ?/, n: nil)
10
34
  n or return string
11
35
  n, path = n.to_i, string.split(separator)
@@ -17,6 +41,15 @@ def path_shifter(string, separator: ?/, n: nil)
17
41
  path * separator
18
42
  end
19
43
 
44
+ # The underscore method converts a string to underscored format.
45
+ #
46
+ # This method processes a string by first applying path shifting based on
47
+ # options, then applies the standard underscore transformation.
48
+ # It optionally appends '.rb' to the result if specified in the options.
49
+ #
50
+ # @param string [ String ] the input string to be converted
51
+ #
52
+ # @return [ String ] the underscored version of the input string
20
53
  def underscore(string)
21
54
  string = path_shifter(string, n: $opts[?n], separator: '::')
22
55
  string = Tins::StringUnderscore.instance_method(:underscore).bind(string).()
@@ -24,31 +57,89 @@ def underscore(string)
24
57
  string
25
58
  end
26
59
 
60
+ # The parameterize method converts a string into a URL-friendly format by
61
+ # replacing spaces and special characters with a specified separator.
62
+ #
63
+ # This method takes an input string and transforms it into a lowercase,
64
+ # underscore-separated format suitable for use in URLs or file names. It
65
+ # handles forward slashes by replacing them with the specified separator
66
+ # character.
67
+ #
68
+ # @param string [ String ] the input string to be parameterized
69
+ # @param separator [ String ] the character to replace forward slashes with
70
+ #
71
+ # @return [ String ] the parameterized string with forward slashes replaced by
72
+ # the specified separator
27
73
  def parameterize(string, separator)
28
74
  underscore(string).gsub(?/, separator) # quick and dirty
29
75
  end
30
76
 
77
+ # The camelize method converts a string into camelCase format by processing...
78
+ # It removes the file extension first, then applies camelization to the
79
+ # remaining string.
80
+ #
81
+ # @param string [ String ] the input string to be converted
82
+ #
83
+ # @return [ String ] the camelized string result
31
84
  def camelize(string)
32
85
  string = path_shifter(string, n: $opts[?n])
33
86
  string = string.gsub(/#{Regexp.quote(File.extname(string))}\Z/, '')
34
87
  string.camelize
35
88
  end
36
89
 
90
+ # The camelcase? method checks whether a string starts with an uppercase
91
+ # letter.
92
+ #
93
+ # This method determines if the provided string begins with a capital letter,
94
+ # returning true if it does and false otherwise.
95
+ #
96
+ # @param string [ String ] the string to be checked for camelCase format
97
+ #
98
+ # @return [ TrueClass, FalseClass ] true if the string starts with an uppercase
99
+ # letter, false otherwise
37
100
  def camelcase?(string)
38
- string[0, 1] =~ /[A-Z]/
101
+ string =~ /\A[A-Z]/
39
102
  end
40
103
 
104
+ # The compute_shift method determines the shift value for a string based on
105
+ # configuration settings.
106
+ #
107
+ # This method processes a string by converting it to underscore format and then
108
+ # checks against configured shift path prefixes to determine an appropriate
109
+ # shift value.
110
+ # If a matching prefix is found, it returns the count of forward slashes in the
111
+ # prefix plus one. Otherwise, it returns the default shift path value from the
112
+ # configuration.
113
+ #
114
+ # @param config [ Object ] the configuration object containing classify
115
+ # settings
116
+ # @param string [ String ] the input string to process and determine shift
117
+ # value for
118
+ #
119
+ # @return [ Integer ] the calculated shift value based on prefix matching or
120
+ # default setting
41
121
  def compute_shift(config, string)
42
- string = underscore(string)
43
- result = config.classify.shift_path_by_default
122
+ string = underscore(string)
123
+ default = config.classify.shift_path_by_default
44
124
  for prefix in config.classify.shift_path_for_prefix
45
125
  if string.start_with? prefix
46
126
  return prefix.count(?/) + 1
47
127
  end
48
128
  end
49
- result
129
+ default
50
130
  end
51
131
 
132
+ # The usage method displays the command-line interface help text and exits the
133
+ # program.
134
+ #
135
+ # This method prints a formatted usage message that describes the available
136
+ # options for the command-line tool, including descriptions of each flag and
137
+ # their functionality.
138
+ # It provides information about how to classify and declassify path names into
139
+ # module namespaces, along with various toggle and formatting options.
140
+ #
141
+ # This method always exits the program with status code 0 after displaying
142
+ # help.
52
143
  def usage
53
144
  puts <<~EOT
54
145
  Usage: #{File.basename($0)} [OPTS]
@@ -65,6 +156,32 @@ def usage
65
156
  -p SEPARATOR used for declassification
66
157
  -h display this help
67
158
 
159
+ Examples:
160
+
161
+ classify Foo::BarBaz ⇢ Foo::BarBaz
162
+ classify -d Foo::Bar ⇢ foo/bar
163
+ classify -d foo/bar_baz ⇢ foo/bar_baz
164
+ classify foo/bar ⇢ Foo::Bar
165
+ classify -b Foo::BarBaz ⇢ BarBaz
166
+ classify -d -s Foo::Bar ⇢ foo/bar.rb
167
+ classify -t Foo::Bar ⇢ foo/bar
168
+ classify -t foo/bar ⇢ Foo::Bar
169
+ classify -p . -d Foo::Bar::Baz ⇢ foo.bar.baz
170
+ classify -p : -d Foo::Bar::Baz ⇢ foo:bar:baz
171
+ classify -n 1 lib/foo/bar ⇢ Foo::Bar
172
+
173
+ With this configuration in .utilsrc:
174
+ classify do
175
+ shift_path_by_default 1 # if no prefix matched
176
+ shift_path_for_prefix [ # prefixes checked in order
177
+ 'a/b',
178
+ 'c/d/e',
179
+ ]
180
+ end
181
+
182
+ classify lib/foo/bar ⇢ Foo::Bar
183
+ classify a/b/foo/bar ⇢ Foo::Bar
184
+ classify c/d/e/foo/bar ⇢ Foo::Bar
68
185
  EOT
69
186
  exit 0
70
187
  end
@@ -103,6 +220,10 @@ print(
103
220
  underscore string
104
221
  end
105
222
  else
106
- camelize string
223
+ if camelcase?(string)
224
+ path_shifter(string, separator: '::', n: $opts[?n])
225
+ else
226
+ camelize string
227
+ end
107
228
  end
108
229
  )