na 1.1.21 → 1.1.22
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 +15 -0
- data/Gemfile.lock +1 -1
- data/README.md +8 -8
- data/bin/na +38 -22
- data/lib/na/next_action.rb +6 -6
- data/lib/na/string.rb +52 -8
- data/lib/na/version.rb +1 -1
- data/src/README.md +4 -4
- metadata +1 -1
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 584d55c84c26fddeb65bf537b4743b5cac4308f39d796d336d95c900fc966deb
         | 
| 4 | 
            +
              data.tar.gz: 73ea4289a1e43ce0b67f66f803a0db07359fe3f077358328a58c172c06daa107
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 89945d2a8df1c1ea11360da4258c09f9b5c8ad38f41ca5ef98a68b99c33b41fb0b718919cc680eb356903f284cef8dd4271acea94af7f8c4adca031d445a6a26
         | 
| 7 | 
            +
              data.tar.gz: 7c3f8c30bf5a4c69270641aadfb036303c42ee8678a09c2e8b5faad7883aff0ac0139caf465f9d37b84cf170ed4ee072ad20d4872b8c760b97d0e2ca1f3b6e2e
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,3 +1,18 @@ | |
| 1 | 
            +
            ### 1.1.22
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            2022-10-07 05:58
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            #### IMPROVED
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            - Help output and code documentation
         | 
| 8 | 
            +
            - Allow wildcards (* and ?) when matching todo history
         | 
| 9 | 
            +
            - Allow multiple todo queries separated by comma
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            #### FIXED
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            - Remove file extension when matching todo history
         | 
| 14 | 
            +
            - Todo history query failed on exact match
         | 
| 15 | 
            +
             | 
| 1 16 | 
             
            ### 1.1.21
         | 
| 2 17 |  | 
| 3 18 | 
             
            2022-10-07 04:26
         | 
    
        data/Gemfile.lock
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -9,7 +9,7 @@ | |
| 9 9 | 
             
            _If you're one of the rare people like me who find this useful, feel free to
         | 
| 10 10 | 
             
            [buy me some coffee][donate]._
         | 
| 11 11 |  | 
| 12 | 
            -
            The current version of `na` is 1.1. | 
| 12 | 
            +
            The current version of `na` is 1.1.22
         | 
| 13 13 | 
             
            .
         | 
| 14 14 |  | 
| 15 15 | 
             
            `na` ("next action") is a command line tool designed to make it easy to see what your next actions are for any project, right from the command line. It works with TaskPaper-formatted files (but any plain text format will do), looking for `@na` tags (or whatever you specify) in todo files in your current folder. 
         | 
| @@ -59,7 +59,7 @@ SYNOPSIS | |
| 59 59 | 
             
                na [global options] command [command options] [arguments...]
         | 
| 60 60 |  | 
| 61 61 | 
             
            VERSION
         | 
| 62 | 
            -
                1.1. | 
| 62 | 
            +
                1.1.22
         | 
| 63 63 |  | 
| 64 64 | 
             
            GLOBAL OPTIONS
         | 
| 65 65 | 
             
                -a, --[no-]add          - Add a next action (deprecated, for backwards compatibility)
         | 
| @@ -171,7 +171,7 @@ DESCRIPTION | |
| 171 171 | 
             
            COMMAND OPTIONS
         | 
| 172 172 | 
             
                -d, --depth=DEPTH                      - Recurse to depth (default: none)
         | 
| 173 173 | 
             
                -e, --regex                            - Interpret search pattern as regular expression
         | 
| 174 | 
            -
                --in=TODO_PATH                         - Show actions from a specific todo file in history (default: none)
         | 
| 174 | 
            +
                --in=TODO_PATH                         - Show actions from a specific todo file in history. May use wildcards (* and ?) (default: none)
         | 
| 175 175 | 
             
                -o, --or                               - Combine search tokens with OR, displaying actions matching ANY of the terms
         | 
| 176 176 | 
             
                --proj, --project=PROJECT[/SUBPROJECT] - Show actions from a specific project (default: none)
         | 
