squared 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/README.ruby.md +14 -8
- data/lib/squared/common/class.rb +2 -2
- data/lib/squared/common/format.rb +3 -3
- data/lib/squared/common/prompt.rb +2 -2
- data/lib/squared/common/shell.rb +33 -20
- data/lib/squared/common/system.rb +1 -1
- data/lib/squared/config.rb +13 -10
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +30 -6
- data/lib/squared/workspace/project/base.rb +33 -15
- data/lib/squared/workspace/project/git.rb +100 -60
- data/lib/squared/workspace/project/node.rb +17 -19
- data/lib/squared/workspace/project/python.rb +11 -11
- data/lib/squared/workspace/project/ruby.rb +40 -40
- data/lib/squared/workspace/repo.rb +12 -12
- data/lib/squared/workspace/series.rb +3 -2
- metadata +3 -6
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 11c047668befa13733be4f81fbac270909c72be73754f70b464e804c11f8204e
         | 
| 4 | 
            +
              data.tar.gz: fac920aa92d55210e48c2f780ea366b58f0c9ed870d524b5bf19eeeeb2628ab1
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 78b3346cbf690fa4ce9a36431eaad0ffb24d464a46700810c19f6938b5e020c94c1ede8709f61e448f75443f3b8c9df8a00877e380e81beb7ce37732dc244289
         | 
| 7 | 
            +
              data.tar.gz: ee6b18f73590b38fa91a2f73852cbc6ccc467255bed2c5c540731d565dc43e15b1b6c103866003979518ef416fcb450beb5c58f5f1ad1c20119437d5f795aa84
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,5 +1,34 @@ | |
| 1 1 | 
             
            # Changelog
         | 
| 2 2 |  | 
| 3 | 
            +
            ## [0.1.3] - 2024-01-02
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ### Fixed
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            - Output lines from IO were missing theme styling.
         | 
| 8 | 
            +
            - Node did not apply build options when stored as Array.
         | 
| 9 | 
            +
            - Git commit push did not send origin and branch.
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            ## [0.1.2] - 2024-12-23
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            ### Added
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            - Git command tag was implemented.
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            ### Deprecated
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            - Repo static method empty? was relocated into Application.
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            ### Fixed
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            - Namespace prefix was sometimes missing or duplicated.
         | 
| 24 | 
            +
            - Silent operation used undefined variable.
         | 
| 25 | 
            +
            - Unnecessary shell option escapes were removed.
         | 
| 26 | 
            +
            - Ruby command outdated did not display in order when threaded.
         | 
| 27 | 
            +
            - Regexp uses \A|\z format and not ^|$ for standard matches.
         | 
| 28 | 
            +
            - Rake being called by a project did not escape options.
         | 
| 29 | 
            +
            - Workspace did not check base project for Windows filename.
         | 
| 30 | 
            +
            - Regexp for SemVer did not recognize package names.
         | 
| 31 | 
            +
             | 
| 3 32 | 
             
            ## [0.1.1] - 2024-12-14
         | 
| 4 33 |  | 
| 5 34 | 
             
            ### Added
         | 
| @@ -50,6 +79,8 @@ | |
| 50 79 |  | 
| 51 80 | 
             
            - Changelog was created.
         | 
| 52 81 |  | 
| 82 | 
            +
            [0.1.3]: https://github.com/anpham6/squared/releases/tag/v0.1.3-ruby
         | 
| 83 | 
            +
            [0.1.2]: https://github.com/anpham6/squared/releases/tag/v0.1.2-ruby
         | 
| 53 84 | 
             
            [0.1.1]: https://github.com/anpham6/squared/releases/tag/v0.1.1-ruby
         | 
| 54 85 | 
             
            [0.1.0]: https://github.com/anpham6/squared/releases/tag/v0.1.0-ruby
         | 
