Skip to content

Commit 9726e44

Browse files
authored
Merge pull request #646 from bashly-framework/add/lint-customization
Add ability to choose a different formatter
2 parents e558a57 + 96ed811 commit 9726e44

File tree

21 files changed

+242
-31
lines changed

21 files changed

+242
-31
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ jobs:
3333
- name: Install pandoc
3434
run: rush get pandoc
3535

36+
- name: Install shfmt
37+
run: rush get shfmt
38+
3639
# libyaml needed for Ruby's YAML library
3740
- name: Install OS dependencies
3841
run: sudo apt-get -y install libyaml-dev

examples/render-mandoc/docs/download.1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.\" Automatically generated by Pandoc 3.2
22
.\"
3-
.TH "download" "1" "July 2025" "Version 0.1.0" "Sample application"
3+
.TH "download" "1" "August 2025" "Version 0.1.0" "Sample application"
44
.SH NAME
55
\f[B]download\f[R] \- Sample application
66
.SH SYNOPSIS

examples/render-mandoc/docs/download.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
% download(1) Version 0.1.0 | Sample application
22
% Lana Lang
3-
% July 2025
3+
% August 2025
44

55
NAME
66
==================================================

lib/bashly.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ module Bashly
2222
module Script
2323
autoloads 'bashly/script', %i[
2424
Argument Base CatchAll Command Dependency EnvironmentVariable Flag
25-
Variable Wrapper
25+
Formatter Variable Wrapper
2626
]
2727

2828
module Introspection

lib/bashly/extensions/string.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ def wrap(length = 80)
4444
end * "\n"
4545
end
4646

47-
def lint
48-
gsub(/\s+\n/m, "\n\n").lines.grep_v(/^\s*##/).join
47+
def remove_private_comments
48+
lines.grep_v(/^\s*##/).join
4949
end
5050

5151
def remove_front_matter

lib/bashly/libraries/settings/settings.yml

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,26 @@ partials_extension: sh
4141
#-------------------------------------------------------------------------------
4242

4343
# Configure the bash options that will be added to the initialize function:
44-
# strict: true Bash strict mode (set -euo pipefail)
45-
# strict: false Only exit on errors (set -e)
46-
# strict: '' Do not add any 'set' directive
47-
# strict: <string> Add any other custom 'set' directive
44+
# strict: true # Bash strict mode (set -euo pipefail)
45+
# strict: false # Only exit on errors (set -e)
46+
# strict: '' # Do not add any 'set' directive
47+
# strict: <string> # Add any other custom 'set' directive
4848
strict: false
4949

5050
# When true, the generated script will use tab indentation instead of spaces
5151
# (every 2 leading spaces will be converted to a tab character)
5252
tab_indent: false
5353

54+
# Choose a post-processor for the generated script:
55+
# formatter: internal # Use Bashly's internal formatter (compacts newlines)
56+
# formatter: external # Run the external command `shfmt --case-indent --indent 2`
57+
# formatter: none # Disable formatting entirely
58+
# formatter: <string> # Use a custom shell command to format the script.
59+
# # The command will receive the script via stdin and
60+
# # must output the result to stdout.
61+
# # Example: shfmt --minify
62+
formatter: internal
63+
5464

5565
#-------------------------------------------------------------------------------
5666
# INTERFACE OPTIONS
@@ -100,10 +110,10 @@ env: development
100110

101111
# Tweak the script output by enabling or disabling some script output.
102112
# These options accept one of the following strings:
103-
# - production render this feature only when env == production
104-
# - development render this feature only when env == development
105-
# - always render this feature in any environment
106-
# - never do not render this feature
113+
# - production # render this feature only when env == production
114+
# - development # render this feature only when env == development
115+
# - always # render this feature in any environment
116+
# - never # do not render this feature
107117
enable_header_comment: always
108118
enable_bash3_bouncer: always
109119
enable_view_markers: development

lib/bashly/script/formatter.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
require 'open3'
2+
require 'shellwords'
3+
4+
module Bashly
5+
module Script
6+
class Formatter
7+
attr_reader :script, :mode
8+
9+
def initialize(script, mode: nil)
10+
@script = script
11+
@mode = mode&.to_s || 'internal'
12+
end
13+
14+
def formatted_script
15+
case mode
16+
when 'internal' then script.gsub(/\s+\n/m, "\n\n")
17+
when 'external' then shfmt_result
18+
when 'none' then script
19+
else custom_formatter_result mode
20+
end
21+
end
22+
23+
private
24+
25+
def shfmt_result
26+
custom_formatter_result %w[shfmt --case-indent --indent 2]
27+
end
28+
29+
def custom_formatter_result(command)
30+
command = Shellwords.split command if command.is_a? String
31+
32+
begin
33+
output, error, status = Open3.capture3(*command, stdin_data: script)
34+
rescue Errno::ENOENT
35+
raise Error, "Command not found: g`#{command.first}`"
36+
end
37+
38+
raise Error, "Failed running g`#{Shellwords.join command}`:\n\n#{error}" unless status.success?
39+
40+
output
41+
end
42+
end
43+
end
44+
end

lib/bashly/script/wrapper.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,13 @@ def base_code
2323
[header, body]
2424
end
2525

26-
result.join("\n").lint
26+
clean_code result.join("\n")
27+
end
28+
29+
def clean_code(script)
30+
result = script.remove_private_comments
31+
formatter = Formatter.new result, mode: Settings.formatter
32+
formatter.formatted_script
2733
end
2834

2935
def header

lib/bashly/settings.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class << self
1515
:enable_inspect_args,
1616
:enable_sourcing,
1717
:enable_view_markers,
18+
:formatter,
1819
:function_names,
1920
:lib_dir,
2021
:partials_extension,
@@ -86,6 +87,10 @@ def env=(value)
8687
@env = value&.to_sym
8788
end
8889

90+
def formatter
91+
@formatter ||= get :formatter
92+
end
93+
8994
def full_lib_dir
9095
"#{source_dir}/#{lib_dir}"
9196
end

schemas/settings.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,25 @@
213213
],
214214
"default": "development"
215215
},
216+
"formatter": {
217+
"title": "formatter",
218+
"description": "Choose how to post-process the generated script\nhttps://bashly.dev/usage/settings/#formatter",
219+
"anyOf": [
220+
{
221+
"type": "string",
222+
"enum": [
223+
"internal",
224+
"external",
225+
"none"
226+
]
227+
},
228+
{
229+
"type": "string",
230+
"minLength": 1
231+
}
232+
],
233+
"default": "internal"
234+
},
216235
"partials_extension": {
217236
"title": "partials extension",
218237
"description": "The extension to use when reading/writing partial script snippets\nhttps://bashly.dev/usage/settings/#partials_extension",

0 commit comments

Comments
 (0)