amun 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rspec +1 -0
- data/.rubocop.yml +6 -1
- data/.ruby-version +1 -1
- data/Guardfile +26 -6
- data/README.md +1 -0
- data/Rakefile +4 -6
- data/_config.yml +1 -0
- data/amun.gemspec +6 -5
- data/exe/amun +1 -1
- data/lib/amun/application.rb +11 -5
- data/lib/amun/behaviours/emacs.rb +14 -122
- data/lib/amun/behaviours/erasing.rb +67 -0
- data/lib/amun/behaviours/insertion.rb +22 -0
- data/lib/amun/behaviours/movement.rb +83 -0
- data/lib/amun/buffer.rb +103 -0
- data/lib/amun/event_manager.rb +12 -3
- data/lib/amun/features/echo_event.rb +4 -1
- data/lib/amun/features/files.rb +26 -0
- data/lib/amun/helpers/colors.rb +8 -7
- data/lib/amun/helpers/keyboard.rb +25 -8
- data/lib/amun/major_modes/fundamental.rb +8 -40
- data/lib/amun/major_modes/irb.rb +40 -0
- data/lib/amun/mode_line_segments/buffer_name.rb +10 -0
- data/lib/amun/mode_line_segments/major_mode.rb +11 -0
- data/lib/amun/object.rb +21 -0
- data/lib/amun/primitives/rect.rb +15 -0
- data/lib/amun/version.rb +1 -1
- data/lib/amun/windows/base.rb +42 -0
- data/lib/amun/windows/buffer_window.rb +73 -0
- data/lib/amun/windows/echo_area.rb +34 -0
- data/lib/amun/windows/frame.rb +92 -0
- data/lib/amun/windows/mini_buffer_window.rb +126 -0
- data/lib/amun/windows/mode_line.rb +50 -0
- data/lib/amun/windows/text_renderer.rb +41 -0
- metadata +56 -31
- data/lib/amun/ui/buffer.rb +0 -90
- data/lib/amun/ui/echo_area.rb +0 -42
- data/lib/amun/ui/mode_line.rb +0 -44
- data/lib/amun/ui/mode_line_segments/buffer_name.rb +0 -16
- data/lib/amun/ui/mode_line_segments/major_mode.rb +0 -17
- data/lib/amun/ui/windows/buffer_window.rb +0 -40
- data/lib/amun/ui/windows/frame.rb +0 -75
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c19c96c195a1b4c07b725041f93ab2d4b55c686bfe43f43f3b073ae05cc12ade
|
4
|
+
data.tar.gz: 1760fc63a9b6748b887c5f502736713c18b1428b03ecc72488073e5444f99a29
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f424f219a3815db2c5499862f5ffdb65c27a1f55eaecb50a79fbda5a9b6fc69aac93bc392a6b19d318cc107953b491bae528e605b07f2c26e6ded8b5b22bfaa
|
7
|
+
data.tar.gz: '0866d9947a3e98b8e5a08d8d3f3c09e6c0b41727f86e15cd383f20b1780a0999cdcf14ed3d5087ecd7dd903aad600cb2ac7846b2b971a3d19eb821e5c97dd2bd'
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color --format doc
|
data/.rubocop.yml
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
AllCops:
|
2
|
+
TargetRubyVersion: 2.0
|
2
3
|
Exclude:
|
3
|
-
- '
|
4
|
+
- 'spec/**/*'
|
4
5
|
- '*.gemspec'
|
5
6
|
DisplayCopNames: true
|
6
7
|
Style/FrozenStringLiteralComment:
|
@@ -9,3 +10,7 @@ Style/StringLiterals:
|
|
9
10
|
Enabled: false
|
10
11
|
Style/WordArray:
|
11
12
|
Enabled: false
|
13
|
+
Metrics/LineLength:
|
14
|
+
Max: 120
|
15
|
+
Security/Eval:
|
16
|
+
Enabled: false
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.6.6
|
data/Guardfile
CHANGED
@@ -1,7 +1,27 @@
|
|
1
|
-
directories ['lib', '
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
directories ['lib', 'spec']
|
2
|
+
|
3
|
+
# Note: The cmd option is now required due to the increasing number of ways
|
4
|
+
# rspec may be run, below are examples of the most common uses.
|
5
|
+
# * bundler: 'bundle exec rspec'
|
6
|
+
# * bundler binstubs: 'bin/rspec'
|
7
|
+
# * spring: 'bin/rspec' (This will use spring if running and you have
|
8
|
+
# installed the spring binstubs per the docs)
|
9
|
+
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
10
|
+
# * 'just' rspec: 'rspec'
|
11
|
+
|
12
|
+
guard :rspec, cmd: "bundle exec rspec" do
|
13
|
+
require "guard/rspec/dsl"
|
14
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
15
|
+
|
16
|
+
# Feel free to open issues for suggestions and improvements
|
17
|
+
|
18
|
+
# RSpec files
|
19
|
+
rspec = dsl.rspec
|
20
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
21
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
22
|
+
watch(rspec.spec_files)
|
23
|
+
|
24
|
+
# Ruby files
|
25
|
+
ruby = dsl.ruby
|
26
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
7
27
|
end
|
data/README.md
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
[![Build Status](https://travis-ci.org/blazeeboy/amun.svg?branch=master)](https://travis-ci.org/blazeeboy/amun)
|
6
6
|
[![Code Climate](https://codeclimate.com/github/blazeeboy/amun/badges/gpa.svg)](https://codeclimate.com/github/blazeeboy/amun)
|
7
7
|
[![Test Coverage](https://codeclimate.com/github/blazeeboy/amun/badges/coverage.svg)](https://codeclimate.com/github/blazeeboy/amun)
|
8
|
+
[![Inline docs](http://inch-ci.org/github/blazeeboy/amun.svg?branch=master)](http://inch-ci.org/github/blazeeboy/amun)
|
8
9
|
|
9
10
|
A minimal CLI text editor, built on Ruby, looking for Emacs as it's father and idol.
|
10
11
|
|
data/Rakefile
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
-
require "rake/testtask"
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
t.test_files = FileList['test/**/*_test.rb']
|
3
|
+
begin
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
6
|
end
|
9
7
|
|
10
|
-
task default: :
|
8
|
+
task default: :spec
|
data/_config.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
theme: jekyll-theme-minimal
|
data/amun.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = "amun"
|
8
8
|
spec.version = Amun::VERSION
|
9
9
|
spec.authors = ["Emad Elsaid"]
|
10
|
-
spec.email = ["
|
10
|
+
spec.email = ["emad.elsaid.hamed@gmail.com"]
|
11
11
|
|
12
12
|
spec.summary = "Emacs like editor, with Ruby core instead of ELisp"
|
13
13
|
spec.description = "A CLI editor built to have an Emacs similar development environment, with ruby in the heart of it instead of Elisp, that will make developing plugins and extensions faster and more enjoyable, this editor is kept to the minimum, anything that could be written as an pluging will be found as a plugin."
|
@@ -21,13 +21,14 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
22
|
spec.require_paths = ["lib"]
|
23
23
|
|
24
|
-
spec.add_dependency "curses"
|
25
|
-
spec.add_development_dependency "bundler"
|
24
|
+
spec.add_dependency "curses"
|
25
|
+
spec.add_development_dependency "bundler"
|
26
26
|
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
-
spec.add_development_dependency "minitest", "~> 5.0"
|
28
27
|
spec.add_development_dependency "pry"
|
29
28
|
spec.add_development_dependency "guard"
|
30
|
-
spec.add_development_dependency "
|
29
|
+
spec.add_development_dependency "rspec"
|
30
|
+
spec.add_development_dependency "rspec-its"
|
31
|
+
spec.add_development_dependency "guard-rspec"
|
31
32
|
spec.add_development_dependency "simplecov"
|
32
33
|
spec.add_development_dependency "codeclimate-test-reporter", "~> 1.0.0"
|
33
34
|
end
|
data/exe/amun
CHANGED
data/lib/amun/application.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'curses'
|
2
2
|
require 'singleton'
|
3
|
-
require '
|
3
|
+
require 'forwardable'
|
4
|
+
require 'amun/windows/frame'
|
4
5
|
require 'amun/event_manager'
|
5
6
|
require 'amun/features_loader'
|
6
7
|
require 'amun/helpers/keyboard'
|
@@ -14,7 +15,7 @@ module Amun
|
|
14
15
|
attr_writer :frame
|
15
16
|
|
16
17
|
def frame
|
17
|
-
@frame ||=
|
18
|
+
@frame ||= Windows::Frame.new
|
18
19
|
end
|
19
20
|
|
20
21
|
def run
|
@@ -24,6 +25,12 @@ module Amun
|
|
24
25
|
keyboard_thread.join
|
25
26
|
end
|
26
27
|
|
28
|
+
class << self
|
29
|
+
extend Forwardable
|
30
|
+
def_delegators :instance,
|
31
|
+
:run, :frame, :frame=
|
32
|
+
end
|
33
|
+
|
27
34
|
private
|
28
35
|
|
29
36
|
def init_curses
|
@@ -41,9 +48,8 @@ module Amun
|
|
41
48
|
chain = []
|
42
49
|
while (ch = Helpers::Keyboard.char)
|
43
50
|
chain << ch
|
44
|
-
if
|
45
|
-
|
46
|
-
end
|
51
|
+
chain.clear if frame.trigger(chain.join(' ')) != EventManager::CHAINED
|
52
|
+
frame.render
|
47
53
|
end
|
48
54
|
end
|
49
55
|
end
|
@@ -1,130 +1,22 @@
|
|
1
|
-
require 'amun/
|
1
|
+
require 'amun/behaviours/movement'
|
2
|
+
require 'amun/behaviours/erasing'
|
3
|
+
require 'amun/behaviours/insertion'
|
2
4
|
require 'curses'
|
3
5
|
|
4
6
|
module Amun
|
5
7
|
module Behaviours
|
8
|
+
# Emacs default behaviour module
|
9
|
+
# should be included in the mode
|
10
|
+
# which needs this behaviour as part of it
|
6
11
|
module Emacs
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
event_manager.bind Curses::KEY_DOWN.to_s, self, :next_line
|
16
|
-
|
17
|
-
event_manager.bind "\C-p", self, :previous_line
|
18
|
-
event_manager.bind Curses::KEY_UP.to_s, self, :previous_line
|
19
|
-
|
20
|
-
event_manager.bind "\C-a", self, :beginning_of_line
|
21
|
-
event_manager.bind Curses::KEY_HOME.to_s, self, :beginning_of_line
|
22
|
-
|
23
|
-
event_manager.bind "\C-e", self, :end_of_line
|
24
|
-
event_manager.bind Curses::KEY_END.to_s, self, :end_of_line
|
25
|
-
|
26
|
-
event_manager.bind "\C-d", self, :delete_char
|
27
|
-
event_manager.bind Curses::Key::BACKSPACE.to_s, self, :backward_delete_char # this doesn't work, check linux
|
28
|
-
event_manager.bind "\C-?", self, :backward_delete_char # C-? is backspace on mac terminal for some reason
|
29
|
-
|
30
|
-
event_manager.bind Curses::Key::DC.to_s, self, :forward_delete_char
|
31
|
-
|
32
|
-
event_manager.bind "\C-k", self, :kill_line
|
33
|
-
event_manager.bind "\M-d", self, :kill_word
|
34
|
-
end
|
35
|
-
|
36
|
-
def forward_char(*)
|
37
|
-
buffer.point += 1
|
38
|
-
true
|
39
|
-
end
|
40
|
-
|
41
|
-
def backward_char(*)
|
42
|
-
buffer.point -= 1
|
43
|
-
true
|
44
|
-
end
|
45
|
-
|
46
|
-
def next_line(*)
|
47
|
-
line_begin = buffer.text.rindex("\n", buffer.point) || 0
|
48
|
-
line_end = buffer.text.index("\n", buffer.point + 1) || buffer.text.size + 1
|
49
|
-
next_line_end = buffer.text.index("\n", line_end + 1) || buffer.text.size + 1
|
50
|
-
point_offset = buffer.point - line_begin
|
51
|
-
buffer.point = [line_end + point_offset, next_line_end].min
|
52
|
-
true
|
53
|
-
end
|
54
|
-
|
55
|
-
def previous_line(*)
|
56
|
-
line_begin = buffer.text.rindex("\n", buffer.point) || 0
|
57
|
-
previous_line_begin = buffer.text.rindex("\n", line_begin - 1) || 0
|
58
|
-
point_offset = buffer.point - line_begin
|
59
|
-
buffer.point = [previous_line_begin + point_offset, line_begin - 1].min
|
60
|
-
true
|
61
|
-
end
|
62
|
-
|
63
|
-
def beginning_of_line(*)
|
64
|
-
point = buffer.point
|
65
|
-
return true if point.zero?
|
66
|
-
return true if buffer.text[point - 1] == "\n"
|
67
|
-
|
68
|
-
line_start = buffer.text.rindex("\n", point - 1)
|
69
|
-
buffer.point = line_start.nil? ? 0 : line_start + 1
|
70
|
-
true
|
71
|
-
end
|
72
|
-
|
73
|
-
def end_of_line(*)
|
74
|
-
point = buffer.point
|
75
|
-
return true if buffer.text[point] == "\n"
|
76
|
-
|
77
|
-
line_end = buffer.text.index("\n", point)
|
78
|
-
buffer.point = line_end || buffer.text.length
|
79
|
-
true
|
80
|
-
end
|
81
|
-
|
82
|
-
def delete_char(*)
|
83
|
-
buffer.text.slice!(buffer.point)
|
84
|
-
true
|
85
|
-
end
|
86
|
-
|
87
|
-
def backward_delete_char(*)
|
88
|
-
return true if buffer.point.zero?
|
89
|
-
|
90
|
-
buffer.point -= 1
|
91
|
-
buffer.text.slice!(buffer.point)
|
92
|
-
true
|
93
|
-
end
|
94
|
-
|
95
|
-
def forward_delete_char(*)
|
96
|
-
delete_char
|
97
|
-
end
|
98
|
-
|
99
|
-
# TODO should move text to kill ring
|
100
|
-
def kill_line(*)
|
101
|
-
if buffer.text[buffer.point] == "\n"
|
102
|
-
buffer.text.slice!(buffer.point)
|
103
|
-
return true
|
104
|
-
end
|
105
|
-
|
106
|
-
line_end = buffer.text.index(/$/, buffer.point)
|
107
|
-
buffer.text.slice!(buffer.point...line_end)
|
108
|
-
true
|
109
|
-
end
|
110
|
-
|
111
|
-
# TODO should move text to kill ring
|
112
|
-
def kill_word(*)
|
113
|
-
first_non_letter = buffer.text.index(/\P{L}/, buffer.point) || buffer.text.size
|
114
|
-
word_beginning = buffer.text.index(/\p{L}/, first_non_letter) || buffer.text.size
|
115
|
-
buffer.text.slice!(buffer.point...word_beginning)
|
116
|
-
true
|
117
|
-
end
|
118
|
-
|
119
|
-
# This should be bound to \M-BACKSPACE or \M-DEL but I think the terminal doesn't send it
|
120
|
-
# So the implementation will remain there until we find a way to catch this key
|
121
|
-
#
|
122
|
-
# TODO should move text to kill ring
|
123
|
-
def backward_kill_word(*)
|
124
|
-
first_letter_backward = buffer.text.rindex(/\p{L}/, buffer.point) || 0
|
125
|
-
first_non_letter_before_word = buffer.text.rindex(/\P{L}/, first_letter_backward) || -1
|
126
|
-
buffer.text.slice!(first_non_letter_before_word + 1 .. buffer.point)
|
127
|
-
true
|
12
|
+
include Movement
|
13
|
+
include Erasing
|
14
|
+
include Insertion
|
15
|
+
|
16
|
+
def emacs_behaviour_initialize
|
17
|
+
movement_keymap_initialize
|
18
|
+
erasing_keymap_initialize
|
19
|
+
insertion_keymap_initialize
|
128
20
|
end
|
129
21
|
end
|
130
22
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Amun
|
2
|
+
module Behaviours
|
3
|
+
# erasing, killing and deleting text from buffer and Emacs keymap for it
|
4
|
+
module Erasing
|
5
|
+
def erasing_keymap_initialize
|
6
|
+
bind "\C-d", self, :delete_char
|
7
|
+
|
8
|
+
# this doesn't work, check linux
|
9
|
+
bind Curses::Key::BACKSPACE, self, :backward_delete_char
|
10
|
+
# C-? is backspace on mac terminal for some reason
|
11
|
+
bind "\C-?", self, :backward_delete_char
|
12
|
+
|
13
|
+
bind Curses::Key::DC, self, :forward_delete_char
|
14
|
+
bind "\C-k", self, :kill_line
|
15
|
+
bind "\M-d", self, :kill_word
|
16
|
+
end
|
17
|
+
|
18
|
+
def delete_char(*)
|
19
|
+
buffer.slice!(buffer.point)
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def backward_delete_char(*)
|
24
|
+
return true if buffer.point.zero?
|
25
|
+
|
26
|
+
buffer.point -= 1
|
27
|
+
buffer.slice!(buffer.point)
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
def forward_delete_char(*)
|
32
|
+
delete_char
|
33
|
+
end
|
34
|
+
|
35
|
+
# TODO: should move text to kill ring
|
36
|
+
def kill_line(*)
|
37
|
+
if buffer[buffer.point] == "\n"
|
38
|
+
buffer.slice!(buffer.point)
|
39
|
+
return true
|
40
|
+
end
|
41
|
+
|
42
|
+
line_end = buffer.index(/$/, buffer.point)
|
43
|
+
buffer.slice!(buffer.point, line_end - buffer.point)
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
# TODO: should move text to kill ring
|
48
|
+
def kill_word(*)
|
49
|
+
first_non_letter = buffer.index(/\P{L}/, buffer.point) || buffer.length
|
50
|
+
word_beginning = buffer.index(/\p{L}/, first_non_letter) || buffer.length
|
51
|
+
buffer.slice!(buffer.point, word_beginning - buffer.point)
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
55
|
+
# This should be bound to \M-BACKSPACE or \M-DEL but I think the terminal doesn't send it
|
56
|
+
# So the implementation will remain there until we find a way to catch this key
|
57
|
+
#
|
58
|
+
# TODO: should move text to kill ring
|
59
|
+
def backward_kill_word(*)
|
60
|
+
first_letter_backward = buffer.rindex(/\p{L}/, buffer.point) || 0
|
61
|
+
first_non_letter_before_word = buffer.rindex(/\P{L}/, first_letter_backward) || -1
|
62
|
+
buffer.slice!(first_non_letter_before_word + 1..buffer.point)
|
63
|
+
true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Amun
|
2
|
+
module Behaviours
|
3
|
+
# inserting text to buffer behaviour and emacs keymap
|
4
|
+
module Insertion
|
5
|
+
def insertion_keymap_initialize
|
6
|
+
bind_all self, :insert_char
|
7
|
+
end
|
8
|
+
|
9
|
+
def insert_char(char)
|
10
|
+
return true unless char.is_a? String
|
11
|
+
return true unless char.length == 1
|
12
|
+
return true unless char.valid_encoding?
|
13
|
+
return true unless char.match?(/[[:print:]\n\t]/)
|
14
|
+
|
15
|
+
buffer.insert(buffer.point, char)
|
16
|
+
buffer.point += 1
|
17
|
+
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Amun
|
2
|
+
module Behaviours
|
3
|
+
# Movement behaviour between lines, characters and paragraphs
|
4
|
+
# along with emacs keymap for it
|
5
|
+
module Movement
|
6
|
+
# attach the movement events only
|
7
|
+
def movement_keymap_initialize
|
8
|
+
bind "\C-f", self, :forward_char
|
9
|
+
bind Curses::KEY_RIGHT, self, :forward_char
|
10
|
+
|
11
|
+
bind "\C-b", self, :backward_char
|
12
|
+
bind Curses::KEY_LEFT, self, :backward_char
|
13
|
+
|
14
|
+
bind "\C-n", self, :next_line
|
15
|
+
bind Curses::KEY_DOWN, self, :next_line
|
16
|
+
|
17
|
+
bind "\C-p", self, :previous_line
|
18
|
+
bind Curses::KEY_UP, self, :previous_line
|
19
|
+
|
20
|
+
bind "\C-a", self, :beginning_of_line
|
21
|
+
bind Curses::KEY_HOME, self, :beginning_of_line
|
22
|
+
|
23
|
+
bind "\C-e", self, :end_of_line
|
24
|
+
bind Curses::KEY_END, self, :end_of_line
|
25
|
+
end
|
26
|
+
|
27
|
+
def forward_char(*)
|
28
|
+
buffer.point += 1
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
def backward_char(*)
|
33
|
+
buffer.point -= 1
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
def next_line(*)
|
38
|
+
point = buffer.point
|
39
|
+
|
40
|
+
line_begin = buffer.rindex(/^/, point)
|
41
|
+
|
42
|
+
line_end = buffer.index(/$/, point)
|
43
|
+
return true if line_end == buffer.size
|
44
|
+
|
45
|
+
next_line_end = buffer.index(/$/, line_end + 1)
|
46
|
+
point_offset = point - line_begin
|
47
|
+
buffer.point = [line_end + 1 + point_offset, next_line_end].min
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
def previous_line(*)
|
52
|
+
point = buffer.point
|
53
|
+
|
54
|
+
line_begin = point == buffer.size && buffer[point - 1] == "\n" ? point : buffer.rindex(/^/, point)
|
55
|
+
return true if line_begin.zero?
|
56
|
+
|
57
|
+
previous_line_begin = buffer.rindex(/^/, line_begin - 1)
|
58
|
+
|
59
|
+
point_offset = point - line_begin
|
60
|
+
buffer.point = [previous_line_begin + point_offset, line_begin - 1].min
|
61
|
+
true
|
62
|
+
end
|
63
|
+
|
64
|
+
def beginning_of_line(*)
|
65
|
+
point = buffer.point
|
66
|
+
return true if point == buffer.size
|
67
|
+
|
68
|
+
line_start = buffer.rindex(/^/, point)
|
69
|
+
buffer.point = line_start <= point ? line_start : 0
|
70
|
+
true
|
71
|
+
end
|
72
|
+
|
73
|
+
def end_of_line(*)
|
74
|
+
point = buffer.point
|
75
|
+
return true if buffer[point] == "\n"
|
76
|
+
|
77
|
+
line_end = buffer.index("\n", point)
|
78
|
+
buffer.point = line_end || buffer.length
|
79
|
+
true
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|