intent 0.5.5 → 0.7.0
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/.gitignore +2 -0
 - data/LICENSE.txt +1 -1
 - data/README.md +10 -28
 - data/bin/{review → intent} +1 -2
 - data/bin/inventory +12 -0
 - data/bin/project_doc +30 -0
 - data/bin/projects +1 -1
 - data/bin/projects_active +123 -0
 - data/bin/todo +1 -1
 - data/bin/todo_review +123 -0
 - data/intent.gemspec +15 -7
 - data/lib/gem_ext/todo-txt.rb +26 -2
 - data/lib/intent/commands/base.rb +40 -0
 - data/lib/intent/commands/errors.rb +7 -0
 - data/lib/intent/commands/intent.rb +9 -0
 - data/lib/intent/commands/inventory.rb +174 -0
 - data/lib/intent/commands/projects.rb +34 -0
 - data/lib/intent/commands/todo.rb +51 -0
 - data/lib/intent/commands.rb +9 -0
 - data/lib/intent/core.rb +184 -0
 - data/lib/intent/desktop.rb +3 -0
 - data/lib/intent/projects.rb +1 -1
 - data/lib/intent/review.rb +10 -1
 - data/lib/intent/text/inventory.help.txt +6 -0
 - data/lib/intent/text/project.help.txt +7 -0
 - data/lib/intent/text/projects.help.txt +9 -0
 - data/lib/intent/text/todo.help.txt +15 -0
 - data/lib/intent/todo.rb +3 -1
 - data/lib/intent/ui/ttyui.rb +90 -0
 - data/lib/intent/verbs/add.rb +21 -0
 - data/lib/intent/verbs/cite.rb +14 -0
 - data/lib/intent/verbs/install.rb +20 -0
 - data/lib/intent/verbs/review.rb +131 -0
 - data/lib/intent/{todo/manager.rb → verbs/todo.rb} +3 -16
 - data/lib/intent/version.rb +1 -1
 - data/lib/intent.rb +20 -3
 - metadata +179 -32
 - data/.travis.yml +0 -4
 - data/CODE_OF_CONDUCT.md +0 -13
 - data/lib/intent/projects/manager.rb +0 -20
 - data/lib/intent/review/manager.rb +0 -17
 - /data/lib/intent/{projects → verbs}/status.rb +0 -0
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: a80e9d9082642b1f2325b40629ff95ffb096cdba644d0f2d5aa2af25541c2d2b
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 90ed06f5afbf84636fbeb70e6fab66a4868dc0d485b751178b2ff31568315237
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: a4a23b8d4882af953e2d330c26388c91bb86513c1881192952998f6f74b5f49b682f4b609566ea18b0b6f0ad7517020ac15ccc22ce8756edc001ac5fc25c455b
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: cfc14324613fc505a6ec0a591e73f667dd3360b4ec1d8ee7f05d86813fcbaf5e645f12b917579adc6b046223dbc251f665f65b0cd70087dac39d59cc7adfdccf
         
     | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/LICENSE.txt
    CHANGED
    
    | 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            The MIT License (MIT)
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            Copyright (c) 2016 Mark Rickerby
         
     | 
| 
      
 3 
     | 
    
         
            +
            Copyright (c) 2016-2024 Mark Rickerby <https://maetl.net>
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            Permission is hereby granted, free of charge, to any person obtaining a copy
         
     | 
| 
       6 
6 
     | 
    
         
             
            of this software and associated documentation files (the "Software"), to deal
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,41 +1,23 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # Intent
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
      
 3 
     | 
    
         
            +
            Automation engine with todo.txt
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
      
 5 
     | 
    
         
            +
            This tool is mired deep in the obscurity and pedantry of the text-based computing culture that originated in the 1970s and still continues today. You probably don’t want to use this.
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            ## Installation
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
            Add this line to your application's Gemfile:
         
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       12 
     | 
    
         
            -
            gem 'intent'
         
     | 
| 
       13 
9 
     | 
    
         
             
            ```
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
                $ bundle
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
            Or install it yourself as:
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                $ gem install intent
         
     | 
| 
      
 10 
     | 
    
         
            +
            gem install intent
         
     | 
| 
      
 11 
     | 
    
         
            +
            ```
         
     | 
| 
       22 
12 
     | 
    
         | 
| 
       23 
13 
     | 
    
         
             
            ## Usage
         
     | 
| 
       24 
14 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
            After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
            To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
            ## Contributing
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
            Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/intent. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
      
 15 
     | 
    
         
            +
            ```
         
     | 
| 
      
 16 
     | 
    
         
            +
            intent help
         
     | 
| 
      
 17 
     | 
    
         
            +
            ```
         
     | 
| 
       37 
18 
     | 
    
         | 
| 
       38 
     | 
    
         
            -
            ## License
         
     | 
| 
      
 19 
     | 
    
         
            +
            ## Copyright & License
         
     | 
| 
       39 
20 
     | 
    
         | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
      
 21 
     | 
    
         
            +
            Copyright 2024 Mark Rickerby <https://maetl.net>.
         
     | 
| 
       41 
22 
     | 
    
         | 
| 
      
 23 
     | 
    
         
            +
            All documentation and modelling concepts are **CC BY-NC**. Source code and command line tools are MIT.
         
     | 
    
        data/bin/{review → intent}
    RENAMED
    
    | 
         @@ -1,5 +1,4 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            #!/usr/bin/env ruby
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
2 
     | 
    
         
             
            path = __FILE__
         
     | 
| 
       4 
3 
     | 
    
         
             
            while File.symlink?(path)
         
     | 
| 
       5 
4 
     | 
    
         
             
              path = File.expand_path(File.readlink(path), File.dirname(path))
         
     | 
| 
         @@ -8,4 +7,4 @@ $:.unshift(File.join(File.dirname(File.expand_path(path)), '..', 'lib')) 
     | 
|
| 
       8 
7 
     | 
    
         | 
| 
       9 
8 
     | 
    
         
             
            require 'intent'
         
     | 
| 
       10 
9 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
            Intent:: 
     | 
| 
      
 10 
     | 
    
         
            +
            Intent::Dispatcher.exec_command(:intent, ARGV.dup)
         
     | 
    
        data/bin/inventory
    ADDED
    
    | 
         @@ -0,0 +1,12 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            path = __FILE__
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            while File.symlink?(path)
         
     | 
| 
      
 5 
     | 
    
         
            +
              path = File.expand_path(File.readlink(path), File.dirname(path))
         
     | 
| 
      
 6 
     | 
    
         
            +
            end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            $:.unshift(File.join(File.dirname(File.expand_path(path)), '..', 'lib'))
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            require 'intent'
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            Intent::Dispatcher.exec_command(:inventory, ARGV.dup)
         
     | 
    
        data/bin/project_doc
    ADDED
    
    | 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "tty-markdown"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "tty-pager"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            PROJECTS_PATH = File.dirname(ENV['TODO_TXT'])
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            class ProjectDocCommand
         
     | 
| 
      
 8 
     | 
    
         
            +
              def self.print_help(output)
         
     | 
| 
      
 9 
     | 
    
         
            +
                output.puts "Pass in a project name to read its main document."
         
     | 
| 
      
 10 
     | 
    
         
            +
                output.puts "Future iterations could display a list of available documents."
         
     | 
| 
      
 11 
     | 
    
         
            +
                # Command idea: Add milestone to document
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              def self.run(args, output=STDOUT)
         
     | 
| 
      
 15 
     | 
    
         
            +
                if args.empty?
         
     | 
| 
      
 16 
     | 
    
         
            +
                  print_help(output)
         
     | 
| 
      
 17 
     | 
    
         
            +
                else
         
     | 
| 
      
 18 
     | 
    
         
            +
                  project_name = args.first.delete("^0–9a-z\-")
         
     | 
| 
      
 19 
     | 
    
         
            +
                  project_path = "#{PROJECTS_PATH}/#{project_name}"
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  if Dir.exists?(project_path)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    pager = TTY::Pager.new
         
     | 
| 
      
 23 
     | 
    
         
            +
                    intent = File.read("#{project_path}/#{project_name}.md")
         
     | 
| 
      
 24 
     | 
    
         
            +
                    pager.page(TTY::Markdown.parse(intent))
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            ProjectDocCommand.run(ARGV.dup)
         
     | 
    
        data/bin/projects
    CHANGED
    
    
    
        data/bin/projects_active
    ADDED
    
    | 
         @@ -0,0 +1,123 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "tty-box"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "tty-screen"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "tty-reader"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "tty-cursor"
         
     | 
| 
      
 6 
     | 
    
         
            +
            require "tty-pager"
         
     | 