| 55 86 | 
             
            [0.0.12]: https://github.com/anpham6/squared/releases/tag/v0.0.12-ruby
         | 
    
        data/README.ruby.md
    CHANGED
    
    | @@ -37,17 +37,23 @@ Projects from any accessible folder can be added relative to the parent director | |
| 37 37 | 
             
            require "squared"
         | 
| 38 38 |  | 
| 39 39 | 
             
            require "squared/workspace"
         | 
| 40 | 
            -
            require "squared/workspace/repo" | 
| 41 | 
            -
            require "squared/workspace/project/node" | 
| 42 | 
            -
            require "squared/workspace/project/python" | 
| 43 | 
            -
            require "squared/workspace/project/ruby" | 
| 40 | 
            +
            require "squared/workspace/repo"                     # Optional
         | 
| 41 | 
            +
            require "squared/workspace/project/node"             #
         | 
| 42 | 
            +
            require "squared/workspace/project/python"           #
         | 
| 43 | 
            +
            require "squared/workspace/project/ruby"             #
         | 
| 44 44 | 
             
            # OR
         | 
| 45 | 
            -
            require "squared/app" | 
| 45 | 
            +
            require "squared/app"                                # All workspace related modules
         | 
| 46 46 |  | 
| 47 47 | 
             
            # NODE_ENV  = production
         | 
| 48 | 
            -
             | 
| 49 | 
            -
            #  | 
| 50 | 
            -
            #  | 
| 48 | 
            +
             | 
| 49 | 
            +
            # REPO_ROOT = /workspaces                            #
         | 
| 50 | 
            +
            # REPO_HOME = /workspaces/squared                    # Dir.pwd
         | 
| 51 | 
            +
            # rake      = /workspaces/squared/Rakefile           # main?
         | 
| 52 | 
            +
            # OR
         | 
| 53 | 
            +
            # REPO_ROOT = /workspaces                            # Dir.pwd
         | 
| 54 | 
            +
            # rake      = /workspaces/Rakefile                   #
         | 
| 55 | 
            +
            # REPO_HOME = /workspaces/squared                    # main: "squared"
         | 
| 56 | 
            +
             | 
| 51 57 | 
             
            # pathname  = /workspaces/pathname
         | 
| 52 58 | 
             
            # optparse  = /workspaces/optparse
         | 
| 53 59 | 
             
            # log       = /workspaces/logger
         | 
    
        data/lib/squared/common/class.rb
    CHANGED
    
    | @@ -9,7 +9,7 @@ module Squared | |
| 9 9 | 
             
                  extend Forwardable
         | 
| 10 10 |  | 
| 11 11 | 
             
                  def self.to_s
         | 
