defcli 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 671ad3b060e2945f7eeda6802e5327565596986a2934c85635efcb7678ad065e
4
+ data.tar.gz: 22927817e5e29dc4845b44575af9ca1d061b81ff7f8bd4cae047d4aba86c11bc
5
+ SHA512:
6
+ metadata.gz: 5be8378f87f339c13a49c660d01dca507b59467ffd5ae033f487f562b22cd2210ab2bf65d36a96bb346625a6110b2f1169406515caef9e97ea2206fedd112eb4
7
+ data.tar.gz: 43fdb3e659694db3b5a34c5fedbe3d56f40ba0f0ba0a8089c9bca9c0446d30209dd2f9210d7c815d57a6f0565f3e4e9c826f32c72e6b5929afdde325e6c612e6
checksums.yaml.gz.sig ADDED
Binary file
data.tar.gz.sig ADDED
Binary file
data/lib/defcli.rb ADDED
@@ -0,0 +1,44 @@
1
+ # -*- coding: UTF-8 -*-
2
+
3
+ require "uri"
4
+ require "json"
5
+ require "open-uri"
6
+
7
+ require_relative "./defcli/formatting"
8
+
9
+ module Defcli
10
+ class << self
11
+ def version
12
+ "0.0.1"
13
+ end
14
+
15
+ # Format results for output
16
+ # @param results [Array] array of results
17
+ # @param color [Boolean] colored output
18
+ # @return [String]
19
+ def format_results(results, color = true)
20
+ Defcli::Formatting.format_results(results, color)
21
+ end
22
+
23
+ def read_url(url)
24
+ OpenURI.open_uri(url).read
25
+ end
26
+
27
+ def open_in_browser(url)
28
+ system open_cmd, url
29
+ end
30
+
31
+ private
32
+
33
+ def open_cmd
34
+ case RbConfig::CONFIG["host_os"]
35
+ when /darwin/
36
+ "open"
37
+ when /bsd|linux/
38
+ "xdg-open"
39
+ when /cygwin|mingw|mswin/
40
+ "start"
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,114 @@
1
+ # -*- coding: UTF-8 -*-
2
+
3
+ module Defcli
4
+ module Formatting
5
+ class << self
6
+ # Fit a text in a given width (number of chars).
7
+ # @param txt [String]
8
+ # @param width [Integer] maximum width
9
+ # @return [Array] list of lines of text
10
+ def fit(txt, width = 79)
11
+ return [] if width < 1
12
+
13
+ # from https://stackoverflow.com/a/7567210/735926
14
+ r = /(.{1,#{width}})(?:\s|$)/m
15
+ txt.split("\n").map { |l| l.scan(r) }.flatten
16
+ end
17
+
18
+ # Add a tab at the beginning of a text. If it's a list, add a tab at
19
+ # the beginning of each element.
20
+ # @param txt [String] The text to tab, may be a string or a list of
21
+ # strings
22
+ # @param width [Integer] tab width
23
+ # @return [String]
24
+ def tab(txt, width = 4)
25
+ return txt if width <= 0
26
+
27
+ tab = " " * width
28
+
29
+ return tab + txt if txt.is_a? String
30
+
31
+ txt.map { |l| tab + l }
32
+ end
33
+
34
+ # Format results for text output (e.g. in the terminal)
35
+ # @param results [Array<Hash>] array of results
36
+ # @param color [Boolean] colored output
37
+ # @return [String]
38
+ def format_results(results, color = true)
39
+ results.map { |r| format_result(r, color) }.join "\n"
40
+ end
41
+
42
+ def format_result(r, color = true)
43
+ require "colored" if color
44
+
45
+ word = r[:word]
46
+ word = word.bold if color
47
+
48
+ rating = format_result_rating(r, color)
49
+
50
+ definition = tab(fit(r[:definition], 75)).join "\n"
51
+
52
+ text = "* #{word}"
53
+ text << " (#{rating})" if rating
54
+ text << ":\n\n#{definition}\n"
55
+
56
+ text << "(📍 #{r[:location]})\n" if r[:location]
57
+
58
+ text << (format_result_examples(r, color) or "")
59
+
60
+ text + "\n\n"
61
+ end
62
+
63
+ private
64
+
65
+ def format_result_examples(r, color = true)
66
+ examples = if r[:example]
67
+ [r[:example]]
68
+ elsif r[:examples]
69
+ r[:examples]
70
+ else
71
+ []
72
+ end
73
+
74
+ if examples.count == 1
75
+ example = tab(fit(examples.first, 75)).join "\n"
76
+ "\n Example:\n#{example}\n"
77
+
78
+ elsif examples.count > 1
79
+ examples = examples.map do |e|
80
+ tab(fit(e, 75)).join "\n"
81
+ end.join "\n"
82
+ "\n Examples:\n#{examples}\n"
83
+ end
84
+ end
85
+
86
+ def format_result_rating(r, color = true)
87
+ if r[:upvotes]
88
+ # upvotes/downvotes
89
+ upvotes = r[:upvotes]
90
+ downvotes = r[:downvotes]
91
+ if color
92
+ upvotes = upvotes.to_s.green
93
+ downvotes = downvotes.to_s.red
94
+ end
95
+
96
+ "#{upvotes}/#{downvotes}"
97
+ elsif r[:ratio]
98
+ percentage = r[:ratio] * 100.0
99
+ rating = format("%2d%%", percentage)
100
+
101
+ if color
102
+ if percentage > 60
103
+ rating = rating.green
104
+ else
105
+ rating = rating.red
106
+ end
107
+ end
108
+
109
+ rating
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,96 @@
1
+ class DefcliFormattingTest < Test::Unit::TestCase
2
+
3
+ # == Defcli::Formatting.format_results == #
4
+
5
+ def test_format_results_empty_list
6
+ assert_equal('', Defcli.format_results([]))
7
+ end
8
+
9
+ def test_format_results_one_element_no_color
10
+ res = {
11
+ :word => 'XYZ',
12
+ :upvotes => 42,
13
+ :downvotes => 78,
14
+ :definition => 'xyz',
15
+ :example => 'zyx'
16
+ }
17
+
18
+ output = Defcli.format_results([res], false).strip
19
+ expected = <<EOS
20
+ * XYZ (42/78):
21
+
22
+ xyz
23
+
24
+ Example:
25
+ zyx
26
+ EOS
27
+
28
+ assert_equal(expected.strip, output)
29
+ end
30
+
31
+ def test_format_results_one_element_color
32
+ green = "\e[32m"
33
+ bold = "\e[1m"
34
+ red = "\e[31m"
35
+ reset = "\e[0m"
36
+ res = {
37
+ :word => 'XYZ',
38
+ :upvotes => 42,
39
+ :downvotes => 78,
40
+ :definition => 'xyz',
41
+ :example => 'zyx'
42
+ }
43
+
44
+ output = Defcli.format_results([res], true).strip
45
+ expected = <<EOS
46
+ * #{bold}XYZ#{reset} (#{green}42#{reset}/#{red}78#{reset}):
47
+
48
+ xyz
49
+
50
+ Example:
51
+ zyx
52
+ EOS
53
+
54
+ assert_equal(expected.strip, output)
55
+ end
56
+
57
+ # == Defcli::Formatting.fit == #
58
+
59
+ def test_fit_0_width
60
+ assert_equal([], Defcli::Formatting.fit('foo', 0))
61
+ end
62
+
63
+ def test_fit_negative_width
64
+ assert_equal([], Defcli::Formatting.fit('foo', -1))
65
+ end
66
+
67
+ def test_fit_right_width
68
+ assert_equal(['foo'], Defcli::Formatting.fit('foo', 3))
69
+ end
70
+
71
+ def test_fit_larger_width
72
+ assert_equal(['foo'], Defcli::Formatting.fit('foo', 4))
73
+ end
74
+
75
+ def test_fit_smaller_width
76
+ assert_equal(['a', 'b'], Defcli::Formatting.fit('a b', 2))
77
+ end
78
+
79
+ # == Defcli::Formatting.tab == #
80
+
81
+ def test_tab_0_width
82
+ assert_equal('foo', Defcli::Formatting.tab('foo', 0))
83
+ end
84
+
85
+ def test_tab_negative_width
86
+ assert_equal('foo', Defcli::Formatting.tab('foo', -1))
87
+ end
88
+
89
+ def test_tab_2_width
90
+ assert_equal(' foo', Defcli::Formatting.tab('foo', 2))
91
+ end
92
+
93
+ def test_tab_array
94
+ assert_equal([' a', ' b'], Defcli::Formatting.tab(['a', 'b'], 1))
95
+ end
96
+ end
data/tests/tests.rb ADDED
@@ -0,0 +1,54 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ ci = ENV["CI"] || ENV["CONTINUOUS_INTEGRATION"]
4
+
5
+ if ci
6
+ require 'coveralls'
7
+ Coveralls.wear!
8
+ end
9
+
10
+ require 'test/unit'
11
+ require 'simplecov'
12
+
13
+ test_dir = File.expand_path( File.dirname(__FILE__) )
14
+
15
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter if ci
16
+ SimpleCov.start { add_filter '/tests/' }
17
+
18
+ require 'defcli'
19
+
20
+ for t in Dir.glob( File.join( test_dir, '*_tests.rb' ) )
21
+ require t
22
+ end
23
+
24
+ class DefcliTests < Test::Unit::TestCase
25
+
26
+ # == Defcli.version == #
27
+
28
+ def test_version
29
+ assert(Defcli.version =~ /^\d+\.\d+\.\d+/)
30
+ end
31
+
32
+ # == Defcli.open_cmd (private) == #
33
+
34
+ def test_open_cmd
35
+ os = RbConfig::CONFIG["host_os"]
36
+
37
+ RbConfig::CONFIG["host_os"] = "darwin"
38
+ assert_equal "open", Defcli.send(:open_cmd)
39
+
40
+ RbConfig::CONFIG["host_os"] = "linux"
41
+ assert_equal "xdg-open", Defcli.send(:open_cmd)
42
+
43
+ RbConfig::CONFIG["host_os"] = "bsd"
44
+ assert_equal "xdg-open", Defcli.send(:open_cmd)
45
+
46
+ RbConfig::CONFIG["host_os"] = "cygwin"
47
+ assert_equal "start", Defcli.send(:open_cmd)
48
+ ensure
49
+ RbConfig::CONFIG["host_os"] = os
50
+ end
51
+ end
52
+
53
+
54
+ exit Test::Unit::AutoRunner.run
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: defcli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Baptiste Fontaine
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIID/DCCAmSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAkMSIwIAYDVQQDDBliL0RD
14
+ PXB0aXN0ZWZvbnRhaW5lL0RDPWZyMB4XDTIwMDMwNDE5MDMyMVoXDTIxMDMwNDE5
15
+ MDMyMVowJDEiMCAGA1UEAwwZYi9EQz1wdGlzdGVmb250YWluZS9EQz1mcjCCAaIw
16
+ DQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAKdjTwN/gnJ3WHxKeusaRN1o902Q
17
+ BmIRgdtbhpsHtgUruKNujutEBpmhG1fka8+mujhqh885blckeC8hXgqpHGK1MsJU
18
+ tgsNB2F2Nvof/uGBzi+OZ76HPLmfvJFb/KUiwrh08jTbFftMBCmuekbxBajt2N2F
19
+ shF6DFEqO2hl/itVt5UeIZhpIZvO7qSZ9FtLRXs0q2O27h4QfAv6XobNDwH5TBs5
20
+ z+EYufgTtupf26xW0v6z2NDG6z36Eap7QAwoivuPCuXO+IPgxhubtGvFYSo7ygP4
21
+ RbYsaGucRneCCzezTD+i1LnhGt9TCbQjdvidgM+i616JC/HRXglM0apgBZSjayoI
22
+ XHoajIajnU+570cu01Wsa+SF9m4stKao0hLnCUMeYybmA/Ilk58nJ2xZJWMULu76
23
+ 7Ttzead1Ah25ZdWefKG5FIGkpezEp4z/YihGEJt+hxS7Aa2xYiIlnYFwUno530/8
24
+ So5Ibqdd3pMKJDUQJvGIBhsQIXF4Iogk4txoPwIDAQABozkwNzAJBgNVHRMEAjAA
25
+ MAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUsV1eKnEFtVRwyz6/nTuharH3G+UwDQYJ
26
+ KoZIhvcNAQELBQADggGBAJz7tbRe/iyMthV7fdqnhFv0SZo1UVWZSaIjB39W4lUi
27
+ 7X1Smag2Fe7IqARUPLn2e49ObyupAmTi0zHoSG/+HsBUqNPPoVW1Y67dtrMM49o7
28
+ qSN66EogB4nvGdvqJ9eOlioiAX7vczWmQjfSONuk0ihOfaTChD7LwoPptTUu/Q6+
29
+ aT8zz7TH+sxxx+D09Q9+Ywf1RVnUe+i1PTo8kadnHIQdeBPudKrw5GWcIoLz1V16
30
+ A+j/SNEUqY1ui8TBX6axkd8vh6C1YcVAFCcdrxTMFTeB1irvL8jns6SulRHM08UC
31
+ 9NR+YthP16QuQzb5R2wIGX6WT11cnIpo0LzTnY/QSZGgwJkuLalBLzUssMiVnoSX
32
+ rVdmQBLrs38YcJouqHpf0wCGygf5430Bq4nCu0xUaH5umPcwJE9qaF1ZfgSCfZEz
33
+ Qe5fflfwGHtlmT6SWZoQD48xF/ILJ+cLTpF79ardGYnWT6N7VUAI5lKp7OjZYd+q
34
+ wwYlmlBW0Femxy5WoxzECQ==
35
+ -----END CERTIFICATE-----
36
+ date: 2020-04-02 00:00:00.000000000 Z
37
+ dependencies:
38
+ - !ruby/object:Gem::Dependency
39
+ name: optimist
40
+ requirement: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - "~>"
43
+ - !ruby/object:Gem::Version
44
+ version: '3.0'
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - "~>"
50
+ - !ruby/object:Gem::Version
51
+ version: '3.0'
52
+ - !ruby/object:Gem::Dependency
53
+ name: colored
54
+ requirement: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - "~>"
57
+ - !ruby/object:Gem::Version
58
+ version: '1.2'
59
+ type: :runtime
60
+ prerelease: false
61
+ version_requirements: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - "~>"
64
+ - !ruby/object:Gem::Version
65
+ version: '1.2'
66
+ - !ruby/object:Gem::Dependency
67
+ name: simplecov
68
+ requirement: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - "~>"
71
+ - !ruby/object:Gem::Version
72
+ version: '0.18'
73
+ type: :development
74
+ prerelease: false
75
+ version_requirements: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '0.18'
80
+ - !ruby/object:Gem::Dependency
81
+ name: rake
82
+ requirement: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - "~>"
85
+ - !ruby/object:Gem::Version
86
+ version: '12.3'
87
+ type: :development
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - "~>"
92
+ - !ruby/object:Gem::Version
93
+ version: '12.3'
94
+ - !ruby/object:Gem::Dependency
95
+ name: test-unit
96
+ requirement: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - "~>"
99
+ - !ruby/object:Gem::Version
100
+ version: '3.3'
101
+ type: :development
102
+ prerelease: false
103
+ version_requirements: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - "~>"
106
+ - !ruby/object:Gem::Version
107
+ version: '3.3'
108
+ - !ruby/object:Gem::Dependency
109
+ name: coveralls
110
+ requirement: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - "~>"
113
+ - !ruby/object:Gem::Version
114
+ version: '0.8'
115
+ type: :development
116
+ prerelease: false
117
+ version_requirements: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - "~>"
120
+ - !ruby/object:Gem::Version
121
+ version: '0.8'
122
+ description: Utilities to build simple dictionnary CLI tools.
123
+ email: b@ptistefontaine.fr
124
+ executables: []
125
+ extensions: []
126
+ extra_rdoc_files: []
127
+ files:
128
+ - lib/defcli.rb
129
+ - lib/defcli/formatting.rb
130
+ - tests/formatting_tests.rb
131
+ - tests/tests.rb
132
+ homepage: https://github.com/bfontaine/defcli
133
+ licenses:
134
+ - MIT
135
+ metadata: {}
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubygems_version: 3.1.2
152
+ signing_key:
153
+ specification_version: 4
154
+ summary: Dictionnary CLI tools utilities
155
+ test_files:
156
+ - tests/tests.rb
157
+ - tests/formatting_tests.rb
metadata.gz.sig ADDED
@@ -0,0 +1,2 @@
1
+ H�y�����}^G|��>��ސ�J����>����k.^["O��* �O�-!��<�|�!HH?X�ȟ���,��I�V�Y����W�����mv q�4<<b���� �� y�D��W�#幗E-z��o�k�T���Pn�^�h�jHE�Zs5e������rъ��G8�P��V�֠dŢِ� ���!r�wF�%���2���5mƔv�{�\����]�8BNQ���V��{��������0W �d�YL��Id��Oo�E=�aC�}Cu���<��ъy
2
+ e���F� �u��x�u흝�8�9{�T��d�J�e�q�v��5 ����mM��'�C����a���9����20n=�}��| �L�I(<1�����k