Skip to content

Commit

Permalink
Refactor makefile generation and tasks list generation
Browse files Browse the repository at this point in the history
  • Loading branch information
imdrasil committed Jul 2, 2020
1 parent 4b8d942 commit a1d1e3f
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 90 deletions.
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
language: crystal
env:
- TERM=xterm-256color
before_script:
- crystal examples/sam.cr -- setup
- crystal examples/sam.cr setup
script: ./bin/ameba && crystal spec
42 changes: 42 additions & 0 deletions spec/makefile_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require "./spec_helper"

describe Sam::Makefile do
makefile = Sam::Makefile.new("src/sam.cr")

describe "#generate" do
declaration_part = <<-FILE
# === Sam shortcut
# next lines are autogenerated and any changes will be discarded after regenerating
CRYSTAL_BIN ?= `which crystal`
SAM_PATH ?= "src/sam.cr"
.PHONY: sam
sam:
\t$(CRYSTAL_BIN) $(SAM_PATH) $(filter-out $@,$(MAKECMDGOALS))
%:
\t@:
# === Sam shortcut\n
FILE
makefile_path = "Makefile"

it "creates new makefile" do
begin
File.exists?(makefile_path).should eq(false)
makefile.generate
File.read(makefile_path).should eq(declaration_part)
ensure
File.delete(makefile_path) if File.exists?(makefile_path)
end
end

it "correctly regenerates existing file" do
begin
File.exists?(makefile_path).should eq(false)
File.write(makefile_path, "# before\n" + declaration_part + "# after\n")
makefile.generate
File.read(makefile_path).should eq("# before\n# after\n" + declaration_part)
ensure
File.delete(makefile_path) if File.exists?(makefile_path)
end
end
end
end
37 changes: 0 additions & 37 deletions spec/sam_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -55,43 +55,6 @@ describe Sam do
end
end

describe ".generate_makefile" do
desclaration_part = <<-FILE
# === Sam shortcut
# next lines are autogenerated and any changes will be discarded after regenerating
CRYSTAL_BIN ?= `which crystal`
SAM_PATH ?= "src/sam.cr"
.PHONY: sam
sam:
\t$(CRYSTAL_BIN) $(SAM_PATH) $(filter-out $@,$(MAKECMDGOALS))
%:
\t@:
# === Sam shortcut\n
FILE
makefile = "Makefile"

it "creates new makefile" do
begin
File.exists?(makefile).should eq(false)
Sam.generate_makefile("src/sam.cr")
File.read(makefile).should eq(desclaration_part)
ensure
File.delete(makefile) if File.exists?(makefile)
end
end

it "correctly regenerates existing file" do
begin
File.exists?(makefile).should eq(false)
File.write(makefile, "# before\n" + desclaration_part + "# after\n")
Sam.generate_makefile("src/sam.cr")
File.read(makefile).should eq("# before\n# after\n" + desclaration_part)
ensure
File.delete(makefile) if File.exists?(makefile)
end
end
end

describe "%load_dependencies" do
context "given as splat array" do
it "properly loads tasks from dependencies" do
Expand Down
37 changes: 37 additions & 0 deletions spec/shell_table_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
require "./spec_helper"

describe Sam::ShellTable do
describe "#generate" do
it "generates correct table" do
fail "terminal should has width 80" if `tput cols`.to_i != 80

namespace = Sam::Namespace.new("name", nil)
Sam::ShellTable.new([
Sam::Task.new(
-> {},
%w[],
namespace,
"short_name",
"but very long description, such long that it requires multiple lines to be written"
),
Sam::Task.new(
-> {},
%w[],
namespace,
"very_long_task_name_such_long_that_it_requires_multiple_lines_to_be_written",
"and short description"
),
]).generate.should eq(
<<-TEXT
Name Description
-------------------------------------- | ---------------------------------------
short_name | but very long description, such long th
| at it requires multiple lines to be wri
| tten
very_long_task_name_such_long_that_it_ | and short description
requires_multiple_lines_to_be_written | \n
TEXT
)
end
end
end
49 changes: 0 additions & 49 deletions src/sam.cr
Original file line number Diff line number Diff line change
Expand Up @@ -54,40 +54,6 @@ module Sam
end
end

def self.pretty_print
tasks = @@root_namespace.all_tasks
paths = tasks.map(&.path)
max_length = paths.map(&.size).max
puts "Tasks:"
puts "-" * (max_length + 2) + ":" + "-" * 20
tasks.each_with_index do |task, i|
puts paths[i].ljust(max_length + 5) + task.description
end
end