| 
      
 7 
     | 
    
         
            +
            require "pastel"
         
     | 
| 
      
 8 
     | 
    
         
            +
            require "todo-txt"
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            list = Todo::List.new(ENV['TODO_TXT'])
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            box = TTY::Box.frame(
         
     | 
| 
      
 13 
     | 
    
         
            +
              width: TTY::Screen.width,
         
     | 
| 
      
 14 
     | 
    
         
            +
              height: TTY::Screen.height-1,
         
     | 
| 
      
 15 
     | 
    
         
            +
              align: :center,
         
     | 
| 
      
 16 
     | 
    
         
            +
              border: :thick,
         
     | 
| 
      
 17 
     | 
    
         
            +
              style: {
         
     | 
| 
      
 18 
     | 
    
         
            +
                fg: :bright_yellow,
         
     | 
| 
      
 19 
     | 
    
         
            +
                border: {
         
     | 
| 
      
 20 
     | 
    
         
            +
                  fg: :white,
         
     | 
| 
      
 21 
     | 
    
         
            +
                }
         
     | 
| 
      
 22 
     | 
    
         
            +
              }
         
     | 
| 
      
 23 
     | 
    
         
            +
            )
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            focus_index = 0
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            def truncate(str, width)
         
     | 
| 
      
 28 
     | 
    
         
            +
              return str unless str.length >= width
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              "#{str.slice(0, width-3)}..."
         
     | 
| 
      
 31 
     | 
    
         
            +
            end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            def draw_card(top, item, focus)
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              style = unless top == focus
         
     | 
| 
      
 36 
     | 
    
         
            +
                { fg: :white, border: { fg: :white } }
         
     | 
| 
      
 37 
     | 
    
         
            +
              else
         
     | 
| 
      
 38 
     | 
    
         
            +
                { fg: :bright_white, border: { fg: :bright_magenta, bg: :black } }
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              title = if top == focus
         
     | 
| 
      
 42 
     | 
    
         
            +
                {bottom_right: "[x: close][enter: launch]"}
         
     | 
| 
      
 43 
     | 
    
         
            +
              else
         
     | 
| 
      
 44 
     | 
    
         
            +
                {}
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
              #pastel = Pastel.new
         
     | 
| 
      
 48 
     | 
    
         
            +
              width = 90
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              TTY::Box.frame(width: width, height: 4, left: 4, title: title, border: :thick, style: style) do
         
     | 
| 
      
 51 
     | 
    
         
            +
                "\s#{truncate(item[:title], 88)}"
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            projects = [
         
     | 
| 
      
 56 
     | 
    
         
            +
              { title: "maetl", index: File.read(File.expand_path("~/Documents/Projects/maetl/maetl.md")) },
         
     | 
| 
      
 57 
     | 
    
         
            +
              { title: "calyx", index: File.read(File.expand_path("~/Documents/Projects/calyx/calyx.md")) },
         
     | 
| 
      
 58 
     | 
    
         
            +
              { title: "yarrow", index: File.read(File.expand_path("~/Documents/Projects/yarrow/yarrow.md")) }
         
     | 
| 
      
 59 
     | 
    
         
            +
            ]
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            items_per_page = (TTY::Screen.height-1) / 4
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            # items = list.by_not_done.by_context("@reading").slice(0, items_per_page).map do |item|
         
     | 
| 
      
 64 
     | 
    
         
            +
            #   { title: item.text, href: item.text }
         
     | 
| 
      
 65 
     | 
    
         
            +
            # end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            $cursor = TTY::Cursor
         
     | 
| 
      
 68 
     | 
    
         
            +
            #print $cursor.hide
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            def draw_list(items, focus)
         
     | 
| 
      
 71 
     | 
    
         
            +
              buffer = []
         
     | 
| 
      
 72 
     | 
    
         
            +
              items.each_with_index do |item, i|
         
     | 
| 
      
 73 
     | 
    
         
            +
                buffer << draw_card(i, item, focus)
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
              result = buffer.join("")
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
              print $cursor.clear_screen + $cursor.move_to(0,0)
         
     | 
| 
      
 78 
     | 
    
         
            +
              print result
         
     | 
| 
      
 79 
     | 
    
         
            +
            end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            draw_list(projects, focus_index)
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
            reader = TTY::Reader.new(interrupt: :exit)
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            reader.on(:keyctrl_x, :keyescape) do
         
     | 
