coolline 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,15 +1,20 @@
1
1
  require 'io/console'
2
2
 
3
3
  class Coolline
4
- if ENV["XDG_CONFIG_HOME"]
5
- ConfigDir = ENV["XDG_CONFIG_HOME"]
6
- ConfigFile = File.join(ConfigDir, "coolline.rb")
4
+ if config_home = ENV["XDG_CONFIG_HOME"] and !config_home.empty?
5
+ ConfigDir = File.join(config_home, "coolline")
7
6
  else
8
- ConfigDir = ENV["HOME"]
9
- ConfigFile = File.join(ConfigDir, ".coolline.rb")
7
+ ConfigDir = File.join(ENV["HOME"], ".config", "coolline")
10
8
  end
11
9
 
12
- HistoryFile = File.join(ConfigDir, ".coolline-history")
10
+ if cache_home = ENV["XDG_CACHE_HOME"] and !cache_home.empty?
11
+ CacheDir = File.join(cache_home, "coolline")
12
+ else
13
+ CacheDir = File.join(ENV["HOME"], ".cache", "coolline")
14
+ end
15
+
16
+ ConfigFile = File.join(ConfigDir, "coolline.rb")
17
+ HistoryFile = File.join(CacheDir, "history")
13
18
 
14
19
  NullFile = if defined? File::NULL
15
20
  File::NULL
@@ -17,7 +22,7 @@ class Coolline
17
22
  "/dev/null"
18
23
  end
19
24
 
20
- AnsiCode = %r{(\e\[\??\d+(?:;\d+)?\w)}
25
+ AnsiCode = %r{(\e\[\??\d+(?:[;\d]*)\w)}
21
26
 
22
27
  # @return [Hash] All the defaults settings
23
28
  Settings = {
@@ -29,6 +34,7 @@ class Coolline
29
34
  Handler.new(?\C-a, &:beginning_of_line),
30
35
  Handler.new(?\C-e, &:end_of_line),
31
36
  Handler.new(?\C-k, &:kill_line),
37
+ Handler.new(?\C-u, &:clear_line),
32
38
  Handler.new(?\C-f, &:forward_char),
33
39
  Handler.new(?\C-b, &:backward_char),
34
40
  Handler.new(?\C-d, &:kill_current_char_or_leave),
@@ -38,6 +44,7 @@ class Coolline
38
44
  Handler.new(?\C-n, &:next_history_line),
39
45
  Handler.new(?\C-p, &:previous_history_line),
40
46
  Handler.new(?\C-r, &:interactive_search),
47
+ Handler.new(?\C-l, &:clear_screen),
41
48
  Handler.new(?\t, &:complete),
42
49
  Handler.new(?\C-a..?\C-z) {},
43
50
 
@@ -46,14 +53,21 @@ class Coolline
46
53
  Handler.new("\ef", &:forward_word),
47
54
  Handler.new("\e[A", &:previous_history_line),
48
55
  Handler.new("\e[B", &:next_history_line),
56
+ Handler.new("\e[3~", &:kill_current_char),
49
57
  Handler.new("\e[5~", &:previous_history_line),
50
58
  Handler.new("\e[6~", &:next_history_line),
59
+ Handler.new("\e[7~", &:beginning_of_line),
60
+ Handler.new("\e[8~", &:end_of_line),
51
61
  Handler.new("\e[C", &:forward_char),
52
62
  Handler.new("\e[D", &:backward_char),
63
+ Handler.new("\e[F", &:end_of_line),
64
+ Handler.new("\e[H", &:beginning_of_line),
53
65
  Handler.new("\et", &:transpose_words),
54
66
  Handler.new("\ec", &:capitalize_word),
55
67
  Handler.new("\eu", &:uppercase_word),
56
68
  Handler.new("\el", &:lowercase_word),
69
+ Handler.new("\e<", &:first_history_line),
70
+ Handler.new("\e>", &:last_history_line),
57
71
 
58
72
  Handler.new(/\e.+/) {},
59
73
  ],
@@ -84,6 +98,15 @@ class Coolline
84
98
  load_config! unless @config_loaded
85
99
  end
86
100
 
101
+ # Binds a key to a block. This key binding will have precedence over already
102
+ # defined key bindings.
103
+ #
104
+ # @param [String] key Key code sent by the terminal
105
+ # @yieldparam [Coolline] cool Coolline instance to use
106
+ def self.bind(key, &action)
107
+ Coolline::Settings[:handlers].unshift Coolline::Handler.new(key, &action)
108
+ end
109
+
87
110
  # Creates a new cool line.
88
111
  #
89
112
  # @yieldparam [Coolline] self
@@ -227,6 +250,8 @@ class Coolline
227
250
  @history[-1] = @line if @history.size != 0
228
251
  @history.index = @history.size
229
252
 
253
+ @history.save_line
254
+
230
255
  @line + "\n"
231
256
  end
232
257
 
@@ -240,6 +265,12 @@ class Coolline
240
265
  @output.print(*objs)
241
266
  end
242
267
 
268
+ # Closes the History object. Should be called when you're done with a Coolline
269
+ # instance.
270
+ def close
271
+ @history.close
272
+ end
273
+
243
274
  # Selects the previous line in history (if any)
244
275
  def previous_history_line
245
276
  if @history.index >= 0
@@ -251,6 +282,15 @@ class Coolline
251
282
  end_of_line
252
283
  end
253
284
 
285
+ # Selects the first line of history
286
+ def first_history_line
287
+ @history.index = 0
288
+ @line.replace @history[0]
289
+
290
+ @history_moved = true
291
+ end_of_line
292
+ end
293
+
254
294
  # Selects the next line in history (if any).
255
295
  #
256
296
  # When on the last line, this method replaces the current line with an empty
@@ -269,6 +309,15 @@ class Coolline
269
309
  end_of_line
270
310
  end
271
311
 
312
+ # Selects the last line of history
313
+ def last_history_line
314
+ @history.index = @history.size - 2
315
+ @line.replace @history[@history.index]
316
+
317
+ @history_moved = true
318
+ end_of_line
319
+ end
320
+
272
321
  # Prompts the user to search for a line
273
322
  def interactive_search
274
323
  found_index = @history.index
@@ -349,6 +398,11 @@ class Coolline
349
398
  (string =~ AnsiCode) == 0
350
399
  end
351
400
 
401
+ def clear_screen
402
+ print "\e[2J" # clear
403
+ print "\e[0;0H" # goto 0, 0
404
+ end
405
+
352
406
  private
353
407
  def transform(line)
354
408
  @transform_proc.call(line)
@@ -128,6 +128,12 @@ class Coolline
128
128
  line[pos..-1] = ""
129
129
  end
130
130
 
131
+ # Removes all the characters in the line
132
+ def clear_line
133
+ line.clear
134
+ self.pos = 0
135
+ end
136
+
131
137
  # Swaps the previous character with the current one
132
138
  def transpose_chars
133
139
  if line.size >= 2
@@ -5,7 +5,7 @@ class Coolline
5
5
  attr_accessor :index
6
6
 
7
7
  def initialize(filename, max_size = 5000)
8
- @io = File.open(filename, 'a+')
8
+ @io = open_file(filename)
9
9
  @max_size = max_size
10
10
 
11
11
  @lines = []
@@ -17,7 +17,7 @@ class Coolline
17
17
 
18
18
  def reopen(filename)
19
19
  close
20
- @io = File.open(filename, 'a+')
20
+ @io = open_file(filename)
21
21
 
22
22
  load_lines
23
23
  end
@@ -42,9 +42,6 @@ class Coolline
42
42
  end
43
43
 
44
44
  def <<(el)
45
- @io.puts el
46
- @io.flush
47
-
48
45
  @lines << el.dup
49
46
  @lines.delete_at(0) if @lines.size > @max_size
50
47
 
@@ -63,6 +60,11 @@ class Coolline
63
60
  @lines[id] = val
64
61
  end
65
62
 
63
+ def save_line
64
+ @io.puts self[-1]
65
+ @io.flush
66
+ end
67
+
66
68
  def size
67
69
  @lines.size
68
70
  end
@@ -70,6 +72,7 @@ class Coolline
70
72
  attr_accessor :max_size
71
73
 
72
74
  private
75
+
73
76
  def load_lines
74
77
  line_count = @io.count
75
78
  @io.rewind
@@ -83,5 +86,25 @@ class Coolline
83
86
  end
84
87
  end
85
88
  end
89
+
90
+ def open_file(filename)
91
+ dirname = File.dirname(filename)
92
+
93
+ if !Dir.exist?(dirname)
94
+ create_path(dirname)
95
+ end
96
+
97
+ File.open(filename, "a+")
98
+ end
99
+
100
+ def create_path(path)
101
+ dir = File.dirname(path)
102
+
103
+ if !Dir.exist? dir
104
+ create_path(dir)
105
+ end
106
+
107
+ Dir.mkdir(path, 0700)
108
+ end
86
109
  end
87
110
  end
@@ -1,3 +1,3 @@
1
1
  class Coolline
2
- Version = "0.2.0"
2
+ Version = "0.3.0"
3
3
  end
data/repl.rb CHANGED
@@ -4,6 +4,10 @@ require 'coolline'
4
4
  require 'coderay'
5
5
  require 'pp'
6
6
 
7
+ Coolline.bind "\C-z" do |c|
8
+ puts c.object_id
9
+ end
10
+
7
11
  cool = Coolline.new do |c|
8
12
  c.transform_proc = proc do
9
13
  CodeRay.scan(c.line, :ruby).term
@@ -20,8 +24,12 @@ end
20
24
 
21
25
  loop do
22
26
  line = cool.readline
23
- obj = eval(line)
27
+ break if line == "exit\n"
28
+
29
+ obj = eval(line)
24
30
 
25
31
  print "=> "
26
32
  pp obj
27
33
  end
34
+
35
+ cool.close
@@ -0,0 +1,17 @@
1
+ require File.expand_path("helpers.rb", File.dirname(__FILE__))
2
+
3
+ context "a user uses colors for live code highlighting" do
4
+ setup do
5
+ Coolline.new
6
+ end
7
+
8
+ context "stripping 8-color ANSI codes" do
9
+ asserts(:strip_ansi_codes, "\033[42mLove\033[0m").equals "Love"
10
+ asserts(:strip_ansi_codes, "\e[42mLove\e[0m").equals "Love"
11
+ end
12
+
13
+ context "stripping non 8-color ANSI codes" do
14
+ asserts(:strip_ansi_codes, "\033[38;5;232mHate\033[0m").equals "Hate"
15
+ asserts(:strip_ansi_codes, "\e[38;5;232mHate\e[0m").equals "Hate"
16
+ end
17
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coolline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-03 00:00:00.000000000 Z
12
+ date: 2012-07-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: riot
16
- requirement: &12993820 !ruby/object:Gem::Requirement
16
+ requirement: &18648680 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *12993820
24
+ version_requirements: *18648680
25
25
  description: ! 'A readline-like library that allows to change how the input
26
26
 
27
27
  is displayed.
@@ -40,6 +40,7 @@ files:
40
40
  - lib/coolline.rb
41
41
  - test/helpers.rb
42
42
  - test/editor_test.rb
43
+ - test/coolline_test.rb
43
44
  - test/run_all.rb
44
45
  - test/history_test.rb
45
46
  - repl.rb