Codemirror 6: Offset line numbers

Is it possible to start the line numbers counting from some arbitrary number instead of 1? I’m hoping to do a kind of literate programming interface composed of multiple editor instances. I’d like to be able to offset the beginning number of subsequent instances.

You can use the formatNumber option to lineNumbers to display the numbers in the gutter differently. But you can’t change the way the document is indexed internally.

That’s just what I need. Thanks!

I’m trying to do that exactly.

I’m writing a React component that wraps react-codemirror. Customizing formatNumber works when the component/editor is initialized. But if the lineNumberOffset property of my component is changed, the CodeMirror extension/component is not affected:

type Props = PropsFromRedux & {
  cellIndex: number;
  lineNumberOffset: number;
}

const CodeEditor = (props: Props) => {
  const dispatch = useAppDispatch();
  const cell: CatalaCell = props.fileContent![props.cellIndex];

  const formatLineNumber = (n: number, s: EditorState) => {
    return (n + props.lineNumberOffset).toString();
  };
  const extensions = [
    lineNumbers({ formatNumber: formatLineNumber }),
  ];

  return (
    <div style={{ marginTop: 10, marginBottom: 10 }}>
      <ReactCodeMirror
        basicSetup={false}
        value={cell?.code?.code}
        onChange={(value, viewUpdate) => {
          dispatch(setCodeValue([props.cellIndex, value]));
        }}
        extensions={extensions}
        theme="dark"
      />
    </div>
  );
}

Should I reconfigure the extensions of the editor? How?

Thanks a lot!

I don’t know how all this interacts with react, but this example describes setting up dynamic configuration.

I’ve made a codesandbox example to reproduce the problem:

I’ve read that documentation but I’m not sure which example applies best.

Update: fixed the codesandbox link

Looks like my codesandbox did not save properly. I’ll fix that right now.

Update: here you go: react-codemirror-example (codemirror 6) (forked) - CodeSandbox

I have edited my codesandbox example to use view.dispatch() to reconfigure the lineNumbers extension:


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.

@marijn is there a way to force an editor update after reconfiguring an extension without focusing it/typing anything in it?

That’s how it should work. If you can reproduce the issue without react and react-codemirror, I’ll gladly take a look.

@marijn here you go: a complete example without React and IMHO the bug is the same.

The line numbers are not updated until the content is edited by adding/removing chars. Am I missing something?

Thanks, that was a bug. This patch should solve it.

@marijn thanks a ton! And a 0.19.5 release with the fix: you’re too kind. :pray: :+1: :100: