diff --git a/ivette/src/frama-c/kernel/SourceCode.tsx b/ivette/src/frama-c/kernel/SourceCode.tsx index aaf770e7399bc4c1bb8c4709fe7982c573ad930f..440f51a1ab98d3357997e678ff3020885391cc8d 100644 --- a/ivette/src/frama-c/kernel/SourceCode.tsx +++ b/ivette/src/frama-c/kernel/SourceCode.tsx @@ -28,7 +28,7 @@ import React from 'react'; import * as States from 'frama-c/states'; import * as Dome from 'dome'; -import { readFile } from 'dome/system'; +import * as System from 'dome/system'; import { RichTextBuffer } from 'dome/text/buffers'; import { Text } from 'dome/text/editors'; import { TitleBar } from 'ivette'; @@ -37,6 +37,7 @@ import { functions, markerInfo } from 'frama-c/api/kernel/ast'; import { Code } from 'dome/controls/labels'; import { Hfill } from 'dome/layout/boxes'; import * as Path from 'path'; +import * as Settings from 'dome/data/settings'; import 'codemirror/addon/selection/active-line'; import 'codemirror/addon/dialog/dialog.css'; @@ -86,12 +87,20 @@ export default function SourceCode() { // Updating the buffer content. const errorMsg = () => { D.error(`Fail to load source code file ${file}`); }; const onError = () => { if (file) errorMsg(); return ''; }; - const read = () => readFile(file).catch(onError); + const read = () => System.readFile(file).catch(onError); const text = React.useMemo(read, [file, onError]); const { result } = Dome.usePromise(text); React.useEffect(() => buffer.setValue(result), [buffer, result]); React.useEffect(() => buffer.setCursorOnTop(line), [buffer, line, result]); + const [command] = Settings.useGlobalSettings(Preferences.EditorCommand); + const launchEditor = () => { + const cmd = command.replace('\%s', file).replace('\%d', line.toString()); + const args = cmd.split(' '); + const prog = args.shift(); + if (prog) System.spawn(prog, args); + }; + // Building the React component. return ( <> @@ -109,7 +118,7 @@ export default function SourceCode() { selection={theMarker} lineNumbers={!!theFunction} styleActiveLine={!!theFunction} - extraKeys={{ 'Alt-F': 'findPersistent' }} + extraKeys={{ 'Ctrl-LeftClick': launchEditor }} readOnly /> </> diff --git a/ivette/src/ivette/prefs.tsx b/ivette/src/ivette/prefs.tsx index 71df4d94ca47ab24bd17921320064355fec3cafe..b4fd8e08190ddefcdbc0f9738a2a53e10e7ad367 100644 --- a/ivette/src/ivette/prefs.tsx +++ b/ivette/src/ivette/prefs.tsx @@ -127,3 +127,20 @@ export function useThemeButtons(props: ThemeProps): ThemeControls { } // -------------------------------------------------------------------------- +// --- Editor configuration +// -------------------------------------------------------------------------- + +export const EditorCommand = + new Settings.GString('Editor.Command', 'emacs +\%d \%s'); + +export interface EditorCommandProps { + command: Settings.GlobalSettings<string>; +} + +// function produceCommand(command: string, file: string, line: number): string { +// command.replace('\%s', file); +// command.replace('\%d', line.toString()); +// return ""; +// } + +// -------------------------------------------------------------------------- diff --git a/ivette/src/renderer/Preferences.tsx b/ivette/src/renderer/Preferences.tsx index a16aea3fdb2d8aa71fef5f9ed7451e9a832b52f4..b6696ab22adf0897681c3da0fb88c4d8b6f828cd 100644 --- a/ivette/src/renderer/Preferences.tsx +++ b/ivette/src/renderer/Preferences.tsx @@ -83,6 +83,16 @@ function ThemeFields(props: P.ThemeProps) { ); } +// -------------------------------------------------------------------------- +// --- Editor Command Forms +// -------------------------------------------------------------------------- +function EditorCommandFields(props : P.EditorCommandProps) { + const command = Forms.useDefined( + Forms.useValid(Settings.useGlobalSettings(props.command) + )); + return (<Forms.TextCodeField state={command} label="Command"/>); +} + // -------------------------------------------------------------------------- // --- Export Components // -------------------------------------------------------------------------- @@ -105,6 +115,9 @@ export default (() => ( wrapText={P.SourceWrapText} /> </Forms.Section> + <Forms.Section label="Editor Command" unfold> + <EditorCommandFields command={P.EditorCommand}/> + </Forms.Section> </Forms.Page> ));