markdown_exec 2.0.4 → 2.0.6

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: eadeecd7019d53202aabe57d9486ee616826e6b5f42fce0fa24f8e377c1b50e5
4
- data.tar.gz: cde007bddd4821263045eeba415cc1e2f42591d03294fc678c4093384373146b
3
+ metadata.gz: d1b2a98d8279b5a5705ba3dc3221d46f55387c0d834ec4283e93ac54f5929835
4
+ data.tar.gz: 440070d30a4650c0bb8b9a8b472d91d0bcb4357d18f5330194b10d1c5d6a764d
5
5
  SHA512:
6
- metadata.gz: 5a4a3a36d420c41403be33dbc7ac8e53f446dac53ba3ce8e9cd2fafb1ff0c1026aa1df633f6d79e1742ea11a07f71bd3f64df95f772798ff4624b8c36a8f93b2
7
- data.tar.gz: 1acc6cb2bf716b30a1ab8037ad0e43ff3646b23b991cd1bd9d31b1aad37ccf6ae97bd01eaeecc57e644ceb580a9aa9bf61742075777a528ffc180a43a955ccb1
6
+ metadata.gz: 32702e459d5eeac152583bd7dd8c5de3f6049b0fa8b2c389441f45afadc132678dabbb6898336297d09fa5411ae44963cd0b2353a69f9dc319eb9b302d4ec2db
7
+ data.tar.gz: a2ea933810ec3e90ed1cc62eccc9a2e8c94ee5dee1ed8c267b8750a97c67fb4a44bbcf8eb471137a65618b991966692d05684b3f69a97e5911dad3a777a15c60
data/.rubocop.yml CHANGED
@@ -13,10 +13,8 @@ Layout/LeadingCommentSpace:
13
13
  Layout/LineContinuationLeadingSpace:
14
14
  Enabled: false
15
15
 
16
- Layout/LineLength: # 2024-01-21 temp disable
17
- Enabled: false
16
+ Layout/LineLength:
18
17
  Max: 96
19
- Max: 120
20
18
 
21
19
  Lint/Debugger:
22
20
  Enabled: false
@@ -24,6 +22,9 @@ Lint/Debugger:
24
22
  Lint/SafeNavigationChain:
25
23
  Enabled: false
26
24
 
25
+ Lint/UnusedMethodArgument:
26
+ Enabled: false
27
+
27
28
  Metrics/AbcSize:
28
29
  Enabled: false
29
30
 
@@ -54,13 +55,16 @@ Minitest/MultipleAssertions:
54
55
  Naming/RescuedExceptionsVariableName:
55
56
  PreferredName: err
56
57
 
58
+ Security/Eval:
59
+ Enabled: false
60
+
57
61
  Security/YAMLLoad:
58
62
  Enabled: false
59
63
 
60
- Style/CommentedKeyword:
64
+ Style/ClassVars:
61
65
  Enabled: false
62
66
 
63
- Style/Documentation: # 2024-01-21 temp disable
67
+ Style/CommentedKeyword:
64
68
  Enabled: false
65
69
 
66
70
  Style/DoubleNegation:
@@ -87,6 +91,9 @@ Style/MultilineBlockChain:
87
91
  Style/OpenStructUse:
88
92
  Enabled: false
89
93
 
94
+ Style/OptionalBooleanParameter:
95
+ Enabled: false
96
+
90
97
  Style/PerlBackrefs: # Prefer ::Regexp.last_match.post_match over $'.
91
98
  Enabled: false
92
99
 
