textbringer 1.2.0 → 1.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f26fbba03cd3a598394d22f7edee8521b01c0ff0492c41fff8b2ede22dfbc321
4
- data.tar.gz: 2eb497b690e8a3c36a724a68675daeae0ca29936bd42a5ac367abf5b8408e751
3
+ metadata.gz: f10c30433280a10e91f251f04f68ddd5b2cf02347de8712a9828b4488d49f7b4
4
+ data.tar.gz: fced66d8271da69b0bc8425c00f8dade0e8f4ee842bd6454d3584455a4d9cc9d
5
5
  SHA512:
6
- metadata.gz: 4d39ca69665b6383083bab06f724d961c9d88c41d50ac23c1abc44c15ec9d4440b6d9fff304c49d96b150d9c2145382d466f5449707a5d6c350247bc2726d08f
7
- data.tar.gz: e6baed2d72e9af279bded9ece8671dabb8cdddce1230b4fe308eb7c20fd875d6c0ebd5e98eb8f0ad75d450642c221bcd1c1481a194267b739ee47c4ebabd8fd1
6
+ metadata.gz: b69a7f035f1d502845d50ac578e25a02546207e0a7c3bc84ffd45c7bb1b2f8f58e833540c3b1f01e617923e1f74dc1fdd26ea4e1f7ad28d476ba198585ea05be
7
+ data.tar.gz: 98363d4a9d74c8b8ff785e244f07d982214a5fd40029c5cf634c48d6e214d084d4939bf58b5bd97008051771dd96522bc78e2bb981dcca611eeafc78d6713101
@@ -3,14 +3,21 @@ name: macos
3
3
  on: [push]
4
4
 
5
5
  jobs:
6
- build:
6
+ test:
7
7
  runs-on: macos-latest
8
+ strategy:
9
+ matrix:
10
+ ruby: [ head, 3.3 ]
8
11
  timeout-minutes: 10
12
+ env:
13
+ RUBYOPT: --enable-frozen-string-literal --debug-frozen-string-literal
9
14
  steps:
10
- - uses: actions/checkout@master
15
+ - uses: actions/checkout@v4
16
+ - uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: ${{ matrix.ruby }}
11
19
  - name: Install dependencies
12
20
  run: |
13
- gem install bundler --no-document
14
21
  bundle install
15
22
  - name: Run test
16
23
  run: bundle exec rake test
@@ -4,20 +4,21 @@ on: [push]
4
4
 
5
5
  jobs:
6
6
  test:
7
+ runs-on: ubuntu-latest
7
8
  strategy:
8
9
  matrix:
9
- ruby: [ head, 3.1, 3.0, 2.7 ]
10
- runs-on: ubuntu-latest
10
+ ruby: [ head, 3.3, 3.2, 3.1 ]
11
11
  timeout-minutes: 10
12
+ env:
13
+ RUBYOPT: --enable-frozen-string-literal --debug-frozen-string-literal
12
14
  steps:
13
- - uses: actions/checkout@v2
15
+ - uses: actions/checkout@v4
14
16
  - uses: ruby/setup-ruby@v1
15
17
  with:
16
18
  ruby-version: ${{ matrix.ruby }}
17
19
  - name: Install dependencies
18
20
  run: |
19
21
  sudo apt install libncursesw5-dev
20
- gem install bundler --no-document
21
22
  bundle install
22
23
  - name: Run test
23
24
  run: xvfb-run bundle exec rake test
@@ -3,14 +3,16 @@ name: windows
3
3
  on: [push]
4
4
 
5
5
  jobs:
6
- build:
6
+ test:
7
7
  runs-on: windows-latest
8
8
  strategy:
9
9
  matrix:
10
- ruby: [ 'mingw', 'mswin', '3.0', '2.7' ]
10
+ ruby: [ 'mingw', 'mswin', '3.3' ]
11
11
  timeout-minutes: 10
12
+ env:
13
+ RUBYOPT: --enable-frozen-string-literal --debug-frozen-string-literal
12
14
  steps:
13
- - uses: actions/checkout@v2
15
+ - uses: actions/checkout@v4
14
16
  - name: Set up Ruby
15
17
  uses: ruby/setup-ruby@v1
16
18
  with:
