Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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/completions/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set -x

bashly add comp function
bashly add comp function --force
bashly generate

### Try Me ###
Expand Down
1 change: 1 addition & 0 deletions lib/bashly.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
requires 'bashly/exceptions'
requires 'bashly/script/base'
requires 'bashly/commands/base'
requires 'bashly/library/base'
requires 'bashly'
120 changes: 36 additions & 84 deletions lib/bashly/commands/add.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class Add < Base
usage "bashly add colors [--force]"
usage "bashly add yaml [--force]"
usage "bashly add validations [--force]"
usage "bashly add comp FORMAT [OUTPUT]"
usage "bashly add comp FORMAT [OUTPUT --force]"
usage "bashly add (-h|--help)"

option "-f --force", "Overwrite existing files"
Expand All @@ -32,129 +32,81 @@ class Add < Base
environment "BASHLY_SOURCE_DIR", "The path containing the bashly configuration and source files [default: src]"

def strings_command
safe_copy asset("templates/strings.yml"), "#{Settings.source_dir}/bashly-strings.yml"
add_lib Library::Strings.new
end

def lib_command
safe_copy_file "sample_function.sh"
add_lib Library::Sample.new
end

def config_command
safe_copy_file "config.sh"
add_lib Library::Config.new
end

def colors_command
safe_copy_file "colors.sh"
add_lib Library::Colors.new
end

def yaml_command
safe_copy_file "yaml.sh"
add_lib Library::YAML.new
end

def validations_command
safe_copy_dir "validations"
add_lib Library::Validations.new
end

def comp_command
format = args['FORMAT']
output = args['OUTPUT']

case format
when "script"
path = output || "#{Settings.target_dir}/completions.bash"
add_lib Library::CompletionsScript.new(path)

when "function"
save_comp_function output
function = output || "send_completions"
path = "#{Settings.source_dir}/lib/#{function}.sh"
add_lib Library::CompletionsFunction.new(path, function: function)

when "yaml"
save_comp_yaml output
when "script"
save_comp_script output
path = output || "#{Settings.target_dir}/completions.yml"
add_lib Library::CompletionsYAML.new(path)

else
raise Error, "Unrecognized format: #{format}"

end

end

private

def safe_copy_dir(dir)
Dir[asset("templates/lib/#{dir}/*.sh")].sort.each do |file|
safe_copy_file "#{dir}/#{File.basename file}"
def add_lib(handler)
files_created = 0
handler.files.each do |file|
created = safe_write file[:path], file[:content]
files_created += 1 if created
end
message = handler.post_install_message
say "\n#{message}" if message and files_created > 0
end

def safe_copy_file(file)
safe_copy asset("templates/lib/#{file}"), "#{Settings.source_dir}/lib/#{file}"
end

def safe_copy(source, target)
def safe_write(path, content)
if !Dir.exist? Settings.source_dir
raise InitError, "Directory !txtgrn!#{Settings.source_dir}!txtrst! does not exist\nRun !txtpur!bashly init!txtrst! first"
end

if File.exist? target and !args['--force']
say "skipped !txtgrn!#{target}!txtrst! (exists)"
if File.exist? path and !args['--force']
say "skipped !txtgrn!#{path}!txtrst! (exists)"
false

else
deep_copy source, target
say "created !txtgrn!#{target}"
end
end

def deep_copy(source, target)
target_dir = File.dirname target
FileUtils.mkdir_p target_dir unless Dir.exist? target_dir
FileUtils.cp source, target
end

def config
@config ||= Config.new "#{Settings.source_dir}/bashly.yml"
end

def command
@command ||= Script::Command.new config
end

def completions
@completions ||= command.completion_data
end

def completions_script
@completions_script ||= command.completion_script
end

def completions_function
@completions_function ||= command.completion_function
end

def save_comp_yaml(filename = nil)
filename ||= "#{Settings.target_dir}/completions.yml"
File.write filename, completions.to_yaml
say "created !txtgrn!#{filename}"
say ""
say "This file can be converted to a completions script using the !txtgrn!completely!txtrst! gem."
end

def save_comp_script(filename = nil)
filename ||= "#{Settings.target_dir}/completions.bash"
File.write filename, completions_script
say "created !txtgrn!#{filename}"
say ""
say "In order to enable completions, run:"
say ""
say " !txtpur!$ source #{filename}"
end

