Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/render-mandoc/docs/download.1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.\" Automatically generated by Pandoc 3.2
.\"
.TH "download" "1" "July 2025" "Version 0.1.0" "Sample application"
.TH "download" "1" "August 2025" "Version 0.1.0" "Sample application"
.SH NAME
\f[B]download\f[R] \- Sample application
.SH SYNOPSIS
Expand Down
2 changes: 1 addition & 1 deletion examples/render-mandoc/docs/download.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
% download(1) Version 0.1.0 | Sample application
% Lana Lang
% July 2025
% August 2025

NAME
==================================================
Expand Down
2 changes: 1 addition & 1 deletion lib/bashly.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ module Bashly
module Script
autoloads 'bashly/script', %i[
Argument Base CatchAll Command Dependency EnvironmentVariable Flag
Variable Wrapper
Formatter Variable Wrapper
]

module Introspection
Expand Down
1 change: 1 addition & 0 deletions lib/bashly/exceptions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ class Interrupt < Interrupt; end
class Error < StandardError; end
class InitError < Error; end
class ConfigurationError < Error; end
class DependencyError < Error; end
end
4 changes: 2 additions & 2 deletions lib/bashly/extensions/string.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ def wrap(length = 80)
end * "\n"
end

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

def remove_front_matter
Expand Down
22 changes: 14 additions & 8 deletions lib/bashly/libraries/settings/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,22 @@ partials_extension: sh
#-------------------------------------------------------------------------------

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

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

# Choose a post-processor for the generated script:
# formatter: internal # Use Bashly's internal formatter (compacts newlines)
# formatter: none # Disable all post-processing
# formatter: shfmt # Use shfmt if installed
formatter: internal


#-------------------------------------------------------------------------------
# INTERFACE OPTIONS
Expand Down Expand Up @@ -100,10 +106,10 @@ env: development

# Tweak the script output by enabling or disabling some script output.
# These options accept one of the following strings:
# - production render this feature only when env == production
# - development render this feature only when env == development
# - always render this feature in any environment
# - never do not render this feature
# - production # render this feature only when env == production
# - development # render this feature only when env == development
# - always # render this feature in any environment
# - never # do not render this feature
enable_header_comment: always
enable_bash3_bouncer: always
enable_view_markers: development
Expand Down
40 changes: 40 additions & 0 deletions lib/bashly/script/formatter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
require 'open3'

module Bashly
module Script
class Formatter
MODES = %i[internal none shfmt]

attr_reader :script, :mode

def initialize(script, mode: nil)
@script = script
@mode = MODES.include?(mode&.to_sym) ? mode.to_sym : MODES.first
end

def formatted_script
case mode
when :internal then script.gsub(/\s+\n/m, "\n\n")
when :shfmt then shfmt_result
else script
end
end

private

def shfmt_result
unless system 'command -v shfmt > /dev/null 2>&1'
raise DependencyError,
'Cannot find g`shfmt`.\nEither install it or change to the g`internal` formatter.'
end

output, error, status =
Open3.capture3 %w[shfmt --case-indent --indent 2], stdin_data: script

raise DependencyError, "Failed running g`shfmt`:\n\n#{error}" unless status.success?

output
end
end
end
end
8 changes: 7 additions & 1 deletion lib/bashly/script/wrapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@ def base_code
[header, body]
end

result.join("\n").lint
clean_code result.join("\n")
end

def clean_code(script)
result = script.remove_private_comments
formatter = Formatter.new result, mode: Settings.formatter
formatter.formatted_script
end

def header
Expand Down
5 changes: 5 additions & 0 deletions lib/bashly/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class << self
:enable_inspect_args,
:enable_sourcing,
:enable_view_markers,
:formatter,
:function_names,
:lib_dir,
:partials_extension,
Expand Down Expand Up @@ -86,6 +87,10 @@ def env=(value)
@env = value&.to_sym
end

def formatter
@formatter ||= get :formatter
end

def full_lib_dir
"#{source_dir}/#{lib_dir}"
end
Expand Down
11 changes: 11 additions & 0 deletions schemas/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,17 @@
],
"default": "development"
},
"formatter": {
"title": "formatter",
"description": "Choose how to post-process the generated script\nhttps://bashly.dev/usage/settings/#formatter",
"type": "string",
"enum": [
"internal",
"none",
"shfmt"
],
"default": "internal"
},
"partials_extension": {
"title": "partials extension",
"description": "The extension to use when reading/writing partial script snippets\nhttps://bashly.dev/usage/settings/#partials_extension",
Expand Down
2 changes: 1 addition & 1 deletion spec/approvals/examples/render-mandoc
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ ISSUE TRACKER
AUTHORS
Lana Lang.

Version 0.1.0 July 2025 download(1)
Version 0.1.0 August 2025 download(1)
4 changes: 2 additions & 2 deletions spec/approvals/examples/stacktrace
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@ Examples:

Stack trace:
from ./download:15 in `root_command`
from ./download:260 in `run`
from ./download:266 in `main`
from ./download:259 in `run`
from ./download:265 in `main`
18 changes: 4 additions & 14 deletions spec/bashly/extensions/string_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,21 +125,11 @@
end
end

describe '#lint' do
context 'with a string that contains multiple consecutive newlines' do
subject { "one\n two\n \n three\n \n \nfour\n\n\n\n" }
describe '#remove_private_comments' do
subject { "this is important\n## SECRET\n ## ANOTHER SECRET\n also important\n" }

it 'replaces two or more newlines with two newlines' do
expect(subject.lint).to eq "one\n two\n\n three\n\nfour\n\n"
end
end

context 'with a string that contains double-hash comments' do
subject { "this is important\n## SECRET\n ## ANOTHER SECRET\n also important\n" }

it 'removes these comments' do
expect(subject.lint).to eq "this is important\n also important\n"
end
it 'removes these comments' do
expect(subject.remove_private_comments).to eq "this is important\n also important\n"
end
end

Expand Down
11 changes: 11 additions & 0 deletions support/schema/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,17 @@ properties:
type: string
enum: *feature_toggles
default: development
formatter:
title: formatter
description: |-
Choose how to post-process the generated script
https://bashly.dev/usage/settings/#formatter
type: string
enum:
- internal
- none
- shfmt
default: internal
partials_extension:
title: partials extension
description: |-
Expand Down