data/CHANGES.md CHANGED
@@ -1,3 +1,14 @@
1
+ This file is no longer being updated after version 1.3.0.
2
+ For changes since version 1.3.0, see <URL:https://github.com/shugo/textbringer/releases>.
3
+
4
+ ## 1.3.0
5
+
6
+ * Kernel#print etc. inserts the given string into the current buffer now.
7
+ * Add find_source.
8
+ * Add describe_class and describe_method.
9
+ * Support completion for eval_expression
10
+ * Fix digraph indentation in C mode.
11
+
1
12
  ## 1.2.0
2
13
 
3
14
  * Drop Ruby 2.6 support.
data/README.ja.md ADDED
@@ -0,0 +1,104 @@
1
+ # ![Textbringer](logo/logo.png)
2
+
3
+ [![LatestVer](https://badgen.net/badge/latestver/0.1)](https://latestver.org/)
4
+ [![Gem Version](https://badge.fury.io/rb/textbringer.svg)](https://badge.fury.io/rb/textbringer)
5
+ [![ubuntu](https://github.com/shugo/textbringer/workflows/ubuntu/badge.svg)](https://github.com/shugo/textbringer/actions?query=workflow%3Aubuntu)
6
+ [![windows](https://github.com/shugo/textbringer/workflows/windows/badge.svg)](https://github.com/shugo/textbringer/actions?query=workflow%3Awindows)
7
+ [![macos](https://github.com/shugo/textbringer/workflows/macos/badge.svg)](https://github.com/shugo/textbringer/actions?query=workflow%3Amacos)
8
+
9
+ TextbringerはRubyで実装されたEmacsライクなテキストエディタです。
10
+ Lispの代りにRubyで拡張することができます。
11
+
12
+ ## スクリーンショット
13
+
14
+ ![Screenshot](screenshot.png)
15
+
16
+ ## デモ
17
+
18
+ * FizzBuzz: https://asciinema.org/a/103357
19
+ * Rubyプログラミング: https://asciinema.org/a/100156
20
+ * 日本語テキストの編集: https://asciinema.org/a/100166
21
+
22
+ ## インストール
23
+
24
+ $ gem install textbringer
25
+
26
+ マルチバイト文字を使用するためにはncurseswが必要です。
27
+ Textbringerが依存するcurses.gemをインストールする前に、ncurseswをインストールしておいてください。
28
+
29
+ $ sudo apt-get install libncursesw5-dev
30
+ $ gem install curses
31
+
32
+ ## 使い方
33
+
34
+ $ txtb
35
+
36
+ `Ctrl-x Ctrl-c` で終了できます。 
37
+
38
+ 多くのコマンドとキーバインディングは[Emacs](https://www.gnu.org/software/emacs/)に似ています。
39
+
40
+ キーバインディングを確認するには、 `F1 b` または `Alt+x describe_bindings RET` とタイプしてください。
41
+
42
+ ## 設定
43
+
44
+ ### メタキー
45
+
46
+ 端末エミュレータでメタキーを使用するためには、以下のような設定が必要です。
47
+
48
+ #### xterm
49
+
50
+ ~/.Xresourcesに以下の行を追加してください。
51
+
52
+ XTerm*metaSendsEscape: true
53
+
54
+ #### mlterm
55
+
56
+ ~/.mlterm/mainに以下の行を追加してください。
57
+
58
+ mod_meta_key = alt
59
+ mod_meta_mode = esc
60
+
61
+ ### 東アジアの曖昧な文字幅
62
+
63
+ [曖昧な文字](http://unicode.org/reports/tr11/#Ambiguous)を全角扱いするには、以下の設定を~/.textbringer.rbに記述してください。
64
+
65
+ CONFIG[:east_asian_ambiguous_width] = 2
66
+
67
+ ncurseswはwcwidth(3)を使用するため、LD_PRELOADハックやlocale charmapの修正が必要かもしれません。
68
+
69
+ * https://github.com/fumiyas/wcwidth-cjk
70
+ * https://github.com/hamano/locale-eaw
71
+
72
+ xterm、 mlterm、screenにはそれぞれ独自の設定項目があります。
73
+
74
+ #### xterm
75
+
76
+ ~/.Xresourcesに以下の設定を追加してください。
77
+
78
+ xterm*utf8: 1
79
+ xterm*locale: true
80
+ xterm*cjkWidth: true
81
+
82
+ #### mlterm
83
+
84
+ ~/.mlterm/mainに以下の設定を追加してください。
85
+
86
+ col_size_of_width_a = 2
87
+
88
+ #### screen
89
+
90
+ ~/.screenrcに以下の設定を追加してください。
91
+
92
+ cjkwidth on
93
+
94
+ ## プラグイン
95
+
96
+ * [Mournmail](https://github.com/shugo/mournmail): 電子メールクライアント
97
+ * [MedicineShield](https://github.com/shugo/medicine_shield): Mastodonクライアント
98
+ * [textbringer-presentation](https://github.com/shugo/textbringer-presentation): プレゼンテーションツール
99
+ * [textbringer-ghost_text](https://github.com/shugo/textbringer-ghost_text): [GhostText](https://github.com/fregante/GhostText)プラグイン
100
+
101
+ ## ライセンス
102
+
103
+ [MIT License](http://opensource.org/licenses/MIT)の下でオープンソースとして利用可能です。
104
+
data/README.md CHANGED
@@ -1,12 +1,15 @@
1
1
  # ![Textbringer](logo/logo.png)
2
2
 
3
+ [![LatestVer](https://badgen.net/badge/latestver/0.1)](https://latestver.org/)
3
4
  [![Gem Version](https://badge.fury.io/rb/textbringer.svg)](https://badge.fury.io/rb/textbringer)
4
5
  [![ubuntu](https://github.com/shugo/textbringer/workflows/ubuntu/badge.svg)](https://github.com/shugo/textbringer/actions?query=workflow%3Aubuntu)
5
6
  [![windows](https://github.com/shugo/textbringer/workflows/windows/badge.svg)](https://github.com/shugo/textbringer/actions?query=workflow%3Awindows)
6
7
  [![macos](https://github.com/shugo/textbringer/workflows/macos/badge.svg)](https://github.com/shugo/textbringer/actions?query=workflow%3Amacos)
7
8
 
8
- Textbringer is a member of a demon race that takes on the form of an Emacs-like
9
- text editor.
9
+ * [Japanese version](README.ja.md)
10
+
11
+ Textbringer is an Emacs-like text editor written in Ruby.
12
+ It is extensible by Ruby instead of Lisp.
10
13
 
11
14
  ## Screenshot
12
15
 
@@ -93,6 +96,13 @@ Add the following line to ~/.screenrc.
93
96
 
94
97
  cjkwidth on
95
98
 
99
+ ## Plugins
100
+
101
+ * [Mournmail](https://github.com/shugo/mournmail): a mail user agent
102
+ * [MedicineShield](https://github.com/shugo/medicine_shield): a Mastodon client
103
+ * [textbringer-presentation](https://github.com/shugo/textbringer-presentation): a presentation tool
104
+ * [textbringer-ghost_text](https://github.com/shugo/textbringer-ghost_text): a [GhostText](https://github.com/fregante/GhostText) plugin
105
+
96
106
  ## Development
97
107
 
98
108
  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.
data/exe/txtb CHANGED
@@ -4,6 +4,7 @@ require "warning"
4
4
 
5
5
  Warning.ignore(/already initialized constant /)
6
6
  Warning.ignore(/previous definition of /)
7
+ Warning.ignore(/not part of the default gems/)
7
8
 
8
9
  require "textbringer"
9
10
 
@@ -26,6 +27,7 @@ end
26
27
  Controller.current = Controller.new
27
28
  begin
28
29
  Window.start do
30
+ $stdout = DefaultOutput.new
29
31
  begin
30
32
  load_user_config("~/.textbringer/init.rb")
31
33
  Plugin.load_plugins
@@ -44,7 +44,11 @@ module Textbringer
44
44
  e = NKF.guess(s)
45
45
  case e
46
46
  when Encoding::US_ASCII
47
- Encoding::UTF_8
47
+ if s.ascii_only?
48
+ Encoding::UTF_8
49
+ else
50
+ Encoding::ASCII_8BIT
51
+ end
48
52
  when Encoding::ASCII_8BIT
49
53
  s.force_encoding(Encoding::UTF_8)
50
54
  if s.valid_encoding?
@@ -58,7 +62,14 @@ module Textbringer
58
62
  end
59
63
  }
60
64
 
61
- STRING_HAS_BYTE_BASED_METHODS = String.instance_methods.include?(:bytesplice)
65
+ HAS_BYTEINDEX = String.instance_methods.include?(:byteindex)
66
+ HAS_BYTESPLICE = String.instance_methods.include?(:bytesplice)
67
+ BYTESPLICE_SUPPORTS_PARTIAL_COPY =
68
+ begin
69
+ (+"foo").bytesplice(0, 2, "bar", 1, 2) == "aro"
70
+ rescue NoMethodError, ArgumentError
71
+ false
72
+ end
62
73
 
63
74
  if !defined?(@@detect_encoding_proc)
64
75
  @@detect_encoding_proc = DEFAULT_DETECT_ENCODING
@@ -271,13 +282,6 @@ module Textbringer
271
282
  def file_encoding=(enc)
272
283
  @file_encoding = Encoding.find(enc)
273
284
  @binary = @file_encoding == Encoding::ASCII_8BIT
274
- if STRING_HAS_BYTE_BASED_METHODS
275
- if @binary
276
- @contents.force_encoding(Encoding::ASCII_8BIT)
277
- else
278
- @contents.force_encoding(Encoding::UTF_8)
279
- end
280
- end
281
285
  end
282
286
 
283
287
  def binary?
@@ -448,7 +452,7 @@ module Textbringer
448
452
  def to_s
449
453
  result = @contents.byteslice(0...@gap_start) +
450
454
  @contents.byteslice(@gap_end..-1)
451
- if !@binary && !STRING_HAS_BYTE_BASED_METHODS
455
+ if !@binary
452
456
  result.force_encoding(Encoding::UTF_8)
453
457
  end
454
458
  result
@@ -463,7 +467,7 @@ module Textbringer
463
467
  @contents.byteslice(user_to_gap(s), len) +
464
468
  @contents.byteslice(@gap_end, e - s - len)
465
469
  end
466
- if !@binary && !STRING_HAS_BYTE_BASED_METHODS
470
+ if !@binary
467
471
  result.force_encoding(Encoding::UTF_8)
468
472
  end
469
473
  result
@@ -525,7 +529,7 @@ module Textbringer
525
529
  if pos == point_min
526
530
  column = 1
527
531
  else
528
- if STRING_HAS_BYTE_BASED_METHODS
532
+ if HAS_BYTEINDEX
529
533
  begin
530
534
  i = @contents.byterindex("\n", user_to_gap(get_pos(pos, -1)))
531
535
  rescue RangeError
@@ -562,7 +566,7 @@ module Textbringer
562
566
  pos = point_min
563
567
  i = 1
564
568
  while i < n && pos < @contents.bytesize
565
- if STRING_HAS_BYTE_BASED_METHODS
569
+ if HAS_BYTEINDEX
566
570
  pos = @contents.byteindex("\n", pos)
567
571
  else
568
572
  pos = @contents.index("\n", pos)
@@ -586,7 +590,7 @@ module Textbringer
586
590
  pos = @point
587
591
  size = s.bytesize
588
592
  adjust_gap(size)
589
- splice_contents(@point, size, STRING_HAS_BYTE_BASED_METHODS ? s : s.b)
593
+ splice_contents(@point, size, s.b)
590
594
  @marks.each do |m|
591
595
  if m.location > @point
592
596
  m.location += size
@@ -995,10 +999,7 @@ module Textbringer
995
999
 
996
1000
  def clear
997
1001
  check_read_only_flag
998
- @contents = +""
999
- if binary? || !STRING_HAS_BYTE_BASED_METHODS
1000
- @contents.force_encoding(Encoding::ASCII_8BIT)
1001
- end
1002
+ @contents = String.new
1002
1003
  @point = @gap_start = @gap_end = 0
1003
1004
  @marks.each do |m|
1004
1005
  m.location = 0
@@ -1158,7 +1159,7 @@ module Textbringer
1158
1159
  byteindex(true, r, @point) == @point
1159
1160
  end
1160
1161
 
1161
- if STRING_HAS_BYTE_BASED_METHODS
1162
+ if HAS_BYTEINDEX
1162
1163
  def byteindex(forward, re, pos)
1163
1164
  @match_offsets = []
1164
1165
  method = forward ? :byteindex : :byterindex
@@ -1480,9 +1481,7 @@ module Textbringer
1480
1481
  else
1481
1482
  @contents = s.encode(Encoding::UTF_8)
1482
1483
  end
1483
- if !STRING_HAS_BYTE_BASED_METHODS
1484
- @contents.force_encoding(Encoding::ASCII_8BIT)
1485
- end
1484
+ @contents.force_encoding(Encoding::ASCII_8BIT)
1486
1485
  self.file_encoding = enc
1487
1486
  begin
1488
1487
  case @contents
@@ -1502,7 +1501,7 @@ module Textbringer
1502
1501
  end
1503
1502
  end
1504
1503
 
1505
- if STRING_HAS_BYTE_BASED_METHODS
1504
+ if HAS_BYTESPLICE
1506
1505
  def splice_contents(*args)
1507
1506
  @contents.bytesplice(*args)
1508
1507
  end
@@ -1515,37 +1514,37 @@ module Textbringer
1515
1514
  def adjust_gap(min_size = 0, pos = @point)
1516
1515
  if @gap_start < pos
1517
1516
  len = user_to_gap(pos) - @gap_end
1518
- s = @contents.byteslice(@gap_end, len)
1519
1517
  new_gap_start = @gap_start + len
1520
1518
  new_gap_end = @gap_end + len
1521
1519
  nul_filling_start = new_gap_start > @gap_end ? new_gap_start : @gap_end
1522
- unless @binary
1523
- # find the character boundary
1524
- while nul_filling_start > @gap_end &&
1525
- @contents.byteslice(nul_filling_start)&.b&.match?(/[\x80-\xbf]/n)
1526
- nul_filling_start -= 1
1527
- end
1520
+ if BYTESPLICE_SUPPORTS_PARTIAL_COPY
1521
+ @contents.bytesplice(@gap_start, len,
1522
+ @contents, @gap_end, len)
1523
+ @contents.bytesplice(nul_filling_start...new_gap_end,
1524
+ "\0" * (new_gap_end - nul_filling_start))
1525
+ else
1526
+ s = @contents.byteslice(@gap_end, len)
1527
+ splice_contents(nul_filling_start...new_gap_end,
1528
+ "\0" * (new_gap_end - nul_filling_start))
1529
+ splice_contents(@gap_start...new_gap_start, s)
1528
1530
  end
1529
- splice_contents(nul_filling_start...new_gap_end,
1530
- "\0" * (new_gap_end - nul_filling_start))
1531
- splice_contents(@gap_start...new_gap_start, s)
1532
1531
  @gap_start = new_gap_start
1533
1532
  @gap_end = new_gap_end
1534
1533
  elsif @gap_start > pos
1535
1534
  len = @gap_start - pos
1536
- s = @contents.byteslice(pos, len)
1537
1535
  new_gap_start = @gap_start - len
1538
1536
  new_gap_end = @gap_end - len
1539
1537
  nul_filling_end = new_gap_end < @gap_start ? new_gap_end : @gap_start
1540
- unless @binary
1541
- # find the character boundary
1542
- while nul_filling_end < @gap_start &&
1543
- @contents.byteslice(nul_filling_end)&.b&.match?(/[\x80-\xbf]/n)
1544
- nul_filling_end += 1
1545
- end
1538
+ if BYTESPLICE_SUPPORTS_PARTIAL_COPY
1539
+ @contents.bytesplice(new_gap_end, len,
1540
+ @contents, pos, len)
1541
+ @contents.bytesplice(pos...nul_filling_end,
1542
+ "\0" * (nul_filling_end - pos))
1543
+ else
1544
+ s = @contents.byteslice(pos, len)
1545
+ splice_contents(pos...nul_filling_end, "\0" * (nul_filling_end - pos))
1546
+ splice_contents(new_gap_end...@gap_end, s)
1546
1547
  end
1547
- splice_contents(pos...nul_filling_end, "\0" * (nul_filling_end - pos))
1548
- splice_contents(new_gap_end...@gap_end, s)
1549
1548
  @gap_start = new_gap_start
1550
1549
  @gap_end = new_gap_end
1551
1550
  end
@@ -1619,7 +1618,7 @@ module Textbringer
1619
1618
  @current_column += substring(pos, new_pos).size
1620
1619
  else
1621
1620
  @current_line += n
1622
- if STRING_HAS_BYTE_BASED_METHODS
1621
+ if HAS_BYTEINDEX
1623
1622
  begin
1624
1623
  i = @contents.byterindex("\n", user_to_gap(get_pos(new_pos, -1)))
1625
1624
  rescue RangeError
@@ -1641,7 +1640,7 @@ module Textbringer
1641
1640
  @current_column -= substring(new_pos, pos).size
1642
1641
  else
1643
1642
  @current_line -= n
1644
- if STRING_HAS_BYTE_BASED_METHODS
1643
+ if HAS_BYTEINDEX
1645
1644
  begin
1646
1645
  i = @contents.byterindex("\n", user_to_gap(get_pos(new_pos, - 1)))
1647
1646
  rescue RangeError
@@ -1687,9 +1686,7 @@ module Textbringer
1687
1686
  @contents.byteslice(0...@gap_start),
1688
1687
  @contents.byteslice(@gap_end..-1)
1689
1688
  ].each do |s|
1690
- if !STRING_HAS_BYTE_BASED_METHODS
1691
- s.force_encoding(Encoding::UTF_8) unless @binary
1692
- end
1689
+ s.force_encoding(Encoding::UTF_8) unless @binary
1693
1690
  case @file_format
1694
1691
  when :dos
1695
1692
  s.gsub!(/\n/, "\r\n")
@@ -7,8 +7,7 @@ require "clipboard"
7
7
  module Textbringer
8
8
  module Commands
9
9
  CLIPBOARD_AVAILABLE =
10
- Clipboard.implementation.name != "Clipboard::Linux" ||
11
- (ENV["DISPLAY"] && system("which xclip > /dev/null 2>&1"))
10
+ Clipboard.implementation.name != "Clipboard::File"
12
11
 
13
12
  if CLIPBOARD_AVAILABLE
14
13
  GLOBAL_MAP.define_key("\M-w", :clipboard_copy_region)
@@ -143,5 +143,20 @@ module Textbringer
143
143
  File.dirname(Buffer.current.file_name))|
144
144
  FileUtils.mkdir_p(dir_name)
145
145
  end
146
+
147
+ define_command(:find_source, doc: "Open the source file.") do
148
+ |obj = read_object("Object or Class: ")|
149
+ klass = obj.is_a?(Module) ? obj : obj.class
150
+ method_name = klass.instance_methods(false).first
151
+ if method_name.nil?
152
+ raise EditorError, "Source not found"
153
+ end
154
+ method = klass.instance_method(method_name)
155
+ file_name = method.source_location.first
156
+ if !File.exist?(file_name)
157
+ raise EditorError, "Source not found"
158
+ end
159
+ find_file(method.source_location.first)
160
+ end
146
161
  end
147
162
  end
@@ -1,3 +1,6 @@
1
+ $".push("readline.rb")
2
+ require "rdoc/ri/driver"
3
+
1
4
  module Textbringer
2
5
  module Commands
3
6
  HELP_RING = Ring.new
@@ -38,7 +41,7 @@ module Textbringer
38
41
  define_command(:describe_bindings,
39
42
  doc: "Display the key bindings.") do
40
43
  show_help do |help|
41
- s = ""
44
+ s = +""
42
45
  if Controller.current.overriding_map
43
46
  s << "Overriding Bindings:\n"
44
47
  s << keymap_bindings(Controller.current.overriding_map)
@@ -102,6 +105,44 @@ module Textbringer
102
105
  push_help_command([:describe_key, key])
103
106
  end
104
107
 
108
+ define_command(:describe_class,
109
+ doc: "Display the documentation of the class.") do
110
+ |name = read_expression("Describe class: ")|
111
+ show_help do |help|
112
+ old_stdout = $stdout
113
+ $stdout = StringIO.new
114
+ begin
115
+ rdoc = RDoc::RI::Driver.new(use_stdout: true,
116
+ formatter: RDoc::Markup::ToRdoc,
117
+ interactive: false)
118
+ rdoc.display_class(name)
119
+ help.insert($stdout.string)
120
+ ensure
121
+ $stdout = old_stdout
122
+ end
123
+ end
124
+ push_help_command([:describe_class, name])
125
+ end
126
+
127
+ define_command(:describe_method,
128
+ doc: "Display the documentation of the method.") do
129
+ |name = read_expression("Describe method: ")|
130
+ show_help do |help|
131
+ old_stdout = $stdout
132
+ $stdout = StringIO.new
133
+ begin
134
+ rdoc = RDoc::RI::Driver.new(use_stdout: true,
135
+ formatter: RDoc::Markup::ToRdoc,
136
+ interactive: false)
137
+ rdoc.display_method(name)
138
+ help.insert($stdout.string)
139
+ ensure
140
+ $stdout = old_stdout
141
+ end
142
+ end
143
+ push_help_command([:describe_method, name])
144
+ end
145
+
105
146
  define_command(:help_go_back, doc: "Go back to the previous help.") do
106
147
  if !HELP_RING.empty?
107
148
  HELP_RING.rotate(1)
@@ -32,7 +32,7 @@ module Textbringer
32
32
  end
33
33
 
34
34
  define_command(:eval_expression) do
35
- |s = read_from_minibuffer("Eval: ")|
35
+ |s = read_expression("Eval: ")|
36
36
  result = eval(s, TOPLEVEL_BINDING, "(eval_expression)", 1)
37
37
  message(result.inspect)
38
38
  result
@@ -243,6 +243,9 @@ module Textbringer
243
243
  mark = yield(global_mark_ring)
244
244
  end
245
245
  if mark.detached?
246
+ unless mark.file_name
247
+ raise EditorError, "The buffer has gone"
248
+ end
246
249
  find_file(mark.file_name)
247
250
  goto_char(mark.location)
248
251
  else
@@ -0,0 +1,18 @@
1
+ require "stringio"
2
+
3
+ module Textbringer
4
+ class DefaultOutput
5
+ def write(*args)
6
+ Buffer.current.insert(args.join)
7
+ end
8
+
9
+ def flush
10
+ end
11
+
12
+ def method_missing(mid, ...)
13
+ buffer = StringIO.new
14
+ buffer.send(mid, ...)
15
+ write(buffer.string)
16
+ end
17
+ end
18
+ end
@@ -57,7 +57,11 @@ module Textbringer
57
57
  end
58
58
  if key_index.nil?
59
59
  @prev_key_index = nil
60
- return event
60
+ if event.is_a?(String) && /\A[A-Z]\z/.match?(event)
61
+ return event.downcase
62
+ else
63
+ return event
64
+ end
61
65
  end
62
66
  if @prev_key_index.nil?
63
67
  @prev_key_index = key_index
@@ -153,6 +153,7 @@ module Textbringer
153
153
  GLOBAL_MAP.define_key(?\C-_, :undo)
154
154
  GLOBAL_MAP.define_key("\C-xu", :undo)
155
155
  GLOBAL_MAP.define_key("\C-x\C-_", :redo_command)
156
+ GLOBAL_MAP.define_key("\M-\C-_", :redo_command)
156
157
  GLOBAL_MAP.define_key("\C-t", :transpose_chars)
157
158
  GLOBAL_MAP.define_key("\C-j", :newline)
158
159
  GLOBAL_MAP.define_key("\C-m", :newline)
@@ -210,6 +211,8 @@ module Textbringer
210
211
  GLOBAL_MAP.define_key([:f1, "b"], :describe_bindings)
211
212
  GLOBAL_MAP.define_key([:f1, "f"], :describe_command)
212
213
  GLOBAL_MAP.define_key([:f1, "k"], :describe_key)
214
+ GLOBAL_MAP.define_key([:f1, "c"], :describe_class)
215
+ GLOBAL_MAP.define_key([:f1, "m"], :describe_method)
213
216
  GLOBAL_MAP.define_key("\C-x#", :server_edit_done)
214
217
  GLOBAL_MAP.define_key("\C-\\", :toggle_input_method)
215
218
  GLOBAL_MAP.handle_undefined_key do |key|
@@ -1,6 +1,6 @@
1
1
  module Textbringer
2
2
  CONFIG[:c_indent_level] = 4
3
- CONFIG[:c_indent_tabs_mode] = true
3
+ CONFIG[:c_indent_tabs_mode] = false
4
4
  CONFIG[:c_continued_statement_offset] = 4
5
5
  CONFIG[:c_case_label_offset] = -4
6
6
  CONFIG[:c_label_offset] = -2
@@ -187,7 +187,7 @@ module Textbringer
187
187
  if text.empty?
188
188
  raise EditorError, "Empty token: (#{line},#{column}) #{$~.inspect}"
189
189
  end
190
- tokens.push([[line, column], token_name, text])
190
+ tokens.push([[line, column], token_name, CANONICAL_PUNCTUATORS[text]])
191
191
  lf_count = text.count("\n")
192
192
  if lf_count > 0
193
193
  line += lf_count
@@ -1,4 +1,6 @@
1
1
  require "rbconfig"
2
+ require "irb"
3
+ require "irb/completion"
2
4
 
3
5
  module Textbringer
4
6
  module Utils
@@ -323,6 +325,31 @@ module Textbringer
323
325
  end
324
326
  end
325
327
 
328
+ if defined?(IRB::RegexpCompletor)
329
+ EXPRESSION_COMPLETOR = IRB::RegexpCompletor.new
330
+ EXPRESSION_COMPLETOR_OPTIONS = {
331
+ bind: TOPLEVEL_BINDING,
332
+ doc_namespace: false
333
+ }
334
+ else
335
+ EXPRESSION_COMPLETOR = IRB::InputCompletor
336
+ EXPRESSION_COMPLETOR_OPTIONS = {
337
+ bind: TOPLEVEL_BINDING
338
+ }
339
+ end
340
+
341
+ def read_expression(prompt = "Expression: ")
342
+ f = ->(s) {
343
+ EXPRESSION_COMPLETOR.retrieve_completion_data(s, **EXPRESSION_COMPLETOR_OPTIONS).compact
344
+ }
345
+ read_from_minibuffer(prompt, completion_proc: f)
346
+ end
347
+
348
+ def read_object(prompt = "Object: ")
349
+ s = read_expression(prompt)
350
+ eval(s)
351
+ end
352
+
326
353
  HOOKS = Hash.new { |h, k| h[k] = [] }
327
354
 
328
355
  def add_hook(name, func = nil, &block)
@@ -1,3 +1,3 @@
1
1
  module Textbringer
2
- VERSION = "1.2.0"
2
+ VERSION = "1.4.0"
3
3
  end
@@ -1,5 +1,4 @@
1
1
  require "curses"
2
- require "unicode/display_width"
3
2
 
4
3
  module Textbringer
5
4
  class Window
data/lib/textbringer.rb CHANGED
@@ -38,3 +38,4 @@ require_relative "textbringer/input_methods/t_code_input_method"
38
38
  require_relative "textbringer/input_methods/hiragana_input_method"
39
39
  require_relative "textbringer/plugin"
40
40
  require_relative "textbringer/controller"
41
+ require_relative "textbringer/default_output"
data/textbringer.gemspec CHANGED
@@ -19,8 +19,10 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.required_ruby_version = '>= 2.7'
22
+ spec.required_ruby_version = '>= 3.1'
23
23
 
24
+ spec.add_runtime_dependency "nkf"
25
+ spec.add_runtime_dependency "drb"
24
26
  spec.add_runtime_dependency "curses", ">= 1.2.7"
25
27
  spec.add_runtime_dependency "unicode-display_width", ">= 1.1"
26
28
  spec.add_runtime_dependency "clipboard", ">= 1.1"
metadata CHANGED
@@ -1,15 +1,42 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: textbringer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shugo Maeda
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2022-10-24 00:00:00.000000000 Z
10
+ date: 2024-05-24 00:00:00.000000000 Z
12
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: nkf
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: drb
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
13
40
  - !ruby/object:Gem::Dependency
14
41
  name: curses
15
42
  requirement: !ruby/object:Gem::Requirement
@@ -184,6 +211,7 @@ files:
184
211
  - CHANGES.md
185
212
  - Gemfile
186
213
  - LICENSE.txt
214
+ - README.ja.md
187
215
  - README.md
188
216
  - Rakefile
189
217
  - bin/console
@@ -212,6 +240,7 @@ files:
212
240
  - lib/textbringer/commands/windows.rb
213
241
  - lib/textbringer/config.rb
214
242
  - lib/textbringer/controller.rb
243
+ - lib/textbringer/default_output.rb
215
244
  - lib/textbringer/errors.rb
216
245
  - lib/textbringer/face.rb
217
246
  - lib/textbringer/faces/basic.rb
@@ -243,7 +272,6 @@ homepage: https://github.com/shugo/textbringer
243
272
  licenses:
244
273
  - MIT
245
274
  metadata: {}
246
- post_install_message:
247
275
  rdoc_options: []
248
276
  require_paths:
249
277
  - lib
@@ -251,15 +279,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
251
279
  requirements:
252
280
  - - ">="
253
281
  - !ruby/object:Gem::Version
254
- version: '2.7'
282
+ version: '3.1'
255
283
  required_rubygems_version: !ruby/object:Gem::Requirement
256
284
  requirements:
257
285
  - - ">="
258
286
  - !ruby/object:Gem::Version
259
287
  version: '0'
260
288
  requirements: []
261
- rubygems_version: 3.4.0.dev
262
- signing_key:
289
+ rubygems_version: 3.6.0.dev
263
290
  specification_version: 4
264
291
  summary: An Emacs-like text editor
265
292
  test_files: []