| 
      
 86 
     | 
    
         
            +
              print $cursor.clear_screen + $cursor.move_to(0,0)
         
     | 
| 
      
 87 
     | 
    
         
            +
              print $cursor.show
         
     | 
| 
      
 88 
     | 
    
         
            +
              exit
         
     | 
| 
      
 89 
     | 
    
         
            +
            end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
            reader.on(:keytab, :keydown) do
         
     | 
| 
      
 92 
     | 
    
         
            +
              if focus_index == projects.count - 1
         
     | 
| 
      
 93 
     | 
    
         
            +
                focus_index = 0
         
     | 
| 
      
 94 
     | 
    
         
            +
              else
         
     | 
| 
      
 95 
     | 
    
         
            +
                focus_index += 1
         
     | 
| 
      
 96 
     | 
    
         
            +
              end
         
     | 
| 
      
 97 
     | 
    
         
            +
              draw_list(projects, focus_index)
         
     | 
| 
      
 98 
     | 
    
         
            +
            end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
            reader.on(:keyup) do
         
     | 
| 
      
 101 
     | 
    
         
            +
              if focus_index == 0
         
     | 
| 
      
 102 
     | 
    
         
            +
                focus_index = projects.count - 1
         
     | 
| 
      
 103 
     | 
    
         
            +
              else
         
     | 
| 
      
 104 
     | 
    
         
            +
                focus_index -= 1
         
     | 
| 
      
 105 
     | 
    
         
            +
              end
         
     | 
| 
      
 106 
     | 
    
         
            +
              draw_list(projects, focus_index)
         
     | 
| 
      
 107 
     | 
    
         
            +
            end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
            reader.on(:keypress) do |key|
         
     | 
| 
      
 110 
     | 
    
         
            +
              # if key.value == "x"
         
     | 
| 
      
 111 
     | 
    
         
            +
              #   items.delete_at(focus_index)
         
     | 
| 
      
 112 
     | 
    
         
            +
              #   focus_index -= 1 if focus_index >= items.count
         
     | 
| 
      
 113 
     | 
    
         
            +
              #   draw_list(items, focus_index)
         
     | 
| 
      
 114 
     | 
    
         
            +
              # end
         
     | 
| 
      
 115 
     | 
    
         
            +
            end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            reader.on(:keyenter) do
         
     | 
| 
      
 118 
     | 
    
         
            +
              `chrome-cli open #{items[focus_index][:href]}`
         
     | 
| 
      
 119 
     | 
    
         
            +
            end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
            loop do
         
     | 
| 
      
 122 
     | 
    
         
            +
              reader.read_line(echo: false)
         
     | 
| 
      
 123 
     | 
    
         
            +
            end
         
     | 
    
        data/bin/todo
    CHANGED
    
    
    
        data/bin/todo_review
    ADDED
    
    | 
         @@ -0,0 +1,123 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "tty-box"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "tty-screen"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "tty-reader"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "tty-cursor"
         
     | 
| 
      
 6 
     | 
    
         
            +
            require "tty-pager"
         
     | 
| 
      
 7 
     | 
    
         
            +
            require "pastel"
         
     | 
| 
      
 8 
     | 
    
         
            +
            require "todo-txt"
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            list = Todo::List.new(ENV['TODO_TXT'])
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            box = TTY::Box.frame(
         
     | 
| 
      
 13 
     | 
    
         
            +
              width: TTY::Screen.width,
         
     | 
| 
      
 14 
     | 
    
         
            +
              height: TTY::Screen.height-1,
         
     | 
| 
      
 15 
     | 
    
         
            +
              align: :center,
         
     | 
| 
      
 16 
     | 
    
         
            +
              border: :thick,
         
     | 
| 
      
 17 
     | 
    
         
            +
              style: {
         
     | 
| 
      
 18 
     | 
    
         
            +
                fg: :bright_yellow,
         
     | 
| 
      
 19 
     | 
    
         
            +
                border: {
         
     | 
| 
      
 20 
     | 
    
         
            +
                  fg: :white,
         
     | 
| 
      
 21 
     | 
    
         
            +
                }
         
     | 
| 
      
 22 
     | 
    
         
            +
              }
         
     | 
| 
      
 23 
     | 
    
         
            +
            )
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            focus_index = 0
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            def truncate(str, width)
         
     | 
| 
      
 28 
     | 
    
         
            +
              return str unless str.length >= width
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              "#{str.slice(0, width-3)}..."
         
     | 
