react-codemirror icon indicating copy to clipboard operation
react-codemirror copied to clipboard

Hide multiple lines

Open LeleDallas opened this issue 1 year ago • 9 comments

Hi 👋

I'm trying to build something like the GitHub code search

Example

image

For now I'm able to highlight words based on start and end index:

image

Code


const getDecorations = (
  highlights: Array<{ start: number; end: number }> = []
) => {
  const decorations = highlights.map(({ start, end }) =>
    Decoration.mark({
      attributes: { style: "background-color: #dadb1699" },
    }).range(start, end)
  );
  return Decoration.set(decorations);
};

export const highlightPlugin = (
  highlights: Array<{ start: number; end: number }>
) =>
  ViewPlugin.fromClass(
    class {
      decorations: DecorationSet;
      constructor() {
        this.decorations = getDecorations(highlights);
      }

      update(update: ViewUpdate) {
        if (update.docChanged || update.viewportChanged) {
          this.decorations = getDecorations();
        }
      }
    },
    {
      decorations: (v) => v.decorations,
    }
  );

const pointIsInRanges = (point: number, start: number, end: number) => point >= start && point <= end


export const foldLinesPlugin = (
  rangesToKeep: { start: number; end: number }[]
): ViewPlugin<{ decorations: DecorationSet }> => {
   return ViewPlugin.fromClass(
    class {
      decorations: DecorationSet;
      constructor(view: EditorView) {
        this.decorations = this.foldLines(view);
      }

      update(update: ViewUpdate) {
        if (update.docChanged || update.viewportChanged) {
          this.decorations = this.foldLines(update.view);
        }
      }

      foldLines(view: EditorView): DecorationSet {
        const builder = new RangeSetBuilder<Decoration>();
        const lines = view.state.doc.lines;
        for (let i = 1; i <= lines; i++) {
          const line = view.state.doc.line(i);
          let found = false;
          for (const range of rangesToKeep) {
            if (
              pointIsInRanges(range.start, line.from, line.to) ||
              pointIsInRanges(range.end, line.from, line.to)
            ) {
              found = true;
              break;
            }
          }
          if (!found) {
            builder.add(
              line.from,
              line.to,
              Decoration.replace({ widget: new FoldWidget() })
            );
          }
        }
        return builder.finish();
      }
    },
    {
      decorations: (v) => v.decorations,
    }
  );
};

class FoldWidget extends WidgetType {
  toDOM() {
    const span = document.createElement("span");
    span.style.display = "none";
    return span;
  }
}

How can I just show only the match result without all other lines and how can I keep the only the original line number?

LeleDallas avatar Sep 09 '24 08:09 LeleDallas

@LeleDallas I have an extension for changing line numbers; you can modify it to display the line numbers you want.

Example: https://uiwjs.github.io/react-codemirror/#/extensions/line-numbers-relative

https://github.com/uiwjs/react-codemirror/blob/e79b1f3b58a6c0bb0d1068a3f188ba87bafbb9c1/extensions/line-numbers-relative/src/index.ts#L4-L20

jaywcjlove avatar Sep 10 '24 14:09 jaywcjlove

Cool thanks!

But how can I remove those empty lines?

LeleDallas avatar Sep 10 '24 14:09 LeleDallas

@LeleDallas Can these be handled when passing in the text?

jaywcjlove avatar Sep 10 '24 15:09 jaywcjlove

No, because it will destroy the original line logic

LeleDallas avatar Sep 10 '24 15:09 LeleDallas

@LeleDallas I think you can look into the implementation of merge -> https://uiwjs.github.io/react-codemirror/#/merge/document

jaywcjlove avatar Sep 10 '24 18:09 jaywcjlove

I don't understand the connection... What is the connection?

LeleDallas avatar Sep 11 '24 07:09 LeleDallas

image

@LeleDallas It isn't. Are there any hidden rows?

jaywcjlove avatar Sep 11 '24 07:09 jaywcjlove

Oh you mean that! Yeah that will be cool!

But how can I fold plaintext based on my previous code?

LeleDallas avatar Sep 11 '24 07:09 LeleDallas

@jaywcjlove any suggestions?

LeleDallas avatar Sep 18 '24 07:09 LeleDallas