From 3cc36bd18c157fa2185c5d3b55998b0bab22d2ed Mon Sep 17 00:00:00 2001 From: Roman Kalnytskyi Date: Mon, 10 Jul 2023 11:27:13 +0200 Subject: [PATCH] Execute default task if nothing specified; fix default path where sam sample file is placed --- README.md | 15 ++++++++++++++- examples/sam.cr | 14 +++++++++----- examples/sam.template | 4 ++-- examples/with_default.cr | 5 +++++ shard.yml | 2 +- spec/sam_spec.cr | 36 +++++++++++++++++++++++++++++------- spec/spec_helper.cr | 9 +++++++++ src/sam.cr | 18 +++++++++++++----- src/sam/dsl.cr | 4 +--- src/sam/namespace.cr | 11 ++++------- src/sam/task.cr | 4 ++-- src/sam/tasks.cr | 2 +- 12 files changed, 90 insertions(+), 34 deletions(-) create mode 100644 examples/with_default.cr diff --git a/README.md b/README.md index 0d90267..3a97387 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Add this to your application's `shard.yml`: dependencies: sam: github: imdrasil/sam.cr - version: 0.4.2 + version: 0.5.0 ``` After executing `shards install` Sam-file will be added to the root of your project (unless you already have one). @@ -63,6 +63,19 @@ To see a list of all available tasks with their descriptions: $ crystal sam.cr help ``` +If you pass no arguments - the task `"default"` will be invoked. + +```crystal +task "default" do + puts "Hi" +end +``` + +```shell +$ crystal sam.cr +Hi +``` + #### Tasks with arguments To pass arguments to your task just list them after it's name: diff --git a/examples/sam.cr b/examples/sam.cr index 4f91cc7..4e6df6d 100644 --- a/examples/sam.cr +++ b/examples/sam.cr @@ -1,3 +1,5 @@ +#!/bin/crystal + require "../src/sam" require "file_utils" @@ -5,7 +7,7 @@ class Container def self.add(a); end end -Sam.task "setup" do +task "setup" do lib1 = "./lib/lib1/src/lib1" lib2 = "./lib/lib2/src/lib2" lib3 = "./lib/lib3/src/lib3" @@ -78,11 +80,11 @@ Sam.task "setup" do ) end -Sam.task "clear" do +task "clear" do FileUtils.rm_r("./lib") end -Sam.namespace "db" do +namespace "db" do namespace "schema" do desc "just test" task "load" do |t, args| @@ -116,6 +118,8 @@ Sam.namespace "db" do task "ping" do puts "ping" end -end -Sam.help + task "with_argument" do |_, args| + puts args["f1"] + end +end diff --git a/examples/sam.template b/examples/sam.template index 62862e8..080ec2b 100644 --- a/examples/sam.template +++ b/examples/sam.template @@ -1,3 +1,5 @@ +#!/bin/crystal + require "sam" # Here you can define your tasks @@ -5,5 +7,3 @@ require "sam" # task "test" do # puts "ping" # end - -Sam.help diff --git a/examples/with_default.cr b/examples/with_default.cr new file mode 100644 index 0000000..fee8bb5 --- /dev/null +++ b/examples/with_default.cr @@ -0,0 +1,5 @@ +require "../src/sam" + +task "default" do + puts "this is by default" +end diff --git a/shard.yml b/shard.yml index 43191c4..48fe251 100644 --- a/shard.yml +++ b/shard.yml @@ -11,7 +11,7 @@ license: MIT development_dependencies: ameba: github: crystal-ameba/ameba - version: "= 0.14.3" + version: "= 1.4.3" scripts: postinstall: "false | [ -f ../../sam.cr ] && true || cp -i examples/sam.template ../../sam.cr 2>/dev/null" diff --git a/spec/sam_spec.cr b/spec/sam_spec.cr index 1d9e183..e1fafe9 100644 --- a/spec/sam_spec.cr +++ b/spec/sam_spec.cr @@ -1,17 +1,17 @@ require "./spec_helper" describe Sam do - describe "::namespace" do + describe ".namespace" do pending "add" do end end - describe "::task" do + describe ".task" do pending "add" do end end - describe "::invoke" do + describe ".invoke" do it "raises error if given task is not exists" do expect_raises(Exception, "Task giberrish was not found") do Sam.invoke("giberrish") @@ -19,18 +19,40 @@ describe Sam do end end - describe "::find" do + describe ".find" do it "finds correct task by path" do Sam.find!("db:schema:load").name.should eq("load") end end - describe "::help" do - pending "add" do + describe ".help" do + it "with multiple tasks" do + res = execute("crystal examples/sam.cr", ["db:with_argument", "f1=a", "@", "db:ping"]) + res[1].should eq(<<-TEXT) + a + ping + + TEXT + end + + it "without a specified task but with a default task defined" do + res = execute("crystal examples/with_default.cr", %w[]) + res[1].should eq(<<-TEXT) + this is by default + + TEXT + end + + it "without a specified task and without a default task defined" do + res = execute("crystal examples/sam.cr", %w[]) + res[1].should eq(<<-TEXT) + Hm, nothing to do... + + TEXT end end - describe "::process_tasks" do + describe ".process_tasks" do context "one task" do it "executes given task" do Sam.process_tasks(["db:schema"]) diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr index 7a62ba6..57e5e5b 100644 --- a/spec/spec_helper.cr +++ b/spec/spec_helper.cr @@ -4,6 +4,8 @@ require "../src/sam" load_dependencies "lib1" load_dependencies "lib2": "special", "lib3": ["/special"] +# Helpers + class Container @@executed_tasks = [] of String @@ -20,6 +22,13 @@ class Container end end +def execute(command, options) + io = IO::Memory.new + + status = Process.run("#{command} \"${@}\"", options, shell: true, output: io, error: io).exit_status + {status, io.to_s} +end + # Callbacks Spec.before_each do diff --git a/src/sam.cr b/src/sam.cr index 5276bb2..ff882fc 100644 --- a/src/sam.cr +++ b/src/sam.cr @@ -3,7 +3,8 @@ require "./sam/*" module Sam extend Execution - VERSION = "0.4.2" + VERSION = "0.5.0" + DEFAULT_TASK_NAME = "default" # Task separation symbol used in command line. TASK_SEPARATOR = "@" @@ -15,7 +16,7 @@ module Sam @@root_namespace end - def self.namespace(name : String) + def self.namespace(name : String, &) n = @@root_namespace.touch_namespace(name) with n yield end @@ -38,9 +39,10 @@ module Sam end def self.help - return puts "Hm, nothing to do..." if ARGV.empty? + return process_tasks(ARGV.clone) unless ARGV.empty? + return invoke(DEFAULT_TASK_NAME) if find(DEFAULT_TASK_NAME) - process_tasks(ARGV.clone) + puts "Hm, nothing to do..." rescue e : NotFound puts e.message exit 1 @@ -51,7 +53,7 @@ module Sam # :nodoc: def self.process_tasks(args) - while (definition = read_task(args)) + while definition = read_task(args) invoke(*definition) end end @@ -66,3 +68,9 @@ module Sam {task, task_args} end end + +include Sam::DSL + +at_exit do + Sam.help +end diff --git a/src/sam/dsl.cr b/src/sam/dsl.cr index acd2c18..3a3aa7c 100644 --- a/src/sam/dsl.cr +++ b/src/sam/dsl.cr @@ -1,7 +1,7 @@ module Sam # Task definition DSL. Delegates all calls to `Sam` itself. module DSL - def namespace(name : String) + def namespace(name : String, &) namespace = Sam.root_namespace.touch_namespace(name) with namespace yield end @@ -40,5 +40,3 @@ module Sam end end end - -include Sam::DSL diff --git a/src/sam/namespace.cr b/src/sam/namespace.cr index 350b70e..0036580 100644 --- a/src/sam/namespace.cr +++ b/src/sam/namespace.cr @@ -10,12 +10,9 @@ module Sam end def path - if @parent - @parent.not_nil!.path + @name + ":" - else - # this is a root namespace - "" - end + return "" if @parent.nil? # NOTE: this is a root namespace + + @parent.as(Namespace).path + @name + ":" end # Sets description to the next defined task. @@ -24,7 +21,7 @@ module Sam end # Defines nested namespace. - def namespace(name) + def namespace(name, &) with touch_namespace(name) yield @namespaces[name] end diff --git a/src/sam/task.cr b/src/sam/task.cr index ee2a937..6c52c8a 100644 --- a/src/sam/task.cr +++ b/src/sam/task.cr @@ -59,8 +59,8 @@ module Sam end end - def find(name : String) - @parent.find(name) + def find(path : String) + @parent.find(path) end end end diff --git a/src/sam/tasks.cr b/src/sam/tasks.cr index 65e72a2..a587b52 100644 --- a/src/sam/tasks.cr +++ b/src/sam/tasks.cr @@ -9,7 +9,7 @@ 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_file_path = args.raw.size == 1 ? args.raw[0].as(String) : "sam.cr" Sam::Makefile.new(sam_file_path).generate end end