| 
      
 31 
     | 
    
         
            +
            end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            def draw_card(top, item, focus)
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              style = unless top == focus
         
     | 
| 
      
 36 
     | 
    
         
            +
                { fg: :white, border: { fg: :white } }
         
     | 
| 
      
 37 
     | 
    
         
            +
              else
         
     | 
| 
      
 38 
     | 
    
         
            +
                { fg: :bright_white, border: { fg: :bright_magenta, bg: :black } }
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              title = if top == focus
         
     | 
| 
      
 42 
     | 
    
         
            +
                {bottom_right: "[x: close][enter: launch]"}
         
     | 
| 
      
 43 
     | 
    
         
            +
              else
         
     | 
| 
      
 44 
     | 
    
         
            +
                {}
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
              #pastel = Pastel.new
         
     | 
| 
      
 48 
     | 
    
         
            +
              width = 90
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              TTY::Box.frame(width: width, height: 4, left: 4, title: title, border: :thick, style: style) do
         
     | 
| 
      
 51 
     | 
    
         
            +
                "\s#{truncate(item[:title], 88)}\n\s#{truncate(item[:href], 88)}"
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            items = [
         
     | 
| 
      
 56 
     | 
    
         
            +
              { title: "maetl website", href: "https://maetl.net/" },
         
     | 
| 
      
 57 
     | 
    
         
            +
              { title: "tty-cursor on Github", href: "https://github.com/piotrmurach/tty-cursor" },
         
     | 
| 
      
 58 
     | 
    
         
            +
              { title: "Tangram Design", href: "https://tangram.co.nz" },
         
     | 
| 
      
 59 
     | 
    
         
            +
            ]
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            items_per_page = (TTY::Screen.height-1) / 4
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            items = list.by_not_done.by_context("@reading").slice(0, items_per_page).map do |item|
         
     | 
| 
      
 64 
     | 
    
         
            +
              { title: item.text, href: item.text }
         
     | 
| 
      
 65 
     | 
    
         
            +
            end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            $cursor = TTY::Cursor
         
     | 
| 
      
 68 
     | 
    
         
            +
            print $cursor.hide
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            def draw_list(items, focus)
         
     | 
| 
      
 71 
     | 
    
         
            +
              buffer = []
         
     | 
| 
      
 72 
     | 
    
         
            +
              items.each_with_index do |item, i|
         
     | 
| 
      
 73 
     | 
    
         
            +
                buffer << draw_card(i, item, focus)
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
              result = buffer.join("")
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
              print $cursor.clear_screen + $cursor.move_to(0,0)
         
     | 
| 
      
 78 
     | 
    
         
            +
              print result
         
     | 
| 
      
 79 
     | 
    
         
            +
            end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            draw_list(items, focus_index)
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
            reader = TTY::Reader.new(interrupt: :exit)
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            reader.on(:keyctrl_x, :keyescape) do
         
     | 
| 
      
 86 
     | 
    
         
            +
              print $cursor.clear_screen + $cursor.move_to(0,0)
         
     | 
| 
      
 87 
     | 
    
         
            +
              print $cursor.show
         
     | 
| 
      
 88 
     | 
    
         
            +
              exit
         
     | 
| 
      
 89 
     | 
    
         
            +
            end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
            reader.on(:keytab, :keydown) do
         
     | 
| 
      
 92 
     | 
    
         
            +
              if focus_index == items.count - 1
         
     | 
| 
      
 93 
     | 
    
         
            +
                focus_index = 0
         
     | 
| 
      
 94 
     | 
    
         
            +
              else
         
     | 
| 
      
 95 
     | 
    
         
            +
                focus_index += 1
         
     | 
| 
      
 96 
     | 
    
         
            +
              end
         
     | 
| 
      
 97 
     | 
    
         
            +
              draw_list(items, focus_index)
         
     | 
| 
      
 98 
     | 
    
         
            +
            end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
            reader.on(:keyup) do
         
     | 
| 
      
 101 
     | 
    
         
            +
              if focus_index == 0
         
     | 
| 
      
 102 
     | 
    
         
            +
                focus_index = items.count - 1
         
     | 
| 
      
 103 
     | 
    
         
            +
              else
         
     | 
| 
      
 104 
     | 
    
         
            +
                focus_index -= 1
         
     | 
| 
      
 105 
     | 
    
         
            +
              end
         
     | 
