rbpad 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rbpad/page.rb ADDED
@@ -0,0 +1,257 @@
1
+
2
+ require 'gtk3'
3
+ require 'gtksourceview3'
4
+ require 'uri'
5
+
6
+ require 'rbpad/blockmatch'
7
+
8
+
9
+ module Rbpad
10
+
11
+ class Page < Gtk::ScrolledWindow
12
+ attr_reader :status, :dirname, :basename
13
+
14
+ def initialize(conf, status_area)
15
+ super()
16
+
17
+ language = GtkSource::LanguageManager.new.get_language('ruby')
18
+ buffer = GtkSource::Buffer.new(language)
19
+ buffer.highlight_syntax = true # syntax highlight
20
+
21
+ @conf = conf
22
+ schememgr = GtkSource::StyleSchemeManager.new.set_search_path([@conf.sourceview])
23
+ #p schememgr.scheme_ids
24
+ #p schememgr.search_path
25
+
26
+ scheme = schememgr.get_scheme("rbpad")
27
+ buffer.set_style_scheme(scheme)
28
+
29
+ @view = GtkSource::View.new(buffer)
30
+ @view.override_font(Pango::FontDescription.new("#{@conf.platform[:font][:page]}"))
31
+ @view.left_margin = 6
32
+ @view.pixels_above_lines = 1
33
+ @view.pixels_below_lines = 1
34
+ @view.accepts_tab = false # 'TAB' is used for moving focus
35
+ @view.editable = true # editable
36
+ @view.cursor_visible = true # show cursor
37
+ @view.show_line_numbers = true # show line number
38
+ @view.auto_indent = true # auto indent
39
+ @view.highlight_current_line = true # show current line with highlight
40
+
41
+ self.add(@view)
42
+
43
+ @status = :EMPTY
44
+ @dirname = nil
45
+ @basename = nil
46
+ @status_area = status_area
47
+
48
+ attr = {
49
+ color: scheme.get_style("def:comment").foreground.downcase,
50
+ bold: scheme.get_style("def:comment").bold?,
51
+ italic: scheme.get_style("def:comment").italic?
52
+ }
53
+ @bm = BlockMatch.new(@view, attr)
54
+
55
+ _display_status # show status
56
+
57
+ @view.drag_dest_set(Gtk::DestDefaults::MOTION |
58
+ Gtk::DestDefaults::HIGHLIGHT |
59
+ Gtk::DestDefaults::DROP,
60
+ [["text/uri-list", :other_app, 49334]],
61
+ Gdk::DragAction::COPY |
62
+ Gdk::DragAction::MOVE)
63
+
64
+ @view.signal_connect(:drag_data_received) do |widget, context, x, y, data, info, time|
65
+ # decode the data which is uri encoded,
66
+ # and process each file from multi files list
67
+ if @last_received_time != time # [BUG?] Signal is sent dupulicate including last time data since 2nd operation, isn't it ?
68
+ data.uris.each do |uri|
69
+ dec_uri = URI.decode(uri)
70
+ if /cygwin|mingw|mswin/ === RUBY_PLATFORM and /file:\/\/\/[A-Z]:/ === dec_uri # UNC is formatted like file://host/path/file
71
+ filename = dec_uri.sub('file:///', '') # Windows : e.g. file:/// (file:///C:/foo/bar.rb --> C:/foo/bar.rb)
72
+ else
73
+ filename = dec_uri.sub('file://', '') # Linux, macOS : e.g. file:// (file:///home/foo/bar.rb --> /home/foo/bar.rb)
74
+ end
75
+ self.parent.load(filename)
76
+ end
77
+ @last_received_time = time
78
+ end
79
+ end
80
+
81
+ @view.signal_connect(:button_release_event) do
82
+ # by pointing mouse cursor
83
+ _display_status
84
+ @bm.scan if @block_match
85
+ false # if true, event about selecting range by mouse pointer is happend
86
+ end
87
+
88
+ @view.signal_connect_after(:move_cursor) do |widget, step, count, extend_selection|
89
+ _display_status
90
+ @bm.scan if @block_match
91
+ end
92
+
93
+ @view.buffer.signal_connect(:changed) do |widget|
94
+ @status = :UNSAVED # update status of editing
95
+ _display_status
96
+ end
97
+ end
98
+
99
+ def destroy
100
+ self.instance_variables.each do |v|
101
+ remove_instance_variable(v)
102
+ end
103
+ end
104
+
105
+ def undo
106
+ @view.signal_emit(:undo)
107
+ end
108
+
109
+ def redo
110
+ @view.signal_emit(:redo)
111
+ end
112
+
113
+ def cut
114
+ @view.signal_emit(:cut_clipboard)
115
+ end
116
+
117
+ def copy
118
+ @view.signal_emit(:copy_clipboard)
119
+ end
120
+
121
+ def paste
122
+ @view.signal_emit(:paste_clipboard) # scroll till bottom of pasted line
123
+ end
124
+
125
+ def select_all
126
+ @view.signal_emit(:select_all, true)
127
+ end
128
+
129
+ def set_draw_spaces(status)
130
+ if status
131
+ @view.draw_spaces = GtkSource::DrawSpacesFlags::SPACE # show space character
132
+ else
133
+ @view.draw_spaces = 0
134
+ end
135
+ end
136
+
137
+ def set_block_match(status)
138
+ @block_match = status
139
+ if status
140
+ @bm.scan
141
+ else
142
+ @bm.clear
143
+ end
144
+ end
145
+
146
+ def find_and_select(word, direction)
147
+ return true unless word
148
+ @view.set_focus(true)
149
+ iter = @view.buffer.get_iter_at(mark: @view.buffer.get_mark("insert"))
150
+ if direction == :forward
151
+ if @view.buffer.get_iter_at(mark: @view.buffer.get_mark("selection_bound")).offset > @view.buffer.get_iter_at(mark: @view.buffer.get_mark("insert")).offset
152
+ # avoid duplicate hits of the same word
153
+ # when reversing the search direction
154
+ iter = @view.buffer.get_iter_at(mark: @view.buffer.get_mark("selection_bound"))
155
+ end
156
+ match_iters = iter.forward_search(word, :text_only)
157
+ next_iter = [match_iters[1], match_iters[0]] if match_iters
158
+ else
159
+ if @view.buffer.get_iter_at(mark: @view.buffer.get_mark("selection_bound")).offset < @view.buffer.get_iter_at(mark: @view.buffer.get_mark("insert")).offset
160
+ # avoid duplicate hits of the same word
161
+ # when reversing the search direction
162
+ iter = @view.buffer.get_iter_at(mark: @view.buffer.get_mark("selection_bound"))
163
+ end
164
+ match_iters = iter.backward_search(word, :text_only)
165
+ next_iter = match_iters if match_iters
166
+ end
167
+ if match_iters
168
+ @view.buffer.place_cursor(next_iter[0])
169
+ @view.scroll_mark_onscreen(@view.buffer.get_mark("insert"))
170
+ @view.buffer.move_mark(@view.buffer.get_mark("selection_bound"), next_iter[1])
171
+ _display_status
172
+ @bm.scan if @block_match
173
+ true
174
+ else
175
+ false
176
+ end
177
+ end
178
+
179
+ # insert text block with indent at cursor place
180
+ def insert_block(text, cursor = nil)
181
+ mark = @view.buffer.selection_bound # get mark of cursor place
182
+ iter = @view.buffer.get_iter_at(mark: mark) # get iter from mark
183
+ text.gsub!("\n", "\n#{" " * iter.line_offset}") # adjust indent of text (add space after line-feed)
184
+ @view.buffer.insert_at_cursor(text) # insert text
185
+ @view.scroll_to_mark(mark, 0, false, 0, 1) # move to mark
186
+ if cursor == :start
187
+ @view.buffer.place_cursor(@view.buffer.start_iter)
188
+ end
189
+ _display_status
190
+ end
191
+
192
+ # save file
193
+ def save(filename, temporary = false)
194
+ content = @view.buffer.text
195
+ File.open(filename, "wb:utf-8") do |fp|
196
+ fp.puts content
197
+ end
198
+
199
+ unless temporary
200
+ @status = :SAVED
201
+ @dirname = File.dirname(filename)
202
+ @basename = File.basename(filename)
203
+ end
204
+ _display_status
205
+ end
206
+
207
+ # load file
208
+ def load(filename, template = false)
209
+ begin
210
+ File.open(filename, "rb:utf-8") do |file|
211
+ # replace incorrect bytes to 'U+FFFD'
212
+ content = file.read.scrub
213
+ @view.buffer.insert(@view.buffer.end_iter, content)
214
+ end
215
+
216
+ if template
217
+ @status = :UNSAVED
218
+ else
219
+ @status = :SAVED
220
+ @dirname = File.dirname(filename)
221
+ @basename = File.basename(filename)
222
+ end
223
+
224
+ @view.buffer.place_cursor(@view.buffer.start_iter)
225
+ _display_status
226
+ true
227
+ rescue
228
+ # when has read binary file, etc
229
+ false
230
+ end
231
+ end
232
+
233
+ # set focus
234
+ def set_focus
235
+ @view.set_focus(true)
236
+ end
237
+
238
+ # show information
239
+ def display_status
240
+ _display_status
241
+ end
242
+
243
+ # show information at status area (line, columun, saving status)
244
+ private def _display_status(movement_step = nil, count = 0)
245
+ mark = @view.buffer.selection_bound # get the mark at the cursor position
246
+ iter = @view.buffer.get_iter_at(mark: mark)
247
+
248
+ stat = @conf.messages[:status_saved]
249
+ stat = @conf.messages[:status_unsaved] if @status == :UNSAVED
250
+ # e.g. "%5L%4C (UNSAVED)"
251
+ format = "%5d#{@conf.messages[:status_pos_l]}%4d#{@conf.messages[:status_pos_c]} %-10s"
252
+ @status_area.text = format % [iter.line + 1, iter.line_offset + 1, stat]
253
+ end
254
+
255
+ end
256
+ end
257
+
data/lib/rbpad/util.rb ADDED
@@ -0,0 +1,30 @@
1
+
2
+ module Rbpad
3
+
4
+ module Utility
5
+ module_function def get_uniqname
6
+ # generate a random 8-character string
7
+ (1..8).map {
8
+ [*'A'..'Z', *'a'..'z', *'0'..'9'].sample
9
+ }.join
10
+ end
11
+
12
+ module_function def get_os
13
+ (
14
+ host_os = RbConfig::CONFIG['host_os']
15
+ case host_os
16
+ when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
17
+ :windows
18
+ when /darwin|mac os/
19
+ :mac
20
+ when /linux/
21
+ :linux
22
+ else
23
+ :unknown
24
+ end
25
+ )
26
+ end
27
+ end
28
+
29
+ end
30
+
@@ -0,0 +1,3 @@
1
+ module Rbpad
2
+ VERSION = "3.1.0"
3
+ end
data/lib/rbpad.rb ADDED
@@ -0,0 +1,32 @@
1
+ =begin
2
+ 'rbpad'
3
+ Copyright (c) 2018 Koki Kitamura
4
+ Released under the MIT license
5
+ https://opensource.org/licenses/mit-license.php
6
+ =end
7
+
8
+ require 'gtk3'
9
+ require 'optparse'
10
+
11
+ require 'rbpad/pad'
12
+
13
+ Encoding.default_external = 'UTF-8'
14
+
15
+ opts = ARGV.getopts('ex')
16
+
17
+ lang = (opts['e'] ? :en : :jp) # :jp or :en
18
+
19
+ if opts['x']
20
+ pad = Rbpad::Pad.new(lang, 0, 0) # maximized
21
+ else
22
+ if ARGV.size >= 2
23
+ w = ARGV[0].to_i
24
+ h = ARGV[1].to_i
25
+ pad = Rbpad::Pad.new(lang, w, h) # specified
26
+ else
27
+ pad = Rbpad::Pad.new(lang) # default
28
+ end
29
+ end
30
+
31
+ Gtk.main
32
+
data/rbpad.gemspec ADDED
@@ -0,0 +1,43 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "rbpad/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rbpad"
8
+ spec.version = Rbpad::VERSION
9
+ spec.authors = ["Koki Kitamura"]
10
+ spec.email = ["spool.kitamura@nifty.ne.jp"]
11
+
12
+ spec.summary = %q{programming editor for Ruby using Ruby/GTK3 and Ruby/GtkSourceView3}
13
+ spec.description = %q{'rbpad' is a programming editor for Ruby using Ruby/GTK3 and Ruby/GtkSourceView3}
14
+ spec.homepage = "https://github.com/spoolkitamura/rbpad3"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ #if spec.respond_to?(:metadata)
20
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
21
+ #
22
+ # spec.metadata["homepage_uri"] = spec.homepage
23
+ # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
24
+ # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
25
+ #else
26
+ # raise "RubyGems 2.0 or newer is required to protect against " \
27
+ # "public gem pushes."
28
+ #end
29
+
30
+ # Specify which files should be added to the gem when it is released.
31
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
32
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
33
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
34
+ end
35
+ spec.bindir = "exe"
36
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
37
+ spec.require_paths = ["lib"]
38
+
39
+ spec.add_runtime_dependency "gtksourceview3", "~> 3.3", ">= 3.3.1"
40
+
41
+ #spec.add_development_dependency "bundler", "~> 1.17"
42
+ #spec.add_development_dependency "rake", "~> 10.0"
43
+ end
data/rbpad3_en.png ADDED
Binary file
data/rbpad3_jp.png ADDED
Binary file
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rbpad
3
+ version: !ruby/object:Gem::Version
4
+ version: 3.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Koki Kitamura
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-08-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: gtksourceview3
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.3'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 3.3.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '3.3'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 3.3.1
33
+ description: "'rbpad' is a programming editor for Ruby using Ruby/GTK3 and Ruby/GtkSourceView3"
34
+ email:
35
+ - spool.kitamura@nifty.ne.jp
36
+ executables:
37
+ - rbpad
38
+ extensions: []
39
+ extra_rdoc_files: []
40
+ files:
41
+ - Gemfile
42
+ - LICENSE.txt
43
+ - README.md
44
+ - Rakefile
45
+ - bin/console
46
+ - bin/setup
47
+ - exe/rbpad
48
+ - lib/rbpad.rb
49
+ - lib/rbpad/blockmatch.rb
50
+ - lib/rbpad/config.rb
51
+ - lib/rbpad/config/actions_menubar.xml
52
+ - lib/rbpad/config/actions_menubar_template.xml
53
+ - lib/rbpad/config/actions_menubar_toggle.xml
54
+ - lib/rbpad/config/find_next.xpm
55
+ - lib/rbpad/config/find_prev.xpm
56
+ - lib/rbpad/config/menu.xml
57
+ - lib/rbpad/config/messages.xml
58
+ - lib/rbpad/config/platform.xml
59
+ - lib/rbpad/config/run.xpm
60
+ - lib/rbpad/config/sourceview.xml
61
+ - lib/rbpad/editor.rb
62
+ - lib/rbpad/error_jp.rb
63
+ - lib/rbpad/input.rb
64
+ - lib/rbpad/output.rb
65
+ - lib/rbpad/pad.rb
66
+ - lib/rbpad/page.rb
67
+ - lib/rbpad/util.rb
68
+ - lib/rbpad/version.rb
69
+ - rbpad.gemspec
70
+ - rbpad3_en.png
71
+ - rbpad3_jp.png
72
+ homepage: https://github.com/spoolkitamura/rbpad3
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubygems_version: 3.0.3
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: programming editor for Ruby using Ruby/GTK3 and Ruby/GtkSourceView3
95
+ test_files: []