defcli 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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