Browse Source

WIP cleanup and refactoring of how searches work.

Jason Grout 6 years ago
parent
commit
d33ae81088

+ 19 - 19
packages/documentsearch-extension/src/index.ts

@@ -1,12 +1,5 @@
 // Copyright (c) Jupyter Development Team.
 // Distributed under the terms of the Modified BSD License.
-import '@jupyterlab/documentsearch/style/index.css';
-
-import {
-  SearchProviderRegistry,
-  ISearchProviderRegistry
-} from '@jupyterlab/documentsearch';
-import { SearchInstance } from '@jupyterlab/documentsearch';
 
 import {
   JupyterFrontEnd,
@@ -15,9 +8,13 @@ import {
 
 import { ICommandPalette } from '@jupyterlab/apputils';
 
-import { IMainMenu } from '@jupyterlab/mainmenu';
+import {
+  ISearchProviderRegistry,
+  SearchInstance,
+  SearchProviderRegistry
+} from '@jupyterlab/documentsearch';
 
-export { ISearchProviderRegistry } from '@jupyterlab/documentsearch';
+import { IMainMenu } from '@jupyterlab/mainmenu';
 
 /**
  * Initialization data for the document-search extension.
@@ -35,9 +32,10 @@ const extension: JupyterFrontEndPlugin<ISearchProviderRegistry> = {
   ) => {
     // Create registry, retrieve all default providers
     const registry: SearchProviderRegistry = new SearchProviderRegistry();
-    const activeSearches: {
-      [key: string]: SearchInstance;
-    } = {};
+    // TODO: Should register the default providers, with an application-specific
+    // enabler.
+
+    const activeSearches = new Map<string, SearchInstance>();
 
     const startCommand: string = 'documentsearch:start';
     const nextCommand: string = 'documentsearch:highlightNext';
@@ -57,7 +55,7 @@ const extension: JupyterFrontEndPlugin<ISearchProviderRegistry> = {
           return;
         }
         const widgetId = currentWidget.id;
-        let searchInstance = activeSearches[widgetId];
+        let searchInstance = activeSearches.get(widgetId);
         if (!searchInstance) {
           const searchProvider = registry.getProviderForWidget(currentWidget);
           if (!searchProvider) {
@@ -65,12 +63,12 @@ const extension: JupyterFrontEndPlugin<ISearchProviderRegistry> = {
           }
           searchInstance = new SearchInstance(currentWidget, searchProvider);
 
-          activeSearches[widgetId] = searchInstance;
+          activeSearches.set(widgetId, searchInstance);
           // find next and previous are now enabled
           app.commands.notifyCommandChanged();
 
           searchInstance.disposed.connect(() => {
-            delete activeSearches[widgetId];
+            activeSearches.delete(widgetId);
             // find next and previous are now not enabled
             app.commands.notifyCommandChanged();
           });
@@ -86,14 +84,14 @@ const extension: JupyterFrontEndPlugin<ISearchProviderRegistry> = {
         if (!currentWidget) {
           return;
         }
-        return !!activeSearches[currentWidget.id];
+        return activeSearches.has(currentWidget.id);
       },
       execute: async () => {
         const currentWidget = app.shell.currentWidget;
         if (!currentWidget) {
           return;
         }
-        const instance = activeSearches[currentWidget.id];
+        const instance = activeSearches.get(currentWidget.id);
         if (!instance) {
           return;
         }
@@ -110,14 +108,14 @@ const extension: JupyterFrontEndPlugin<ISearchProviderRegistry> = {
         if (!currentWidget) {
           return;
         }
-        return !!activeSearches[currentWidget.id];
+        return activeSearches.has(currentWidget.id);
       },
       execute: async () => {
         const currentWidget = app.shell.currentWidget;
         if (!currentWidget) {
           return;
         }
-        const instance = activeSearches[currentWidget.id];
+        const instance = activeSearches.get(currentWidget.id);
         if (!instance) {
           return;
         }
@@ -143,6 +141,8 @@ const extension: JupyterFrontEndPlugin<ISearchProviderRegistry> = {
         10
       );
     }
+
+    // Provide the registry to the system.
     return registry;
   }
 };

+ 4 - 2
packages/documentsearch/src/index.ts

@@ -1,6 +1,8 @@
 // Copyright (c) Jupyter Development Team.
 // Distributed under the terms of the Modified BSD License.
 
-export * from './searchproviderregistry';
-export * from './searchinstance';
+import '../style/index.css';
+
 export * from './interfaces';
+export * from './searchinstance';
+export * from './searchproviderregistry';

+ 3 - 2
packages/documentsearch/src/interfaces.ts

@@ -2,6 +2,7 @@
 // Distributed under the terms of the Modified BSD License.
 
 import { ISignal } from '@phosphor/signaling';
+import { Widget } from '@phosphor/widgets';
 
 export interface IDisplayState {
   /**
@@ -81,7 +82,7 @@ export interface ISearchProviderConstructor {
   /**
    * Report whether or not this provider has the ability to search on the given object
    */
-  canSearchOn(domain: any): boolean;
+  canSearchOn(domain: Widget): boolean;
 }
 
 export interface ISearchProvider {
@@ -94,7 +95,7 @@ export interface ISearchProvider {
    *
    * @returns A promise that resolves with a list of all matches
    */
-  startQuery(query: RegExp, searchTarget: any): Promise<ISearchMatch[]>;
+  startQuery(query: RegExp, searchTarget: Widget): Promise<ISearchMatch[]>;
 
   /**
    * Clears state of a search provider to prepare for startQuery to be called

+ 37 - 9
packages/documentsearch/src/providers/codemirrorsearchprovider.ts

@@ -30,14 +30,16 @@
   THE SOFTWARE.
 */
 
-import * as CodeMirror from 'codemirror';
-
-import { ISearchProvider, ISearchMatch } from '../index';
+import { ISearchProvider, ISearchMatch } from '../interfaces';
 
+import { MainAreaWidget } from '@jupyterlab/apputils';
 import { CodeMirrorEditor } from '@jupyterlab/codemirror';
 import { CodeEditor } from '@jupyterlab/codeeditor';
-
 import { ISignal, Signal } from '@phosphor/signaling';
+import { Widget } from '@phosphor/widgets';
+
+import * as CodeMirror from 'codemirror';
+import { IDocumentWidget } from '@jupyterlab/docregistry';
 
 type MatchMap = { [key: number]: { [key: number]: ISearchMatch } };
 
@@ -51,12 +53,34 @@ export class CodeMirrorSearchProvider implements ISearchProvider {
    *
    * @returns A promise that resolves with a list of all matches
    */
-  async startQuery(query: RegExp, searchTarget: any): Promise<ISearchMatch[]> {
+  // TODO: Make the searchTarget a normal file editor, and get the codemirror
+  // out of that. TODO: change the canSearch to be a function from the
+  // registrar, so that it can interface with the system at registration time.
+  async startQuery(
+    query: RegExp,
+    searchTarget: IDocumentWidget<FileEditor>
+  ): Promise<ISearchMatch[]> {
+    // Extract the codemirror object from the editor widget
+    this._cm = searchTarget.content.editor;
+    return this._startQuery(query);
+
     if (searchTarget instanceof CodeMirrorEditor) {
       this._cm = searchTarget;
-    } else if (searchTarget) {
-      this._cm = searchTarget.content.editor;
+    } else if (searchTarget instanceof MainAreaWidget) {
+    } else {
+      throw new Error('Cannot find Codemirror instance to search');
     }
+  }
+
+  /**
+   * Initialize the search using a CodeMirrorEditor object.
+   */
+  async startQueryCodeMirror(query: RegExp, searchTarget: CodeMirrorEditor): Promise<ISearchMatch[]> {
+    this._cm = searchTarget;
+    return this._startQuery(query);
+  }
+
+  private async _startQuery(query: RegExp): Promise<ISearchMatch[]> {
     await this.endQuery();
 
     this._query = query;
@@ -138,8 +162,12 @@ export class CodeMirrorSearchProvider implements ISearchProvider {
   /**
    * Report whether or not this provider has the ability to search on the given object
    */
-  static canSearchOn(domain: any): boolean {
-    return domain.content && domain.content.editor instanceof CodeMirrorEditor;
+  static canSearchOn(domain: Widget): boolean {
+    return (
+      domain instanceof MainAreaWidget &&
+      domain.content &&
+      domain.content.editor instanceof CodeMirrorEditor
+    );
   }
 
   /**

+ 2 - 3
packages/documentsearch/src/searchinstance.ts

@@ -1,14 +1,13 @@
 // Copyright (c) Jupyter Development Team.
 // Distributed under the terms of the Modified BSD License.
 
-import { IDisplayState, ISearchProvider } from '.';
+import { IDisplayState, ISearchProvider } from './interfaces';
 import { createSearchOverlay } from './searchoverlay';
 
 import { MainAreaWidget } from '@jupyterlab/apputils';
-
-import { Widget } from '@phosphor/widgets';
 import { IDisposable } from '@phosphor/disposable';
 import { ISignal, Signal } from '@phosphor/signaling';
+import { Widget } from '@phosphor/widgets';
 
 /**
  * Represents a search on a single widget.

+ 3 - 4
packages/documentsearch/src/searchoverlay.tsx

@@ -1,13 +1,12 @@
 // Copyright (c) Jupyter Development Team.
 // Distributed under the terms of the Modified BSD License.
-import * as React from 'react';
+import { IDisplayState } from './interfaces';
+import { SearchInstance } from './searchinstance';
 
-import '../style/index.css';
 import { ReactWidget, UseSignal } from '@jupyterlab/apputils';
 import { Signal } from '@phosphor/signaling';
 import { Widget } from '@phosphor/widgets';
-import { IDisplayState } from '.';
-import { SearchInstance } from './searchinstance';
+import * as React from 'react';
 
 const OVERLAY_CLASS = 'jp-DocumentSearch-overlay';
 const INPUT_CLASS = 'jp-DocumentSearch-input';

+ 6 - 8
packages/documentsearch/src/searchproviderregistry.ts

@@ -1,13 +1,11 @@
 // Copyright (c) Jupyter Development Team.
 // Distributed under the terms of the Modified BSD License.
-import { ISearchProvider, ISearchProviderConstructor } from './index';
+import { ISearchProvider, ISearchProviderConstructor } from './interfaces';
 import { CodeMirrorSearchProvider } from './providers/codemirrorsearchprovider';
 import { NotebookSearchProvider } from './providers/notebooksearchprovider';
 
-const DEFAULT_NOTEBOOK_SEARCH_PROVIDER = 'jl-defaultNotebookSearchProvider';
-const DEFAULT_CODEMIRROR_SEARCH_PROVIDER = 'jl-defaultCodeMirrorSearchProvider';
-
 import { Token } from '@phosphor/coreutils';
+import { Widget } from '@phosphor/widgets';
 
 /* tslint:disable */
 /**
@@ -46,11 +44,11 @@ export interface ISearchProviderRegistry {
 export class SearchProviderRegistry implements ISearchProviderRegistry {
   constructor() {
     this._registerDefaultProviders(
-      DEFAULT_NOTEBOOK_SEARCH_PROVIDER,
+      'jl-defaultNotebookSearchProvider',
       NotebookSearchProvider
     );
     this._registerDefaultProviders(
-      DEFAULT_CODEMIRROR_SEARCH_PROVIDER,
+      'jl-defaultCodeMirrorSearchProvider',
       CodeMirrorSearchProvider
     );
   }
@@ -80,7 +78,7 @@ export class SearchProviderRegistry implements ISearchProviderRegistry {
    * @param widget - The widget to search over.
    * @returns the search provider, or undefined if none exists.
    */
-  getProviderForWidget(widget: any): ISearchProvider | undefined {
+  getProviderForWidget(widget: Widget): ISearchProvider | undefined {
     return (
       this._findMatchingProvider(this._customProviders, widget) ||
       this._findMatchingProvider(this._defaultProviders, widget)
@@ -96,7 +94,7 @@ export class SearchProviderRegistry implements ISearchProviderRegistry {
 
   private _findMatchingProvider(
     providerMap: Private.ProviderMap,
-    widget: any
+    widget: Widget
   ): ISearchProvider | undefined {
     // iterate through all providers and ask each one if it can search on the
     // widget.