From 1173dedde2d7bc1f9c22058e845b81520f14fe75 Mon Sep 17 00:00:00 2001 From: Mitch Stanley Date: Sat, 25 Apr 2020 16:21:39 +0100 Subject: [PATCH 01/12] Initial work on crystal 0.34.0 compatability, migrating to new logger --- .tool-versions | 2 +- README.md | 2 +- shard.lock | 8 ++-- shard.yml | 8 ++-- src/snipline_cli.cr | 7 ++- src/snipline_cli/commands/login.cr | 7 ++- .../services/create_config_directory.cr | 2 +- src/snipline_cli/services/display_results.cr | 1 + src/snipline_cli/services/edit_snippet.cr | 7 ++- src/snipline_cli/services/load_snippets.cr | 5 +- src/snipline_cli/services/log.cr | 47 ------------------- src/snipline_cli/services/snipline_api.cr | 6 +-- 12 files changed, 26 insertions(+), 76 deletions(-) diff --git a/.tool-versions b/.tool-versions index 4991363..5e03da4 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -crystal 0.32.1 +crystal 0.34.0 diff --git a/README.md b/README.md index 538970a..d0075a2 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ Set log levels for additional development output. ```bash crystal build src/snipline_cli.cr -o snipcli -env LOG_LEVEL=DEBUG ./snipcli search git +env CRYSTAL_LOG_LEVEL=INFO ./snipcli search git ``` To change the config file location (For testing) use the `CONFIG_FILE` environment variable. diff --git a/shard.lock b/shard.lock index a1ec933..a86c3a8 100644 --- a/shard.lock +++ b/shard.lock @@ -2,11 +2,11 @@ version: 1.0 shards: admiral: github: jwaldrip/admiral.cr - version: 1.9.0 + version: 1.10.1 ameba: github: veelenga/ameba - version: 0.11.0 + version: 0.12.1 crecto: github: Crecto/crecto @@ -14,7 +14,7 @@ shards: crest: github: mamantoha/crest - version: 0.22.0 + version: 0.25.0 db: github: crystal-lang/crystal-db @@ -22,7 +22,7 @@ shards: fuzzy_match: github: acoustep/fuzzy_match.cr - commit: fe9eed429118adc8f0f9f6c91de4f11cdca5840e + commit: 3834b23deab80c4554ce15b015b804f010e2b768 http-client-digest_auth: github: mamantoha/http-client-digest_auth diff --git a/shard.yml b/shard.yml index 8774805..f5e2ea5 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: cli -version: 0.3.3 +version: 0.3.4 authors: - Mitchell Stanley @@ -8,7 +8,7 @@ targets: cli2: main: src/cli.cr -crystal: < 0.33 +crystal: 0.34.0 license: MIT @@ -17,7 +17,7 @@ dependencies: github: jwaldrip/admiral.cr crest: github: mamantoha/crest - version: ~> 0.22.0 + version: ~> 0.25.0 toml: github: crystal-community/toml.cr branch: master @@ -38,4 +38,4 @@ dependencies: development_dependencies: ameba: github: veelenga/ameba - version: ~> 0.11.0 + version: ~> 0.12.1 diff --git a/src/snipline_cli.cr b/src/snipline_cli.cr index 82f90bf..5585744 100644 --- a/src/snipline_cli.cr +++ b/src/snipline_cli.cr @@ -5,6 +5,7 @@ require "json" require "ncurses" require "sqlite3" require "crecto" +require "log" require "./snipline_cli/config" require "./snipline_cli/helpers/*" @@ -17,6 +18,8 @@ require "./snipline_cli/commands/*" include SniplineCli::Services +Log.setup_from_env + module Repo extend Crecto::Repo @@ -37,10 +40,6 @@ module SniplineCli ENV.has_key?("CONFIG_FILE") ? ENV["CONFIG_FILE"] : "~/.config/snipline/config.toml" end - def self.log - Log.log - end - # The base Command Class that inherits from [Admiral](https://github.com/jwaldrip/admiral.cr) # # This command is not used by itself diff --git a/src/snipline_cli/commands/login.cr b/src/snipline_cli/commands/login.cr index e341a47..eda2de3 100644 --- a/src/snipline_cli/commands/login.cr +++ b/src/snipline_cli/commands/login.cr @@ -14,7 +14,6 @@ module SniplineCli def run config = SniplineCli.config - log = SniplineCli.log puts "What's your Snipline email account?".colorize.mode(:bold) puts "Register at #{"https://account.snipline.io/register".colorize.mode(:underline)} if you don't have an account." print "Email:" @@ -30,7 +29,7 @@ module SniplineCli puts "Please enter the verification code that was sent to your email:" print "Verification Code:" verification_code = gets - log.debug("verification_code: #{verification_code}") + Log.debug { "verification_code: #{verification_code}" } if verification_code.nil? || verification_code.empty? puts "Code not entered. Please try again." return @@ -46,9 +45,9 @@ module SniplineCli :length => "year", } ) do |response| - log.debug("response body") + Log.debug { "response body" } json_string = response.body_io.gets_to_end - log.debug(json_string.inspect) + Log.debug { json_string.inspect } token = Token.from_json(json_string) toml_contents = <<-TOML title = "Snipline" diff --git a/src/snipline_cli/services/create_config_directory.cr b/src/snipline_cli/services/create_config_directory.cr index 7b4626c..e1965bc 100644 --- a/src/snipline_cli/services/create_config_directory.cr +++ b/src/snipline_cli/services/create_config_directory.cr @@ -6,7 +6,7 @@ module SniplineCli def self.run(file) directory_name = SniplineCli::Helpers.expand_path(File.dirname(file)) unless File.directory?(directory_name) - SniplineCli.log.debug("Making config directory #{directory_name}") + Log.debug { "Making config directory #{directory_name}" } Dir.mkdir(directory_name) end end diff --git a/src/snipline_cli/services/display_results.cr b/src/snipline_cli/services/display_results.cr index b598469..b754065 100644 --- a/src/snipline_cli/services/display_results.cr +++ b/src/snipline_cli/services/display_results.cr @@ -35,6 +35,7 @@ module SniplineCli::Services break if codepoint == 17 # C+q - quit break if run_character_key(ch, codepoint) == false @left_pane.filter(@search.search_text) + else end @search.window.refresh end diff --git a/src/snipline_cli/services/edit_snippet.cr b/src/snipline_cli/services/edit_snippet.cr index 320a582..4c0cac0 100644 --- a/src/snipline_cli/services/edit_snippet.cr +++ b/src/snipline_cli/services/edit_snippet.cr @@ -10,8 +10,7 @@ module SniplineCli class EditSnippet def self.run(snippet : Snippet, input, output) config = SniplineCli.config - log = SniplineCli.log - log.info("editing snippet #{snippet.name}") + Log.info { "editing snippet #{snippet.name}" } temp_file = TempSnippetEditorFile.new(snippet) temp_file.create loop do @@ -19,8 +18,8 @@ module SniplineCli snippet_attributes = temp_file.read snippet.name = snippet_attributes.name snippet.real_command = snippet_attributes.real_command.strip - log.info(snippet.real_command.not_nil!) - log.info(snippet_attributes.real_command.not_nil!) + Log.info { snippet.real_command.not_nil! } + Log.info { snippet_attributes.real_command.not_nil! } snippet.documentation = snippet_attributes.documentation snippet.tags = (snippet_attributes.tags.nil?) ? nil : snippet_attributes.tags.not_nil!.join(",") snippet.snippet_alias = snippet_attributes.snippet_alias diff --git a/src/snipline_cli/services/load_snippets.cr b/src/snipline_cli/services/load_snippets.cr index 2486fde..64b4696 100644 --- a/src/snipline_cli/services/load_snippets.cr +++ b/src/snipline_cli/services/load_snippets.cr @@ -12,10 +12,9 @@ module SniplineCli class LoadSnippets def self.run : Array(Snippet) config = SniplineCli.config - log = SniplineCli.log - log.info("Looking through file #{config.get("general.db")}") + Log.info { "Looking through file #{config.get("general.db")}" } unless File.readable?(expand_path(config.get("general.db"))) - log.warn("Could not read #{config.get("general.db")}") + Log.warn { "Could not read #{config.get("general.db")}" } abort("Run #{"snipline-cli sync".colorize(:green)} first") end # File.open(File.expand_path(config.get("general.db"))) do |file| diff --git a/src/snipline_cli/services/log.cr b/src/snipline_cli/services/log.cr index ffadc3f..e69de29 100644 --- a/src/snipline_cli/services/log.cr +++ b/src/snipline_cli/services/log.cr @@ -1,47 +0,0 @@ -require "logger" - -module SniplineCli - module Services - # Log is a wrapper around the Crystal `Logger`. - # - # Example Usage - # - # ```crystal - # log = SniplineCli.log - # config = SniplineCli.config - # log.info("Looking through file #{config.get("general.file")}") - # ``` - # - # The output level can then be specified at run-time. - # - # ```bash - # env LOG_LEVEL=WARN snipcli sync - # ``` - class Log - # Constant that creates a fresh version of itself - for use with self.log. - INSTANCE = Log.new - - property logger : Logger - - def initialize - ENV["LOG_LEVEL"] ||= "WARN" - @logger = Logger.new(STDOUT, level: (ENV["LOG_LEVEL"] == "DEBUG") ? Logger::DEBUG : Logger::WARN) - end - - # The static convenience method for retreiving the Log class instance without regenerating it. - def self.log - Log::INSTANCE - end - - macro define_methods(names) - {% for name in names %} - def {{name}}(message : String) - @logger.{{name}}(message) - end - {% end %} - end - - define_methods([debug, warn, info, fatal]) - end - end -end diff --git a/src/snipline_cli/services/snipline_api.cr b/src/snipline_cli/services/snipline_api.cr index e2386d1..50e2a24 100644 --- a/src/snipline_cli/services/snipline_api.cr +++ b/src/snipline_cli/services/snipline_api.cr @@ -37,7 +37,7 @@ module SniplineCli::Services # :tags => snippet.tags # } }, - logging: ENV["LOG_LEVEL"] == "DEBUG" ? true : false + logging: ENV["CRYSTAL_LOG_LEVEL"] == "DEBUG" ? true : false ) SingleSnippetDataParser.from_json(resp.body).data end @@ -61,7 +61,7 @@ module SniplineCli::Services # :tags => snippet.tags # } }, - logging: ENV["LOG_LEVEL"] == "DEBUG" ? true : false + logging: ENV["CRYSTAL_LOG_LEVEL"] == "DEBUG" ? true : false ) response = SingleSnippetDataParser.from_json(resp.body).data snippet.name = response.name.not_nil! @@ -90,7 +90,7 @@ module SniplineCli::Services # "Accept" => "application/vnd.api+json", "Authorization" => "Bearer #{config.get("api.token")}", }, - logging: ENV["LOG_LEVEL"] == "DEBUG" ? true : false + logging: ENV["CRYSTAL_LOG_LEVEL"] == "DEBUG" ? true : false ) true rescue ex From 4f7f72db382201c5e98250953a75a49677690fcb Mon Sep 17 00:00:00 2001 From: Mitch Stanley Date: Tue, 28 Apr 2020 17:14:42 +0100 Subject: [PATCH 02/12] bugfix: execute commands on empty list --- src/snipline_cli/services/display_results.cr | 28 +++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/snipline_cli/services/display_results.cr b/src/snipline_cli/services/display_results.cr index b754065..7dae420 100644 --- a/src/snipline_cli/services/display_results.cr +++ b/src/snipline_cli/services/display_results.cr @@ -55,19 +55,27 @@ module SniplineCli::Services @left_pane.select_lower refresh_right_pane elsif codepoint == 67 || codepoint == 10 # Shift+c / Enter - copy - output = build_snippet - copy_snippet(output) - return false + unless @left_pane.results.size <= 0 + output = build_snippet + copy_snippet(output) + return false + end elsif codepoint == 68 # Shift+d - delete - delete_snippet - return false + unless @left_pane.results.size <= 0 + delete_snippet + return false + end elsif codepoint == 69 # Shift+e - edit - edit_snippet - return false + unless @left_pane.results.size <= 0 + edit_snippet + return false + end elsif codepoint == 82 # Shift+r - run - output = build_snippet - run_snippet(output) - return false + unless @left_pane.results.size <= 0 + output = build_snippet + run_snippet(output) + return false + end else @search.write(ch) @left_pane.filter(@search.search_text) From e58aca63bd3f28a732e5791f455baa84e51a5696 Mon Sep 17 00:00:00 2001 From: Mitch Stanley Date: Sat, 9 May 2020 13:12:56 +0100 Subject: [PATCH 03/12] formatting --- README.md | 6 +-- .../services/create_config_directory.cr | 3 +- src/snipline_cli/services/display_results.cr | 38 +++++++++---------- src/snipline_cli/services/snipline_api.cr | 2 +- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index d0075a2..3e28f87 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ sudo snap install snipcli --beta ### From source -Snipline CLI requires Crystal 0.30.1 to be installed to install from source +Snipline CLI requires Crystal 0.34.0 to be installed to install from source ```bash # Clone the repo @@ -37,9 +37,9 @@ git checkout crystal -v # Install dependencies shards -# Build app for Crystal 0.32.1 / MacOS +# Build app for Crystal 0.34.0 / MacOS crystal build src/snipline_cli.cr -o snipcli --release -o snipcli -# Build app for Crystal 0.31.1 / Linux (Alpine) +# Build app for Crystal 0.34.0 / Linux (Alpine) crystal build src/snipline_cli.cr -o snipcli --release -o snipcli -Dstatic_linux ./snipcli --version ``` diff --git a/src/snipline_cli/services/create_config_directory.cr b/src/snipline_cli/services/create_config_directory.cr index e1965bc..ef31d6a 100644 --- a/src/snipline_cli/services/create_config_directory.cr +++ b/src/snipline_cli/services/create_config_directory.cr @@ -1,10 +1,11 @@ require "../helpers/*" + module SniplineCli module Services # Creates a config directory for storing configuration files for SnipCLI. class CreateConfigDirectory def self.run(file) - directory_name = SniplineCli::Helpers.expand_path(File.dirname(file)) + directory_name = SniplineCli::Helpers.expand_path(File.dirname(file)) unless File.directory?(directory_name) Log.debug { "Making config directory #{directory_name}" } Dir.mkdir(directory_name) diff --git a/src/snipline_cli/services/display_results.cr b/src/snipline_cli/services/display_results.cr index 7dae420..77b4937 100644 --- a/src/snipline_cli/services/display_results.cr +++ b/src/snipline_cli/services/display_results.cr @@ -35,7 +35,7 @@ module SniplineCli::Services break if codepoint == 17 # C+q - quit break if run_character_key(ch, codepoint) == false @left_pane.filter(@search.search_text) - else + else end @search.window.refresh end @@ -55,27 +55,27 @@ module SniplineCli::Services @left_pane.select_lower refresh_right_pane elsif codepoint == 67 || codepoint == 10 # Shift+c / Enter - copy - unless @left_pane.results.size <= 0 - output = build_snippet - copy_snippet(output) - return false - end + unless @left_pane.results.size <= 0 + output = build_snippet + copy_snippet(output) + return false + end elsif codepoint == 68 # Shift+d - delete - unless @left_pane.results.size <= 0 - delete_snippet - return false - end + unless @left_pane.results.size <= 0 + delete_snippet + return false + end elsif codepoint == 69 # Shift+e - edit - unless @left_pane.results.size <= 0 - edit_snippet - return false - end + unless @left_pane.results.size <= 0 + edit_snippet + return false + end elsif codepoint == 82 # Shift+r - run - unless @left_pane.results.size <= 0 - output = build_snippet - run_snippet(output) - return false - end + unless @left_pane.results.size <= 0 + output = build_snippet + run_snippet(output) + return false + end else @search.write(ch) @left_pane.filter(@search.search_text) diff --git a/src/snipline_cli/services/snipline_api.cr b/src/snipline_cli/services/snipline_api.cr index 50e2a24..25b6b37 100644 --- a/src/snipline_cli/services/snipline_api.cr +++ b/src/snipline_cli/services/snipline_api.cr @@ -90,7 +90,7 @@ module SniplineCli::Services # "Accept" => "application/vnd.api+json", "Authorization" => "Bearer #{config.get("api.token")}", }, - logging: ENV["CRYSTAL_LOG_LEVEL"] == "DEBUG" ? true : false + logging: ENV["CRYSTAL_LOG_LEVEL"] == "DEBUG" ? true : false ) true rescue ex From 06a461e70cf4e6c6786cb0a1d6d236f05bd956c4 Mon Sep 17 00:00:00 2001 From: Mitch Stanley Date: Sat, 9 May 2020 13:14:20 +0100 Subject: [PATCH 04/12] Update version number --- shard.yml | 2 +- snap/snapcraft.yaml | 2 +- src/snipline_cli.cr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/shard.yml b/shard.yml index f5e2ea5..78cc9c9 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: cli -version: 0.3.4 +version: 0.4.0 authors: - Mitchell Stanley diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index a648022..e6864f7 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -1,5 +1,5 @@ name: snipcli -version: 0.3.3 +version: 0.4.0 summary: Shell Snippet organiser description: > Snipcli is a commandline interface for managing shell commands. Sync commands with your Snipline account or use in guest mode. Snipline lets you dynamically change command parameters easily so you never have to remember how to build a command. diff --git a/src/snipline_cli.cr b/src/snipline_cli.cr index 5585744..a506f46 100644 --- a/src/snipline_cli.cr +++ b/src/snipline_cli.cr @@ -30,7 +30,7 @@ module Repo end module SniplineCli - VERSION = "0.3.3" + VERSION = "0.4.0" def self.config Config.config From 97da30efb94d9150f467a3416a99d377a4458f68 Mon Sep 17 00:00:00 2001 From: Mitchell Stanley Date: Mon, 11 May 2020 13:26:05 +0100 Subject: [PATCH 05/12] Add Dockerfile for static Linux builds --- Dockerfile | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c502d59 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,3 @@ +FROM crystallang/crystal:0.34.0-alpine + +RUN apk add ncurses-static sqlite-dev sqlite-static From 179a5ccd5c6d24475dc81fe851d07ae1ffb18ba8 Mon Sep 17 00:00:00 2001 From: Mitchell Stanley Date: Mon, 11 May 2020 13:27:15 +0100 Subject: [PATCH 06/12] Add ncurses-dev dependency --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c502d59..8d4c5bd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,3 @@ FROM crystallang/crystal:0.34.0-alpine -RUN apk add ncurses-static sqlite-dev sqlite-static +RUN apk add ncurses-dev ncurses-static sqlite-dev sqlite-static From 1ee3f48811a87f535606176aa1faf2c9eb6b68ac Mon Sep 17 00:00:00 2001 From: Mitchell Stanley Date: Wed, 30 Sep 2020 13:49:32 +0100 Subject: [PATCH 07/12] Add backslash comma functionality for multi select --- src/snipline_cli/models/snippet.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/snipline_cli/models/snippet.cr b/src/snipline_cli/models/snippet.cr index 9783127..7c5ed7f 100644 --- a/src/snipline_cli/models/snippet.cr +++ b/src/snipline_cli/models/snippet.cr @@ -33,7 +33,7 @@ module SniplineCli::Models param_name = split_equals.shift unparsed_params = split_equals.join("=") if unparsed_params.is_a?(String) - options = unparsed_params.split(",").map(&.strip) + options = unparsed_params.gsub("\\,", "###COMMA###").split(",").map(&.gsub("###COMMA###", ",")).map(&.strip) # todo if options.is_a?(Array(String)) options = options.as(Array(String)) From 1f1441c9ec8596a9a606d1f275f1c4d3a153a846 Mon Sep 17 00:00:00 2001 From: Mitchell Stanley Date: Wed, 30 Sep 2020 13:50:15 +0100 Subject: [PATCH 08/12] Updates for Crystal 0.35.1 --- .tool-versions | 2 +- README.md | 4 +- shard.lock | 46 +++++++++--------- shard.yml | 11 +++-- src/snipline_cli.cr | 7 +-- src/snipline_cli/commands/login.cr | 7 ++- .../parsers/snippet_data_parser.cr | 36 ++++++++------ src/snipline_cli/parsers/snippet_parser.cr | 21 +++++++-- .../services/create_config_directory.cr | 3 +- src/snipline_cli/services/edit_snippet.cr | 8 ++-- src/snipline_cli/services/load_snippets.cr | 5 +- src/snipline_cli/services/log.cr | 47 ------------------- 12 files changed, 85 insertions(+), 112 deletions(-) delete mode 100644 src/snipline_cli/services/log.cr diff --git a/.tool-versions b/.tool-versions index 4991363..6a1399d 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -crystal 0.32.1 +crystal 0.35.1 diff --git a/README.md b/README.md index 538970a..8b7291e 100644 --- a/README.md +++ b/README.md @@ -26,13 +26,13 @@ sudo snap install snipcli --beta ### From source -Snipline CLI requires Crystal 0.30.1 to be installed to install from source +Snipline CLI requires Crystal 0.35.1 to be installed to install from source ```bash # Clone the repo git clone git@github.com:snipline/snipcli.git # Checkout the latest release -git checkout +git checkout # Make sure you have the same Crystal installed that's required in shard.yml crystal -v # Install dependencies diff --git a/shard.lock b/shard.lock index a1ec933..aa27eea 100644 --- a/shard.lock +++ b/shard.lock @@ -1,42 +1,46 @@ -version: 1.0 +version: 2.0 shards: admiral: - github: jwaldrip/admiral.cr - version: 1.9.0 + git: https://github.com/jwaldrip/admiral.cr.git + version: 1.11.2 ameba: - github: veelenga/ameba - version: 0.11.0 + git: https://github.com/veelenga/ameba.git + version: 0.13.2 crecto: - github: Crecto/crecto - version: 0.11.2 + git: https://github.com/Crecto/crecto.git + version: 0.11.3 crest: - github: mamantoha/crest - version: 0.22.0 + git: https://github.com/mamantoha/crest.git + version: 0.26.1 db: - github: crystal-lang/crystal-db - version: 0.7.0 + git: https://github.com/crystal-lang/crystal-db.git + version: 0.9.0 fuzzy_match: - github: acoustep/fuzzy_match.cr - commit: fe9eed429118adc8f0f9f6c91de4f11cdca5840e + git: https://github.com/acoustep/fuzzy_match.cr.git + version: 0.3.0+git.commit.3834b23deab80c4554ce15b015b804f010e2b768 http-client-digest_auth: - github: mamantoha/http-client-digest_auth - version: 0.3.0 + git: https://github.com/mamantoha/http-client-digest_auth.git + version: 0.4.0 + + http_proxy: + git: https://github.com/mamantoha/http_proxy.git + version: 0.7.1 ncurses: - github: JohnDowson/ncurses - commit: d0e46f673b6a443255269ce610d598a0fdc7d159 + git: https://github.com/JohnDowson/ncurses.git + version: 0.0.3+git.commit.d0e46f673b6a443255269ce610d598a0fdc7d159 sqlite3: - github: crystal-lang/crystal-sqlite3 - version: 0.14.0 + git: https://github.com/crystal-lang/crystal-sqlite3.git + version: 0.16.0 toml: - github: crystal-community/toml.cr - commit: d02de85eed68a70dc97ab6d6e52831a4d0e890fe + git: https://github.com/crystal-community/toml.cr.git + version: 0.6.1+git.commit.d02de85eed68a70dc97ab6d6e52831a4d0e890fe diff --git a/shard.yml b/shard.yml index 8774805..0b4874d 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: cli -version: 0.3.3 +version: 0.4.0 authors: - Mitchell Stanley @@ -8,7 +8,7 @@ targets: cli2: main: src/cli.cr -crystal: < 0.33 +crystal: < 0.36.0 license: MIT @@ -17,7 +17,7 @@ dependencies: github: jwaldrip/admiral.cr crest: github: mamantoha/crest - version: ~> 0.22.0 + version: ~> 0.26.1 toml: github: crystal-community/toml.cr branch: master @@ -26,9 +26,10 @@ dependencies: branch: borders_and_lines crecto: github: Crecto/crecto + version: ~> 0.11.3 sqlite3: github: crystal-lang/crystal-sqlite3 - version: ~> 0.14.0 + version: ~> 0.16.0 fuzzy_match: github: acoustep/fuzzy_match.cr branch: master @@ -38,4 +39,4 @@ dependencies: development_dependencies: ameba: github: veelenga/ameba - version: ~> 0.11.0 + version: ~> 0.13.2 diff --git a/src/snipline_cli.cr b/src/snipline_cli.cr index 82f90bf..bca1578 100644 --- a/src/snipline_cli.cr +++ b/src/snipline_cli.cr @@ -5,6 +5,7 @@ require "json" require "ncurses" require "sqlite3" require "crecto" +require "log" require "./snipline_cli/config" require "./snipline_cli/helpers/*" @@ -27,7 +28,7 @@ module Repo end module SniplineCli - VERSION = "0.3.3" + VERSION = "0.4.0" def self.config Config.config @@ -37,10 +38,6 @@ module SniplineCli ENV.has_key?("CONFIG_FILE") ? ENV["CONFIG_FILE"] : "~/.config/snipline/config.toml" end - def self.log - Log.log - end - # The base Command Class that inherits from [Admiral](https://github.com/jwaldrip/admiral.cr) # # This command is not used by itself diff --git a/src/snipline_cli/commands/login.cr b/src/snipline_cli/commands/login.cr index e341a47..eda2de3 100644 --- a/src/snipline_cli/commands/login.cr +++ b/src/snipline_cli/commands/login.cr @@ -14,7 +14,6 @@ module SniplineCli def run config = SniplineCli.config - log = SniplineCli.log puts "What's your Snipline email account?".colorize.mode(:bold) puts "Register at #{"https://account.snipline.io/register".colorize.mode(:underline)} if you don't have an account." print "Email:" @@ -30,7 +29,7 @@ module SniplineCli puts "Please enter the verification code that was sent to your email:" print "Verification Code:" verification_code = gets - log.debug("verification_code: #{verification_code}") + Log.debug { "verification_code: #{verification_code}" } if verification_code.nil? || verification_code.empty? puts "Code not entered. Please try again." return @@ -46,9 +45,9 @@ module SniplineCli :length => "year", } ) do |response| - log.debug("response body") + Log.debug { "response body" } json_string = response.body_io.gets_to_end - log.debug(json_string.inspect) + Log.debug { json_string.inspect } token = Token.from_json(json_string) toml_contents = <<-TOML title = "Snipline" diff --git a/src/snipline_cli/parsers/snippet_data_parser.cr b/src/snipline_cli/parsers/snippet_data_parser.cr index ade32aa..f22f53d 100644 --- a/src/snipline_cli/parsers/snippet_data_parser.cr +++ b/src/snipline_cli/parsers/snippet_data_parser.cr @@ -1,28 +1,36 @@ module SniplineCli::Parsers class SnippetDataParser - JSON.mapping({ - data: Array(SnippetParser), - }) + include JSON::Serializable + + @[JSON::Field(key: "data")] + property data : Array(SnippetParser) end class SingleSnippetDataParser - JSON.mapping({ - data: SnippetParser, - }) + include JSON::Serializable + + @[JSON::Field(key: "data")] + property data : SnippetParser end class SnippetError - JSON.mapping({ - detail: String, - source: Hash(String, String), - title: String, - }) + include JSON::Serializable + + @[JSON::Field(key: "detail")] + property detail : String + + @[JSON::Field(key: "source")] + property source : Hash(String, String) + + @[JSON::Field(key: "title")] + property title : String end class SnippetErrorResponse - JSON.mapping({ - errors: Array(SnippetError), - }) + include JSON::Serializable + + @[JSON::Field(key: "errors")] + property errors : Array(SnippetError) def has_key?(key) @errors.any? { |error| diff --git a/src/snipline_cli/parsers/snippet_parser.cr b/src/snipline_cli/parsers/snippet_parser.cr index 9753a8e..d93a5e5 100644 --- a/src/snipline_cli/parsers/snippet_parser.cr +++ b/src/snipline_cli/parsers/snippet_parser.cr @@ -5,11 +5,22 @@ module SniplineCli::Parsers # # Note how most attributes are contained within the `attribute` attribute. This is to conform to the JSON-API specification. class SnippetParser - JSON.mapping({ - id: String | Nil, - type: String, - attributes: SnippetAttributeParser, - }) + include JSON::Serializable + + @[JSON::Field(key: "id")] + property id : String | Nil + + @[JSON::Field(key: "type")] + property type : String + + @[JSON::Field(key: "attributes")] + property attributes : SnippetAttributeParser + + # JSON.mapping({ + # id: String | Nil, + # type: String, + # attributes: SnippetAttributeParser, + # }) def initialize(@id : String | Nil, @type : String, @attributes : SnippetAttributeParser) end diff --git a/src/snipline_cli/services/create_config_directory.cr b/src/snipline_cli/services/create_config_directory.cr index 7b4626c..ce89cf8 100644 --- a/src/snipline_cli/services/create_config_directory.cr +++ b/src/snipline_cli/services/create_config_directory.cr @@ -1,4 +1,5 @@ require "../helpers/*" +require "log" module SniplineCli module Services # Creates a config directory for storing configuration files for SnipCLI. @@ -6,7 +7,7 @@ module SniplineCli def self.run(file) directory_name = SniplineCli::Helpers.expand_path(File.dirname(file)) unless File.directory?(directory_name) - SniplineCli.log.debug("Making config directory #{directory_name}") + Log.debug { "Making config directory #{directory_name}" } Dir.mkdir(directory_name) end end diff --git a/src/snipline_cli/services/edit_snippet.cr b/src/snipline_cli/services/edit_snippet.cr index 320a582..cf60697 100644 --- a/src/snipline_cli/services/edit_snippet.cr +++ b/src/snipline_cli/services/edit_snippet.cr @@ -1,4 +1,5 @@ require "../helpers/*" +require "log" module SniplineCli module Services @@ -10,8 +11,7 @@ module SniplineCli class EditSnippet def self.run(snippet : Snippet, input, output) config = SniplineCli.config - log = SniplineCli.log - log.info("editing snippet #{snippet.name}") + Log.info { "editing snippet #{snippet.name}" } temp_file = TempSnippetEditorFile.new(snippet) temp_file.create loop do @@ -19,8 +19,8 @@ module SniplineCli snippet_attributes = temp_file.read snippet.name = snippet_attributes.name snippet.real_command = snippet_attributes.real_command.strip - log.info(snippet.real_command.not_nil!) - log.info(snippet_attributes.real_command.not_nil!) + Log.info { snippet.real_command.not_nil! } + Log.info { snippet_attributes.real_command.not_nil! } snippet.documentation = snippet_attributes.documentation snippet.tags = (snippet_attributes.tags.nil?) ? nil : snippet_attributes.tags.not_nil!.join(",") snippet.snippet_alias = snippet_attributes.snippet_alias diff --git a/src/snipline_cli/services/load_snippets.cr b/src/snipline_cli/services/load_snippets.cr index 2486fde..64b4696 100644 --- a/src/snipline_cli/services/load_snippets.cr +++ b/src/snipline_cli/services/load_snippets.cr @@ -12,10 +12,9 @@ module SniplineCli class LoadSnippets def self.run : Array(Snippet) config = SniplineCli.config - log = SniplineCli.log - log.info("Looking through file #{config.get("general.db")}") + Log.info { "Looking through file #{config.get("general.db")}" } unless File.readable?(expand_path(config.get("general.db"))) - log.warn("Could not read #{config.get("general.db")}") + Log.warn { "Could not read #{config.get("general.db")}" } abort("Run #{"snipline-cli sync".colorize(:green)} first") end # File.open(File.expand_path(config.get("general.db"))) do |file| diff --git a/src/snipline_cli/services/log.cr b/src/snipline_cli/services/log.cr deleted file mode 100644 index ffadc3f..0000000 --- a/src/snipline_cli/services/log.cr +++ /dev/null @@ -1,47 +0,0 @@ -require "logger" - -module SniplineCli - module Services - # Log is a wrapper around the Crystal `Logger`. - # - # Example Usage - # - # ```crystal - # log = SniplineCli.log - # config = SniplineCli.config - # log.info("Looking through file #{config.get("general.file")}") - # ``` - # - # The output level can then be specified at run-time. - # - # ```bash - # env LOG_LEVEL=WARN snipcli sync - # ``` - class Log - # Constant that creates a fresh version of itself - for use with self.log. - INSTANCE = Log.new - - property logger : Logger - - def initialize - ENV["LOG_LEVEL"] ||= "WARN" - @logger = Logger.new(STDOUT, level: (ENV["LOG_LEVEL"] == "DEBUG") ? Logger::DEBUG : Logger::WARN) - end - - # The static convenience method for retreiving the Log class instance without regenerating it. - def self.log - Log::INSTANCE - end - - macro define_methods(names) - {% for name in names %} - def {{name}}(message : String) - @logger.{{name}}(message) - end - {% end %} - end - - define_methods([debug, warn, info, fatal]) - end - end -end From e0c8087a58b9712fd5cf93b067a3825d40169f03 Mon Sep 17 00:00:00 2001 From: Mitchell Stanley Date: Fri, 16 Oct 2020 15:23:18 +0100 Subject: [PATCH 09/12] Change to password auth --- src/snipline_cli/commands/login.cr | 57 ++++++++++++++++++------------ 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/src/snipline_cli/commands/login.cr b/src/snipline_cli/commands/login.cr index eda2de3..35a89e0 100644 --- a/src/snipline_cli/commands/login.cr +++ b/src/snipline_cli/commands/login.cr @@ -16,33 +16,45 @@ module SniplineCli config = SniplineCli.config puts "What's your Snipline email account?".colorize.mode(:bold) puts "Register at #{"https://account.snipline.io/register".colorize.mode(:underline)} if you don't have an account." + Log.debug { "Test debug" } print "Email:" email = gets - spawn do - Crest.post( - "#{config.get("api.url")}/sessions", - form: {:email => email} - ) - end - puts "Thanks, we're sending you a verification code..." - sleep 1 - puts "Please enter the verification code that was sent to your email:" - print "Verification Code:" - verification_code = gets - Log.debug { "verification_code: #{verification_code}" } - if verification_code.nil? || verification_code.empty? - puts "Code not entered. Please try again." + # spawn do + # Crest.post( + # "#{config.get("api.url")}/sessions", + # form: {:email => email} + # ) + # end + print "Enter your Snipline Account password:" + # password = gets + password = STDIN.noecho &.gets.try &.chomp + password = password.as?(String) || "" + + Log.debug { + + password_length = password.size + hidden_password = password.chars.map_with_index { |c, i| + unless i == 0 || i == (password_length - 1) + '*' + else + c + end + }.to_s + + "password: #{hidden_password}" + } + if password.empty? + puts "Password not entered. Please try again." return end + puts "" puts "One moment..." - puts "URL: #{config.get("api.url")}" begin Crest.post( - "#{config.get("api.url")}/tokens/create", + "#{config.get("api.url")}/v2/sessions", form: { - :id => email, - :token => verification_code, - :length => "year", + :email => email, + :password => password } ) do |response| Log.debug { "response body" } @@ -67,13 +79,12 @@ module SniplineCli end rescue ex : Crest::NotFound puts "404 Not Found :(" - ex.response rescue ex : Crest::InternalServerError puts "Internal server error" - ex.response rescue ex : Crest::Forbidden - puts "Incorrect Token" - ex.response + puts "Incorrect password" + rescue + puts "Unknown error" end end end From 4cd4c2832b7db580d46ac3e64ca4ebd95cfe2ade Mon Sep 17 00:00:00 2001 From: Mitchell Stanley Date: Fri, 16 Oct 2020 15:31:02 +0100 Subject: [PATCH 10/12] Fix Aemba styling --- README.md | 5 +++-- src/snipline_cli/commands/login.cr | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index be427c6..185cf94 100644 --- a/README.md +++ b/README.md @@ -128,11 +128,12 @@ As of 0.3.0 the web interface has been removed infavour of the new TUI. See the Installation section on building from source. -Set log levels for additional development output. +Set log levels for additional development output and specifiy different config files for testing ```bash crystal build src/snipline_cli.cr -o snipcli -env CRYSTAL_LOG_LEVEL=INFO ./snipcli search git +env CONFIG_FILE=~/.config/snipline/config.dev.toml ./snipcli search login +env CONFIG_FILE=~/.config/snipline/config.dev.toml env CRYSTAL_LOG_LEVEL=INFO ./snipcli search git ``` To change the config file location (For testing) use the `CONFIG_FILE` environment variable. diff --git a/src/snipline_cli/commands/login.cr b/src/snipline_cli/commands/login.cr index 35a89e0..b426633 100644 --- a/src/snipline_cli/commands/login.cr +++ b/src/snipline_cli/commands/login.cr @@ -30,14 +30,14 @@ module SniplineCli password = STDIN.noecho &.gets.try &.chomp password = password.as?(String) || "" - Log.debug { + Log.debug { password_length = password.size - hidden_password = password.chars.map_with_index { |c, i| - unless i == 0 || i == (password_length - 1) - '*' - else + hidden_password = password.chars.map_with_index { |c, i| + if i == 0 || i == (password_length - 1) c + else + '*' end }.to_s From 80016faa5cc5c4fa06eb5ca0421bd29759017e93 Mon Sep 17 00:00:00 2001 From: Mitchell Stanley Date: Tue, 20 Oct 2020 15:34:26 +0100 Subject: [PATCH 11/12] Change info log to debug in sync command --- src/snipline_cli/services/load_snippets.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/snipline_cli/services/load_snippets.cr b/src/snipline_cli/services/load_snippets.cr index 64b4696..21f6263 100644 --- a/src/snipline_cli/services/load_snippets.cr +++ b/src/snipline_cli/services/load_snippets.cr @@ -12,7 +12,7 @@ module SniplineCli class LoadSnippets def self.run : Array(Snippet) config = SniplineCli.config - Log.info { "Looking through file #{config.get("general.db")}" } + Log.debug { "Looking through file #{config.get("general.db")}" } unless File.readable?(expand_path(config.get("general.db"))) Log.warn { "Could not read #{config.get("general.db")}" } abort("Run #{"snipline-cli sync".colorize(:green)} first") From c12d40939eb11e2556c26ed9dcb7c6fdb2c64434 Mon Sep 17 00:00:00 2001 From: Mitchell Stanley Date: Tue, 20 Oct 2020 16:01:38 +0100 Subject: [PATCH 12/12] Add the Dockerfile for linux builds --- Dockerfile | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8d4c5bd..f1884d9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,8 @@ -FROM crystallang/crystal:0.34.0-alpine +FROM crystallang/crystal:0.35.1-alpine +RUN apk add --update --no-cache --force-overwrite \ +openssl-libs-static openssl-dev g++ gc-dev \ +libc-dev libevent-dev libevent-static libxml2-dev llvm llvm-dev \ +llvm-static make pcre-dev readline-dev readline-static \ +yaml-dev zlib-dev zlib-static ncurses-static sqlite-dev sqlite-static openssl-dev +#ncurses-libs ncurses-dev -RUN apk add ncurses-dev ncurses-static sqlite-dev sqlite-static