Closed JMLX42 closed 2 years ago
I just asked on the CodeMirror forum: https://discuss.codemirror.net/t/codemirror-6-offset-line-numbers/2675/4
@JMLX42 Can you provide examples through codesandbox
?
@jaywcjlove here you go:
https://codesandbox.io/s/react-codemirror-example-codemirror-6-forked-k0uyu?file=/src/App.js
Update: just fixed the codesandbox link
@jaywcjlove I have tried reconfiguring the extension but it doesn't help:
function CodeEditor(props) {
const gutter = new Compartment();
const lines = lineNumbers({
formatNumber: (n, s) => {
return (n + props.lineNumberOffset).toString();
}
});
const extensions = [gutter.of(lines)];
const ref = useRef(null);
useEffect(() => {
if (ref.current.view) {
console.log("reconfigure");
ref.current.view.dispatch({
effects: gutter.reconfigure(lines)
});
}
});
return (
<CodeMirror
ref={ref}
value="some_code();"
height="200px"
extensions={extensions}
/>
);
}
Sadly, the editor is not refreshed (and the line number are not updated) until it is focused the 1st time. Then if new lines are added, focusing the editor doesn’t update the lines anymore. But adding content to the editor updates the line numbers.
Is there a way to force an editor update after reconfiguring an extension without focusing it/typing anything in it?
@jaywcjlove it might actually be a CodeMirror bug: https://discuss.codemirror.net/t/codemirror-6-offset-line-numbers/2675/10
It was a bug and it is now fixed in @codemirror/gutter
version 0.19.5. The following code now works as expected:
import { CatalaCell, setCodeValue } from "../file/fileSlice";
import { connect, ConnectedProps } from "react-redux";
import { RootState } from "../../app/store";
import { lineNumbers } from "@codemirror/gutter";
import { useAppDispatch } from "../../app/hooks";
import CodeMirror from "@uiw/react-codemirror";
import { EditorState } from "@codemirror/state";
const mapState = (state: RootState) => ({
fileContent: state.file.content,
});
const mapDispatch = {
};
const connector = connect(mapState, mapDispatch);
type PropsFromRedux = ConnectedProps<typeof connector>;
type Props = PropsFromRedux & {
cellIndex: number;
lineNumberOffset: number;
}
const CodeEditor = (props: Props) => {
const dispatch = useAppDispatch();
const cell: CatalaCell = props.fileContent![props.cellIndex];
const extensions = [
lineNumbers({ formatNumber: (n: number, s: EditorState) =>
(n + props.lineNumberOffset).toString()
}),
];
return (
<div style={{ marginTop: 10, marginBottom: 10 }}>
<CodeMirror
value={cell?.code?.code}
onChange={(value, viewUpdate) => {
dispatch(setCodeValue([props.cellIndex, value]));
}}
extensions={extensions}
theme="dark"
/>
</div>
);
}
export default connector(CodeEditor);
And here is the updated CodeSandbox:
https://codesandbox.io/s/react-codemirror-example-codemirror-6-forked-2s82t?file=/src/App.js
https://codesandbox.io/s/react-codemirror-example-codemirror-6-forked-2s82t?file=/src/App.js
import CodeMirror from "@uiw/react-codemirror";
import { lineNumbers } from "@codemirror/gutter";
import React from "react";
export function TextEditor(props) {
const [value, setValue] = React.useState(props.defaultValue);
const onChange = (e) => {
setValue(e.target.value);
props.onChange(e);
};
return (
<textarea
style={{ width: 400, height: 200 }}
onChange={onChange}
value={value}
></textarea>
);
}
function CodeEditor(props) {
const extensions = [
lineNumbers({
formatNumber: (n, s) => {
return (n + props.lineNumberOffset).toString();
}
})
];
return (
<CodeMirror value="some_code();" height="200px" extensions={extensions} />
);
}
export default function App() {
const defaultText = "some text\nadd lines to test";
const countLines = (s) => s.match(/\n/gm)?.length ?? 0;
const [lineNumberOffset, setLineNumberOffset] = React.useState(
countLines(defaultText) + 1
);
const onChange = (e) => {
setLineNumberOffset(countLines(e.target.value) + 1);
};
return (
<div>
<TextEditor onChange={onChange} defaultValue={defaultText} />
<div>Line number offset = {lineNumberOffset}</div>
<CodeEditor lineNumberOffset={lineNumberOffset} />
</div>
);
}
https://codesandbox.io/s/react-codemirror-example-codemirror-6-forked-2s82t?file=/src/App.js
import CodeMirror from "@uiw/react-codemirror"; import { lineNumbers } from "@codemirror/gutter"; import React from "react"; export function TextEditor(props) { const [value, setValue] = React.useState(props.defaultValue); const onChange = (e) => { setValue(e.target.value); props.onChange(e); }; return ( <textarea style={{ width: 400, height: 200 }} onChange={onChange} value={value} ></textarea> ); } function CodeEditor(props) { const extensions = [ lineNumbers({ formatNumber: (n, s) => { return (n + props.lineNumberOffset).toString(); } }) ]; return ( <CodeMirror value="some_code();" height="200px" extensions={extensions} /> ); } export default function App() { const defaultText = "some text\nadd lines to test"; const countLines = (s) => s.match(/\n/gm)?.length ?? 0; const [lineNumberOffset, setLineNumberOffset] = React.useState( countLines(defaultText) + 1 ); const onChange = (e) => { setLineNumberOffset(countLines(e.target.value) + 1); }; return ( <div> <TextEditor onChange={onChange} defaultValue={defaultText} /> <div>Line number offset = {lineNumberOffset}</div> <CodeEditor lineNumberOffset={lineNumberOffset} /> </div> ); }
its not wroking in latest @uiw/react-codemirror (4.21.20).
how can i set the linenum offet of react-codemiirror?
https://codesandbox.io/s/react-codemirror-example-codemirror-6-forked-2s82t?file=/src/App.js
import CodeMirror from "@uiw/react-codemirror"; import { lineNumbers } from "@codemirror/gutter"; import React from "react"; export function TextEditor(props) { const [value, setValue] = React.useState(props.defaultValue); const onChange = (e) => { setValue(e.target.value); props.onChange(e); }; return ( <textarea style={{ width: 400, height: 200 }} onChange={onChange} value={value} ></textarea> ); } function CodeEditor(props) { const extensions = [ lineNumbers({ formatNumber: (n, s) => { return (n + props.lineNumberOffset).toString(); } }) ]; return ( <CodeMirror value="some_code();" height="200px" extensions={extensions} /> ); } export default function App() { const defaultText = "some text\nadd lines to test"; const countLines = (s) => s.match(/\n/gm)?.length ?? 0; const [lineNumberOffset, setLineNumberOffset] = React.useState( countLines(defaultText) + 1 ); const onChange = (e) => { setLineNumberOffset(countLines(e.target.value) + 1); }; return ( <div> <TextEditor onChange={onChange} defaultValue={defaultText} /> <div>Line number offset = {lineNumberOffset}</div> <CodeEditor lineNumberOffset={lineNumberOffset} /> </div> ); }
its not wroking in latest @uiw/react-codemirror (4.21.20).
how can i set the linenum offet of react-codemiirror?
For those who need it:
import { lineNumbers } from "@codemirror/gutter"; // remove this
import { lineNumbers } from "@codemirror/view"; // use this
make it work.
Hello,
I'm trying to use the
lineNumbers
extension to add an offset to each line number. It works fine when the component is created/rendered for the first time.But then if the
lineNumberOffset
prop is changed, the CodeMirror editor is not updated. Any idea how to fix this?