textbringer 1.2.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
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: []