mbeditor 0.9.0 → 0.10.1

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.
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mbeditor
4
+ # Per-line git status for one file, for colouring the editor's line numbers.
5
+ #
6
+ # Wraps `git diff -U0` (working tree vs HEAD) and turns its hunk headers into
7
+ # line ranges in the *current* file:
8
+ #
9
+ # {
10
+ # "added" => [{ "start" => 12, "end" => 14 }, ...],
11
+ # "modified" => [{ "start" => 30, "end" => 30 }, ...],
12
+ # "deleted" => [{ "start" => 47, "end" => 47 }, ...],
13
+ # "tracked" => true
14
+ # }
15
+ #
16
+ # A deletion has no lines left to mark, so it is reported as the single line
17
+ # the removed content sat after — line 0 when the file's opening lines were
18
+ # the ones deleted, which the frontend renders above the first line.
19
+ #
20
+ # An untracked file has no HEAD side at all, so every line counts as added.
21
+ class GitLineDiffService
22
+ include GitService
23
+
24
+ # @@ -<old_start>[,<old_count>] +<new_start>[,<new_count>] @@
25
+ HUNK_HEADER = /\A@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/
26
+
27
+ attr_reader :repo_path, :file_path
28
+
29
+ def initialize(repo_path:, file_path:)
30
+ @repo_path = repo_path.to_s
31
+ @file_path = file_path.to_s
32
+ end
33
+
34
+ def call
35
+ return untracked_result if untracked?
36
+
37
+ output, status = GitService.run_git(
38
+ repo_path, "diff", "--no-color", "--no-ext-diff", "-U0", "HEAD", "--", file_path
39
+ )
40
+ # A non-zero status here means the diff could not be produced at all (no
41
+ # HEAD yet, path outside the repo). Report a clean file rather than
42
+ # raising: line colouring is decoration, never a reason to fail a load.
43
+ return empty_result unless status.success?
44
+
45
+ parse(output)
46
+ end
47
+
48
+ private
49
+
50
+ def empty_result
51
+ { "added" => [], "modified" => [], "deleted" => [], "tracked" => true }
52
+ end
53
+
54
+ def untracked_result
55
+ line_count = count_lines
56
+ added = line_count.positive? ? [{ "start" => 1, "end" => line_count }] : []
57
+ { "added" => added, "modified" => [], "deleted" => [], "tracked" => false }
58
+ end
59
+
60
+ def untracked?
61
+ output, status = GitService.run_git(repo_path, "ls-files", "--error-unmatch", "--", file_path)
62
+ !(status.success? && output.present?)
63
+ end
64
+
65
+ def count_lines
66
+ absolute = File.join(repo_path, file_path)
67
+ return 0 unless File.file?(absolute)
68
+
69
+ File.foreach(absolute).count
70
+ rescue SystemCallError
71
+ 0
72
+ end
73
+
74
+ def parse(output)
75
+ result = empty_result
76
+
77
+ output.each_line do |line|
78
+ match = HUNK_HEADER.match(line)
79
+ next unless match
80
+
81
+ old_count = match[2] ? match[2].to_i : 1
82
+ new_start = match[3].to_i
83
+ new_count = match[4] ? match[4].to_i : 1
84
+
85
+ if new_count.zero?
86
+ # Pure deletion. git reports the line the removed block followed, so
87
+ # new_start is already that line (and 0 when it was the file's head).
88
+ result["deleted"] << { "start" => new_start, "end" => new_start }
89
+ elsif old_count.zero?
90
+ result["added"] << { "start" => new_start, "end" => new_start + new_count - 1 }
91
+ else
92
+ result["modified"] << { "start" => new_start, "end" => new_start + new_count - 1 }
93
+ end
94
+ end
95
+
96
+ result
97
+ end
98
+ end
99
+ end
@@ -54,6 +54,7 @@ module Mbeditor
54
54
  # ── Git & Code Review ──────────────────────────────────────────────────────
55
55
  get 'git/diff', to: 'git#diff'
56
56
  get 'git/blame', to: 'git#blame'
57
+ get 'git/line_diff', to: 'git#line_diff'
57
58
  get 'git/file_history', to: 'git#file_history'
58
59
  get 'git/commit_graph', to: 'git#commit_graph'
59
60
  get 'git/commit_detail', to: 'git#commit_detail'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mbeditor
4
- VERSION = "0.9.0"
4
+ VERSION = "0.10.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mbeditor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oliver Noonan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-07-23 00:00:00.000000000 Z
11
+ date: 2026-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -70,6 +70,7 @@ files:
70
70
  - app/assets/javascripts/mbeditor/components/GitPanel.js
71
71
  - app/assets/javascripts/mbeditor/components/LogPanel.js
72
72
  - app/assets/javascripts/mbeditor/components/MbeditorApp.js
73
+ - app/assets/javascripts/mbeditor/components/ProblemsPanel.js
73
74
  - app/assets/javascripts/mbeditor/components/QuickOpenDialog.js
74
75
  - app/assets/javascripts/mbeditor/components/ShortcutHelp.js
75
76
  - app/assets/javascripts/mbeditor/components/TabBar.js
@@ -81,6 +82,7 @@ files:
81
82
  - app/assets/javascripts/mbeditor/file_service.js
82
83
  - app/assets/javascripts/mbeditor/git_service.js
83
84
  - app/assets/javascripts/mbeditor/history_service.js
85
+ - app/assets/javascripts/mbeditor/js_outline.js
84
86
  - app/assets/javascripts/mbeditor/log_service.js
85
87
  - app/assets/javascripts/mbeditor/ruby_outline.js
86
88
  - app/assets/javascripts/mbeditor/search_service.js
@@ -107,6 +109,7 @@ files:
107
109
  - app/services/mbeditor/git_diff_service.rb
108
110
  - app/services/mbeditor/git_file_history_service.rb
109
111
  - app/services/mbeditor/git_info_service.rb
112
+ - app/services/mbeditor/git_line_diff_service.rb
110
113
  - app/services/mbeditor/git_service.rb
111
114
  - app/services/mbeditor/js_definition_service.rb
112
115
  - app/services/mbeditor/js_globals_service.rb