| 12 | 
            -
                    super.match(/[^:] | 
| 12 | 
            +
                    super.match(/[^:]+\z/)[0]
         | 
| 13 13 | 
             
                  end
         | 
| 14 14 |  | 
| 15 15 | 
             
                  def_delegators :@data, :+, :each, :each_with_index, :entries, :to_a, :include?
         | 
| @@ -31,7 +31,7 @@ module Squared | |
| 31 31 |  | 
| 32 32 | 
             
                class JoinSet < Set
         | 
| 33 33 | 
             
                  def self.to_s
         | 
| 34 | 
            -
                    super.match(/[^:] | 
| 34 | 
            +
                    super.match(/[^:]+\z/)[0]
         | 
| 35 35 | 
             
                  end
         | 
| 36 36 |  | 
| 37 37 | 
             
                  def initialize(data = [], delim: ' ')
         | 
| @@ -46,7 +46,7 @@ module Squared | |
| 46 46 | 
             
                    if pat && index != 0
         | 
| 47 47 | 
             
                      return val unless (data = pat.match(val))
         | 
| 48 48 |  | 
| 49 | 
            -
                      ret = index == -1 ? data.to_a | 
| 49 | 
            +
                      ret = index == -1 ? data.to_a.drop(1) : data[index]
         | 
| 50 50 | 
             
                    else
         | 
| 51 51 | 
             
                      ret = val
         | 
| 52 52 | 
             
                      index = 0
         | 
| @@ -235,8 +235,8 @@ module Squared | |
| 235 235 | 
             
                      sub.each { |h| s = sub_style(s, **h) }
         | 
| 236 236 | 
             
                      s = "| #{s} |"
         | 
| 237 237 | 
             
                      if border
         | 
| 238 | 
            -
                        s = sub_style(s, pat:  | 
| 239 | 
            -
                        s = sub_style(s, pat:  | 
| 238 | 
            +
                        s = sub_style(s, pat: /\A(\|)(.+)\z/m, styles: border)
         | 
| 239 | 
            +
                        s = sub_style(s, pat: /\A(.+)(\|)\z/m, styles: border, index: 2)
         | 
| 240 240 | 
             
                      end
         | 
| 241 241 | 
             
                      s
         | 
| 242 242 | 
             
                    end
         | 
| @@ -8,8 +8,8 @@ module Squared | |
| 8 8 | 
             
                  def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts: 5, timeout: 15)
         | 
| 9 9 | 
             
                    require 'readline'
         | 
| 10 10 | 
             
                    require 'timeout'
         | 
| 11 | 
            -
                    agree =  | 
| 12 | 
            -
                    cancel =  | 
| 11 | 
            +
                    agree = /\A#{agree}\z/i if agree.is_a?(::String)
         | 
| 12 | 
            +
                    cancel = /\A#{cancel}\z/i if cancel.is_a?(::String)
         | 
| 13 13 | 
             
                    Timeout.timeout(timeout) do
         | 
| 14 14 | 
             
                      begin
         | 
| 15 15 | 
             
                        while (ch = Readline.readline(msg, true))
         | 
    
        data/lib/squared/common/shell.rb
    CHANGED
    
    | @@ -8,38 +8,51 @@ module Squared | |
| 8 8 | 
             
                module Shell
         | 
| 9 9 | 
             
                  module_function
         | 
| 10 10 |  | 
| 11 | 
            -
                  def shell_escape(val, quote: false)
         | 
| 12 | 
            -
                    val = val.to_s
         | 
| 13 | 
            -
             | 
| 11 | 
            +
                  def shell_escape(val, quote: false, force: false)
         | 
| 12 | 
            +
                    if (data = /\A(--?[^= ]+)((=|\s+)(["'])?(.+?)(["'])?)?\z/m.match(val = val.to_s))
         | 
| 13 | 
            +
                      return val unless data[2]
         | 
| 14 14 |  | 
| 15 | 
            -
             | 
| 15 | 
            +
                      join = ->(opt) { data[1] + data[3] + shell_quote(opt) }
         | 
| 16 | 
            +
                      if data[4] == data[6]
         | 
| 17 | 
            +
                        data[4] ? val : join.(data[5])
         | 
| 18 | 
            +
                      else
         | 
| 19 | 
            +
                        join.("#{data[4]}#{data[5]}#{data[6]}")
         | 
| 20 | 
            +
                      end
         | 
| 21 | 
            +
                    elsif Rake::Win32.windows?
         | 
| 22 | 
            +
                      quote ? shell_quote(val, force: force) : val
         | 
| 23 | 
            +
                    else
         | 
| 24 | 
            +
                      Shellwords.escape(val)
         | 
| 25 | 
            +
                    end
         | 
| 16 26 | 
             
                  end
         | 
| 17 27 |  | 
| 18 28 | 
             
                  def shell_quote(val, force: true)
         | 
| 19 | 
            -
                     | 
| 20 | 
            -
                    return  | 
| 29 | 
            +
                    val = val.to_s
         | 
| 30 | 
            +
                    return val if (!force && !val.include?(' ')) || val =~ /(?:^|\S=|[^=]\s+)(["']).+\1\z/m
         | 
| 21 31 |  | 
| 22 | 
            -
                     | 
| 32 | 
            +
                    Rake::Win32.windows? ? "\"#{double_quote(val)}\"" : "'#{single_quote(val)}'"
         | 
| 23 33 | 
             
                  end
         | 
| 24 34 |  | 
| 25 | 
            -
                  def shell_split(val, quote: false, join:  | 
| 26 | 
            -
                     | 
| 27 | 
            -
             | 
| 28 | 
            -
                        next opt unless data[2] && !data[3]
         | 
| 35 | 
            +
                  def shell_split(val, quote: false, join: nil)
         | 
| 36 | 
            +
                    val = Shellwords.split(val).map { |opt| shell_escape(opt, quote: quote) }
         | 
| 37 | 
            +
                    return val unless join
         | 
| 29 38 |  | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
                     | 
| 35 | 
            -
             | 
| 39 | 
            +
                    val.join(join.is_a?(::String) ? join : ' ')
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  def shell_option(flag, val = nil, quote: false, escape: true)
         | 
| 43 | 
            +
                    "--#{flag}#{if val
         | 
| 44 | 
            +
                                  "=#{if escape
         | 
| 45 | 
            +
                                        shell_escape(val, quote: quote)
         | 
| 46 | 
            +
                                      else
         | 
| 47 | 
            +
                                        quote ? shell_quote(val) : val
         | 
| 48 | 
            +
                                      end}"
         | 
| 49 | 
            +
                                end}"
         | 
| 36 50 | 
             
                  end
         | 
| 37 51 |  | 
| 38 52 | 
             
                  def fill_option(val)
         | 
| 39 | 
            -
                    return "-#{val}" if val | 
| 53 | 
            +
                    return "-#{val}" if val =~ /\A[a-z](?:\d*)\z/i
         | 
| 40 54 |  | 
| 41 | 
            -
                    val  | 
| 42 | 
            -
                    shell_escape(val).sub('\\=', '=')
         | 
| 55 | 
            +
                    shell_escape(val.start_with?('-') ? val : "--#{val}")
         | 
| 43 56 | 
             
                  end
         | 
| 44 57 |  | 
| 45 58 | 
             
                  def single_quote(val)
         | 
    
        data/lib/squared/config.rb
    CHANGED
    
    | @@ -12,7 +12,7 @@ module Squared | |
| 12 12 | 
             
                  include Rake::DSL
         | 
| 13 13 |  | 
| 14 14 | 
             
                  def self.to_s
         | 
| 15 | 
            -
                    super.match(/[^:] | 
| 15 | 
            +
                    super.match(/[^:]+\z/)[0]
         | 
| 16 16 | 
             
                  end
         | 
| 17 17 |  | 
| 18 18 | 
             
                  attr_reader :main, :name, :project, :theme
         | 
| @@ -199,17 +199,18 @@ module Squared | |
| 199 199 | 
             
                    title = Pathname.new(file)
         | 
| 200 200 | 
             
                                    .realpath
         | 
| 201 201 | 
             
                                    .to_s
         | 
| 202 | 
            -
                                    .sub(Regexp.new(" | 
| 202 | 
            +
                                    .sub(Regexp.new("\\A#{Regexp.escape(File.join(Dir.pwd, ''))}"), '')
         | 
| 203 203 | 
             
                    emphasize(lines, title: title, sub: unless stdin?
         | 
| 204 204 | 
             
                                                          [
         | 
| 205 | 
            -
                                                            { pat:  | 
| 206 | 
            -
                                                            { pat:  | 
| 207 | 
            -
                                                            { pat:  | 
| 208 | 
            -
                                                            { pat:  | 
| 209 | 
            -
             | 
| 210 | 
            -
                                                            { pat:  | 
| 211 | 
            -
                                                            { pat:  | 
| 212 | 
            -
                                                            { pat:  | 
| 205 | 
            +
                                                            { pat: /\A((?:[^:]|(?<! ):(?! ))+)\z/, styles: theme[:banner] },
         | 
| 206 | 
            +
                                                            { pat: /\A(.*?)(<[^>]+>)(.+)\z/m, styles: theme[:undefined], index: 2 },
         | 
| 207 | 
            +
                                                            { pat: /\A(.+)( : (?!undefined).+)\z/m, styles: theme[:key] },
         | 
| 208 | 
            +
                                                            { pat: /\A(.+ : )(-?[\d.]+)(\s*)\z/m, styles: theme[:number],
         | 
| 209 | 
            +
                                                              index: 2 },
         | 
| 210 | 
            +
                                                            { pat: /\A(.+ : ")(.+)("\s*)\z/m, styles: theme[:string], index: 2 },
         | 
| 211 | 
            +
                                                            { pat: /\A(.+ : \{)(.+)(\}\s*)\z/m, styles: theme[:hash], index: 2 },
         | 
| 212 | 
            +
                                                            { pat: /\A(.+ : \[)(.+)(\]\s*)\z/m, styles: theme[:array], index: 2 },
         | 
| 213 | 
            +
                                                            { pat: /\A(.+ : (?!undefined))([^"\[{].*)\z/m, styles: theme[:value],
         | 
| 213 214 | 
             
                                                              index: 2 }
         | 
| 214 215 | 
             
                                                          ]
         | 
| 215 216 | 
             
                                                        end)
         | 
| @@ -261,6 +262,8 @@ module Squared | |
| 261 262 | 
             
                  end
         | 
| 262 263 |  | 
| 263 264 | 
             
                  def format_desc(command, *ext, exist: exist?)
         | 
| 265 | 
            +
                    return unless Rake::TaskManager.record_task_metadata
         | 
| 266 | 
            +
             | 
| 264 267 | 
             
                    val = "#{ext.first}[#{exist ? '' : "file?=#{File.basename(main)}.#{ext.last},"}keys+]"
         | 
| 265 268 | 
             
                    message(@prefix, *name.split(':'), command, val, empty: true)
         | 
| 266 269 | 
             
                  end
         | 
    
        data/lib/squared/version.rb
    CHANGED
    
    
| @@ -56,7 +56,7 @@ module Squared | |
| 56 56 | 
             
                    end
         | 
| 57 57 |  | 
| 58 58 | 
             
                    def to_s
         | 
| 59 | 
            -
                      super.match(/[^:] | 
| 59 | 
            +
                      super.match(/[^:]+\z/)[0]
         | 
| 60 60 | 
             
                    end
         | 
| 61 61 |  | 
| 62 62 | 
             
                    attr_reader :kind_project
         | 
| @@ -70,8 +70,14 @@ module Squared | |
| 70 70 | 
             
                  def initialize(home = Dir.pwd, *, main: nil, prefix: nil,
         | 
| 71 71 | 
             
                                 verbose: ARG[:VERBOSE], common: ARG[:COMMON], pipe: ARG[:PIPE], exception: ARG[:FAIL], **)
         | 
| 72 72 | 
             
                    @home = Pathname.new(home).realdirpath
         | 
| 73 | 
            +
                    basename = @home.basename.to_s
         | 
| 74 | 
            +
                    if main
         | 
| 75 | 
            +
                      @main = main.to_s.freeze
         | 
| 76 | 
            +
                      @home = @home.join(@main) unless @main == basename || (windows? && @main.downcase == basename.downcase)
         | 
| 77 | 
            +
                    else
         | 
| 78 | 
            +
                      @main = basename.freeze
         | 
| 79 | 
            +
                    end
         | 
| 73 80 | 
             
                    @root = @home.parent
         | 
| 74 | 
            -
                    @main = (main || @home.basename).to_s.freeze
         | 
| 75 81 | 
             
                    @prefix = prefix
         | 
| 76 82 | 
             
                    @series = Application.impl_series.new(self)
         | 
| 77 83 | 
             
                    @project = {}
         | 
| @@ -322,7 +328,7 @@ module Squared | |
| 322 328 |  | 
| 323 329 | 
             
                  def task_name(val, desc: false)
         | 
| 324 330 | 
             
                    ret = @prefix ? task_join(@prefix, val) : val.to_s
         | 
| 325 | 
            -
                    desc ? ret.split(':') | 
| 331 | 
            +
                    desc ? message(*ret.split(':')) : ret
         | 
| 326 332 | 
             
                  end
         | 
| 327 333 |  | 
| 328 334 | 
             
                  def task_namespace(val, first: false)
         | 
| @@ -383,7 +389,7 @@ module Squared | |
| 383 389 |  | 
| 384 390 | 
             
                      return ret
         | 
| 385 391 | 
             
                    end
         | 
| 386 | 
            -
                    @script[:ref!][: | 
| 392 | 
            +
                    @script[:ref!][:''] || SCRIPT_OBJ
         | 
| 387 393 | 
             
                  end
         | 
| 388 394 |  | 
| 389 395 | 
             
                  def script_get(*args, group: nil, ref: nil)
         | 
| @@ -409,7 +415,7 @@ module Squared | |
| 409 415 | 
             
                    return ret if group && (ret = @banner[:group][group.to_sym])
         | 
| 410 416 |  | 
| 411 417 | 
             
                    ref.reverse_each { |val| return ret if (ret = @banner[:ref][val]) }
         | 
| 412 | 
            -
                    @banner[:ref][: | 
| 418 | 
            +
                    @banner[:ref][:'']
         | 
| 413 419 | 
             
                  end
         | 
| 414 420 |  | 
| 415 421 | 
             
                  def enabled?
         | 
| @@ -444,6 +450,10 @@ module Squared | |
| 444 450 | 
             
                    !(proj = find(home)).nil? && proj.enabled?
         | 
| 445 451 | 
             
                  end
         | 
| 446 452 |  | 
| 453 | 
            +
                  def windows?
         | 
| 454 | 
            +
                    Rake::Win32.windows?
         | 
| 455 | 
            +
                  end
         | 
| 456 | 
            +
             | 
| 447 457 | 
             
                  def rootpath(*args)
         | 
| 448 458 | 
             
                    root.join(*args)
         | 
| 449 459 | 
             
                  end
         | 
| @@ -505,7 +515,21 @@ module Squared | |
| 505 515 | 
             
                    elsif ref
         | 
| 506 516 | 
             
                      as_a(ref).each { |val| @script[:ref!][val.to_sym] = data }
         | 
| 507 517 | 
             
                    else
         | 
| 508 | 
            -
                      @script[:ref!][: | 
| 518 | 
            +
                      @script[:ref!][:''] = data
         | 
| 519 | 
            +
                    end
         | 
| 520 | 
            +
                  end
         | 
| 521 | 
            +
             | 
| 522 | 
            +
                  def root?(path, pass: [])
         | 
| 523 | 
            +
                    return false unless path.directory?
         | 
| 524 | 
            +
             | 
| 525 | 
            +
                    case path.children.size
         | 
| 526 | 
            +
                    when 0
         | 
| 527 | 
            +
                      true
         | 
| 528 | 
            +
                    when 1
         | 
| 529 | 
            +
                      target = path.children.first
         | 
| 530 | 
            +
                      target.to_s == __FILE__ || pass.any? { |val| val == target.basename.to_s }
         | 
| 531 | 
            +
                    else
         | 
| 532 | 
            +
                      false
         | 
| 509 533 | 
             
                    end
         | 
| 510 534 | 
             
                  end
         | 
| 511 535 |  | 
| @@ -15,7 +15,7 @@ module Squared | |
| 15 15 | 
             
                    include Rake::DSL
         | 
| 16 16 |  | 
| 17 17 | 
             
                    VAR_SET = %i[parent global envname dependfile theme run script env].freeze
         | 
| 18 | 
            -
                    SEM_VER =  | 
| 18 | 
            +
                    SEM_VER = /\b(\d+)(?:(\.)(\d+))?(?:(\.)(\d+)(\S+)?)?\b/.freeze
         | 
| 19 19 | 
             
                    private_constant :VAR_SET, :SEM_VER
         | 
| 20 20 |  | 
| 21 21 | 
             
                    class << self
         | 
| @@ -46,7 +46,7 @@ module Squared | |
| 46 46 | 
             
                      end
         | 
| 47 47 |  | 
| 48 48 | 
             
                      def to_s
         | 
| 49 | 
            -
                        super.match(/[^:] | 
| 49 | 
            +
                        super.match(/[^:]+\z/)[0]
         | 
| 50 50 | 
             
                      end
         | 
| 51 51 | 
             
                    end
         | 
| 52 52 |  | 
| @@ -264,9 +264,9 @@ module Squared | |
| 264 264 | 
             
                                      val
         | 
| 265 265 | 
             
                                    end
         | 
| 266 266 | 
             
                                    emphasize(out, title: path, right: true, border: borderstyle, sub: [
         | 
| 267 | 
            -
                                      { pat:  | 
| 268 | 
            -
                                      { pat:  | 
| 269 | 
            -
                                      { pat:  | 
| 267 | 
            +
                                      { pat: /\A(#{Regexp.escape(path.to_s)})(.*)\z/, styles: theme[:header] },
         | 
| 268 | 
            +
                                      { pat: /\A(#{Regexp.escape(name)})(.*)\z/, styles: theme[:active] },
         | 
| 269 | 
            +
                                      { pat: /\A(.+ )(\()(\d+)(\))(.*)\z/, styles: theme[:inline], index: 3 }
         | 
| 270 270 | 
             
                                    ])
         | 
| 271 271 | 
             
                                  end
         | 
| 272 272 | 
             
                                end
         | 
| @@ -550,7 +550,7 @@ module Squared | |
| 550 550 | 
             
                      cmd = session_done(cmd)
         | 
| 551 551 | 
             
                      log.info cmd
         | 
| 552 552 | 
             
                      begin
         | 
| 553 | 
            -
                        if cmd =~  | 
| 553 | 
            +
                        if cmd =~ /\A[^:]+:[^:]/ && workspace.task_defined?(cmd)
         | 
| 554 554 | 
             
                          log.warn "ENV was discarded: #{var}" if var
         | 
| 555 555 | 
             
                          task_invoke(cmd, exception: exception, warning: warning?)
         | 
| 556 556 | 
             
                        else
         | 
| @@ -749,6 +749,8 @@ module Squared | |
| 749 749 | 
             
                    end
         | 
| 750 750 |  | 
| 751 751 | 
             
                    def format_desc(action, flag, opts = nil, req: nil, arg: 'opts*')
         | 
| 752 | 
            +
                      return unless Rake::TaskManager.record_task_metadata
         | 
| 753 | 
            +
             | 
| 752 754 | 
             
                      opts = "#{arg}=#{opts.join(',')}" if opts.is_a?(Array)
         | 
| 753 755 | 
             
                      out = [@desc]
         | 
| 754 756 | 
             
                      if flag
         | 
| @@ -771,7 +773,7 @@ module Squared | |
| 771 773 | 
             
                      end
         | 
| 772 774 | 
             
                      if verbose
         | 
| 773 775 | 
             
                        out = []
         | 
| 774 | 
            -
                        out << cmd.sub( | 
| 776 | 
            +
                        out << cmd.sub(/\A\S+/, &:upcase) if data[:command]
         | 
| 775 777 | 
             
                        data[:order].each do |val|
         | 
| 776 778 | 
             
                          if val.is_a?(Array)
         | 
| 777 779 | 
             
                            s = ' '
         | 
| @@ -793,7 +795,7 @@ module Squared | |
| 793 795 | 
             
                          out << val.to_s
         | 
| 794 796 | 
             
                        end
         | 
| 795 797 | 
             
                        print_banner(*out, styles: data[:styles], border: data[:border], client: client)
         | 
| 796 | 
            -
                      elsif  | 
| 798 | 
            +
                      elsif workspace.series.multiple?
         | 
| 797 799 | 
             
                        "## #{__send__(data[:order].first || :path)} ##"
         | 
| 798 800 | 
             
                      end
         | 
| 799 801 | 
             
                    end
         | 
| @@ -818,10 +820,10 @@ module Squared | |
| 818 820 | 
             
                        end
         | 
| 819 821 | 
             
                        if from
         | 
| 820 822 | 
             
                          out << from
         | 
| 821 | 
            -
                          pat =  | 
| 823 | 
            +
                          pat = /\A(#{Regexp.escape(out.last)})(.*)\z/m
         | 
| 822 824 | 
             
                        end
         | 
| 823 825 | 
             
                      else
         | 
| 824 | 
            -
                        pat =  | 
| 826 | 
            +
                        pat = /\A(\s*\d+\.)(.+)\z/m
         | 
| 825 827 | 
             
                      end
         | 
| 826 828 | 
             
                      sub = [headerstyle]
         | 
| 827 829 | 
             
                      sub << { pat: pat, styles: theme[:active] } if pat
         | 
| @@ -833,16 +835,32 @@ module Squared | |
| 833 835 | 
             
                    end
         | 
| 834 836 |  | 
| 835 837 | 
             
                    def append_repeat(flag, opts)
         | 
| 836 | 
            -
                      opts.each { |val| @session <<  | 
| 838 | 
            +
                      opts.each { |val| @session << shell_option(flag, val, quote: true) }
         | 
| 837 839 | 
             
                    end
         | 
| 838 840 |  | 
| 839 | 
            -
                    def append_value(opts, delim: false)
         | 
| 841 | 
            +
                    def append_value(opts, delim: false, escape: true)
         | 
| 840 842 | 
             
                      @session << '--' if delim && !opts.empty?
         | 
| 841 | 
            -
                      opts.each { |val| @session << shell_escape(val) }
         | 
| 843 | 
            +
                      opts.each { |val| @session << (escape ? shell_escape(val) : shell_quote(val)) }
         | 
| 842 844 | 
             
                    end
         | 
| 843 845 |  | 
| 844 | 
            -
                    def  | 
| 845 | 
            -
                      list.each  | 
| 846 | 
            +
                    def append_first(list, flag: true, equals: false, quote: false, **kwargs)
         | 
| 847 | 
            +
                      list.each do |opt|
         | 
| 848 | 
            +
                        next unless (val = option(opt, **kwargs))
         | 
| 849 | 
            +
             | 
| 850 | 
            +
                        return @session << (if flag
         | 
| 851 | 
            +
                                              shell_option(opt, equals ? val : nil, quote: quote)
         | 
| 852 | 
            +
                                            else
         | 
| 853 | 
            +
                                              shell_quote(val)
         | 
| 854 | 
            +
                                            end)
         | 
| 855 | 
            +
                      end
         | 
| 856 | 
            +
                    end
         | 
| 857 | 
            +
             | 
| 858 | 
            +
                    def append_option(list, equals: false, quote: false, **kwargs)
         | 
| 859 | 
            +
                      list.each do |flag|
         | 
| 860 | 
            +
                        next unless (val = option(flag, **kwargs))
         | 
| 861 | 
            +
             | 
| 862 | 
            +
                        @session << shell_option(flag, equals ? val : nil, quote: quote)
         | 
| 863 | 
            +
                      end
         | 
| 846 864 | 
             
                    end
         | 
| 847 865 |  | 
| 848 866 | 
             
                    def append_nocolor(flag = nil)
         |