Skip to content

Commit f320296

Browse files
committed
Add click handlers to line numbers
1 parent 8fa2bcc commit f320296

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

index.html

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,11 @@ <h1 class="text-3xl font-semibold mb-2">Bash Script Tools</h1>
177177
}
178178
}
179179

180+
function jumpToLine(lineNum, column) {
181+
editor.gotoLine(lineNum, column || 0, true);
182+
editor.focus();
183+
}
184+
180185
async function checkCode() {
181186
const code = editor.getValue();
182187
showSpinner("check-spinner");
@@ -192,6 +197,19 @@ <h1 class="text-3xl font-semibold mb-2">Bash Script Tools</h1>
192197
const result = await response.json();
193198
document.getElementById("output-box").innerHTML = result.html;
194199

200+
// Add click handlers to line numbers
201+
// Find corresponding annotation for column position
202+
document.querySelectorAll(".line-link").forEach((link) => {
203+
link.addEventListener("click", (e) => {
204+
e.preventDefault();
205+
const lineNum = parseInt(link.dataset.line);
206+
// Find annotation for this line to get column
207+
const annotation = result.annotations?.find((a) => a.row === lineNum - 1);
208+
const column = annotation ? annotation.column : 0;
209+
jumpToLine(lineNum, column);
210+
});
211+
});
212+
195213
if (result.annotations && result.annotations.length > 0) {
196214
editor.session.setAnnotations(result.annotations);
197215
}

main.go

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ type LineError struct {
3636
Code string
3737
Severity string
3838
Message string
39+
Column int
3940
}
4041

4142
func getEnvOrDefault(key, defaultValue string) string {
@@ -147,22 +148,31 @@ func parseShellcheckOutput(output string) []Annotation {
147148
lines := regexp.MustCompile(`\r?\n`).Split(output, -1)
148149
scCodeRegex := regexp.MustCompile(`(SC\d+)\s+\((error|warning|info|style)\):\s*(.+)`)
149150
lineRegex := regexp.MustCompile(`\bline\s+(\d+):`)
151+
columnRegex := regexp.MustCompile(`^(\s*)\^`)
150152

151153
var currentLine int
154+
var currentColumn int
152155
for _, line := range lines {
153156
// Extract line number
154-
if lineMatch := lineRegex.FindStringSubmatch(line); lineMatch != nil && len(lineMatch) >= 2 {
157+
if lineMatch := lineRegex.FindStringSubmatch(line); len(lineMatch) >= 2 {
155158
if num, err := strconv.Atoi(lineMatch[1]); err == nil {
156159
currentLine = num
160+
currentColumn = 0
157161
}
158162
}
159163

164+
// Extract column position from ^-- marker
165+
if colMatch := columnRegex.FindStringSubmatch(line); len(colMatch) > 1 {
166+
currentColumn = len(colMatch[1])
167+
}
168+
160169
// Extract error code and message
161-
if scMatch := scCodeRegex.FindStringSubmatch(line); scMatch != nil && currentLine > 0 && len(scMatch) >= 4 {
170+
if scMatch := scCodeRegex.FindStringSubmatch(line); currentLine > 0 && len(scMatch) >= 4 {
162171
lineErrors[currentLine] = append(lineErrors[currentLine], LineError{
163172
Code: scMatch[1],
164173
Severity: scMatch[2],
165174
Message: scMatch[3],
175+
Column: currentColumn,
166176
})
167177
}
168178
}
@@ -175,6 +185,7 @@ func parseShellcheckOutput(output string) []Annotation {
175185

176186
// Determine annotation type based on most severe error
177187
annotationType := "info"
188+
column := 0
178189
for _, err := range errors {
179190
if err.Severity == "error" {
180191
annotationType = "error"
@@ -184,6 +195,11 @@ func parseShellcheckOutput(output string) []Annotation {
184195
}
185196
}
186197

198+
// Use column from first error (they should all be the same for a given line)
199+
if len(errors) > 0 {
200+
column = errors[0].Column
201+
}
202+
187203
// Build combined error message with one line per issue
188204
var messages []string
189205
for _, err := range errors {
@@ -192,7 +208,7 @@ func parseShellcheckOutput(output string) []Annotation {
192208

193209
annotations = append(annotations, Annotation{
194210
Row: lineNum - 1, // Ace uses 0-based indexing
195-
Column: 0,
211+
Column: column,
196212
Text: strings.Join(messages, "\n"),
197213
Type: annotationType,
198214
})
@@ -245,8 +261,8 @@ func formatShellcheckHTML(output string) string {
245261
formatted = regexp.MustCompile(`(?m)^(.+SC\d+.+\(info\):.+)$`).ReplaceAllString(formatted, `<span class="text-blue-400">$1</span>`)
246262
formatted = regexp.MustCompile(`(?m)^(.+SC\d+.+\(style\):.+)$`).ReplaceAllString(formatted, `<span class="text-green-400">$1</span>`)
247263

248-
// Color line numbers (now just "Line X:")
249-
formatted = regexp.MustCompile(`(?m)^Line (\d+):`).ReplaceAllString(formatted, `<span class="text-cyan-400">Line $1:</span>`)
264+
// Color line numbers and make them clickable (now just "Line X:")
265+
formatted = regexp.MustCompile(`(?m)^Line (\d+):`).ReplaceAllString(formatted, `<a href="#" class="line-link text-cyan-400 hover:text-cyan-300 cursor-pointer underline" data-line="$1">Line $1:</a>`)
250266

251267
return fmt.Sprintf(`<pre class="text-xs whitespace-pre-wrap font-mono">%s</pre>`, formatted)
252268
}

0 commit comments

Comments
 (0)