| 
      
 106 
     | 
    
         
            +
              draw_list(items, focus_index)
         
     | 
| 
      
 107 
     | 
    
         
            +
            end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
            reader.on(:keypress) do |key|
         
     | 
| 
      
 110 
     | 
    
         
            +
              if key.value == "x"
         
     | 
| 
      
 111 
     | 
    
         
            +
                items.delete_at(focus_index)
         
     | 
| 
      
 112 
     | 
    
         
            +
                focus_index -= 1 if focus_index >= items.count
         
     | 
| 
      
 113 
     | 
    
         
            +
                draw_list(items, focus_index)
         
     | 
| 
      
 114 
     | 
    
         
            +
              end
         
     | 
| 
      
 115 
     | 
    
         
            +
            end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            reader.on(:keyenter) do
         
     | 
| 
      
 118 
     | 
    
         
            +
              `chrome-cli open #{items[focus_index][:href]}`
         
     | 
| 
      
 119 
     | 
    
         
            +
            end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
            loop do
         
     | 
| 
      
 122 
     | 
    
         
            +
              reader.read_line(echo: false)
         
     | 
| 
      
 123 
     | 
    
         
            +
            end
         
     | 
    
        data/intent.gemspec
    CHANGED
    
    | 
         @@ -18,14 +18,22 @@ Gem::Specification.new do |spec| 
     | 
|
| 
       18 
18 
     | 
    
         
             
              spec.executables   = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
         
     | 
| 
       19 
19 
     | 
    
         
             
              spec.require_paths = ["lib"]
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
              spec.add_runtime_dependency "todo-txt", "~> 0. 
     | 
| 
       22 
     | 
    
         
            -
              spec.add_runtime_dependency "pastel", "~> 0. 
     | 
| 
       23 
     | 
    
         
            -
              spec.add_runtime_dependency "git", "~> 1. 
     | 
| 
       24 
     | 
    
         
            -
              spec.add_runtime_dependency "terminal-notifier", "~>  
     | 
| 
      
 21 
     | 
    
         
            +
              spec.add_runtime_dependency "todo-txt", "~> 0.12"
         
     | 
| 
      
 22 
     | 
    
         
            +
              spec.add_runtime_dependency "pastel", "~> 0.8"
         
     | 
| 
      
 23 
     | 
    
         
            +
              spec.add_runtime_dependency "git", "~> 1.19.1"
         
     | 
| 
      
 24 
     | 
    
         
            +
              spec.add_runtime_dependency "terminal-notifier", "~> 2.0"
         
     | 
| 
       25 
25 
     | 
    
         
             
              spec.add_runtime_dependency "ghost", "~> 1.0.0"
         
     | 
| 
      
 26 
     | 
    
         
            +
              spec.add_runtime_dependency "unicode_plot", "0.0.5"
         
     | 
| 
      
 27 
     | 
    
         
            +
              spec.add_runtime_dependency "kdl", "1.0.3"
         
     | 
| 
      
 28 
     | 
    
         
            +
              spec.add_runtime_dependency "sorted_set", "1.0.3"
         
     | 
| 
      
 29 
     | 
    
         
            +
              spec.add_runtime_dependency "strings-ansi", "0.2.0"
         
     | 
| 
      
 30 
     | 
    
         
            +
              spec.add_runtime_dependency "bibtex-ruby", "6.1.0"
         
     | 
| 
      
 31 
     | 
    
         
            +
              spec.add_runtime_dependency "tty-prompt", "~> 0.23.1"
         
     | 
| 
      
 32 
     | 
    
         
            +
              spec.add_runtime_dependency "tty-table", "~> 0.12.0"
         
     | 
| 
      
 33 
     | 
    
         
            +
              spec.add_runtime_dependency "tty-tree", "~> 0.4.0"
         
     | 
| 
      
 34 
     | 
    
         
            +
              spec.add_runtime_dependency "nanoid", "~> 2.0.0"
         
     | 
| 
       26 
35 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
              spec.add_development_dependency " 
     | 
| 
       29 
     | 
    
         
            -
              spec.add_development_dependency "rake", "~> 10.0"
         
     | 
| 
      
 36 
     | 
    
         
            +
              spec.add_development_dependency "bundler"
         
     | 
| 
      
 37 
     | 
    
         
            +
              spec.add_development_dependency "rake"
         
     | 
| 
       30 
