fix: add copy path to line in Monaco editor context menu

Adds "Copy Path to Line" and "Copy Relative Path to Line" as Monaco
editor context menu actions so they appear on right-click anywhere in
the editor. Also handles right-click on line number gutter to show
the context menu there too.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Neil
2026-03-23 23:32:55 -07:00
co-authored by Claude Opus 4.6
parent e8aa9d5a24
commit aa88ce3ac1
2 changed files with 47 additions and 2 deletions
@@ -215,6 +215,7 @@ export default function EditorPanel(): React.JSX.Element | null {
return (
<MonacoEditor
filePath={activeFile.filePath}
relativePath={activeFile.relativePath}
content={editBuffers[activeFile.id] ?? fc.content}
language={resolvedLanguage}
onContentChange={handleContentChange}
@@ -6,6 +6,7 @@ import '@/lib/monaco-setup'
type MonacoEditorProps = {
filePath: string
relativePath: string
content: string
language: string
onContentChange: (content: string) => void
@@ -17,6 +18,7 @@ type MonacoEditorProps = {
export default function MonacoEditor({
filePath,
relativePath,
content,
language,
onContentChange,
@@ -45,11 +47,53 @@ export default function MonacoEditor({
// Track cursor line for "copy path to line" feature
const pos = editorInstance.getPosition()
if (pos) setEditorCursorLine(filePath, pos.lineNumber)
if (pos) {
setEditorCursorLine(filePath, pos.lineNumber)
}
editorInstance.onDidChangeCursorPosition((e) => {
setEditorCursorLine(filePath, e.position.lineNumber)
})
// Show context menu on line number gutter right-click
editorInstance.onMouseDown((e) => {
if (
e.event.rightButton &&
e.target.type === monaco.editor.MouseTargetType.GUTTER_LINE_NUMBERS
) {
e.event.preventDefault()
e.event.stopPropagation()
// Move cursor to the clicked line so actions use the right line number
const line = e.target.position?.lineNumber
if (line) {
editorInstance.setPosition({ lineNumber: line, column: 1 })
}
// Trigger Monaco's context menu programmatically
editorInstance.trigger('gutter', 'editor.action.showContextMenu', null)
}
})
// Add "Copy Path to Line" actions to Monaco's right-click context menu
editorInstance.addAction({
id: 'orca.copyPathToLine',
label: 'Copy Path to Line',
contextMenuGroupId: '9_cutcopypaste',
contextMenuOrder: 100,
run: (ed) => {
const line = ed.getPosition()?.lineNumber ?? 1
navigator.clipboard.writeText(`${filePath}#L${line}`)
}
})
editorInstance.addAction({
id: 'orca.copyRelativePathToLine',
label: 'Copy Relative Path to Line',
contextMenuGroupId: '9_cutcopypaste',
contextMenuOrder: 101,
run: (ed) => {
const line = ed.getPosition()?.lineNumber ?? 1
navigator.clipboard.writeText(`${relativePath}#L${line}`)
}
})
// If there's a pending reveal at mount time, execute it now
const reveal = useAppStore.getState().pendingEditorReveal
if (reveal) {
@@ -59,7 +103,7 @@ export default function MonacoEditor({
editorInstance.focus()
}
},
[onSave, filePath, setEditorCursorLine, setPendingEditorReveal]
[onSave, filePath, relativePath, setEditorCursorLine]
)
const handleChange = useCallback(