tinylinks 0.1.0 → 0.3.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/lib/tinylinks/cli.rb +25 -6
- data/lib/tinylinks/colorizer.rb +22 -0
- data/lib/tinylinks/formatter.rb +34 -7
- data/lib/tinylinks.rb +2 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bd4a470b6c9c25a8e96eb05ae5daaca8f40b3568110c0b70dd3f4e015e70aef3
|
|
4
|
+
data.tar.gz: b67838e3360ac7487dd844b17d67e3c92a1b04b5fff5bb1781a060f74104d91b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 32d3af576e893be5c0c865d1ac14aa715451c65114611bf0a0ebf2f3df63c4505613920a8ddc25bfca70f0da83a6bc84ce91dfe8ffdb4060fb262cb353de89e5
|
|
7
|
+
data.tar.gz: 9f391f8ddf3d190b196c9831daefe014f7fed0f5954fcb327ee3471e7d185492d3b0f5975ed0c55814ee2c79f13c2c104a0c4ed3aafb737bcadcbc9c4acb5f16
|
data/lib/tinylinks/cli.rb
CHANGED
|
@@ -9,6 +9,7 @@ module Tinylinks
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
class_option :help, aliases: "-h", type: :boolean, desc: "Show help for a command"
|
|
12
|
+
class_option :no_color, type: :boolean, default: false, desc: "Disable color output"
|
|
12
13
|
|
|
13
14
|
no_commands do
|
|
14
15
|
def invoke_command(command, *args)
|
|
@@ -19,9 +20,9 @@ module Tinylinks
|
|
|
19
20
|
super
|
|
20
21
|
rescue Client::ApiError => e
|
|
21
22
|
if e.body.is_a?(Hash) && e.body["errors"]
|
|
22
|
-
say_error
|
|
23
|
+
say_error error_formatter.errors(e.body)
|
|
23
24
|
else
|
|
24
|
-
say_error e.message
|
|
25
|
+
say_error error_colorizer.red(e.message)
|
|
25
26
|
end
|
|
26
27
|
exit 1
|
|
27
28
|
end
|
|
@@ -45,7 +46,7 @@ module Tinylinks
|
|
|
45
46
|
end
|
|
46
47
|
say "Login successful!"
|
|
47
48
|
rescue RuntimeError => e
|
|
48
|
-
say_error "Login failed: #{e.message}"
|
|
49
|
+
say_error error_colorizer.red("Login failed: #{e.message}")
|
|
49
50
|
exit 1
|
|
50
51
|
end
|
|
51
52
|
|
|
@@ -57,10 +58,16 @@ module Tinylinks
|
|
|
57
58
|
|
|
58
59
|
desc "list", "List links"
|
|
59
60
|
method_option :tags, type: :string, desc: "Filter by tags (comma-separated)"
|
|
61
|
+
method_option :filter, type: :string, enum: %w[visited unvisited],
|
|
62
|
+
desc: "Filter by visit status: visited or unvisited"
|
|
63
|
+
method_option :sort, type: :string, enum: %w[newest oldest most_visited least_visited],
|
|
64
|
+
desc: "Sort order: newest (default), oldest, most_visited, least_visited"
|
|
60
65
|
method_option :page, type: :numeric, desc: "Page number"
|
|
61
66
|
def list
|
|
62
67
|
params = {}
|
|
63
68
|
params[:tags] = options[:tags] if options[:tags]
|
|
69
|
+
params[:filter] = options[:filter] if options[:filter]
|
|
70
|
+
params[:sort] = options[:sort] if options[:sort]
|
|
64
71
|
params[:page] = options[:page] if options[:page]
|
|
65
72
|
data = client.get("/links", params)
|
|
66
73
|
say formatter.link_list(data)
|
|
@@ -96,7 +103,7 @@ module Tinylinks
|
|
|
96
103
|
body[:tags] = options[:tags].split(",").map(&:strip) if options[:tags]
|
|
97
104
|
|
|
98
105
|
if body.empty?
|
|
99
|
-
say_error "No changes specified. Use --title, --description, or --tags."
|
|
106
|
+
say_error error_colorizer.red("No changes specified. Use --title, --description, or --tags.")
|
|
100
107
|
exit 1
|
|
101
108
|
end
|
|
102
109
|
|
|
@@ -142,7 +149,7 @@ module Tinylinks
|
|
|
142
149
|
@client ||= begin
|
|
143
150
|
token = Auth.new.token
|
|
144
151
|
unless token
|
|
145
|
-
say_error "Not logged in. Run `tinylinks login` first."
|
|
152
|
+
say_error error_colorizer.red("Not logged in. Run `tinylinks login` first.")
|
|
146
153
|
exit 1
|
|
147
154
|
end
|
|
148
155
|
Client.new(token: token)
|
|
@@ -150,11 +157,23 @@ module Tinylinks
|
|
|
150
157
|
end
|
|
151
158
|
|
|
152
159
|
def formatter
|
|
153
|
-
@formatter ||= Formatter.new
|
|
160
|
+
@formatter ||= Formatter.new(color: color_enabled?($stdout))
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def error_formatter
|
|
164
|
+
@error_formatter ||= Formatter.new(color: color_enabled?($stderr))
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def error_colorizer
|
|
168
|
+
@error_colorizer ||= Colorizer.new(enabled: color_enabled?($stderr))
|
|
154
169
|
end
|
|
155
170
|
|
|
156
171
|
def say_error(message)
|
|
157
172
|
$stderr.puts message
|
|
158
173
|
end
|
|
174
|
+
|
|
175
|
+
def color_enabled?(io)
|
|
176
|
+
!options[:no_color] && io.tty? && ENV["NO_COLOR"].nil?
|
|
177
|
+
end
|
|
159
178
|
end
|
|
160
179
|
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tinylinks
|
|
4
|
+
class Colorizer
|
|
5
|
+
def initialize(enabled: true)
|
|
6
|
+
@enabled = enabled
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def bold(text) = wrap(text, 1)
|
|
10
|
+
def dim(text) = wrap(text, 2)
|
|
11
|
+
def red(text) = wrap(text, 31)
|
|
12
|
+
def green(text) = wrap(text, 32)
|
|
13
|
+
def cyan(text) = wrap(text, 36)
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def wrap(text, code)
|
|
18
|
+
return text unless @enabled
|
|
19
|
+
"\e[#{code}m#{text}\e[0m"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/tinylinks/formatter.rb
CHANGED
|
@@ -2,33 +2,60 @@
|
|
|
2
2
|
|
|
3
3
|
module Tinylinks
|
|
4
4
|
class Formatter
|
|
5
|
+
def initialize(color: false)
|
|
6
|
+
@c = Colorizer.new(enabled: color)
|
|
7
|
+
end
|
|
8
|
+
|
|
5
9
|
def link(data)
|
|
6
10
|
lines = []
|
|
7
|
-
lines << "#{data["title"] || "(untitled)"} [##{data["id"]}]"
|
|
8
|
-
lines << " #{data["url"]}"
|
|
9
|
-
lines << " #{data["description"]}" if data["description"] && !data["description"].empty?
|
|
10
|
-
|
|
11
|
+
lines << @c.bold("#{data["title"] || "(untitled)"} [##{data["id"]}]")
|
|
12
|
+
lines << " #{@c.cyan(data["url"])}"
|
|
13
|
+
lines << " #{@c.dim(data["description"])}" if data["description"] && !data["description"].empty?
|
|
14
|
+
meta = meta_line(data)
|
|
15
|
+
lines << " #{meta}" if meta
|
|
11
16
|
lines.join("\n")
|
|
12
17
|
end
|
|
13
18
|
|
|
14
19
|
def link_list(data)
|
|
20
|
+
return @c.dim("No results found") if data["links"].empty?
|
|
21
|
+
|
|
15
22
|
lines = data["links"].map { |l| link(l) }
|
|
16
|
-
lines << pagination(data["meta"]) if data["meta"]
|
|
23
|
+
lines << @c.dim(pagination(data["meta"])) if data["meta"]
|
|
17
24
|
lines.join("\n\n")
|
|
18
25
|
end
|
|
19
26
|
|
|
20
27
|
def tags(data)
|
|
21
|
-
|
|
28
|
+
return @c.dim("No results found") if data["tags"].empty?
|
|
29
|
+
|
|
30
|
+
data["tags"].map { |t| "#{@c.green(t["name"])} #{@c.dim("(#{t["count"]})")}" }.join("\n")
|
|
22
31
|
end
|
|
23
32
|
|
|
24
33
|
def errors(data)
|
|
25
34
|
data["errors"].flat_map do |field, messages|
|
|
26
|
-
messages.map { |msg| "#{field} #{msg}" }
|
|
35
|
+
messages.map { |msg| @c.red("#{field} #{msg}") }
|
|
27
36
|
end.join("\n")
|
|
28
37
|
end
|
|
29
38
|
|
|
30
39
|
private
|
|
31
40
|
|
|
41
|
+
def meta_line(data)
|
|
42
|
+
parts = []
|
|
43
|
+
parts << "tags: #{@c.green(data["tags"].join(", "))}" if data["tags"] && !data["tags"].empty?
|
|
44
|
+
if data.key?("visit_count") && !data["visit_count"].nil?
|
|
45
|
+
parts << @c.dim(visits_label(data["visit_count"]))
|
|
46
|
+
end
|
|
47
|
+
return if parts.empty?
|
|
48
|
+
parts.join(@c.dim(" · "))
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def visits_label(count)
|
|
52
|
+
case count
|
|
53
|
+
when 0 then "never visited"
|
|
54
|
+
when 1 then "1 visit"
|
|
55
|
+
else "#{count} visits"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
32
59
|
def pagination(meta)
|
|
33
60
|
"Page #{meta["page"]} of #{meta["total_pages"]} (#{meta["total_items"]} total)"
|
|
34
61
|
end
|
data/lib/tinylinks.rb
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Tinylinks
|
|
4
|
-
VERSION = "0.
|
|
4
|
+
VERSION = "0.3.0"
|
|
5
5
|
BASE_URL = "https://links.pati.to"
|
|
6
6
|
API_BASE = "#{BASE_URL}/api/v1"
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
+
require_relative "tinylinks/colorizer"
|
|
9
10
|
require_relative "tinylinks/client"
|
|
10
11
|
require_relative "tinylinks/auth"
|
|
11
12
|
require_relative "tinylinks/formatter"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tinylinks
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jaime Rodas
|
|
@@ -34,6 +34,7 @@ files:
|
|
|
34
34
|
- lib/tinylinks/auth.rb
|
|
35
35
|
- lib/tinylinks/cli.rb
|
|
36
36
|
- lib/tinylinks/client.rb
|
|
37
|
+
- lib/tinylinks/colorizer.rb
|
|
37
38
|
- lib/tinylinks/formatter.rb
|
|
38
39
|
homepage: https://github.com/jaimerodas/tinylinks-cli
|
|
39
40
|
licenses:
|
|
@@ -53,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
53
54
|
- !ruby/object:Gem::Version
|
|
54
55
|
version: '0'
|
|
55
56
|
requirements: []
|
|
56
|
-
rubygems_version: 4.0.
|
|
57
|
+
rubygems_version: 4.0.10
|
|
57
58
|
specification_version: 4
|
|
58
59
|
summary: CLI for TinyLinks
|
|
59
60
|
test_files: []
|