data/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.0.6] - 2024-05-28
4
+
5
+ ### Added
6
+
7
+ - Color-coding to folder names in the menu following a keyword search.
8
+ Implement color-coding for folder names. Each folder name is assigned a color based on the folder name to highlight repetitive folder structures.
9
+
10
+ - Load-code option to read one or more files into inherited lines.
11
+
12
+ - Automatic Load, Edit, Save, and View menu entries to manage inherited lines.
13
+ The value of `document_saved_lines_glob` is displayed above the menu items, if any.
14
+ The Load menu item appears when one or more files match the glob.
15
+ The Edit menu item appears when one or more lines have been inherited.
16
+ The Save menu item appears when one or more lines have been inherited.
17
+ The View menu item appears when one or more lines have been inherited.
18
+
19
+ ### Changed
20
+
21
+ - Fix block name processing for blocks with no name.
22
+ Demo in examples/block_names.md loads content of examples/load1.sh.
23
+
24
+ ## [2.0.5] - 2024-04-24
25
+
26
+ ### Changed
27
+
28
+ - Open option: Search for keyword in block names instead of entire document.
29
+
3
30
  ## [2.0.4] - 2024-04-22
4
31
 
5
32
  ### Added
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- markdown_exec (2.0.4)
4
+ markdown_exec (2.0.6)
5
5
  clipboard (~> 1.3.6)
6
6
  open3 (~> 0.1.1)
7
7
  optparse (~> 0.1.1)
@@ -13,7 +13,7 @@ __filedirs_all()
13
13
  }
14
14
 
15
15
  _mde_echo_version() {
16
- echo "2.0.4"
16
+ echo "2.0.6"
17
17
  }
18
18
 
19
19
  _mde() {
@@ -36,15 +36,15 @@ _mde() {
36
36
 
37
37
  -d) COMPREPLY="0"; return 0 ;;
38
38
 
39
- --dump-dump-delegate-object) COMPREPLY="0"; return 0 ;;
39
+ --dump-delegate-object) COMPREPLY="0"; return 0 ;;
40
40
 
41
41
  --dump-blocks-in-file) COMPREPLY="0"; return 0 ;;
42
42
 
43
- --dump-dump-inherited-block_names) COMPREPLY="0"; return 0 ;;
43
+ --dump-inherited-block_names) COMPREPLY="0"; return 0 ;;
44
44
 
45
- --dump-dump-inherited-dependencies) COMPREPLY="0"; return 0 ;;
45
+ --dump-inherited-dependencies) COMPREPLY="0"; return 0 ;;
46
46
 
47
- --dump-dump-inherited-lines) COMPREPLY="0"; return 0 ;;
47
+ --dump-inherited-lines) COMPREPLY="0"; return 0 ;;
48
48
 
49
49
  --dump-menu-blocks) COMPREPLY="0"; return 0 ;;
50
50
 
@@ -66,12 +66,12 @@ _mde() {
66
66
 
67
67
  --list-count) COMPREPLY="32"; return 0 ;;
68
68
 
69
+ --load-code) COMPREPLY="''"; return 0 ;;
70
+
69
71
  --open) COMPREPLY="''"; return 0 ;;
70
72
 
71
73
  -o) COMPREPLY="''"; return 0 ;;
72
74
 
73
- --output-execution-summary) COMPREPLY="0"; return 0 ;;
74
-
75
75
  --output-script) COMPREPLY="0"; return 0 ;;
76
76
 
77
77
  --output-stdout) COMPREPLY="1"; return 0 ;;
@@ -80,14 +80,6 @@ _mde() {
80
80
 
81
81
  -p) COMPREPLY="."; return 0 ;;
82
82
 
83
- --save-executed-script) COMPREPLY="0"; return 0 ;;
84
-
85
- --save-execution-output) COMPREPLY="0"; return 0 ;;
86
-
87
- --saved-script-folder) COMPREPLY="logs"; return 0 ;;
88
-
89
- --saved-stdout-folder) COMPREPLY="logs"; return 0 ;;
90
-
91
83
  --user-must-approve) COMPREPLY="0"; return 0 ;;
92
84
 
93
85
  -q) COMPREPLY="0"; return 0 ;;