def save_comp_function(name = nil)
name ||= "send_completions"
target_dir = "#{Settings.source_dir}/lib"
filename = "#{target_dir}/#{name}.sh"
File.deep_write path, content
say "created !txtgrn!#{path}"
true

FileUtils.mkdir_p target_dir unless Dir.exist? target_dir
File.write filename, completions_function

say "created !txtgrn!#{filename}"
say ""
say "In order to use it in your script, create a command or a flag (for example: !txtgrn!#{command.name} completions!txtrst! or !txtgrn!#{command.name} --completions!txtrst!) that calls the !txtgrn!#{name}!txtrst! function."
say "Your users can then run something like this to enable completions:"
say ""
say " !txtpur!$ eval \"$(#{command.name} completions)\""
end
end

end
Expand Down
4 changes: 4 additions & 0 deletions lib/bashly/concerns/asset_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@ module AssetHelper
def asset(path)
File.expand_path "../#{path}", __dir__
end

def asset_content(path)
File.read asset(path)
end
end
end
9 changes: 9 additions & 0 deletions lib/bashly/extensions/file.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require "fileutils"

class File
def self.deep_write(file, content)
dir = File.dirname file
FileUtils.mkdir_p dir unless Dir.exist? dir
File.write file, content
end
end
57 changes: 57 additions & 0 deletions lib/bashly/library/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
module Bashly
module Library
class Base
include AssetHelper

attr_reader :target_path, :options

def initialize(target_path = nil, options = nil)
@target_path = target_path || Settings.source_dir
@options = options || {}
end

def files
case content
when String then content_from_string content
when Hash then [content]
else content
end
end

def post_install_message
nil
end

def content
raise NotImplementedError, "Please implement either #content"
end

private

def content_from_string(string)
if File.directory? asset("templates/lib/#{string}")
content_for_dir string
else
[content_for_file(string)]
end
end

def content_for_file(file)
{
path: "#{target_path}/lib/#{file}",
content: asset_content("templates/lib/#{file}")
}
end

def content_for_dir(dir)
Dir[asset("templates/lib/#{dir}/*.sh")].sort.map do |file|
{
path: "#{target_path}/lib/#{dir}/#{File.basename file}",
content: File.read(file)
}
end
end

end
end
end
9 changes: 9 additions & 0 deletions lib/bashly/library/colors.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Bashly
module Library
class Colors < Base
def content
"colors.sh"
end
end
end
end
28 changes: 28 additions & 0 deletions lib/bashly/library/completions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module Bashly
module Library
class Completions < Base
def content
{ path: target_path, content: file_content }
end

def file_content
raise NotImplementedError, "Please implement #file_content"
end

protected

def completions
@completions ||= command.completion_data
end

def config
@config ||= Bashly::Config.new "#{Settings.source_dir}/bashly.yml"
end

def command
@command ||= Script::Command.new config
end

end
end
end
23 changes: 23 additions & 0 deletions lib/bashly/library/completions_function.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module Bashly
module Library
class CompletionsFunction < Completions
def file_content
command.completion_function function_name
end

def post_install_message
<<~EOF
In order to enable completions in your script, create a command or a flag (for example: !txtgrn!#{command.name} completions!txtrst! or !txtgrn!#{command.name} --completions!txtrst!) that calls the !txtgrn!#{function_name}!txtrst! function.

Your users can then run something like this to enable completions:

!txtpur!$ eval \"$(#{command.name} completions)\"
EOF
end

def function_name
options[:function]
end
end
end
end
17 changes: 17 additions & 0 deletions lib/bashly/library/completions_script.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module Bashly
module Library
class CompletionsScript < Completions
def file_content
command.completion_script
end

def post_install_message
<<~EOF
In order to enable completions, run:

!txtpur!$ source #{target_path}
EOF
end
end
end
end
15 changes: 15 additions & 0 deletions lib/bashly/library/completions_yaml.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Bashly
module Library
class CompletionsYAML < Completions
def file_content
completions.to_yaml
end

def post_install_message
<<~EOF
This file can be converted to a completions script using the !txtgrn!completely!txtrst! gem.
EOF
end
end
end
end
9 changes: 9 additions & 0 deletions lib/bashly/library/config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Bashly
module Library
class Config < Base
def content
"config.sh"
end
end
end
end
9 changes: 9 additions & 0 deletions lib/bashly/library/sample.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Bashly
module Library
class Sample < Base
def content
"sample_function.sh"
end
end
end
end
Loading