unicopy 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b52015a55845441084cce91c2820e7faa888078b
4
+ data.tar.gz: e23151d662fac4f0c811748fc5b1be0c4a451637
5
+ SHA512:
6
+ metadata.gz: b40c34ec4178cb320a175f3ad4a716539f167882a251281a6f0320fe0db970d8246048109eca0e95d467187c2bcb160fed8c74ef3dad519dc0fb4c78d9338df1
7
+ data.tar.gz: a8d21e068ea34e19668e09129884def732ea387002defab2870d2696ece52eff01eb4e115099ef3d9ed3d66027669714584924821f883f9355a04f3ee5c64012
@@ -0,0 +1,2 @@
1
+ Gemfile.lock
2
+ /pkg
@@ -0,0 +1,22 @@
1
+ sudo: false
2
+ language: ruby
3
+
4
+ rvm:
5
+ - ruby-head
6
+ - 2.4.1
7
+ - 2.3.4
8
+ - 2.2
9
+ - 2.1
10
+ - 2.0
11
+ - jruby-head
12
+ - jruby-9.1.8.0
13
+
14
+ cache:
15
+ - bundler
16
+
17
+ matrix:
18
+ allow_failures:
19
+ - rvm: jruby-head
20
+ - rvm: ruby-head
21
+ - rvm: 2.0
22
+ # fast_finish: true
@@ -0,0 +1,67 @@
1
+ ## CHANGELOG
2
+
3
+ ### 2.4.0
4
+
5
+ * Extract symbolification logic into extra [symbolify](https://github.com/janlelis/symbolify) gem (includes fixes and non-character detection)
6
+ * Update characteristics gem (includes a new blank)
7
+
8
+ ### 2.3.0
9
+
10
+ * More consistent handling of bidi controls (always symbolify with alias, but highlight ALM, RLM, LRM as blanks)
11
+ * Highlight control chars that are also blanks as blank
12
+ * Highlight CGJ as blank
13
+ * Highlight NEL as blank (only in Unicode)
14
+ * Add Unicode version to `unibits --version` command
15
+
16
+ ### 2.2.0
17
+
18
+ * Add mongolian free variation selectors and combining grapheme joiner to interesting codepoints list
19
+ * Green highlighting of "marks" in Unicode
20
+ * Always use dotted circle for non-spacing marks
21
+ * Always prepend enclosing marks with a space
22
+ * Update characteristics gem (includes new blanks and UTF-8 dialects with japanese emojis)
23
+
24
+ ### 2.1.1
25
+
26
+ * Proper UTF-32 validness / invalid codepoint highlighting, see https://bugs.ruby-lang.org/issues/13292
27
+
28
+ ### 2.1.0
29
+
30
+ * Support more encoding: IBMX, CP85X, macX, TIS-620/Windows-874, and KOI8-X
31
+ * Highlight non-control formatting characters in pink
32
+ * Improve `unibits --help` command
33
+
34
+ ### 2.0.0
35
+
36
+ * Support more encodings: ISO-8859-X and Windows-125X
37
+ * Add three HANGUL characters (U+115F, U+1160, U+3164) to list of possible white spaces
38
+ * Move character handling to separate gem. It is called [characteristics](https://github.com/janlelis/characteristics).
39
+ * Highlight control chars in blue and blanks in light blue
40
+ * Handle encodings that are not convertible to UTF-8
41
+
42
+ ### 1.3.0
43
+
44
+ * Add variation selectors 17-256 (U+E0100 - U+E01EF)
45
+ * Add U+1D159 (MUSICAL SYMBOL NULL NOTEHEAD) to list of possible white spaces
46
+ * Bump unicode-categories dependency for more reliable unassigned codepoint detection
47
+
48
+ ### 1.2.1
49
+
50
+ * Fix bug that inserted wrong bytes
51
+
52
+ ### 1.2.0
53
+
54
+ * Do not display (but highlight) unassigned codepoints
55
+
56
+ ### 1.1.0
57
+
58
+ * Support (and highlight) invalid encodings \o/
59
+ * Improve character symbolification
60
+ * Fix that the Kernel method would not take keyword arguments
61
+ * New option for setting a custom output width to use
62
+ * New option for activating wide ambiguous characters
63
+
64
+ ### 1.0.0
65
+
66
+ * Initial release
67
+
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at opensource@janlelis.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'minitest'
6
+ gem 'rake'
7
+ gem 'irbtools', require: 'irbtools/binding'
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2017 Jan Lelis, mail@janlelis.de
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,188 @@
1
+ # unicopy [![[version]](https://badge.fury.io/rb/unicopy.svg)](http://badge.fury.io/rb/unicopy) [![[travis]](https://travis-ci.org/janlelis/unicopy.svg)](https://travis-ci.org/janlelis/unicopy)
2
+
3
+ CLI utility which converts Unicode codepoints to a string (or vice versa). Copies the result to the system clipboard or just prints it to the console.
4
+
5
+ Can also convert codepoints to many dump formats.
6
+
7
+ ## Setup
8
+
9
+ Make sure you have Ruby installed and installing gems works properly. Then do:
10
+
11
+ ```
12
+ $ gem install unicopy
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### Codepoints to String
18
+
19
+ Codepoints format is hexadecimal, "U+" is permitted, examples:
20
+
21
+ ```ruby
22
+ $ unicopy 52 75 62 79 --print
23
+ Ruby
24
+ ```
25
+
26
+ ```ruby
27
+ $ unicopy U+0052 U+0075 U+0062 U+0079 --print
28
+ Ruby
29
+ ```
30
+
31
+ ### String to Codepoints
32
+
33
+ ```ruby
34
+ $ unicopy --string Ruby --print
35
+ U+0052 U+0075 U+0062 U+0079
36
+ ```
37
+
38
+ ### Options
39
+
40
+ ```
41
+ --help | | this help page
42
+ --parse-decimal | | interpret given codepoints as decimal, instead of hexadecimal values
43
+ --print | -p | do not copy to system clipboard, but print to screen
44
+ --string | -s | see above
45
+ --version | | displays version of unicopy
46
+ --(dump format) | | specify the format to be used for dumping the codepoints (see below)
47
+ ```
48
+
49
+ ### Dump Formats
50
+
51
+ #### Short Hexadecimal
52
+
53
+ ```
54
+ $ unicopy 52 75 62 79 20 1F32B --print --hex
55
+ 52 75 62 79 20 1F32B
56
+ ```
57
+
58
+ ```
59
+ $ unicopy --string "Ruby 🌫" --print --hex
60
+ 52 75 62 79 20 1F32B
61
+ ```
62
+
63
+ #### Hexadecimal With `U+` Prefix
64
+
65
+ ```
66
+ $ unicopy 52 75 62 79 20 1F32B --print --uplus
67
+ U+0052 U+0075 U+0062 U+0079 U+0020 U+1F32B
68
+ ```
69
+
70
+ ```
71
+ $ unicopy --string "Ruby 🌫" --print --uplus
72
+ U+0052 U+0075 U+0062 U+0079 U+0020 U+1F32B
73
+ ```
74
+
75
+ #### Hexadecimal With `0x` Prefix
76
+
77
+ ```
78
+ $ unicopy 52 75 62 79 20 1F32B --print --0x
79
+ 0x0052 0x0075 0x0062 0x0079 0x0020 0x1F32B
80
+ ```
81
+
82
+ ```
83
+ $ unicopy --string "Ruby 🌫" --print --0x
84
+ 0x0052 0x0075 0x0062 0x0079 0x0020 0x1F32B
85
+ ```
86
+
87
+ #### Decimal
88
+
89
+ ```
90
+ $ unicopy 52 75 62 79 20 1F32B --print --dec
91
+ 82 117 98 121 32 127787
92
+ ```
93
+
94
+ ```
95
+ $ unicopy --string "Ruby 🌫" --print --dec
96
+ 82 117 98 121 32 127787
97
+ ```
98
+
99
+ #### Ruby Escape Syntax
100
+
101
+ ```
102
+ $ unicopy 52 75 62 79 20 1F32B --print --ruby
103
+ \\u{52 75 62 79 20 1F32B}
104
+ ```
105
+
106
+ ```
107
+ $ unicopy --string "Ruby 🌫" --print --ruby
108
+ \\u{52 75 62 79 20 1F32B}
109
+ ```
110
+
111
+ #### JavaScript Escape Syntax (Since ES6)
112
+
113
+ ```
114
+ $ unicopy 52 75 62 79 20 1F32B --print --es6
115
+ \\u{52}\\u{75}\\u{62}\\u{79}\\u{20}\\u{1F32B}
116
+ ```
117
+
118
+ ```
119
+ $ unicopy --string "Ruby 🌫" --print --es6
120
+ \\u{52}\\u{75}\\u{62}\\u{79}\\u{20}\\u{1F32B}
121
+ ```
122
+
123
+ #### JavaScript Escape Syntax (Before ES6)
124
+
125
+ ```
126
+ $ unicopy 52 75 62 79 20 1F32B --print --js
127
+ \\u0052\\u0075\\u0062\\u0079\\u0020\\uD83C\\uDF2B
128
+ ```
129
+
130
+ ```
131
+ $ unicopy --string "Ruby 🌫" --print --js
132
+ \\u0052\\u0075\\u0062\\u0079\\u0020\\uD83C\\uDF2B
133
+ ```
134
+
135
+ #### CSS Escape Syntax
136
+
137
+ ```
138
+ $ unicopy 52 75 62 79 20 1F32B --print --css
139
+ \\52\\75\\62\\79\\20\\1f32b
140
+ ```
141
+
142
+ ```
143
+ $ unicopy --string "Ruby 🌫" --print --css
144
+ \\52\\75\\62\\79\\20\\1f32b
145
+ ```
146
+
147
+ #### Hexadecimal HTML Entities
148
+
149
+ ```
150
+ $ unicopy 52 75 62 79 20 1F32B --print --html-hex
151
+ Ruby 🌫
152
+ ```
153
+
154
+ ```
155
+ $ unicopy --string "Ruby 🌫" --print --html-hex
156
+ Ruby 🌫
157
+ ```
158
+
159
+ #### Decimal HTML Entities
160
+
161
+ ```
162
+ $ unicopy 52 75 62 79 20 1F32B --print --html-dec
163
+ Ruby 🌫
164
+ ```
165
+
166
+ ```
167
+ $ unicopy --string "Ruby 🌫" --print --html-dec
168
+ Ruby 🌫
169
+ ```
170
+
171
+ #### UTF-8 in Hexadecimal Bytes
172
+
173
+ ```
174
+ $ unicopy 52 75 62 79 20 1F32B --print --bytes-utf8
175
+ 52 75 62 79 20 F0 9F 8C AB
176
+ ```
177
+
178
+ ```
179
+ $ unicopy --string "Ruby 🌫" --print --bytes-utf8
180
+ 52 75 62 79 20 F0 9F 8C AB
181
+ ```
182
+
183
+ ## Also see
184
+
185
+ - [unibits](https://github.com/janlelis/unibits)
186
+ - [uniscribe](https://github.com/janlelis/uniscribe)
187
+
188
+ Copyright (C) 2017 Jan Lelis <http://janlelis.com>. Released under the MIT license.
@@ -0,0 +1,38 @@
1
+ # # #
2
+ # Get gemspec info
3
+
4
+ gemspec_file = Dir['*.gemspec'].first
5
+ gemspec = eval File.read(gemspec_file), binding, gemspec_file
6
+ info = "#{gemspec.name} | #{gemspec.version} | " \
7
+ "#{gemspec.runtime_dependencies.size} dependencies | " \
8
+ "#{gemspec.files.size} files"
9
+
10
+ # # #
11
+ # Gem build and install task
12
+
13
+ desc info
14
+ task :gem do
15
+ puts info + "\n\n"
16
+ print " "; sh "gem build #{gemspec_file}"
17
+ FileUtils.mkdir_p 'pkg'
18
+ FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", 'pkg'
19
+ puts; sh %{gem install --no-document pkg/#{gemspec.name}-#{gemspec.version}.gem}
20
+ end
21
+
22
+ # # #
23
+ # Start an IRB session with the gem loaded
24
+
25
+ desc "#{gemspec.name} | IRB"
26
+ task :irb do
27
+ sh "irb -I ./lib -r #{gemspec.name.gsub '-','/'}/kernel_method"
28
+ end
29
+
30
+ # # #
31
+ # Run specs
32
+
33
+ desc "#{gemspec.name} | Spec"
34
+ task :spec do
35
+ sh "for file in spec/*_spec.rb; do ruby $file; done"
36
+ end
37
+ task default: :spec
38
+
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rationalist"
4
+ require "paint"
5
+ require "unicopy"
6
+
7
+ argv = Rationalist.parse(
8
+ ARGV,
9
+ string: '_',
10
+ alias: {
11
+ p: 'print',
12
+ s: 'string',
13
+ v: 'version',
14
+ }.merge(Hash[Unicopy::DUMP_FORMATS.select{ |k,v| v[:alias] }.map{ |k,v| [v[:alias], k] }]),
15
+ boolean: [
16
+ 'parse-decimal',
17
+ 'help',
18
+ 'print',
19
+ 'string',
20
+ 'version',
21
+ *Unicopy::DUMP_FORMATS.keys
22
+ ]
23
+ )
24
+
25
+ if argv[:version]
26
+ puts "unicopy #{Unicopy::VERSION} by #{Paint["J-_-L", :bold]} <https://github.com/janlelis/unicopy>"
27
+ exit(0)
28
+ end
29
+
30
+
31
+ if argv[:help]
32
+ dump_format_description = Unicopy::DUMP_FORMATS.map{ |dump_format, info|
33
+ "--#{dump_format.ljust(20)}| #{info[:alias] ? "-#{info[:alias]}" : " "} | #{info[:description]}"
34
+ }.join("\n ")
35
+
36
+ puts <<-HELP
37
+
38
+ #{Paint["DESCRIPTION", :underline]}
39
+
40
+ Converts Unicode codepoints to a string (or vice versa) and copies it to the system clipboard.
41
+ Can also convert codepoints to many dump formats.
42
+
43
+ #{Paint["USAGE", :underline]}
44
+
45
+ CODEPOINTS TO STRING
46
+
47
+ #{Paint["unicopy", :bold]} [options] codepoints
48
+
49
+ Codepoints format is hexadecimal, "U+" is permitted, examples:
50
+
51
+ $ unicopy 52 75 62 79 20 1F32B --print
52
+ Ruby 🌫
53
+
54
+ $ unicopy U+0052 U+0075 U+0062 U+0079 U+0020 U+1F32B --print
55
+ Ruby 🌫
56
+
57
+ STRING TO CODEPOINTS
58
+
59
+ #{Paint["unicopy", :bold]} (--string|-s) [options] string
60
+
61
+ $ unicopy -sp "Ruby 🌫"
62
+ U+0052 U+0075 U+0062 U+0079 U+0020 U+1F32B
63
+
64
+ If data is retrieved via STDIN, it will split alongside newlines.
65
+
66
+ #{Paint["OPTIONS", :underline]}
67
+
68
+ --help | | this help page
69
+ --parse-decimal | | interpret given codepoints as decimal, instead of hexadecimal values
70
+ --print | -p | do not copy to system clipboard, but print to screen
71
+ --string | -s | see above
72
+ --version | | displays version of unicopy
73
+ --(dump format) | | specify the format to be used for dumping the codepoints (see below)
74
+
75
+ #{Paint["DUMP FORMATS", :underline]}
76
+
77
+ #{dump_format_description}
78
+
79
+ Examples:
80
+
81
+ $ unicopy 52 75 62 79 20 1F32B --print --hex
82
+ 52 75 62 79 20 1F32B
83
+
84
+ $ unicopy --string "Ruby 🌫" --print --hex
85
+ 52 75 62 79 20 1F32B
86
+
87
+ $ unicopy 52 75 62 79 20 1F32B --print --uplus
88
+ U+0052 U+0075 U+0062 U+0079 U+0020 U+1F32B
89
+
90
+ $ unicopy --string "Ruby 🌫" --print --uplus
91
+ U+0052 U+0075 U+0062 U+0079 U+0020 U+1F32B
92
+
93
+ $ unicopy 52 75 62 79 20 1F32B --print --0x
94
+ 0x0052 0x0075 0x0062 0x0079 0x0020 0x1F32B
95
+
96
+ $ unicopy --string "Ruby 🌫" --print --0x
97
+ 0x0052 0x0075 0x0062 0x0079 0x0020 0x1F32B
98
+
99
+ $ unicopy 52 75 62 79 20 1F32B --print --dec
100
+ 82 117 98 121 32 127787
101
+
102
+ $ unicopy --string "Ruby 🌫" --print --dec
103
+ 82 117 98 121 32 127787
104
+
105
+ $ unicopy 52 75 62 79 20 1F32B --print --ruby
106
+ \\u{52 75 62 79 20 1F32B}
107
+
108
+ $ unicopy --string "Ruby 🌫" --print --ruby
109
+ \\u{52 75 62 79 20 1F32B}
110
+
111
+ $ unicopy 52 75 62 79 20 1F32B --print --js
112
+ \\u0052\\u0075\\u0062\\u0079\\u0020\\uD83C\\uDF2B
113
+
114
+ $ unicopy --string "Ruby 🌫" --print --js
115
+ \\u0052\\u0075\\u0062\\u0079\\u0020\\uD83C\\uDF2B
116
+
117
+ $ unicopy 52 75 62 79 20 1F32B --print --es6
118
+ \\u{52}\\u{75}\\u{62}\\u{79}\\u{20}\\u{1F32B}
119
+
120
+ $ unicopy --string "Ruby 🌫" --print --es6
121
+ \\u{52}\\u{75}\\u{62}\\u{79}\\u{20}\\u{1F32B}
122
+
123
+ $ unicopy 52 75 62 79 20 1F32B --print --css
124
+ \\52\\75\\62\\79\\20\\1f32b
125
+
126
+ $ unicopy --string "Ruby 🌫" --print --css
127
+ \\52\\75\\62\\79\\20\\1f32b
128
+
129
+ $ unicopy 52 75 62 79 20 1F32B --print --html-hex
130
+ &#x52;&#x75;&#x62;&#x79;&#x20;&#x1F32B;
131
+
132
+ $ unicopy --string "Ruby 🌫" --print --html-hex
133
+ &#x52;&#x75;&#x62;&#x79;&#x20;&#x1F32B;
134
+
135
+ $ unicopy 52 75 62 79 20 1F32B --print --html-dec
136
+ &#82;&#117;&#98;&#121;&#32;&#127787;
137
+
138
+ $ unicopy --string "Ruby 🌫" --print --html-dec
139
+ &#82;&#117;&#98;&#121;&#32;&#127787;
140
+
141
+ $ unicopy 52 75 62 79 20 1F32B --print --bytes-utf8
142
+ 52 75 62 79 20 F0 9F 8C AB
143
+
144
+ $ unicopy --string "Ruby 🌫" --print --bytes-utf8
145
+ 52 75 62 79 20 F0 9F 8C AB
146
+
147
+ #{Paint["MORE INFO", :underline]}
148
+
149
+ https://github.com/janlelis/unicopy
150
+
151
+ HELP
152
+ exit(0)
153
+ end
154
+
155
+ if argv[:_]
156
+ codepoints = argv.delete :_
157
+ elsif !$stdin.tty?
158
+ codepoints = $stdin.read.split($/)
159
+ else
160
+ codepoints = nil
161
+ end
162
+
163
+ options = {
164
+ parse_decimal: argv[:"parse-decimal"],
165
+ print: argv[:print],
166
+ string: argv[:string],
167
+ }
168
+
169
+ dump_formats = Unicopy::DUMP_FORMATS.keys.select{ |dump_format| argv[dump_format.to_sym] }
170
+ case dump_formats.size
171
+ when 0
172
+ # nothing
173
+ when 1
174
+ options[:dump] = dump_formats[0]
175
+ else
176
+ raise ArgumentError, "only one dump format can be passed to unicopy"
177
+ end
178
+
179
+ begin
180
+ Unicopy.unicopy(*codepoints, **options)
181
+ rescue ArgumentError
182
+ $stderr.puts Paint[$!.message, :red]
183
+ exit(1)
184
+ end
@@ -0,0 +1,143 @@
1
+ # enable-frozen-string: true
2
+
3
+ require_relative "unicopy/version"
4
+
5
+ require "clipboard"
6
+
7
+ module Unicopy
8
+ DUMP_FORMATS = {
9
+ 'hex' => {
10
+ description: "____ (hexadecimal)",
11
+ replace: "%X",
12
+ alias: "x",
13
+ },
14
+ 'uplus' => {
15
+ description: "U+____ (hexadecimal)",
16
+ replace: "U+%04X",
17
+ alias: "u",
18
+ },
19
+ '0x' => {
20
+ description: "0x____ (hexadecimal)",
21
+ replace: "0x%04X",
22
+ alias: "0",
23
+ },
24
+ 'dec' => {
25
+ description: "____ (decimal)",
26
+ replace: "%d",
27
+ alias: "d",
28
+ },
29
+ 'ruby' => {
30
+ description: "Ruby \\u{____} (hexadecimal)",
31
+ prefix: "\\u{",
32
+ replace: "%X",
33
+ suffix: "}",
34
+ alias: "r",
35
+ },
36
+ 'css' => {
37
+ description: "CSS \\____ (hexadecimal)",
38
+ replace: "\\%x",
39
+ joiner: "",
40
+ suffix: " ",
41
+ },
42
+ 'js' => {
43
+ description: "JavaScript \\u____ with UTF-16 surrogates (hexadecimal)",
44
+ replace: ->(x){
45
+ [x].pack("U").encode("UTF-16BE").each_byte.each_slice(2).map{ |a,b| "\\u%04X" % (a*256 + b) }
46
+ },
47
+ joiner: "",
48
+ },
49
+ 'es6' => {
50
+ description: "EcmaScript 6+ \\u{____} (hexadecimal)",
51
+ replace: "\\u{%X}",
52
+ joiner: "",
53
+ alias: "6",
54
+ },
55
+ 'html-hex' => {
56
+ description: "HTML entitiy &#x____ (hexadecimal)",
57
+ replace: "&#x%X;",
58
+ joiner: "",
59
+ },
60
+ 'html-dec' => {
61
+ description: "HTML entitiy &#____ (decimal)",
62
+ replace: "&#%d;",
63
+ joiner: "",
64
+ },
65
+ 'bytes-utf8' => {
66
+ description: "UTF-8 encoded (bytes)",
67
+ replace: ->(x){
68
+ [x].pack("U").unpack("C*").map{ |x| x.to_s(16).upcase }.join(" ")
69
+ },
70
+ }
71
+ }
72
+ DUMP_FORMAT_DEFAULTS = {
73
+ prefix: "",
74
+ replace: "%s",
75
+ joiner: " ",
76
+ suffix: "",
77
+ }
78
+
79
+ def self.unicopy(*args, string: false, dump: nil, parse_decimal: false, print: false)
80
+ if args.empty?
81
+ raise ArgumentError, "no data given to copy"
82
+ elsif !string
83
+ codepoints = transform_raw_codepoints(args.join(" ").split(" "), parse_decimal)
84
+ if dump
85
+ deliver(dump_codepoints(codepoints, format: dump), print: print, codepoints_length: codepoints.length, message: "dump of")
86
+ else # default
87
+ deliver(codepoints.pack("U*"), print: print, codepoints_length: codepoints.length, message: "string of")
88
+ end
89
+ else
90
+ data = args.join("")
91
+ data = data.encode("UTF-8") unless data.encoding.name == "UTF-8"
92
+ codepoints = data.unpack("U*")
93
+
94
+ deliver(dump_codepoints(codepoints, format: dump), print: print, codepoints_length: codepoints.length, message: "dump of")
95
+ end
96
+ end
97
+
98
+ def self.deliver(output, print: false, message: "", codepoints_length:)
99
+ if print
100
+ puts(output)
101
+ else
102
+ Clipboard.copy(output)
103
+ puts Paint["Copied #{message} #{codepoints_length} codepoint#{codepoints_length != 1 ? "s" : ""} to clipboard", :green]
104
+ end
105
+ end
106
+
107
+ def self.transform_raw_codepoints(codepoints, parse_decimal = false)
108
+ if parse_decimal
109
+ parse_numerals_regex = /\A([0-9]+)\z/
110
+ numeral_base = 10
111
+ else
112
+ parse_numerals_regex = /\A(?:U\+)?(\h+)\z/
113
+ numeral_base = 16
114
+ end
115
+
116
+ codepoints.map{ |cp|
117
+ case cp
118
+ when Integer
119
+ cp
120
+ when parse_numerals_regex
121
+ $1.to_i(numeral_base)
122
+ else
123
+ raise ArgumentError, "unicopy does not understand codepoint \"#{cp}\". Please pass hexadecimal codepoint values, separated by spaces, or use --string option"
124
+ end
125
+ }.tap{ |codepoints|
126
+ codepoints.pack("U*").valid_encoding? or raise ArgumentError, "invalid codepoints passed to unicopy"
127
+ }
128
+ end
129
+
130
+ def self.dump_codepoints(codepoints, format: nil)
131
+ format ||= "uplus"
132
+ if dump_format_details = DUMP_FORMATS[format]
133
+ prefix = dump_format_details[:prefix] || DUMP_FORMAT_DEFAULTS[:prefix]
134
+ replace = dump_format_details[:replace] || DUMP_FORMAT_DEFAULTS[:replace]
135
+ joiner = dump_format_details[:joiner] || DUMP_FORMAT_DEFAULTS[:joiner]
136
+ suffix = dump_format_details[:suffix] || DUMP_FORMAT_DEFAULTS[:suffix]
137
+ else
138
+ raise ArgumentError, "unicopy does not know dump format \"#{format}\""
139
+ end
140
+
141
+ prefix + codepoints.map{ |cp| replace.is_a?(Proc) ? replace[cp] : replace % cp }.join(joiner) + suffix
142
+ end
143
+ end
@@ -0,0 +1,9 @@
1
+ require_relative '../unicopy'
2
+
3
+ module Kernel
4
+ private
5
+
6
+ def unicopy(string, **kwargs)
7
+ Unicopy.unicopy(string, **kwargs)
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module Unicopy
2
+ VERSION = "1.0.0".freeze
3
+ end
@@ -0,0 +1,102 @@
1
+ require_relative "../lib/unicopy/kernel_method"
2
+ require "minitest/autorun"
3
+
4
+ describe Unicopy do
5
+ it "converts codepoints to string and, with --print, outputs it to STDOUT" do
6
+ assert_output(/Ruby 🌫/){ unicopy("52 75 62 79 20 1F32B", print: true) }
7
+ end
8
+
9
+ it "also works with U+ prefixes" do
10
+ assert_output(/Ruby 🌫/){ unicopy("U+0052 U+0075 U+0062 U+0079 U+0020 U+1F32B", print: true) }
11
+ end
12
+
13
+ it "parses codepoints as decimal if --parse-decimal option is given" do
14
+ assert_output(/4K>O/){ unicopy("52 75 62 79", print: true, parse_decimal: true) }
15
+ end
16
+
17
+ it "will convert string to codepoints with --string option" do
18
+ assert_output(Regexp.compile(Regexp.escape("U+0052 U+0075 U+0062 U+0079 U+0020 U+1F32B"))){
19
+ unicopy("Ruby 🌫", print: true, string: true)
20
+ }
21
+ end
22
+
23
+ it "works with non-UTF-8 input" do
24
+ assert_output(Regexp.compile(Regexp.escape("U+0052 U+0075 U+0062 U+0079 U+0020 U+1F32B"))){
25
+ unicopy("Ruby 🌫".encode("UTF-16LE"), print: true, string: true)
26
+ }
27
+ end
28
+
29
+ describe "[dump formats]" do
30
+ it "dumps hex" do
31
+ assert_output(Regexp.compile(Regexp.escape("52 75 62 79 20 1F32B"))){
32
+ unicopy("52 75 62 79 20 1F32B", print: true, dump: "hex")
33
+ }
34
+ end
35
+
36
+ it "dumps hex (string input)" do
37
+ assert_output(Regexp.compile(Regexp.escape("52 75 62 79 20 1F32B"))){
38
+ unicopy("Ruby 🌫", print: true, string: true, dump: "hex")
39
+ }
40
+ end
41
+
42
+ it "dumps uplus (string input) [default]" do
43
+ assert_output(Regexp.compile(Regexp.escape("U+0052 U+0075 U+0062 U+0079 U+0020 U+1F32B"))){
44
+ unicopy("Ruby 🌫", print: true, string: true)
45
+ }
46
+ end
47
+
48
+ it "dumps 0x (string input)" do
49
+ assert_output(Regexp.compile(Regexp.escape("0x0052 0x0075 0x0062 0x0079 0x0020 0x1F32B"))){
50
+ unicopy("Ruby 🌫", print: true, string: true, dump: "0x")
51
+ }
52
+ end
53
+
54
+ it "dumps dec (string input)" do
55
+ assert_output(Regexp.compile(Regexp.escape("82 117 98 121 32 127787"))){
56
+ unicopy("Ruby 🌫", print: true, string: true, dump: "dec")
57
+ }
58
+ end
59
+
60
+ it "dumps ruby (string input)" do
61
+ assert_output(Regexp.compile(Regexp.escape("\\u{52 75 62 79 20 1F32B}"))){
62
+ unicopy("Ruby 🌫", print: true, string: true, dump: "ruby")
63
+ }
64
+ end
65
+
66
+ it "dumps js (string input)" do
67
+ assert_output(Regexp.compile(Regexp.escape("\\u0052\\u0075\\u0062\\u0079\\u0020\\uD83C\\uDF2B"))){
68
+ unicopy("Ruby 🌫", print: true, string: true, dump: "js")
69
+ }
70
+ end
71
+
72
+ it "dumps es6 (string input)" do
73
+ assert_output(Regexp.compile(Regexp.escape("\\u{52}\\u{75}\\u{62}\\u{79}\\u{20}\\u{1F32B}"))){
74
+ unicopy("Ruby 🌫", print: true, string: true, dump: "es6")
75
+ }
76
+ end
77
+
78
+ it "dumps css (string input)" do
79
+ assert_output(Regexp.compile(Regexp.escape("\\52\\75\\62\\79\\20\\1f32b"))){
80
+ unicopy("Ruby 🌫", print: true, string: true, dump: "css")
81
+ }
82
+ end
83
+
84
+ it "dumps html-hex (string input)" do
85
+ assert_output(Regexp.compile(Regexp.escape("&#x52;&#x75;&#x62;&#x79;&#x20;&#x1F32B;"))){
86
+ unicopy("Ruby 🌫", print: true, string: true, dump: "html-hex")
87
+ }
88
+ end
89
+
90
+ it "dumps html-dec (string input)" do
91
+ assert_output(Regexp.compile(Regexp.escape("&#82;&#117;&#98;&#121;&#32;&#127787;"))){
92
+ unicopy("Ruby 🌫", print: true, string: true, dump: "html-dec")
93
+ }
94
+ end
95
+
96
+ it "dumps bytes-utf8 (string input)" do
97
+ assert_output(Regexp.compile(Regexp.escape("52 75 62 79 20 F0 9F 8C AB"))){
98
+ unicopy("Ruby 🌫", print: true, string: true, dump: "bytes-utf8")
99
+ }
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require File.dirname(__FILE__) + "/lib/unicopy/version"
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "unicopy"
7
+ gem.version = Unicopy::VERSION
8
+ gem.summary = "Converts Unicode codepoints to a string (or vice versa) and copies it to the system clipboard."
9
+ gem.description = "Converts Unicode codepoints to a string (or vice versa) and copies it to the system clipboard. Can also convert codepoints to many dump formats."
10
+ gem.authors = ["Jan Lelis"]
11
+ gem.email = ["mail@janlelis.de"]
12
+ gem.homepage = "https://github.com/janlelis/unicopy"
13
+ gem.license = "MIT"
14
+
15
+ gem.files = Dir["{**/}{.*,*}"].select{ |path| File.file?(path) && path !~ /^(pkg|screenshots)/ }
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency 'paint', '>= 0.9', '< 3.0'
21
+ gem.add_dependency 'rationalist', '~> 2.0'
22
+ gem.add_dependency 'clipboard', '~> 1.1'
23
+
24
+ gem.required_ruby_version = "~> 2.0"
25
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: unicopy
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jan Lelis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-04-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: paint
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0.9'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '3.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '0.9'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '3.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: rationalist
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: clipboard
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.1'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.1'
61
+ description: Converts Unicode codepoints to a string (or vice versa) and copies it
62
+ to the system clipboard. Can also convert codepoints to many dump formats.
63
+ email:
64
+ - mail@janlelis.de
65
+ executables:
66
+ - unicopy
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - ".gitignore"
71
+ - ".travis.yml"
72
+ - CHANGELOG.md
73
+ - CODE_OF_CONDUCT.md
74
+ - Gemfile
75
+ - Gemfile.lock
76
+ - MIT-LICENSE.txt
77
+ - README.md
78
+ - Rakefile
79
+ - bin/unicopy
80
+ - lib/unicopy.rb
81
+ - lib/unicopy/kernel_method.rb
82
+ - lib/unicopy/version.rb
83
+ - spec/unicopy_spec.rb
84
+ - unicopy.gemspec
85
+ homepage: https://github.com/janlelis/unicopy
86
+ licenses:
87
+ - MIT
88
+ metadata: {}
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '2.0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 2.6.8
106
+ signing_key:
107
+ specification_version: 4
108
+ summary: Converts Unicode codepoints to a string (or vice versa) and copies it to
109
+ the system clipboard.
110
+ test_files:
111
+ - spec/unicopy_spec.rb