textbringer 27 → 28
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/README.md +3 -1
- data/lib/textbringer/commands/fill.rb +152 -59
- data/lib/textbringer/input_methods/skk_input_method.rb +710 -74
- data/lib/textbringer/mode.rb +19 -0
- data/lib/textbringer/modes/c_mode.rb +6 -0
- data/lib/textbringer/modes/programming_mode.rb +3 -6
- data/lib/textbringer/modes/ruby_mode.rb +18 -3
- data/lib/textbringer/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a93c844e10f5ad02a288323d8090d5dedea44b7f6050b054f9adc100e2bac129
|
|
4
|
+
data.tar.gz: 6a54096a278fba823491914ea9b184f1c640d64f5234192dabf64afad7ad3ce1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f19c746e74c12884bd99d827faaf0eee55a2dca803c1a2518f857286c00c91b0d7ad7d3516ce3e7e659cabd32db841674d9f42158ce01381ad9ea0b0901d71f0
|
|
7
|
+
data.tar.gz: 9aaf8575f47fd4e20bcd9cd868cad9b232bc7444fc29311c68d844058ab620d94a732b84ade0b527ee1ba2122f2a50f42981d17353de5c78f2c51c4535f24cd9
|
data/README.md
CHANGED
|
@@ -135,7 +135,9 @@ set_background_color "default"
|
|
|
135
135
|
|
|
136
136
|
After checking out the repo, run `bundle install` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
137
137
|
|
|
138
|
-
To
|
|
138
|
+
To run the tests, run `bundle exec rake test`. To install this gem onto your local machine, run `bundle exec rake install`.
|
|
139
|
+
|
|
140
|
+
To release a new version, run `bundle exec rake bump` on a clean `main` branch. It increments the version number in `version.rb`, commits and pushes the change, and pushes a `v<N>` tag. The tag triggers the `push_gem.yml` workflow, which publishes the gem to [rubygems.org](https://rubygems.org) via trusted publishing and creates a GitHub release. Do not run `bundle exec rake release`; it would try to push the gem from your machine as well.
|
|
139
141
|
|
|
140
142
|
## Contributing
|
|
141
143
|
|
|
@@ -2,32 +2,151 @@ require "stringio"
|
|
|
2
2
|
|
|
3
3
|
module Textbringer
|
|
4
4
|
module FillExtension
|
|
5
|
+
class Filler
|
|
6
|
+
GRAPH = /(?=[\u{0000}-\u{00FF}])[[:graph:]]/
|
|
7
|
+
|
|
8
|
+
def initialize(column, prefix)
|
|
9
|
+
@column = column
|
|
10
|
+
@prefix = prefix
|
|
11
|
+
@prefix_width = Buffer.display_width(prefix)
|
|
12
|
+
@fill_column = CONFIG[:fill_column]
|
|
13
|
+
@output = +""
|
|
14
|
+
@line_start = 0
|
|
15
|
+
@prev_c = nil
|
|
16
|
+
@bol = column == 0
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# head is kept as it is at the start of the first line; body is the
|
|
20
|
+
# text to fill, with the prefix already removed from each line.
|
|
21
|
+
def fill(head, body)
|
|
22
|
+
if !head.empty?
|
|
23
|
+
@output << head
|
|
24
|
+
@line_start = head.size
|
|
25
|
+
@column += Buffer.display_width(head)
|
|
26
|
+
@bol = false
|
|
27
|
+
end
|
|
28
|
+
input = StringIO.new(body)
|
|
29
|
+
while c = input.getc
|
|
30
|
+
if c == "\n"
|
|
31
|
+
skip_blanks(input)
|
|
32
|
+
if input.eof?
|
|
33
|
+
insert_final_newline
|
|
34
|
+
elsif @column < @fill_column
|
|
35
|
+
if GRAPH.match?(@prev_c)
|
|
36
|
+
insert_space_between_words(input)
|
|
37
|
+
end
|
|
38
|
+
next
|
|
39
|
+
else
|
|
40
|
+
insert_newline(@prefix)
|
|
41
|
+
end
|
|
42
|
+
else
|
|
43
|
+
w = Buffer.display_width(c)
|
|
44
|
+
if @column + w > @fill_column || @column >= @fill_column
|
|
45
|
+
if /\w/.match?(@prev_c) && /\w/.match?(c)
|
|
46
|
+
insert_newline_before_word
|
|
47
|
+
else
|
|
48
|
+
insert_newline(@prefix)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
insert_char(c, w)
|
|
52
|
+
end
|
|
53
|
+
@prev_c = c
|
|
54
|
+
end
|
|
55
|
+
@output
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def skip_blanks(input)
|
|
61
|
+
while c = input.getc
|
|
62
|
+
if !/[ \t]/.match?(c)
|
|
63
|
+
input.ungetc(c)
|
|
64
|
+
break
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def insert_space_between_words(input)
|
|
70
|
+
c = input.getc
|
|
71
|
+
input.ungetc(c)
|
|
72
|
+
if GRAPH.match?(c)
|
|
73
|
+
@output << " "
|
|
74
|
+
@column += 1
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def insert_newline_before_word
|
|
79
|
+
m = @output.match(/(?:([^\w \t\n])|(\w)[ \t]+)(\w*)\z/, @line_start)
|
|
80
|
+
return if m.nil?
|
|
81
|
+
word = m[3]
|
|
82
|
+
@output[m.begin(0)..] = "#{m[1]}#{m[2]}\n#{@prefix}#{word}"
|
|
83
|
+
@line_start = @output.size - word.size
|
|
84
|
+
@column = @prefix_width + Buffer.display_width(word)
|
|
85
|
+
@bol = false
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def insert_newline(prefix)
|
|
89
|
+
return if @bol
|
|
90
|
+
@output.sub!(/[ \t]+\z/, "")
|
|
91
|
+
@output << "\n" << prefix
|
|
92
|
+
@line_start = @output.size
|
|
93
|
+
@column = Buffer.display_width(prefix)
|
|
94
|
+
@bol = true
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# The newline that ends the text is kept even on an otherwise empty
|
|
98
|
+
# line, and no prefix follows it.
|
|
99
|
+
def insert_final_newline
|
|
100
|
+
@output.sub!(/[ \t]+\z/, "")
|
|
101
|
+
@output << "\n"
|
|
102
|
+
@line_start = @output.size
|
|
103
|
+
@column = 0
|
|
104
|
+
@bol = true
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def insert_char(c, w)
|
|
108
|
+
if @bol && /[ \t]/.match?(c)
|
|
109
|
+
return
|
|
110
|
+
end
|
|
111
|
+
@output << c
|
|
112
|
+
@column += w
|
|
113
|
+
@bol = false
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
5
117
|
refine Buffer do
|
|
6
118
|
def fill_region(s = Buffer.current.point, e = Buffer.current.mark)
|
|
7
119
|
s, e = Buffer.region_boundaries(s, e)
|
|
8
120
|
save_excursion do
|
|
9
|
-
str = substring(s, e)
|
|
10
121
|
goto_char(s)
|
|
11
122
|
pos = point
|
|
12
123
|
beginning_of_line
|
|
13
124
|
column = Buffer.display_width(substring(point, pos))
|
|
14
|
-
|
|
125
|
+
prefix_re = fill_prefix_regexp(comment_line?)
|
|
126
|
+
prefix = fill_prefix(substring(point, e), prefix_re)
|
|
127
|
+
lines = substring(s, e).lines
|
|
128
|
+
head = column == 0 && lines[0] ? lines[0][prefix_re] : ""
|
|
129
|
+
body = lines.each_with_index.map { |line, i|
|
|
130
|
+
i == 0 ? line[head.size..] : line.sub(prefix_re, "")
|
|
131
|
+
}.join
|
|
132
|
+
replace(Filler.new(column, prefix).fill(head, body),
|
|
133
|
+
start: s, end: e)
|
|
15
134
|
end
|
|
16
135
|
end
|
|
17
136
|
|
|
18
137
|
def fill_paragraph
|
|
19
138
|
beginning_of_line
|
|
20
|
-
|
|
21
|
-
|
|
139
|
+
separator = fill_paragraph_separator(comment_line?)
|
|
140
|
+
while !beginning_of_buffer? && !looking_at?(separator)
|
|
22
141
|
backward_line
|
|
23
142
|
end
|
|
24
|
-
while looking_at?(
|
|
143
|
+
while !end_of_buffer? && looking_at?(separator)
|
|
25
144
|
forward_line
|
|
26
145
|
end
|
|
27
146
|
s = point
|
|
28
147
|
begin
|
|
29
148
|
forward_line
|
|
30
|
-
end while !end_of_buffer? && !looking_at?(
|
|
149
|
+
end while !end_of_buffer? && !looking_at?(separator)
|
|
31
150
|
if beginning_of_line?
|
|
32
151
|
backward_char
|
|
33
152
|
end
|
|
@@ -36,69 +155,43 @@ module Textbringer
|
|
|
36
155
|
|
|
37
156
|
private
|
|
38
157
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
while c = input.getc
|
|
45
|
-
if c == "\n"
|
|
46
|
-
if column < fill_column && !input.eof?
|
|
47
|
-
if /(?=[\u{0000}-\u{00FF}])[[:graph:]]/.match?(prev_c)
|
|
48
|
-
column = insert_space_between_words(input, output, column)
|
|
49
|
-
end
|
|
50
|
-
next
|
|
51
|
-
end
|
|
52
|
-
column = insert_newline(output)
|
|
53
|
-
else
|
|
54
|
-
w = Buffer.display_width(c)
|
|
55
|
-
if column + w > fill_column || column >= fill_column
|
|
56
|
-
if /\w/.match?(prev_c) && /\w/.match?(c)
|
|
57
|
-
column = insert_newline_before_word(output, column)
|
|
58
|
-
else
|
|
59
|
-
column = insert_newline(output)
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
column = insert_char(output, column, c, w)
|
|
63
|
-
end
|
|
64
|
-
prev_c = c
|
|
65
|
-
end
|
|
66
|
-
output
|
|
158
|
+
# Whether the current line is a comment line of the buffer's mode.
|
|
159
|
+
# Point must be at the beginning of the line.
|
|
160
|
+
def comment_line?
|
|
161
|
+
re = mode&.comment_prefix_regexp
|
|
162
|
+
!re.nil? && looking_at?(re)
|
|
67
163
|
end
|
|
68
164
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if
|
|
73
|
-
|
|
74
|
-
column + 1
|
|
165
|
+
# A line that ends the paragraph: a blank line, or, when filling a
|
|
166
|
+
# comment, any line that is not a comment with something in it.
|
|
167
|
+
def fill_paragraph_separator(comment)
|
|
168
|
+
if comment
|
|
169
|
+
/^(?!#{mode.comment_prefix_regexp}[^ \t\n])/
|
|
75
170
|
else
|
|
76
|
-
|
|
171
|
+
/^[ \t]*$/
|
|
77
172
|
end
|
|
78
173
|
end
|
|
79
174
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
175
|
+
# What is stripped from the start of each line before filling and
|
|
176
|
+
# put back by the prefix: indentation, and the comment leader when
|
|
177
|
+
# filling a comment.
|
|
178
|
+
def fill_prefix_regexp(comment)
|
|
179
|
+
if comment
|
|
180
|
+
/\A(?:#{mode.comment_prefix_regexp}|[ \t]*)/
|
|
84
181
|
else
|
|
85
|
-
|
|
182
|
+
/\A[ \t]*/
|
|
86
183
|
end
|
|
87
184
|
end
|
|
88
185
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
else
|
|
99
|
-
output << c
|
|
100
|
-
column + w
|
|
101
|
-
end
|
|
186
|
+
# The prefix of the second line, or of the first line when there is
|
|
187
|
+
# no second line, is the prefix of every line after the first, as
|
|
188
|
+
# with adaptive-fill-mode in Emacs. The first line keeps its own
|
|
189
|
+
# prefix.
|
|
190
|
+
def fill_prefix(str, prefix_re)
|
|
191
|
+
first, second = str.lines
|
|
192
|
+
line = second && !second.sub(prefix_re, "").match?(/\A\n?\z/) ?
|
|
193
|
+
second : first
|
|
194
|
+
line ? line[prefix_re] : ""
|
|
102
195
|
end
|
|
103
196
|
end
|
|
104
197
|
end
|