trogdoro / xiki

Emacs libs in ruby

This URL has Read+Write access

xiki / clipboard.rb
100644 291 lines (242 sloc) 6.796 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
require 'keys'
require 'file_tree'
 
# Provides copy and paste functionality
class Clipboard
  extend ElMixin
 
  # Stores things user copies
  @@hash = {}
  @@entered_as_quote = {}
 
  def self.copy loc=nil, txt=nil
    # Use string if user types it quickly
    loc ||= Keys.input(:one_char=>true, :prompt=>"Enter one char (to store this as): ") || "0"
 
    unless txt
      left, right = View.range
      Effects.blink :left=>left, :right=>right
      txt = buffer_substring(region_beginning, region_end)
    end
    self.set(loc, txt, Keys.prefix)
  end
 
  def self.cut loc=nil
    loc = loc.to_s
    prefix = Keys.prefix :clear=>true # If numeric prefix, reset region
 
    if prefix == 0
      l, r = View.paragraph :bounds=>true
      View.cursor = l
      View.mark = r
    elsif prefix.is_a?(Fixnum)
      Line.to_left
      View.mark = Line.left 1+prefix
    end
 
    self.copy loc
    delete_region(region_beginning, region_end)
 
    Location.as_spot('deleted')
  end
 
  def self.paste loc=nil
    # Use string if user types it quickly
    loc ||= Keys.input(:one_char => true, :prompt => "Enter one char: ") || 0
 
    set_mark_command nil
 
    (elvar.current_prefix_arg || 1).times do # Get from corresponding register
      insert @@hash[loc.to_s]
    end
  end
 
  def self.get key='0', options={}
    val = @@hash[key.to_s]
    if options[:add_linebreak]
      val = "#{val}\n" unless val[/\n$/]
    end
    val
  end
 
  def self.[] key
    self.get key.to_s
  end
 
  def self.[]= key, to
    self.set key.to_s, to
  end
 
  def self.display
    @@hash.each do |k, v|
      insert [k, v].to_s
    end
  end
 
  def self.hash
    @@hash
  end
 
  def self.list
    switch_to_buffer "*clipboard*"
    erase_buffer
    notes_mode
 
    Clipboard.hash.sort.each do |a, b|
      insert "| #{a}\n#{b}\n\n"
    end
    beginning_of_buffer
  end
 
  def self.set loc, str, append=nil
    loc = loc.to_s
    # Save in corresponding register (or append if prefix)
    if append
      @@hash[loc] += str
    else
      # Store as path
      @@hash["/"] = expand_file_name( buffer_file_name ? buffer_file_name : elvar.default_directory )
      if buffer_file_name
        # Store as tree snippet
        @@hash["="] = FileTree.snippet(str)
        @@hash["."] = "#{file_name_nondirectory(buffer_file_name)}"
        @@hash["\\"] = "#{elvar.default_directory}\n #{file_name_nondirectory(buffer_file_name)}"
      end
      @@hash[loc] = str
      x_select_text str if loc == "0" # If 0, store in OS clipboard
    end
  end
 
  def self.do_as_snake_case
    Keys.prefix_times.times do
      word = Line.symbol(:delete => true)
      insert TextUtil.snake_case(word)
      Move.forward
    end
  end
 
  def self.do_as_camel_case
    Keys.prefix_times.times do
      word = Line.symbol(:delete => true)
      insert TextUtil.camel_case(word)
      Move.forward
    end
  end
 
  def self.do_as_upper_case
    Keys.prefix_times.times do
      word = Line.symbol(:delete => true)
      insert word.upcase
      Move.forward
    end
  end
 
  def self.do_as_lower_case
    Keys.prefix_times.times do
      word = Line.symbol(:delete => true)
      insert word.downcase
      Move.forward
    end
  end
 
  def self.copy_paragraph options={}
    if Keys.prefix_u? or options[:rest] # If U prefix, get rest of paragraph
      left, right = View.paragraph(:bounds => true, :start_here => true)
    else
      if Keys.prefix # If numeric prefix
        self.as_line
        return
      end
      # If no prefix, get whole paragraph
      left, right = View.paragraph(:bounds => true)
    end
 
    if options[:just_return]
      return [View.txt(left, right), left, right]
    end
    goto_char left
    set_mark right
    Effects.blink(:left => left, :right => right)
    Keys.clear_prefix
    Clipboard.copy("0")
  end
 
  def self.diff_1_and_2
    # Compare clipboard 1 with 2
    # Unquote if several spaces and |
    View.to_buffer "1", :clear => true
    one = Clipboard["1"]
    one.gsub!(/^ +\|/, '') if one =~ /\A +\|/
    $el.insert Clipboard["1"]
 
    View.to_buffer "2", :clear => true
    one = Clipboard["2"]
    one.gsub!(/^ +\|/, '') if one =~ /\A +\|/
    $el.insert Clipboard["2"]
 
    ediff_buffers "1", "2"
  end
 
  def self.as_thing
 
    # If on blank spaces, use them
    if buffer_substring(point-1, point+1) =~ /[ \n] /
      skip_chars_forward " "
      right = point
      skip_chars_backward " "
      left = point
    else
      skip_chars_forward " "
      left, right = bounds_of_thing_at_point(:sexp).to_a
    end
 
    if Keys.prefix_u?
      left += 1
      right -= 1
    end
    Effects.blink(:left=>left, :right=>right)
 
    txt = View.txt(left, right)
    Clipboard.set "0", txt
    View.to right
    View.mark left
    Clipboard.save_for_yank txt
  end
 
  def self.as_object
    set("0", thing_at_point(:symbol))
    left, right = bounds_of_thing_at_point(:symbol).to_a
    Effects.blink(:left=>left, :right=>right)
  end
 
  def self.copy_everything
    Effects.blink :what=>:all
    Clipboard.set("0", buffer_string)
    set_mark(point_max)
  end
 
  def self.as_line many=nil
    many ||= Keys.prefix(:clear=>true) || 1
    Move.to_axis
    left = Line.left
    right = Line.left(many+1)
    line = View.txt(left, right)
    Clipboard.set("0", line)
    Effects.blink :left=>left, :right=>right
    $el.set_mark(right)
    Clipboard.save_for_yank line # Store for retrieval with enter_yank
  end
 
  def self.enter_replacement
    # If on whitespace, move to off of it
    skip_chars_forward " "
 
    orig = point
    Move.to_other_bracket
    View.delete orig, point
    View.insert Clipboard['0']
  end
 
 
  def self.as_clipboard
    prefix = Keys.prefix :clear=>true
 
    if prefix == 0
      l, r = View.paragraph :bounds=>true
      Effects.blink :left=>l, :right=>r
      cursor = View.cursor
      View.cursor = l
      Location.as_spot('clipboard')
      Clipboard["0"] = View.txt(l, r)
      View.cursor = cursor
      return
    end
 
    Location.as_spot('clipboard')
 
    # If numeric prefix, get next n lines and put in clipboard
    if prefix.is_a?(Fixnum)
      l, r = Line.left, Line.left(prefix + 1)
      Effects.blink :left=>l, :right=>r
      Clipboard["0"] = View.txt(l, r)
 
      View.set_mark(r)
      return
    end
 
    Clipboard.copy("0")
    Clipboard.save_for_yank View.selection # Store for retrieval with enter_yank
  end
 
  def self.save_for_yank txt
    key = txt[/[a-z]/i]
    return unless key
    @@entered_as_quote[key.downcase] = txt
  end
 
  def self.enter_yank
    ch = Keys.input :one_char => true
    value = @@entered_as_quote[ch]
    return unless value
    View.insert value
  end
 
  def self.to_yank
    ch = Keys.input :one_char => true
    value = @@entered_as_quote[ch]
    Search.to $el.regexp_quote(value)
  end
 
end