@@ -102,7 +94,7 @@ _mde() {
102
94
  # present matching option names
103
95
  #
104
96
  if [[ ${cur} == -* ]] ; then
105
- opts=("--block-name" "--config" "--debug" "--dump-dump-delegate-object" "--dump-blocks-in-file" "--dump-dump-inherited-block_names" "--dump-dump-inherited-dependencies" "--dump-dump-inherited-lines" "--dump-menu-blocks" "--dump-selected-block" "--exit" "--filename" "--find" "--find-path" "--help" "--how" "--list-blocks" "--list-count" "--list-default-env" "--list-default-yaml" "--list-docs" "--list-recent-output" "--list-recent-scripts" "--open" "--output-execution-summary" "--output-script" "--output-stdout" "--path" "--pwd" "--run-last-script" "--save-executed-script" "--save-execution-output" "--saved-script-folder" "--saved-stdout-folder" "--select-recent-output" "--select-recent-script" "--tab-completions" "--user-must-approve" "--version" "--display-level")
97
+ opts=("--block-name" "--config" "--debug" "--dump-delegate-object" "--dump-blocks-in-file" "--dump-inherited-block_names" "--dump-inherited-dependencies" "--dump-inherited-lines" "--dump-menu-blocks" "--dump-selected-block" "--exit" "--filename" "--find" "--find-path" "--help" "--how" "--list-blocks" "--list-count" "--list-default-env" "--list-default-yaml" "--list-docs" "--list-recent-output" "--list-recent-scripts" "--load-code" "--open" "--output-script" "--output-stdout" "--path" "--pwd" "--run-last-script" "--select-recent-output" "--select-recent-script" "--tab-completions" "--user-must-approve" "--version" "--display-level")
106
98
  COMPREPLY=( $(compgen -W "$(printf "'%s' " "${opts[@]}")" -- "${cur}") )
107
99
 
108
100
  return 0
@@ -125,15 +117,15 @@ _mde() {
125
117
 
126
118
  -d) COMPREPLY=".BOOL."; return 0 ;;
127
119
 
128
- --dump-dump-delegate-object) COMPREPLY=".BOOL."; return 0 ;;
120
+ --dump-delegate-object) COMPREPLY=".BOOL."; return 0 ;;
129
121
 
130
122
  --dump-blocks-in-file) COMPREPLY=".BOOL."; return 0 ;;
131
123
 
132
- --dump-dump-inherited-block_names) COMPREPLY=".BOOL."; return 0 ;;
124
+ --dump-inherited-block_names) COMPREPLY=".BOOL."; return 0 ;;
133
125
 
134
- --dump-dump-inherited-dependencies) COMPREPLY=".BOOL."; return 0 ;;
126
+ --dump-inherited-dependencies) COMPREPLY=".BOOL."; return 0 ;;
135
127
 
136
- --dump-dump-inherited-lines) COMPREPLY=".BOOL."; return 0 ;;
128
+ --dump-inherited-lines) COMPREPLY=".BOOL."; return 0 ;;
137
129
 
138
130
  --dump-menu-blocks) COMPREPLY=".BOOL."; return 0 ;;
139
131
 
@@ -155,12 +147,12 @@ _mde() {
155
147
 
156
148
  --list-count) COMPREPLY=".INT.1-."; return 0 ;;
157
149
 
150
+ --load-code) COMPREPLY=".PATH."; return 0 ;;
151
+
158
152
  --open) COMPREPLY=".OPEN."; return 0 ;;
159
153
 
160
154
  -o) COMPREPLY=".OPEN."; return 0 ;;
161
155
 
162
- --output-execution-summary) COMPREPLY=".BOOL."; return 0 ;;
163
-
164
156
  --output-script) COMPREPLY=".BOOL."; return 0 ;;
165
157
 
166
158
  --output-stdout) COMPREPLY=".BOOL."; return 0 ;;
@@ -169,14 +161,6 @@ _mde() {
169
161
 
170
162
  -p) COMPREPLY=".RELATIVE_PATH."; return 0 ;;
171
163
 