38 
     | 
    
         
             
              spec.add_development_dependency "rspec"
         
     | 
| 
       31 
39 
     | 
    
         
             
            end
         
     | 
    
        data/lib/gem_ext/todo-txt.rb
    CHANGED
    
    | 
         @@ -10,13 +10,37 @@ class Todo::Task 
     | 
|
| 
       10 
10 
     | 
    
         
             
                  # Completed tasks are rendered with a strikethrough
         
     | 
| 
       11 
11 
     | 
    
         
             
                  pastel.strikethrough(to_s)
         
     | 
| 
       12 
12 
     | 
    
         
             
                else
         
     | 
| 
       13 
     | 
    
         
            -
                   
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
      
 13 
     | 
    
         
            +
                  [
         
     | 
| 
      
 14 
     | 
    
         
            +
                    pastel.red(print_priority),
         
     | 
| 
      
 15 
     | 
    
         
            +
                    pastel.yellow(created_on.to_s),
         
     | 
| 
      
 16 
     | 
    
         
            +
                    text,
         
     | 
| 
      
 17 
     | 
    
         
            +
                    pastel.bold.magenta(print_contexts),
         
     | 
| 
      
 18 
     | 
    
         
            +
                    pastel.bold.blue(print_projects),
         
     | 
| 
      
 19 
     | 
    
         
            +
                    pastel.bold.cyan(print_tags)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  ].reject { |item| !item || item.nil? || item.empty? }.join(' ')
         
     | 
| 
       15 
21 
     | 
    
         
             
                end
         
     | 
| 
       16 
22 
     | 
    
         
             
              end
         
     | 
| 
       17 
23 
     | 
    
         | 
| 
      
 24 
     | 
    
         
            +
              def highlight_as_project
         
     | 
| 
      
 25 
     | 
    
         
            +
                return to_s unless STDOUT.tty?
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                pastel = Pastel.new
         
     | 
| 
      
 28 
     | 
    
         
            +
                [
         
     | 
| 
      
 29 
     | 
    
         
            +
                  pastel.bold.cyan(print_projects),
         
     | 
| 
      
 30 
     | 
    
         
            +
                  pastel.red(print_project_context)
         
     | 
| 
      
 31 
     | 
    
         
            +
                ].reject { |item| !item || item.nil? || item.empty? }.join(' ')
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              def text=(label)
         
     | 
| 
      
 35 
     | 
    
         
            +
                @text = label
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
       18 
38 
     | 
    
         
             
              private
         
     | 
| 
       19 
39 
     | 
    
         | 
| 
      
 40 
     | 
    
         
            +
              def print_project_context
         
     | 
| 
      
 41 
     | 
    
         
            +
                'active' if contexts.include?('@active')
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
       20 
44 
     | 
    
         
             
              def print_open_task(pastel)
         
     | 
| 
       21 
45 
     | 
    
         
             
                [
         
     | 
| 
       22 
46 
     | 
    
         
             
                  pastel.red(print_priority),
         
     | 
| 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Intent
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Commands
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Base
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :identity
         
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_reader :documents
         
     | 
| 
      
 6 
     | 
    
         
            +
              
         
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @identity = strip_classname
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @documents = ::Intent::Core::Documents.new
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
              
         
     | 
| 
      
 12 
     | 
    
         
            +
                  def print_help(output)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    output.puts(File.read(help_txt_path))
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def generate_id
         
     | 
| 
      
 17 
     | 
    
         
            +
                    Nanoid.generate(size: 8, alphabet: ID_ALPHABET)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  private
         
     | 
| 
      
 21 
     | 
    
         
            +
              
         
     | 
| 
      
 22 
     | 
    
         
            +
                  T_CLASS_PREFIX = 'Intent::Commands::'
         
     | 
| 
      
 23 
     | 
    
         
            +
              
         
     | 
| 
      
 24 
     | 
    
         
            +
                  ID_ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def strip_classname
         
     | 
| 
      
 27 
     | 
    
         
            +
                    self.class.to_s.sub(T_CLASS_PREFIX, '').downcase
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
              
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def help_txt_path
         
     | 
| 
      
 31 
     | 
    
         
            +
                    # TODO: does this work on Windows?
         
     | 
| 
      
 32 
     | 
    
         
            +
                    "#{__dir__}/../text/#{identity}.help.txt"
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  def create_noun(type, label, tags)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    Intent::Core::Noun.new(type, label, tags)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
            end
         
     |