| 177 177 | 
             
                -v, --invert                           - Show actions not matching search pattern
         | 
| @@ -209,9 +209,9 @@ EXAMPLES | |
| 209 209 |  | 
| 210 210 | 
             
            Examples:
         | 
| 211 211 |  | 
| 212 | 
            -
            - `na  | 
| 213 | 
            -
            - `na  | 
| 214 | 
            -
            - `na  | 
| 212 | 
            +
            - `na next` (list all next actions in the current directory)
         | 
| 213 | 
            +
            - `na next -d 3` (list all next actions in the current directory and look for additional files 3 levels deep from there)
         | 
| 214 | 
            +
            - `na next marked2` (show next actions from another directory you've previously used na on)
         | 
| 215 215 |  | 
| 216 216 | 
             
            ```
         | 
| 217 217 | 
             
            NAME
         | 
| @@ -222,7 +222,7 @@ SYNOPSIS | |
| 222 222 | 
             
                na [global options] next [command options] [QUERY]
         | 
| 223 223 |  | 
| 224 224 | 
             
            DESCRIPTION
         | 
| 225 | 
            -
                Next actions are actions which contain the next action tag (default @na),   do not contain @done, and are not in the Archive project. 
         | 
| 225 | 
            +
                Next actions are actions which contain the next action tag (default @na),   do not contain @done, and are not in the Archive project.   Arguments will target a todo file from history, whether it's in the current   directory or not. Todo file queries can include path components separated by /   or :, and may use wildcards (`*` to match any text, `?` to match a single character). Multiple queries allowed (separate arguments or separated by comma). 
         | 
| 226 226 |  | 
| 227 227 | 
             
            COMMAND OPTIONS
         | 
| 228 228 | 
             
                -d, --depth=DEPTH                      - Recurse to depth (default: 2)
         | 
| @@ -256,7 +256,7 @@ SYNOPSIS | |
| 256 256 | 
             
                na [global options] next [command options] [QUERY]
         | 
| 257 257 |  | 
| 258 258 | 
             
            DESCRIPTION
         | 
| 259 | 
            -
                Next actions are actions which contain the next action tag (default @na),   do not contain @done, and are not in the Archive project. 
         | 
| 259 | 
            +
                Next actions are actions which contain the next action tag (default @na),   do not contain @done, and are not in the Archive project.   Arguments will target a todo file from history, whether it's in the current   directory or not. Todo file queries can include path components separated by /   or :, and may use wildcards (`*` to match any text, `?` to match a single character). Multiple queries allowed (separate arguments or separated by comma). 
         | 
| 260 260 |  | 
| 261 261 | 
             
            COMMAND OPTIONS
         | 
| 262 262 | 
             
                -d, --depth=DEPTH                      - Recurse to depth (default: 2)
         | 
    
        data/bin/na
    CHANGED
    
    | @@ -54,8 +54,12 @@ class App | |
| 54 54 | 
             
              switch %i[debug]
         | 
| 55 55 |  | 
| 56 56 | 
             
              desc 'Show next actions'
         | 
| 57 | 
            -
              long_desc  | 
| 58 | 
            -
              do not contain @done, and are not in the Archive project. | 
| 57 | 
            +
              long_desc 'Next actions are actions which contain the next action tag (default @na),
         | 
| 58 | 
            +
              do not contain @done, and are not in the Archive project.
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              Arguments will target a todo file from history, whether it\'s in the current
         | 
| 61 | 
            +
              directory or not. Todo file queries can include path components separated by /
         | 
| 62 | 
            +
              or :, and may use wildcards (`*` to match any text, `?` to match a single character). Multiple queries allowed (separate arguments or separated by comma).'
         | 
| 59 63 | 
             
              arg_name 'QUERY', optional: true
         | 
| 60 64 | 
             
              command %i[next show] do |c|
         | 
| 61 65 | 
             
                c.example 'na next', desc: 'display the next actions from any todo files in the current directory'
         | 