172
- --save-executed-script) COMPREPLY=".BOOL."; return 0 ;;
173
-
174
- --save-execution-output) COMPREPLY=".BOOL."; return 0 ;;
175
-
176
- --saved-script-folder) COMPREPLY=".RELATIVE_PATH."; return 0 ;;
177
-
178
- --saved-stdout-folder) COMPREPLY=".RELATIVE_PATH."; return 0 ;;
179
-
180
164
  --user-must-approve) COMPREPLY=".BOOL."; return 0 ;;
181
165
 
182
166
  -q) COMPREPLY=".BOOL."; return 0 ;;
@@ -194,4 +178,4 @@ _mde() {
194
178
 
195
179
  complete -o filenames -o nospace -F _mde mde
196
180
  # _mde_echo_version
197
- # echo "Updated: 2024-04-23 01:25:22 UTC"
181
+ # echo "Updated: 2024-05-31 07:22:55 UTC"
@@ -0,0 +1,23 @@
1
+ Demonstrate display of block names and requiring blocks.
2
+
3
+ This block is listed by its name `A`.
4
+ It requires block `[C]`.
5
+ Executing it outputs `1`, `3`.
6
+ ```bash :A +[C]
7
+ echo "1"
8
+ ```
9
+
10
+ This block is listed according to its content `echo "2"`.
11
+ It requires blocks `A`, `[C]`.
12
+ Executing it outputs `1`, `2`, `3`.
13
+ It cannot be addressed/required.
14
+ ```bash +A
15
+ echo "2"
16
+ ```
17
+
18
+ This block is listed according to its content `echo "3"` and addressed by its nick name `[C]`.
19
+ It requires no blocks.
20
+ Executing it outputs `3`.
21
+ ```bash :[C]
22
+ echo "3"
23
+ ```
data/examples/linked.md CHANGED
@@ -92,6 +92,14 @@ load: examples/load2.sh
92
92
  eval: true
93
93
  ```
94
94
 
95
+ ::: Load file into inherited lines and switch document
96
+ Load (do not evaluate) and append to inherited lines and switch document.
97
+ ```link :load_from_file_link_and_show
98
+ block: show_vars
99
+ file: examples/linked_show.md
100
+ load: examples/load1.sh
101
+ ```
102
+
95
103
  ::: Save and Load
96
104
  Save inherited lines to a file.
97
105
  ```link :save1
@@ -0,0 +1,7 @@
1
+ # Demo document linking
2
+
3
+ ::: Display variables set in the calling document
4
+ ```bash :show_vars
5
+ source bin/colorize_env_vars.sh
6
+ colorize_env_vars 'from linked.md load1.sh' var1 var2
7
+ ```
@@ -0,0 +1,10 @@
1
+ Demonstrate loading inherited code via the command line.
2
+
3
+ Run this command to display the inherited code.
4
+ `mde --load-code examples/load1.sh examples/load_code.md display_variables`
5
+
6
+ ```bash :display_variables
7
+ source bin/colorize_env_vars.sh
8
+ echo The current value of environment variables:
9
+ colorize_env_vars '' var1 var2
10
+ ```
@@ -0,0 +1,21 @@
1
+ Demonstrate keyword search in documents.
2
+ Keywords in body: monkey secret
3
+
4
+ Keyword in untyped block name.
5
+ ``` :monkey1
6
+ ```
7
+
8
+ Keyword in Bash block name.
9
+ ```bash :monkey2
10
+ ```
11
+
12
+ Keyword in block body.
13
+ ```
14
+ monkey3
15
+ ```
16
+
17
+ Keyword in Link block body.
18
+ ```link
19
+ vars:
20
+ monkey4: 4
21
+ ```
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ # encoding=utf-8
4
+
5
+ # A class that represents a color scheme based on configurable parameters
6
+ # that determine how the RGB values are calculated for a given string segment.
7
+ class ColorScheme
8
+ attr_accessor :base_red, :multiplier_red, :modulus_red,
9
+ :base_green, :multiplier_green, :modulus_green,
10
+ :base_blue, :multiplier_blue, :modulus_blue
11
+
12
+ # Initializes a new ColorScheme object with base values, multipliers, and moduli
13
+ # for the red, green, and blue components of an RGB color.
14
+ # @param [Integer] base_red Base red component value.
15
+ # @param [Integer] multiplier_red Multiplier for red component based on string hash.
16
+ # @param [Integer] modulus_red Modulus for calculating red component.
17
+ # @param [Integer] base_green Base green component value.
18
+ # @param [Integer] multiplier_green Multiplier for green component based on string hash.
19
+ # @param [Integer] modulus_green Modulus for calculating green component.
20
+ # @param [Integer] base_blue Base blue component value.
21
+ # @param [Integer] multiplier_blue Multiplier for blue component based on string hash.
22
+ # @param [Integer] modulus_blue Modulus for calculating blue component.
23
+ def initialize(base_red, multiplier_red, modulus_red,
24
+ base_green, multiplier_green, modulus_green,
25
+ base_blue, multiplier_blue, modulus_blue)
26
+ @base_red = base_red
27
+ @multiplier_red = multiplier_red
28
+ @modulus_red = modulus_red
29
+ @base_green = base_green
30
+ @multiplier_green = multiplier_green
31
+ @modulus_green = modulus_green
32
+ @base_blue = base_blue
33
+ @multiplier_blue = multiplier_blue
34
+ @modulus_blue = modulus_blue
35
+ end
36
+
37
+ # Calculates and returns the ANSI escape code for coloring a string segment
38
+ # based on its hash value.
39
+ # @param [String] segment The string segment to color.
40
+ # @return [String] ANSI escape code string with RGB color formatting.
41
+ def color_for(segment)
42
+ hash_value = segment.each_byte.reduce(0, :+)
43
+ red = @base_red + (@multiplier_red * (hash_value % @modulus_red))
44
+ green = @base_green + (@multiplier_green * (hash_value % @modulus_green))
45
+ blue = @base_blue + (@multiplier_blue * (hash_value % @modulus_blue))
46
+ "\e[38;2;#{red};#{green};#{blue}m#{segment}\e[0m"
47
+ end
48
+
49
+ # Applies color codes to each segment of a filesystem path, differentiating the
50
+ # final segment from others using a distinct color scheme.
51
+ # @param [String] path The filesystem path to colorize.
52
+ # @return [String] The colorized path.
53
+ def self.colorize_path(path)
54
+ segments = path.split('/')
55
+ segments.map.with_index do |segment, index|
56
+ color_scheme = if index == segments.size - 1
57
+ ColorScheme.new(192, 0, 1, 192, 0, 1, 192, 0, 1)
58
+ else
59
+ ColorScheme.new(32, 1, 192, 32, 1, 192, 255, 0, 1)
60
+ end
61
+
62
+ color_scheme.color_for(segment)
63
+ end.join('/')
64
+ end
65
+ end
data/lib/constants.rb CHANGED
@@ -6,9 +6,9 @@
6
6
  require_relative 'block_types'
7
7
 
8
8
  class ExecutionStreams
9
- StdErr = :stderr
10
- StdIn = :stdin
11
- StdOut = :stdout
9
+ STD_ERR = :stderr
10
+ STD_IN = :stdin
11
+ STD_OUT = :stdout
12
12
  end
13
13
 
14
14
  IndexedLine = Struct.new(:index, :line) do
@@ -18,29 +18,24 @@ IndexedLine = Struct.new(:index, :line) do
18
18
  end
19
19
 
20
20
  class LinkKeys
21
- Block = 'block'
22
- Eval = 'eval'
23
- Exec = 'exec'
24
- File = 'file'
25
- Load = 'load'
26
- NextBlock = 'next_block'
27
- Return = 'return'
28
- Save = 'save'
29
- Vars = 'vars'
21
+ BLOCK = 'block'
22
+ EVAL = 'eval'
23
+ EXEC = 'exec'
24
+ FILE = 'file'
25
+ LOAD = 'load'
26
+ NEXT_BLOCK = 'next_block'
27
+ RETURN = 'return'
28
+ SAVE = 'save'
29
+ VARS = 'vars'
30
30
  end
31
31
 
32
32
  class LoadFile
33
- Load = true
34
- Reuse = false
33
+ LOAD = true
34
+ REUSE = false
35
35
  end
36
36
 
37
37
  LoadFileLinkState = Struct.new(:load_file, :link_state)
38
38
 
39
- class MenuControl
40
- Fresh = false
41
- Repeat = true
42
- end
43
-
44
39
  class MenuOptions
45
40
  YES = 1
46
41
  NO = 2
@@ -51,7 +46,11 @@ end
51
46
  class MenuState
52
47
  BACK = :back
53
48
  CONTINUE = :continue
49
+ EDIT = :edit
54
50
  EXIT = :exit
51
+ LOAD = :load
52
+ SAVE = :save
53
+ VIEW = :view
55
54
  end
56
55
 
57
56
  # a struct to hold the data for a single line
@@ -160,9 +160,11 @@ class DirectorySearcher
160
160
  begin
161
161
  File.foreach(p).with_index(1) do |line, line_num| # Index starts from 1 for line numbers
162
162
  line_utf8 = line.encode('UTF-8', invalid: :replace, undef: :replace, replace: '')
163
- if line_utf8.match?(@pattern)
163
+
164
+ line_utf8 = yield(line_utf8) if block_given?
165
+
166
+ if line_utf8&.match?(@pattern)
164
167
  match_details[p] ||= []
165
- # match_details[p] << { number: line_num, line: line_utf8.chomp }
166
168
  match_details[p] << IndexedLine.new(line_num, line_utf8.chomp)
167
169
  end
168
170
  end
data/lib/find_files.rb CHANGED
@@ -2,13 +2,13 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  # encoding=utf-8
5
- # version 2024-01-15
5
+ # version 2024-05-24
6
6
 
7
7
  # Finds files matching a given pattern within specified directory paths while optionally excluding
8
8
  # "." and ".." entries and directory names from the results.
9
9
  #
10
- # The function takes a pattern (filename or pattern with wildcards), an array of paths, and an
11
- # option to exclude directory entries and special entries "." and "..".
10
+ # The function takes a pattern (filename or pattern with wildcards), an array of paths, and options
11
+ # to exclude directory entries and special entries "." and "..", and to use relative paths.
12
12
  # It searches for files matching the pattern within each of the specified paths. Hidden files
13
13
  # are included in the search. The search can include subdirectories depending on the
14
14
  # path specification (e.g., 'dir/**' for recursive search).
@@ -18,15 +18,17 @@
18
18
  # paths (Array<String>): An array of directory paths where the search will be performed.
19
19
  # Paths can include wildcards for recursive search.
20
20
  # exclude_dirs (Boolean): If true, excludes "." and ".." and directory names from the results.
21
+ # use_relative_paths (Boolean): If true, removes the app's base directory from the file names
22
+ # if present.
21
23
  #
22
24
  # Returns:
23
25
  # Array<String>: A unique list of file paths that match the given pattern in the specified paths,
24
- # excluding directories if exclude_dirs is true.
26
+ # excluding directories if exclude_dirs is true. Paths are relative if use_relative_paths is true.
25
27
  #
26
28
  # Example:
27
- # find_files('version.rb', ['lib/**', 'spec'], true)
28
- # # This might return file paths like ['lib/markdown_exec/version.rb', 'spec/version_spec.rb'].
29
- def find_files(pattern, paths = ['', Dir.pwd], exclude_dirs: false)
29
+ # find_files('version.rb', ['lib/**', 'spec'], true, true)
30
+ # # This might return file paths like ['markdown_exec/version.rb', 'spec/version_spec.rb'].
31
+ def find_files(pattern, paths = ['', Dir.pwd], base_dir: Dir.pwd, exclude_dirs: false, use_relative_paths: true)
30
32
  matched_files = []
31
33
 
32
34
  paths.each do |path_with_wildcard|
@@ -37,9 +39,10 @@ def find_files(pattern, paths = ['', Dir.pwd], exclude_dirs: false)
37
39
  files = Dir.glob(search_pattern, File::FNM_DOTMATCH)
38
40
 
39
41
  # Optionally exclude "." and ".." and directory names
40
- if exclude_dirs
41
- files.reject! { |file| file.end_with?('/.', '/..') || File.directory?(file) }
42
- end
42
+ files.reject! { |file| file.end_with?('/.', '/..') || File.directory?(file) } if exclude_dirs
43
+
44
+ # Optionally use relative paths
45
+ files.map! { |file| file.sub(/^#{Regexp.escape(base_dir)}\//, '') } if use_relative_paths
43
46
 
44
47
  matched_files += files
45
48
  end
@@ -47,38 +50,6 @@ def find_files(pattern, paths = ['', Dir.pwd], exclude_dirs: false)
47
50
  matched_files.uniq
48
51
  end
49
52
 
50
- # # Finds files matching a given pattern within specified directory paths.
51
- # #
52
- # # The function takes a pattern (filename or pattern with wildcards) and an array of paths.
53
- # # It searches for files matching the pattern within each of the specified paths. Hidden files
54
- # # are also included in the search. The search can include subdirectories depending on the
55
- # # path specification (e.g., 'dir/**' for recursive search).
56
- # #
57
- # # Args:
58
- # # pattern (String): A filename or a pattern string with wildcards.
59
- # # paths (Array<String>): An array of directory paths where the search will be performed.
60
- # # Paths can include wildcards for recursive search.
61
- # #
62
- # # Returns:
63
- # # Array<String>: A unique list of file paths that match the given pattern in the specified paths.
64
- # #
65
- # # Example:
66
- # # find_files('version.rb', ['lib/**', 'spec'])
67
- # # # This might return file paths like ['lib/markdown_exec/version.rb', 'spec/version_spec.rb'].
68
- # def find_files(pattern, paths = ['', Dir.pwd])
69
- # matched_files = []
70
-
71
- # paths.each do |path_with_wildcard|
72
- # # Combine the path with the wildcard and the pattern
73
- # search_pattern = File.join(path_with_wildcard, pattern)
74
-
75
- # # Use Dir.glob with the File::FNM_DOTMATCH flag to include hidden files
76
- # matched_files += Dir.glob(search_pattern, File::FNM_DOTMATCH)
77
- # end
78
-
79
- # matched_files.uniq
80
- # end
81
-
82
53
  return if $PROGRAM_NAME != __FILE__
83
54
 
84
55
  # example CLI
@@ -138,4 +109,27 @@ class TestFindFiles < Minitest::Test
138
109
  result = find_files('.gitignore', ['.'])
139
110
  assert_includes result, './.gitignore'
140
111
  end
112
+
113
+ def test_find_files_with_non_existent_paths
114
+ # Test with non-existent paths
115
+ result = find_files('*.rb', %w[non_existent_dir another_fake_dir])
116
+ assert_empty result
117
+ end
118
+
119
+ def test_find_files_with_mixed_existent_and_non_existent_paths
120
+ # Test with a mix of existing and non-existing paths
121
+ result = find_files('*.rb', %w[lib non_existent_dir])
122
+ assert_includes result, 'lib/cli.rb'
123
+ assert_includes result, 'lib/colorize.rb'
124
+ # Ensure that non-existent paths do not cause failure and do not include files
125
+ assert_equal result.length, Dir.glob('lib/*.rb').length
126
+ end
127
+
128
+ def test_find_files_with_relative_paths
129
+ # Test with relative paths
130
+ base_dir = Dir.pwd
131
+ result = find_files('cli.rb', ['lib'], use_relative_paths: true)
132
+ assert_includes result, 'lib/cli.rb'
133
+ refute_includes result, "#{base_dir}/lib/cli.rb"
134
+ end
141
135
  end