def self.generate_makefile(sam_path)
file_path = "Makefile"
delimiter = "# === Sam shortcut"
if File.exists?(file_path)
ignore = false
shortcut = false
content = String.build do |io|
File.read_lines(file_path).each do |line|
if line.starts_with?(delimiter)
shortcut = true
ignore = !ignore
next
end
io << line << "\n" unless ignore
end
io << makefile_template(sam_path, delimiter)
end
File.write(file_path, content)
else
File.write(file_path, makefile_template(sam_path, delimiter))
end
end

private def self.read_task(args : Array(String))
return if args.empty?

Expand All @@ -97,19 +63,4 @@ module Sam
args.shift(task_args.size)
{task, task_args}
end

private def self.makefile_template(sam_path, delimiter)
<<-MAKEFILE
#{delimiter}
# next lines are autogenerated and any changes will be discarded after regenerating
CRYSTAL_BIN ?= `which crystal`
SAM_PATH ?= "#{sam_path}"
.PHONY: sam
sam:
\t$(CRYSTAL_BIN) $(SAM_PATH) $(filter-out $@,$(MAKECMDGOALS))
%:
\t@:
#{delimiter}\n
MAKEFILE
end
end
51 changes: 51 additions & 0 deletions src/sam/makefile.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
module Sam
# :nodoc:
class Makefile
getter executable_path : String

def initialize(@executable_path)
end

def generate
File.write(default_makefile_path, makefile_template) unless File.exists?(default_makefile_path)

ignore = false
shortcut = false
content = String.build do |io|
File.read_lines(default_makefile_path).each do |line|
if line.starts_with?(delimiter)
shortcut = true
ignore = !ignore
next
end
io << line << "\n" unless ignore
end
io << makefile_template
end
File.write(default_makefile_path, content)
end

private def default_makefile_path
"Makefile"
end

private def delimiter
"# === Sam shortcut"
end

private def makefile_template
<<-MAKEFILE
#{delimiter}
# next lines are autogenerated and any changes will be discarded after regenerating
CRYSTAL_BIN ?= `which crystal`
SAM_PATH ?= "#{executable_path}"
.PHONY: sam
sam:
\t$(CRYSTAL_BIN) $(SAM_PATH) $(filter-out $@,$(MAKECMDGOALS))
%:
\t@:
#{delimiter}\n
MAKEFILE
end
end
end
78 changes: 78 additions & 0 deletions src/sam/shell_table.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
require "./task"

module Sam
# :nodoc:
class ShellTable
BORDER = " | "

getter tasks : Array(Task), width : Int32

def initialize(@tasks)
@width = `tput cols`.to_i
end

def generate
String.build do |io|
write_header(io)
tasks.each { |task| write_task(io, task) }
end
end

private def write_header(io)
io << "Name".ljust(name_column_width) << " Description\n"
io << "-" * name_column_width << BORDER << "-" * description_column_width << "\n"
end

private def write_task(io, task)
name = task.path
description = task.description
while !(name.empty? && description.empty?)
if !name.empty?
segment_length = [name.size, name_column_width].min
io << name[0...segment_length].ljust(name_column_width)

name = name.size == segment_length ? "" : name[segment_length..-1]
else
io << " " * name_column_width
end
io << BORDER

if !description.empty?
segment_length = [description.size, description_column_width].min
io << description[0...segment_length]
description = description.size == segment_length ? "" : description[segment_length..-1]
else
io << " " * description_column_width
end
io << "\n"
end
end

private def name_column_width
@name_column_width ||=
[
[
tasks.map(&.path.size).max,
clean_width * min_content_width_ratio
].max,
clean_width * max_content_width_ration
].min.to_i.as(Int32)
end

def description_column_width
@description_column_width ||= (clean_width - name_column_width).as(Int32)
end

private def max_content_width_ration
0.5
end

private def min_content_width_ratio
0.1
end

private def clean_width
width - 3
end
end
end
7 changes: 5 additions & 2 deletions src/sam/tasks.cr
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
require "./makefile"
require "./shell_table"

desc "Prints description for all tasks"
task "help" do
Sam.pretty_print
puts Sam::ShellTable.new(Sam.root_namespace.all_tasks).generate
end

namespace "generate" do
desc "Generates makefile extension. Now command could be executed via `make sam your:command argument`"
task "makefile" do |_, args|
sam_file_path = args.raw.size == 1 ? args.raw[0].as(String) : "src/sam.cr"
Sam.generate_makefile(sam_file_path)
Sam::Makefile.new(sam_file_path).generate
end
end
2 changes: 1 addition & 1 deletion src/sam/version.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Sam
VERSION = "0.3.2"
VERSION = "0.4.0"
end

0 comments on commit a1d1e3f

Please sign in to comment.