| @@ -93,11 +97,13 @@ class App | |
| 93 97 | 
             
                  if args.count.positive?
         | 
| 94 98 | 
             
                    tokens = []
         | 
| 95 99 | 
             
                    args.each do |arg|
         | 
| 96 | 
            -
                       | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 100 | 
            +
                      arg.split(/ *, */).each do |a|
         | 
| 101 | 
            +
                        m = a.match(/^(?<req>\+)?(?<tok>.*?)$/)
         | 
| 102 | 
            +
                        tokens.push({
         | 
| 103 | 
            +
                                      token: m['tok'],
         | 
| 104 | 
            +
                                      required: !m['req'].nil?
         | 
| 105 | 
            +
                                    })
         | 
| 106 | 
            +
                      end
         | 
| 101 107 | 
             
                    end
         | 
| 102 108 | 
             
                  end
         | 
| 103 109 |  | 
| @@ -251,7 +257,7 @@ class App | |
| 251 257 | 
             
                c.arg_name 'DEPTH'
         | 
| 252 258 | 
             
                c.flag %i[d depth], type: :integer, must_match: /^\d+$/
         | 
| 253 259 |  | 
| 254 | 
            -
                c.desc 'Show actions from a specific todo file in history'
         | 
| 260 | 
            +
                c.desc 'Show actions from a specific todo file in history. May use wildcards (* and ?)'
         | 
| 255 261 | 
             
                c.arg_name 'TODO_PATH'
         | 
| 256 262 | 
             
                c.flag %i[in]
         | 
| 257 263 |  | 
| @@ -292,10 +298,14 @@ class App | |
| 292 298 |  | 
| 293 299 | 
             
                  todo = nil
         | 
| 294 300 | 
             
                  if options[:in]
         | 
| 295 | 
            -
                    todo = [ | 
| 296 | 
            -
             | 
| 297 | 
            -
                       | 
| 298 | 
            -
             | 
| 301 | 
            +
                    todo = []
         | 
| 302 | 
            +
                    options[:in].split(/ *, */).each do |a|
         | 
| 303 | 
            +
                      m = a.match(/^(?<req>\+)?(?<tok>.*?)$/)
         | 
| 304 | 
            +
                      todo.push({
         | 
| 305 | 
            +
                                    token: m['tok'],
         | 
| 306 | 
            +
                                    required: !m['req'].nil?
         | 
| 307 | 
            +
                                  })
         | 
| 308 | 
            +
                    end
         | 
| 299 309 | 
             
                  end
         | 
| 300 310 |  | 
| 301 311 | 
             
                  files, actions = NA.parse_actions(depth: depth,
         | 
| @@ -335,7 +345,7 @@ class App | |
| 335 345 | 
             
                c.default_value 1
         | 
| 336 346 | 
             
                c.flag %i[d depth], type: :integer, must_match: /^\d+$/
         | 
| 337 347 |  | 
| 338 | 
            -
                c.desc 'Show actions from a specific todo file in history'
         | 
| 348 | 
            +
                c.desc 'Show actions from a specific todo file in history. May use wildcards (* and ?)'
         | 
| 339 349 | 
             
                c.arg_name 'TODO_PATH'
         | 
| 340 350 | 
             
                c.flag %i[in]
         | 
| 341 351 |  | 
| @@ -373,10 +383,14 @@ class App | |
| 373 383 |  | 
| 374 384 | 
             
                  todo = nil
         | 
| 375 385 | 
             
                  if options[:in]
         | 
| 376 | 
            -
                    todo = [ | 
| 377 | 
            -
             | 
| 378 | 
            -
                       | 
| 379 | 
            -
             | 
| 386 | 
            +
                    todo = []
         | 
| 387 | 
            +
                    options[:in].split(/ *, */).each do |a|
         | 
| 388 | 
            +
                      m = a.match(/^(?<req>\+)?(?<tok>.*?)$/)
         | 
| 389 | 
            +
                      todo.push({
         | 
| 390 | 
            +
                                    token: m['tok'],
         | 
| 391 | 
            +
                                    required: !m['req'].nil?
         | 
| 392 | 
            +
                                  })
         | 
| 393 | 
            +
                    end
         | 
| 380 394 | 
             
                  end
         | 
| 381 395 |  | 
| 382 396 | 
             
                  files, actions = NA.parse_actions(depth: depth,
         | 
| @@ -469,11 +483,13 @@ class App | |
| 469 483 | 
             
                  if args.count.positive?
         | 
| 470 484 | 
             
                    tokens = []
         | 
| 471 485 | 
             
                    args.each do |arg|
         | 
| 472 | 
            -
                       | 
| 473 | 
            -
             | 
| 474 | 
            -
             | 
| 475 | 
            -
             | 
| 476 | 
            -
             | 
| 486 | 
            +
                      arg.split(/ *, */).each do |a|
         | 
| 487 | 
            +
                        m = a.match(/^(?<req>\+)?(?<tok>.*?)$/)
         | 
| 488 | 
            +
                        tokens.push({
         | 
| 489 | 
            +
                                      token: m['tok'],
         | 
| 490 | 
            +
                                      required: !m['req'].nil?
         | 
| 491 | 
            +
                                    })
         | 
| 492 | 
            +
                      end
         | 
| 477 493 | 
             
                    end
         | 
| 478 494 | 
             
                  end
         | 
| 479 495 |  | 
    
        data/lib/na/next_action.rb
    CHANGED
    
    | @@ -379,18 +379,18 @@ module NA | |
| 379 379 | 
             
                ##                       between characters
         | 
| 380 380 | 
             
                ##
         | 
| 381 381 | 
             
                def match_working_dir(search, distance: 1)
         | 
| 382 | 
            -
                  search = search.map { |t| t[:token] }.join('/')
         | 
| 383 | 
            -
                  optional = [search]
         | 
| 384 | 
            -
                  required = [search]
         | 
| 385 | 
            -
             | 
| 386 382 | 
             
                  file = database_path
         | 
| 387 383 | 
             
                  notify('{r}No na database found', exit_code: 1) unless File.exist?(file)
         | 
| 388 384 |  | 
| 389 385 | 
             
                  dirs = IO.read(file).split("\n")
         | 
| 390 386 |  | 
| 391 | 
            -
                   | 
| 387 | 
            +
                  optional = search.map { |t| t[:token] }
         | 
| 388 | 
            +
                  required = search.filter { |s| s[:required] }.map { |t| t[:token] }
         | 
| 389 | 
            +
             | 
| 390 | 
            +
                  NA.notify("{bw}Optional directory regex: {x}#{optional.map(&:dir_to_rx)}", debug: true)
         | 
| 391 | 
            +
                  NA.notify("{bw}Required directory regex: {x}#{required.map(&:dir_to_rx)}", debug: true)
         | 
| 392 392 |  | 
| 393 | 
            -
                  dirs.delete_if { |d| !d.dir_matches(any: optional, all: required) }
         | 
| 393 | 
            +
                  dirs.delete_if { |d| !d.sub(/\.#{NA.extension}$/, '').dir_matches(any: optional, all: required) }
         | 
| 394 394 | 
             
                  dirs.sort.uniq
         | 
| 395 395 | 
             
                end
         | 
| 396 396 |  | 
    
        data/lib/na/string.rb
    CHANGED
    
    | @@ -1,6 +1,12 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            +
            # String helpers
         | 
| 3 4 | 
             
            class ::String
         | 
| 5 | 
            +
              ##
         | 
| 6 | 
            +
              ## Determine indentation level of line
         | 
| 7 | 
            +
              ##
         | 
| 8 | 
            +
              ## @return     [Number] number of indents detected
         | 
| 9 | 
            +
              ##
         | 
| 4 10 | 
             
              def indent_level
         | 
| 5 11 | 
             
                prefix = match(/(^[ \t]+)/)
         | 
| 6 12 | 
             
                return 0 if prefix.nil?
         | 
| @@ -11,7 +17,13 @@ class ::String | |
| 11 17 | 
             
              ##
         | 
| 12 18 | 
             
              ## Colorize @tags with ANSI escapes
         | 
| 13 19 | 
             
              ##
         | 
| 14 | 
            -
              ## @param      color | 
| 20 | 
            +
              ## @param      color       [String] color (see #Color)
         | 
| 21 | 
            +
              ## @param      value       [String] The value color
         | 
| 22 | 
            +
              ##                         template
         | 
| 23 | 
            +
              ## @param      parens      [String] The parens color
         | 
| 24 | 
            +
              ##                         template
         | 
| 25 | 
            +
              ## @param      last_color  [String] Color to restore after
         | 
| 26 | 
            +
              ##                         tag highlight
         | 
| 15 27 | 
             
              ##
         | 
| 16 28 | 
             
              ## @return     [String] string with @tags highlighted
         | 
| 17 29 | 
             
              ##
         | 
| @@ -23,6 +35,16 @@ class ::String | |
| 23 35 | 
             
                     "\\1#{tag_color}\\2#{paren_color}\\3#{value_color}\\4#{paren_color}\\5#{last_color}")
         | 
| 24 36 | 
             
              end
         | 
| 25 37 |  | 
| 38 | 
            +
              ##
         | 
| 39 | 
            +
              ## Highlight search results
         | 
| 40 | 
            +
              ##
         | 
| 41 | 
            +
              ## @param      regexes     [Array] The regexes for the
         | 
| 42 | 
            +
              ##                         search
         | 
| 43 | 
            +
              ## @param      color       [String] The highlight color
         | 
| 44 | 
            +
              ##                         template
         | 
| 45 | 
            +
              ## @param      last_color  [String] Color to restore after
         | 
| 46 | 
            +
              ##                         highlight
         | 
| 47 | 
            +
              ##
         | 
| 26 48 | 
             
              def highlight_search(regexes, color: '{y}', last_color: '{xg}')
         | 
| 27 49 | 
             
                string = dup
         | 
| 28 50 | 
             
                color = NA::Color.template(color)
         | 
| @@ -42,12 +64,13 @@ class ::String | |
| 42 64 |  | 
| 43 65 | 
             
              # Returns the last escape sequence from a string.
         | 
| 44 66 | 
             
              #
         | 
| 45 | 
            -
              # Actually returns all escape codes, with the | 
| 46 | 
            -
              # that the result of inserting them | 
| 47 | 
            -
              # same color as was set at | 
| 48 | 
            -
              # Because you can send | 
| 49 | 
            -
              #  | 
| 50 | 
            -
              #  | 
| 67 | 
            +
              # @note       Actually returns all escape codes, with the
         | 
| 68 | 
            +
              #             assumption that the result of inserting them
         | 
| 69 | 
            +
              #             will generate the same color as was set at
         | 
| 70 | 
            +
              #             the end of the string. Because you can send
         | 
| 71 | 
            +
              #             modifiers like dark and bold separate from
         | 
| 72 | 
            +
              #             color codes, only using the last code may
         | 
| 73 | 
            +
              #             not render the same style.
         | 
| 51 74 | 
             
              #
         | 
| 52 75 | 
             
              # @return     [String]  All escape codes in string
         | 
| 53 76 | 
             
              #
         | 
| @@ -55,8 +78,18 @@ class ::String | |
| 55 78 | 
             
                scan(/\e\[[\d;]+m/).join('').gsub(/\e\[0m/, '')
         | 
| 56 79 | 
             
              end
         | 
| 57 80 |  | 
| 81 | 
            +
              ##
         | 
| 82 | 
            +
              ## Convert a directory path to a regular expression
         | 
| 83 | 
            +
              ##
         | 
| 84 | 
            +
              ## @note       Splits at / or :, adds variable distance
         | 
| 85 | 
            +
              ##             between characters, joins segments with
         | 
| 86 | 
            +
              ##             slashes and requires that last segment
         | 
| 87 | 
            +
              ##             match last segment of target path
         | 
| 88 | 
            +
              ##
         | 
| 89 | 
            +
              ## @param      distance  The distance
         | 
| 90 | 
            +
              ##
         | 
| 58 91 | 
             
              def dir_to_rx(distance: 2)
         | 
| 59 | 
            -
                "#{split(%r{[/:]}).map { |comp| comp.split('').join(".{0,#{distance}}") }.join('.*?/.*?')}[^/] | 
| 92 | 
            +
                "#{split(%r{[/:]}).map { |comp| comp.split('').join(".{0,#{distance}}").gsub(/\*/, '[^ ]*?') }.join('.*?/.*?')}[^/]*?$"
         | 
| 60 93 | 
             
              end
         | 
| 61 94 |  | 
| 62 95 | 
             
              def dir_matches(any: [], all: [])
         | 
| @@ -67,6 +100,11 @@ class ::String | |
| 67 100 | 
             
                matches_any(any) && matches_all(all) && matches_none(none)
         | 
| 68 101 | 
             
              end
         | 
| 69 102 |  | 
| 103 | 
            +
              ##
         | 
| 104 | 
            +
              ## Convert wildcard characters to regular expressions
         | 
| 105 | 
            +
              ##
         | 
| 106 | 
            +
              ## @return     [String] Regex string
         | 
| 107 | 
            +
              ##
         | 
| 70 108 | 
             
              def wildcard_to_rx
         | 
| 71 109 | 
             
                gsub(/\./, '\\.').gsub(/\*/, '[^ ]*?').gsub(/\?/, '.')
         | 
| 72 110 | 
             
              end
         | 
| @@ -75,6 +113,12 @@ class ::String | |
| 75 113 | 
             
                replace cap_first
         | 
| 76 114 | 
             
              end
         | 
| 77 115 |  | 
| 116 | 
            +
              ##
         | 
| 117 | 
            +
              ## Capitalize first character, leaving other
         | 
| 118 | 
            +
              ## capitalization in place
         | 
| 119 | 
            +
              ##
         | 
| 120 | 
            +
              ## @return     [String] capitalized string
         | 
| 121 | 
            +
              ##
         | 
| 78 122 | 
             
              def cap_first
         | 
| 79 123 | 
             
                sub(/^([a-z])(.*)$/) do
         | 
| 80 124 | 
             
                  m = Regexp.last_match
         | 
    
        data/lib/na/version.rb
    CHANGED
    
    
    
        data/src/README.md
    CHANGED
    
    | @@ -9,7 +9,7 @@ | |
| 9 9 | 
             
            _If you're one of the rare people like me who find this useful, feel free to
         | 
| 10 10 | 
             
            [buy me some coffee][donate]._
         | 
| 11 11 |  | 
| 12 | 
            -
            The current version of `na` is <!--VER-->1.1. | 
| 12 | 
            +
            The current version of `na` is <!--VER-->1.1.21<!--END VER-->.
         | 
| 13 13 |  | 
| 14 14 | 
             
            `na` ("next action") is a command line tool designed to make it easy to see what your next actions are for any project, right from the command line. It works with TaskPaper-formatted files (but any plain text format will do), looking for `@na` tags (or whatever you specify) in todo files in your current folder. 
         | 
| 15 15 |  | 
| @@ -92,9 +92,9 @@ Unless `--exact` is specified, search is tokenized and combined with AND, so `na | |
| 92 92 |  | 
| 93 93 | 
             
            Examples:
         | 
| 94 94 |  | 
| 95 | 
            -
            - `na  | 
| 96 | 
            -
            - `na  | 
| 97 | 
            -
            - `na  | 
| 95 | 
            +
            - `na next` (list all next actions in the current directory)
         | 
| 96 | 
            +
            - `na next -d 3` (list all next actions in the current directory and look for additional files 3 levels deep from there)
         | 
| 97 | 
            +
            - `na next marked2` (show next actions from another directory you've previously used na on)
         | 
| 98 98 |  | 
| 99 99 | 
             
            ```
         | 
| 100 100 | 
             
            @cli(bundle exec bin/na help next)
         |