Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hide multiple lines #684

Open
LeleDallas opened this issue Sep 9, 2024 · 9 comments
Open

Hide multiple lines #684

LeleDallas opened this issue Sep 9, 2024 · 9 comments

Comments

@LeleDallas
Copy link

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?

@jaywcjlove
Copy link
Member

@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

function formatNumber() {
return lineNumbers({
formatNumber: (lineNo, state) => {
if (lineNo > state.doc.lines) {
return '0';
}
const cursorLine = state.doc.lineAt(state.selection.asSingle().ranges[0].to).number;
if (lineNo === cursorLine) {
return '0';
} else {
return Math.abs(cursorLine - lineNo).toString();
}
},
});
}
export const lineNumbersRelative: Extension = [formatNumber()];

@LeleDallas
Copy link
Author

Cool thanks!

But how can I remove those empty lines?

@jaywcjlove
Copy link
Member

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

@LeleDallas
Copy link
Author

No, because it will destroy the original line logic

@jaywcjlove
Copy link
Member

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

@LeleDallas
Copy link
Author

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

@jaywcjlove
Copy link
Member

image

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

@LeleDallas
Copy link
Author

LeleDallas commented Sep 11, 2024

Oh you mean that! Yeah that will be cool!

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

@LeleDallas
Copy link
Author

@jaywcjlove any suggestions?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants