├── .copier-answers.yml ├── .github └── workflows │ ├── binder-on-pr.yml │ ├── build.yml │ ├── check-release.yml │ ├── enforce-label.yml │ ├── prep-release.yml │ └── publish-release.yml ├── .gitignore ├── .prettierignore ├── .yarnrc.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── RELEASE.md ├── binder ├── apt.txt ├── environment.yml ├── postBuild └── tutorial.ipynb ├── doc └── settings.png ├── install.json ├── jupyter-config └── server-config │ └── jupyterlab_quickopen.json ├── jupyterlab_quickopen ├── __init__.py └── handler.py ├── package.json ├── pyproject.toml ├── schema └── plugin.json ├── setup.py ├── src ├── handler.ts └── index.ts ├── style ├── base.css ├── index.css └── index.js ├── tsconfig.json └── yarn.lock /.copier-answers.yml: -------------------------------------------------------------------------------- 1 | # Changes here will be overwritten by Copier; NEVER EDIT MANUALLY 2 | _commit: v4.3.5 3 | _src_path: https://github.com/jupyterlab/extension-template 4 | author_email: parente@gmail.com 5 | author_name: Peter Parente 6 | has_binder: true 7 | has_settings: true 8 | kind: server 9 | labextension_name: 'jupyterlab-quickopen' 10 | project_short_description: Quickly open a file in JupyterLab by part of its name 11 | python_name: jupyterlab_quickopen 12 | repository: https://github.com/jupyterlab-contrib/jupyterlab-quickopen.git 13 | test: false 14 | 15 | -------------------------------------------------------------------------------- /.github/workflows/binder-on-pr.yml: -------------------------------------------------------------------------------- 1 | name: Binder Badge 2 | on: 3 | pull_request_target: 4 | types: [opened] 5 | 6 | jobs: 7 | binder: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | pull-requests: write 11 | steps: 12 | - uses: jupyterlab/maintainer-tools/.github/actions/binder-link@v1 13 | with: 14 | github_token: ${{ secrets.GITHUB_TOKEN }} 15 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: main 6 | pull_request: 7 | branches: '*' 8 | 9 | concurrency: 10 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v4 20 | 21 | - name: Base Setup 22 | uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 23 | 24 | - name: Install dependencies 25 | run: python -m pip install -U "jupyterlab>=4.0.0,<5" 26 | 27 | - name: Lint the extension 28 | run: | 29 | set -eux 30 | jlpm 31 | jlpm run lint:check 32 | 33 | - name: Build the extension 34 | run: | 35 | set -eux 36 | python -m pip install . -vv 37 | 38 | jupyter server extension list 39 | jupyter server extension list 2>&1 | grep -ie "jupyterlab_quickopen.*OK" 40 | 41 | jupyter labextension list 42 | jupyter labextension list 2>&1 | grep -ie "jupyterlab-quickopen.*OK" 43 | python -m jupyterlab.browser_check 44 | 45 | - name: Package the extension 46 | run: | 47 | set -eux 48 | 49 | pip install build 50 | python -m build 51 | pip uninstall -y "jupyterlab_quickopen" jupyterlab 52 | 53 | - name: Upload extension packages 54 | uses: actions/upload-artifact@v4 55 | with: 56 | name: extension-artifacts 57 | path: dist/jupyterlab_quickopen* 58 | if-no-files-found: error 59 | 60 | test_isolated: 61 | needs: build 62 | runs-on: ubuntu-latest 63 | 64 | steps: 65 | - name: Install Python 66 | uses: actions/setup-python@v5 67 | with: 68 | python-version: '3.9' 69 | architecture: 'x64' 70 | - uses: actions/download-artifact@v4 71 | with: 72 | name: extension-artifacts 73 | - name: Install and Test 74 | run: | 75 | set -eux 76 | # Remove NodeJS, twice to take care of system and locally installed node versions. 77 | sudo rm -rf $(which node) 78 | sudo rm -rf $(which node) 79 | 80 | pip install "jupyterlab>=4.0.0,<5" jupyterlab_quickopen*.whl 81 | 82 | 83 | jupyter server extension list 84 | jupyter server extension list 2>&1 | grep -ie "jupyterlab_quickopen.*OK" 85 | 86 | jupyter labextension list 87 | jupyter labextension list 2>&1 | grep -ie "jupyterlab-quickopen.*OK" 88 | python -m jupyterlab.browser_check --no-browser-test 89 | 90 | 91 | check_links: 92 | name: Check Links 93 | runs-on: ubuntu-latest 94 | timeout-minutes: 15 95 | steps: 96 | - uses: actions/checkout@v4 97 | - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 98 | - uses: jupyterlab/maintainer-tools/.github/actions/check-links@v1 99 | with: 100 | ignore_links: https://mybinder.org/* 101 | -------------------------------------------------------------------------------- /.github/workflows/check-release.yml: -------------------------------------------------------------------------------- 1 | name: Check Release 2 | on: 3 | push: 4 | branches: ["main"] 5 | pull_request: 6 | branches: ["*"] 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | check_release: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Base Setup 19 | uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 20 | - name: Check Release 21 | uses: jupyter-server/jupyter_releaser/.github/actions/check-release@v2 22 | with: 23 | token: ${{ secrets.GITHUB_TOKEN }} 24 | 25 | - name: Upload Distributions 26 | uses: actions/upload-artifact@v4 27 | with: 28 | name: jupyterlab-quickopen-releaser-dist-${{ github.run_number }} 29 | path: .jupyter_releaser_checkout/dist 30 | -------------------------------------------------------------------------------- /.github/workflows/enforce-label.yml: -------------------------------------------------------------------------------- 1 | name: Enforce PR label 2 | 3 | on: 4 | pull_request: 5 | types: [labeled, unlabeled, opened, edited, synchronize] 6 | jobs: 7 | enforce-label: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | pull-requests: write 11 | steps: 12 | - name: enforce-triage-label 13 | uses: jupyterlab/maintainer-tools/.github/actions/enforce-label@v1 14 | -------------------------------------------------------------------------------- /.github/workflows/prep-release.yml: -------------------------------------------------------------------------------- 1 | name: "Step 1: Prep Release" 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | version_spec: 6 | description: "New Version Specifier" 7 | default: "next" 8 | required: false 9 | branch: 10 | description: "The branch to target" 11 | required: false 12 | post_version_spec: 13 | description: "Post Version Specifier" 14 | required: false 15 | # silent: 16 | # description: "Set a placeholder in the changelog and don't publish the release." 17 | # required: false 18 | # type: boolean 19 | since: 20 | description: "Use PRs with activity since this date or git reference" 21 | required: false 22 | since_last_stable: 23 | description: "Use PRs with activity since the last stable git tag" 24 | required: false 25 | type: boolean 26 | jobs: 27 | prep_release: 28 | runs-on: ubuntu-latest 29 | permissions: 30 | contents: write 31 | steps: 32 | - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 33 | 34 | - name: Prep Release 35 | id: prep-release 36 | uses: jupyter-server/jupyter_releaser/.github/actions/prep-release@v2 37 | with: 38 | token: ${{ secrets.GITHUB_TOKEN }} 39 | version_spec: ${{ github.event.inputs.version_spec }} 40 | # silent: ${{ github.event.inputs.silent }} 41 | post_version_spec: ${{ github.event.inputs.post_version_spec }} 42 | branch: ${{ github.event.inputs.branch }} 43 | since: ${{ github.event.inputs.since }} 44 | since_last_stable: ${{ github.event.inputs.since_last_stable }} 45 | 46 | - name: "** Next Step **" 47 | run: | 48 | echo "Optional): Review Draft Release: ${{ steps.prep-release.outputs.release_url }}" 49 | -------------------------------------------------------------------------------- /.github/workflows/publish-release.yml: -------------------------------------------------------------------------------- 1 | name: "Step 2: Publish Release" 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | branch: 6 | description: "The target branch" 7 | required: false 8 | release_url: 9 | description: "The URL of the draft GitHub release" 10 | required: false 11 | steps_to_skip: 12 | description: "Comma separated list of steps to skip" 13 | required: false 14 | 15 | jobs: 16 | publish_release: 17 | runs-on: ubuntu-latest 18 | environment: release 19 | permissions: 20 | id-token: write 21 | steps: 22 | - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 23 | 24 | - uses: actions/create-github-app-token@v1 25 | id: app-token 26 | with: 27 | app-id: ${{ vars.APP_ID }} 28 | private-key: ${{ secrets.APP_PRIVATE_KEY }} 29 | 30 | - name: Populate Release 31 | id: populate-release 32 | uses: jupyter-server/jupyter_releaser/.github/actions/populate-release@v2 33 | with: 34 | token: ${{ steps.app-token.outputs.token }} 35 | branch: ${{ github.event.inputs.branch }} 36 | release_url: ${{ github.event.inputs.release_url }} 37 | steps_to_skip: ${{ github.event.inputs.steps_to_skip }} 38 | 39 | - name: Finalize Release 40 | id: finalize-release 41 | env: 42 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 43 | uses: jupyter-server/jupyter_releaser/.github/actions/finalize-release@v2 44 | with: 45 | token: ${{ steps.app-token.outputs.token }} 46 | release_url: ${{ steps.populate-release.outputs.release_url }} 47 | 48 | - name: "** Next Step **" 49 | if: ${{ success() }} 50 | run: | 51 | echo "Verify the final release" 52 | echo ${{ steps.finalize-release.outputs.release_url }} 53 | 54 | - name: "** Failure Message **" 55 | if: ${{ failure() }} 56 | run: | 57 | echo "Failed to Publish the Draft Release Url:" 58 | echo ${{ steps.populate-release.outputs.release_url }} 59 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.bundle.* 2 | lib/ 3 | node_modules/ 4 | *.log 5 | .eslintcache 6 | .stylelintcache 7 | *.egg-info/ 8 | .ipynb_checkpoints 9 | *.tsbuildinfo 10 | jupyterlab_quickopen/labextension 11 | # Version file is handled by hatchling 12 | jupyterlab_quickopen/_version.py 13 | 14 | # Created by https://www.gitignore.io/api/python 15 | # Edit at https://www.gitignore.io/?templates=python 16 | 17 | ### Python ### 18 | # Byte-compiled / optimized / DLL files 19 | __pycache__/ 20 | *.py[cod] 21 | *$py.class 22 | 23 | # C extensions 24 | *.so 25 | 26 | # Distribution / packaging 27 | .Python 28 | build/ 29 | develop-eggs/ 30 | dist/ 31 | downloads/ 32 | eggs/ 33 | .eggs/ 34 | lib/ 35 | lib64/ 36 | parts/ 37 | sdist/ 38 | var/ 39 | wheels/ 40 | pip-wheel-metadata/ 41 | share/python-wheels/ 42 | .installed.cfg 43 | *.egg 44 | MANIFEST 45 | 46 | # PyInstaller 47 | # Usually these files are written by a python script from a template 48 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 49 | *.manifest 50 | *.spec 51 | 52 | # Installer logs 53 | pip-log.txt 54 | pip-delete-this-directory.txt 55 | 56 | # Unit test / coverage reports 57 | htmlcov/ 58 | .tox/ 59 | .nox/ 60 | .coverage 61 | .coverage.* 62 | .cache 63 | nosetests.xml 64 | coverage/ 65 | coverage.xml 66 | *.cover 67 | .hypothesis/ 68 | .pytest_cache/ 69 | 70 | # Translations 71 | *.mo 72 | *.pot 73 | 74 | # Scrapy stuff: 75 | .scrapy 76 | 77 | # Sphinx documentation 78 | docs/_build/ 79 | 80 | # PyBuilder 81 | target/ 82 | 83 | # pyenv 84 | .python-version 85 | 86 | # celery beat schedule file 87 | celerybeat-schedule 88 | 89 | # SageMath parsed files 90 | *.sage.py 91 | 92 | # Spyder project settings 93 | .spyderproject 94 | .spyproject 95 | 96 | # Rope project settings 97 | .ropeproject 98 | 99 | # Mr Developer 100 | .mr.developer.cfg 101 | .project 102 | .pydevproject 103 | 104 | # mkdocs documentation 105 | /site 106 | 107 | # mypy 108 | .mypy_cache/ 109 | .dmypy.json 110 | dmypy.json 111 | 112 | # Pyre type checker 113 | .pyre/ 114 | 115 | # End of https://www.gitignore.io/api/python 116 | 117 | # OSX files 118 | .DS_Store 119 | 120 | # Yarn cache 121 | .yarn/ 122 | 123 | # JupyterLab upgrade script 124 | _temp_extension -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | **/node_modules 3 | **/lib 4 | **/package.json 5 | !/package.json 6 | jupyterlab_quickopen 7 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | 4 | 5 | ## 2.0.2 6 | 7 | ([Full Changelog](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/compare/v2.0.1...3c730b09842fa5fcc3245890ab96d681d1855047)) 8 | 9 | ### Bugs fixed 10 | 11 | - Use a relative path because a path cannot start with a drive letter [#65](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/65) ([@yjoer](https://github.com/yjoer)) 12 | 13 | ### Contributors to this release 14 | 15 | ([GitHub contributors page for this release](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/graphs/contributors?from=2024-10-09&to=2024-10-21&type=c)) 16 | 17 | [@yjoer](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Ayjoer+updated%3A2024-10-09..2024-10-21&type=Issues) 18 | 19 | 20 | 21 | ## 2.0.1 22 | 23 | ([Full Changelog](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/compare/v2.0.0...367d06e09d546089dfe6ea168ba7ccc91f51fcd1)) 24 | 25 | ### Bugs fixed 26 | 27 | - Ensure compatibility with both sync and async contents managers [#62](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/62) ([@yjoer](https://github.com/yjoer)) 28 | 29 | ### Documentation improvements 30 | 31 | - Add `conda-forge` install to the README [#64](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/64) ([@jtpio](https://github.com/jtpio)) 32 | - add apt.text with wamerican to add /usr/share/dict/words [#60](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/60) ([@fomightez](https://github.com/fomightez)) 33 | - Add ready badge to the README [#59](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/59) ([@jtpio](https://github.com/jtpio)) 34 | 35 | ### Contributors to this release 36 | 37 | ([GitHub contributors page for this release](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/graphs/contributors?from=2024-09-30&to=2024-10-09&type=c)) 38 | 39 | [@fomightez](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Afomightez+updated%3A2024-09-30..2024-10-09&type=Issues) | [@github-actions](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Agithub-actions+updated%3A2024-09-30..2024-10-09&type=Issues) | [@jtpio](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Ajtpio+updated%3A2024-09-30..2024-10-09&type=Issues) | [@yjoer](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Ayjoer+updated%3A2024-09-30..2024-10-09&type=Issues) 40 | 41 | ## 2.0.0 42 | 43 | ([Full Changelog](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/compare/1.2.0...ec87ceb2cb87900d45db06f265c8ce7034caa876)) 44 | 45 | ### :sparkles: Highlights :sparkles: 46 | 47 | This version adds support for JupyterLab 4. 48 | 49 | It also changes the Quick Open widget to be a modal widget instead of being located in the left area, for consistency with the command palette: 50 | 51 | ![the quick open widget in JupyterLab](https://github.com/user-attachments/assets/c158ecad-c2ed-4138-af82-80cc5b04a3d9) 52 | 53 | The shortcut to open the Quick Open widget is Accel Ctrl P. It can also be opened via the `View > Quick Open` menu: 54 | 55 | ![how to open the quick open widget via the view menu](https://github.com/user-attachments/assets/971d3bf8-ed9f-4bca-b1e8-7a38a99da37f) 56 | 57 | ### Enhancements made 58 | 59 | - Update to JupyterLab 4 [#48](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/48) ([@jtpio](https://github.com/jtpio)) 60 | - Add to the menu [#57](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/57) ([@jtpio](https://github.com/jtpio)) 61 | 62 | ### Maintenance and upkeep improvements 63 | 64 | - More cleanups [#55](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/55) ([@jtpio](https://github.com/jtpio)) 65 | - Cleanups [#54](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/54) ([@jtpio](https://github.com/jtpio)) 66 | 67 | ### Documentation improvements 68 | 69 | - Populate changelog with previous releases [#56](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/56) ([@jtpio](https://github.com/jtpio)) 70 | - Fix link to Binder [#53](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/53) ([@jtpio](https://github.com/jtpio)) 71 | - Add screencasts to the README [#51](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/51) ([@jtpio](https://github.com/jtpio)) 72 | 73 | ### Contributors to this release 74 | 75 | ([GitHub contributors page for this release](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/graphs/contributors?from=2021-12-12&to=2024-09-30&type=c)) 76 | 77 | [@github-actions](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Agithub-actions+updated%3A2021-12-12..2024-09-30&type=Issues) | [@jtpio](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Ajtpio+updated%3A2021-12-12..2024-09-30&type=Issues) 78 | 79 | ## 1.2.0 80 | 81 | ([full changelog](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/compare/311f367...dd12b63)) 82 | 83 | ### Merged PRs 84 | 85 | - Update for JupyterLab 3.1.x, latest cookiecutter [#29](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/29) ([@parente](https://github.com/parente)) 86 | 87 | ### Contributors to this release 88 | 89 | ([GitHub contributors page for this release](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/graphs/contributors?from=2021-08-14&to=2021-12-12&type=c)) 90 | 91 | [@parente](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Aparente+updated%3A2021-08-14..2021-12-12&type=Issues) 92 | 93 | ## 1.1.0 94 | 95 | ([full changelog](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/compare/65a2eac...311f367)) 96 | 97 | ### Merged PRs 98 | 99 | - Update for JupyterLab 3.1.x, latest cookiecutter [#29](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/29) ([@parente](https://github.com/parente)) 100 | - Bump path-parse from 1.0.6 to 1.0.7 [#28](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/28) ([@dependabot](https://github.com/dependabot)) 101 | - Bump tar from 6.0.5 to 6.1.5 [#27](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/27) ([@dependabot](https://github.com/dependabot)) 102 | - Bump postcss from 7.0.35 to 7.0.36 [#26](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/26) ([@dependabot](https://github.com/dependabot)) 103 | - Bump glob-parent from 5.1.1 to 5.1.2 [#25](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/25) ([@dependabot](https://github.com/dependabot)) 104 | - Bump normalize-url from 4.5.0 to 4.5.1 [#24](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/24) ([@dependabot](https://github.com/dependabot)) 105 | - Bump ws from 7.4.2 to 7.4.6 [#23](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/23) ([@dependabot](https://github.com/dependabot)) 106 | - Bump browserslist from 4.16.0 to 4.16.6 [#22](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/22) ([@dependabot](https://github.com/dependabot)) 107 | - Bump lodash from 4.17.20 to 4.17.21 [#21](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/21) ([@dependabot](https://github.com/dependabot)) 108 | - Bump hosted-git-info from 2.8.8 to 2.8.9 [#20](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/20) ([@dependabot](https://github.com/dependabot)) 109 | - Bump ssri from 8.0.0 to 8.0.1 [#19](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/19) ([@dependabot](https://github.com/dependabot)) 110 | - Update binder to use jupyter_server [#18](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/18) ([@parente](https://github.com/parente)) 111 | - Update extension to work with jupyterlab 3.0 [#17](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/17) ([@parente](https://github.com/parente)) 112 | 113 | ### Contributors to this release 114 | 115 | ([GitHub contributors page for this release](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/graphs/contributors?from=2020-12-31&to=2021-08-14&type=c)) 116 | 117 | [@dependabot](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Adependabot+updated%3A2020-12-31..2021-08-14&type=Issues) | [@parente](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Aparente+updated%3A2020-12-31..2021-08-14&type=Issues) 118 | 119 | ## 1.0.0 120 | 121 | ([full changelog](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/compare/eb04bd1...65a2eac)) 122 | 123 | ### Merged PRs 124 | 125 | - Bump node-fetch from 2.6.0 to 2.6.1 [#15](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/15) ([@dependabot](https://github.com/dependabot)) 126 | 127 | ### Contributors to this release 128 | 129 | ([GitHub contributors page for this release](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/graphs/contributors?from=2020-03-20&to=2020-12-31&type=c)) 130 | 131 | [@dependabot](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Adependabot+updated%3A2020-03-20..2020-12-31&type=Issues) | [@parente](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Aparente+updated%3A2020-03-20..2020-12-31&type=Issues) 132 | 133 | ## 0.5.0 134 | 135 | ([full changelog](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/compare/ca55830...eb04bd1)) 136 | 137 | ### Merged PRs 138 | 139 | - Jupyter 2.0.1 support [#13](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/13) ([@itaistopel](https://github.com/itaistopel)) 140 | 141 | ### Contributors to this release 142 | 143 | ([GitHub contributors page for this release](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/graphs/contributors?from=2020-03-07&to=2020-03-20&type=c)) 144 | 145 | [@itaistopel](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Aitaistopel+updated%3A2020-03-07..2020-03-20&type=Issues) | [@parente](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Aparente+updated%3A2020-03-07..2020-03-20&type=Issues) 146 | 147 | ## 0.4.1 148 | 149 | ([full changelog](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/compare/6a1e07a...ca55830)) 150 | 151 | ### Contributors to this release 152 | 153 | ([GitHub contributors page for this release](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/graphs/contributors?from=2020-03-07&to=2020-03-07&type=c)) 154 | 155 | ## 0.4.0 156 | 157 | ([full changelog](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/compare/f7c11a3...6a1e07a)) 158 | 159 | ### Contributors to this release 160 | 161 | ([GitHub contributors page for this release](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/graphs/contributors?from=2019-07-28&to=2020-03-07&type=c)) 162 | 163 | ## 0.3.0 164 | 165 | ([full changelog](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/compare/e23408a...f7c11a3)) 166 | 167 | ### Merged PRs 168 | 169 | - Added relativeSearch functionality [#6](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/6) ([@StevenLaan](https://github.com/StevenLaan)) 170 | - Support JupyterLab 1.0 [#5](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/5) ([@parente](https://github.com/parente)) 171 | 172 | ### Contributors to this release 173 | 174 | ([GitHub contributors page for this release](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/graphs/contributors?from=2019-06-30&to=2019-07-28&type=c)) 175 | 176 | [@parente](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Aparente+updated%3A2019-06-30..2019-07-28&type=Issues) | [@StevenLaan](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3AStevenLaan+updated%3A2019-06-30..2019-07-28&type=Issues) 177 | 178 | ## 0.2.0 179 | 180 | ([full changelog](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/compare/79a935a...e23408a)) 181 | 182 | ### Merged PRs 183 | 184 | - Add binder button and tutorial nb [#1](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/pull/1) ([@parente](https://github.com/parente)) 185 | 186 | ### Contributors to this release 187 | 188 | ([GitHub contributors page for this release](https://github.com/jupyterlab-contrib/jupyterlab-quickopen/graphs/contributors?from=2018-12-04&to=2019-06-30&type=c)) 189 | 190 | [@parente](https://github.com/search?q=repo%3Ajupyterlab-contrib%2Fjupyterlab-quickopen+involves%3Aparente+updated%3A2018-12-04..2019-06-30&type=Issues) 191 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, 2020 Peter Parente 2 | Copyright (c) JupyterLab Contrib Team 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 23 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jupyterlab-quickopen 2 | 3 | [![Extension status](https://img.shields.io/badge/status-ready-success 'ready to be used')](https://jupyterlab-contrib.github.io/) 4 | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/jupyterlab-contrib/jupyterlab-quickopen/main?urlpath=lab%2Ftree%2Fbinder%2Ftutorial.ipynb) 5 | 6 | Quickly open a file in JupyterLab by typing part of its name 7 | 8 | https://github.com/user-attachments/assets/77567c89-ad52-4be8-b0e4-612700353242 9 | 10 | ## Compatibility 11 | 12 | - Python >=3.8.x 13 | - [JupyterLab](https://github.com/jupyterlab/jupyterlab) >=3.2 14 | - [Jupyter Server](https://github.com/jupyter/jupyter_server) >=2.4 15 | - Configurations where notebook documents and other files reside on a filesystem local to the 16 | Jupyter Server (which is the the default), not remote storage (e.g., S3) 17 | 18 | ## Usage 19 | 20 | After installing the extension, you can open the quick open panel by pressing `Ctrl Shift P` (or `Cmd P` on macOS). Start typing the name of the file you want to open, and the quick open panel will show a list of files that match the text you've typed. 21 | 22 | https://github.com/user-attachments/assets/77567c89-ad52-4be8-b0e4-612700353242 23 | 24 | The extension also works in Jupyter Notebook 7: 25 | 26 | https://github.com/user-attachments/assets/49147847-2b98-4016-8a11-5d0e8d9749e1 27 | 28 | ## Install 29 | 30 | To install the extension with `pip`: 31 | 32 | ```bash 33 | pip install jupyterlab-quickopen 34 | ``` 35 | 36 | With `conda` / `mamba`: 37 | 38 | ```bash 39 | conda install -c conda-forge jupyterlab-quickopen 40 | ``` 41 | 42 | ## Configure 43 | 44 | ### Using a custom Keyboard Shortcut 45 | 46 | The default keyboard shortcut for opening the quickopen panel is `Accel Ctrl P`. 47 | 48 | You can assign your own keyboard shortcut to show the quickopen panel at any time. Open the keyboard editor 49 | by clicking _Settings → Advanced Settings Editor → Keyboard Shortcuts_. Then enter JSON in 50 | the _User Overrides_ text area like the following, adjusting the `keys` value to assign the shortcut 51 | of your choosing: 52 | 53 | ```json 54 | { 55 | "shortcuts": [ 56 | { 57 | "command": "quickopen:activate", 58 | "keys": ["Accel Ctrl P"], 59 | "selector": "body", 60 | "title": "Activate Quick Open", 61 | "category": "Main Area" 62 | } 63 | ] 64 | } 65 | ``` 66 | 67 | ### Patterns to Exclude 68 | 69 | You can control which files to exclude from the quick open list using the Jupyter Server settings, 70 | JupyterLab settings, or both. 71 | 72 | On the server side, use the `ContentsManager.allow_hidden` and/or `ContentsManager.hide_globs` 73 | settings. See the 74 | [documentation about Jupyter Server options](https://jupyter-server.readthedocs.io/en/latest/operators/configuring-extensions.html) 75 | for details. 76 | 77 | In the JupyterLab web app, open the _Settings_ menu, click the _Advanced Settings Editor_ option, 78 | select the _Quick Open_ item in the _Raw View_ sidebar, and enter JSON in the _User Overrides_ text 79 | area to override the default values. 80 | 81 | ![Screenshot of the quick open settings editor](./doc/settings.png) 82 | 83 | ### Development install 84 | 85 | Note: You will need NodeJS to build the extension package. 86 | 87 | The `jlpm` command is JupyterLab's pinned version of 88 | [yarn](https://yarnpkg.com/) that is installed with JupyterLab. You may use 89 | `yarn` or `npm` in lieu of `jlpm` below. 90 | 91 | ```bash 92 | # Clone the repo to your local environment 93 | # Change directory to the jupyterlab_quickopen directory 94 | # Install package in development mode 95 | pip install -e . 96 | # Link your development version of the extension with JupyterLab 97 | jupyter labextension develop . --overwrite 98 | # Server extension must be manually installed in develop mode 99 | jupyter server extension enable jupyterlab_quickopen 100 | # Rebuild extension Typescript source after making changes 101 | jlpm build 102 | ``` 103 | 104 | You can watch the source directory and run JupyterLab at the same time in different terminals to watch for changes in the extension's source and automatically rebuild the extension. 105 | 106 | ```bash 107 | # Watch the source directory in one terminal, automatically rebuilding when needed 108 | jlpm watch 109 | # Run JupyterLab in another terminal 110 | jupyter lab 111 | ``` 112 | 113 | With the watch command running, every saved change will immediately be built locally and available in your running JupyterLab. Refresh JupyterLab to load the change in your browser (you may need to wait several seconds for the extension to be rebuilt). 114 | 115 | By default, the `jlpm build` command generates the source maps for this extension to make it easier to debug using the browser dev tools. To also generate source maps for the JupyterLab core extensions, you can run the following command: 116 | 117 | ```bash 118 | jupyter lab build --minimize=False 119 | ``` 120 | 121 | ### Releasing 122 | 123 | See [RELEASE](RELEASE.md) 124 | 125 | ### Acknowledgements 126 | 127 | This extension was originally created by [Peter Parente](https://github.com/parente) and was 128 | later moved to the `jupyterlab-contrib` GitHub organization. 129 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # Making a new release of jupyterlab_quickopen 2 | 3 | The extension can be published to `PyPI` and `npm` manually or using the [Jupyter Releaser](https://github.com/jupyter-server/jupyter_releaser). 4 | 5 | ## Manual release 6 | 7 | ### Python package 8 | 9 | This extension can be distributed as Python packages. All of the Python 10 | packaging instructions are in the `pyproject.toml` file to wrap your extension in a 11 | Python package. Before generating a package, you first need to install some tools: 12 | 13 | ```bash 14 | pip install build twine hatch 15 | ``` 16 | 17 | Bump the version using `hatch`. By default this will create a tag. 18 | See the docs on [hatch-nodejs-version](https://github.com/agoose77/hatch-nodejs-version#semver) for details. 19 | 20 | ```bash 21 | hatch version 22 | ``` 23 | 24 | Make sure to clean up all the development files before building the package: 25 | 26 | ```bash 27 | jlpm clean:all 28 | ``` 29 | 30 | You could also clean up the local git repository: 31 | 32 | ```bash 33 | git clean -dfX 34 | ``` 35 | 36 | To create a Python source package (`.tar.gz`) and the binary package (`.whl`) in the `dist/` directory, do: 37 | 38 | ```bash 39 | python -m build 40 | ``` 41 | 42 | > `python setup.py sdist bdist_wheel` is deprecated and will not work for this package. 43 | 44 | Then to upload the package to PyPI, do: 45 | 46 | ```bash 47 | twine upload dist/* 48 | ``` 49 | 50 | ### NPM package 51 | 52 | To publish the frontend part of the extension as a NPM package, do: 53 | 54 | ```bash 55 | npm login 56 | npm publish --access public 57 | ``` 58 | 59 | ## Automated releases with the Jupyter Releaser 60 | 61 | The extension repository should already be compatible with the Jupyter Releaser. But 62 | the GitHub repository and the package managers need to be properly set up. Please 63 | follow the instructions of the Jupyter Releaser [checklist](https://jupyter-releaser.readthedocs.io/en/latest/how_to_guides/convert_repo_from_repo.html). 64 | 65 | Here is a summary of the steps to cut a new release: 66 | 67 | - Go to the Actions panel 68 | - Run the "Step 1: Prep Release" workflow 69 | - Check the draft changelog 70 | - Run the "Step 2: Publish Release" workflow 71 | 72 | > [!NOTE] 73 | > Check out the [workflow documentation](https://jupyter-releaser.readthedocs.io/en/latest/get_started/making_release_from_repo.html) 74 | > for more information. 75 | 76 | ## Publishing to `conda-forge` 77 | 78 | If the package is not on conda forge yet, check the documentation to learn how to add it: https://conda-forge.org/docs/maintainer/adding_pkgs.html 79 | 80 | Otherwise a bot should pick up the new version publish to PyPI, and open a new PR on the feedstock repository automatically. 81 | -------------------------------------------------------------------------------- /binder/apt.txt: -------------------------------------------------------------------------------- 1 | wamerican -------------------------------------------------------------------------------- /binder/environment.yml: -------------------------------------------------------------------------------- 1 | # a mybinder.org-ready environment for demoing jupyterlab_quickopen 2 | # this environment may also be used locally on Linux/MacOS/Windows, e.g. 3 | # 4 | # conda env update --file binder/environment.yml 5 | # conda activate jupyterlab-quickopen-demo 6 | # 7 | name: jupyterlab-quickopen-demo 8 | 9 | channels: 10 | - conda-forge 11 | 12 | dependencies: 13 | # runtime dependencies 14 | - python >=3.10,<3.11.0a0 15 | - jupyterlab >=4.0.0,<5 16 | # labextension build dependencies 17 | - nodejs >=18,<19 18 | - pip 19 | - wheel 20 | # additional packages for demos 21 | # - ipywidgets 22 | -------------------------------------------------------------------------------- /binder/postBuild: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ perform a development install of jupyterlab_quickopen 3 | 4 | On Binder, this will run _after_ the environment has been fully created from 5 | the environment.yml in this directory. 6 | 7 | This script should also run locally on Linux/MacOS/Windows: 8 | 9 | python3 binder/postBuild 10 | """ 11 | import subprocess 12 | import sys 13 | from pathlib import Path 14 | 15 | 16 | ROOT = Path.cwd() 17 | 18 | def _(*args, **kwargs): 19 | """ Run a command, echoing the args 20 | 21 | fails hard if something goes wrong 22 | """ 23 | print("\n\t", " ".join(args), "\n") 24 | return_code = subprocess.call(args, **kwargs) 25 | if return_code != 0: 26 | print("\nERROR", return_code, " ".join(args)) 27 | sys.exit(return_code) 28 | 29 | # verify the environment is self-consistent before even starting 30 | _(sys.executable, "-m", "pip", "check") 31 | 32 | # install the labextension 33 | _(sys.executable, "-m", "pip", "install", "-e", ".") 34 | _(sys.executable, "-m", "jupyter", "labextension", "develop", "--overwrite", ".") 35 | _( 36 | sys.executable, 37 | "-m", 38 | "jupyter", 39 | "server", 40 | "extension", 41 | "enable", 42 | "jupyterlab_quickopen", 43 | ) 44 | 45 | # verify the environment the extension didn't break anything 46 | _(sys.executable, "-m", "pip", "check") 47 | 48 | # list the extensions 49 | _("jupyter", "server", "extension", "list") 50 | 51 | # initially list installed extensions to determine if there are any surprises 52 | _("jupyter", "labextension", "list") 53 | 54 | 55 | print("JupyterLab with jupyterlab_quickopen is ready to run with:\n") 56 | print("\tjupyter lab\n") 57 | -------------------------------------------------------------------------------- /binder/tutorial.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Tutorial: jupyterlab-quickopen\n", 8 | "\n", 9 | "This notebook is a short, hands-on tutorial about using the JupyterLab quick open extension.\n", 10 | "\n", 11 | "First, assign a hotkey to the extension so you don't have to click the little magnifying glass in the sidebar every time you want to search.\n", 12 | "\n", 13 | "1. Click the *Settings* menu then → *Advanced Settings Editor*.\n", 14 | "2. Select *Keyboard Shortcuts* in the dialog that opens.\n", 15 | "3. Add the following to the JSON in the right panel to assign `Ctrl-Cmd-P` as the hotkey on Mac and `Ctrl-Alt-P` on Windows/Linux.\n", 16 | "\n", 17 | "```\n", 18 | "{\n", 19 | " \"shortcuts\": [\n", 20 | " {\n", 21 | " \"command\": \"quickopen:activate\",\n", 22 | " \"keys\": [\n", 23 | " \"Accel Ctrl P\"\n", 24 | " ],\n", 25 | " \"selector\": \"body\",\n", 26 | " \"title\": \"Activate Quick Open\",\n", 27 | " \"category\": \"Main Area\"\n", 28 | " }\n", 29 | " ]\n", 30 | "}\n", 31 | "```\n", 32 | "\n", 33 | "4. Hit the same button in the top-right." 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "Now, try to find and open the `LICENSE` file included in this repo. \n", 41 | "\n", 42 | "1. Press the hotkey you just assigned and the quick open sidebar panel should appear. \n", 43 | "2. Type *lic* and the panel should show only those paths in your notebook directory containing the letters \"l\", \"i\", and \"c\", in that order.\n", 44 | "3. Use the arrow keys to select the `LICENSE` file (it's probably already selected).\n", 45 | "4. Press *Enter* to open it." 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "Run the code below to generate a thousand more files in the notebook tree." 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": null, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "import os\n", 62 | "import random\n", 63 | "\n", 64 | "# Get a thousand words\n", 65 | "with open('/usr/share/dict/words') as fh:\n", 66 | " words = fh.readlines()\n", 67 | "words = random.choices([w.strip() for w in words if \"'\" not in w], k=1000)\n", 68 | "\n", 69 | "# Make filenames from those words\n", 70 | "os.makedirs('data', exist_ok=True)\n", 71 | "for w in words:\n", 72 | " with open(f'data/{w}.txt', 'w') as fh:\n", 73 | " fh.write(w)" 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "metadata": {}, 79 | "source": [ 80 | "Use the quick open sidebar to find these five generated files. " 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": null, 86 | "metadata": {}, 87 | "outputs": [], 88 | "source": [ 89 | "words[:5]" 90 | ] 91 | } 92 | ], 93 | "metadata": { 94 | "kernelspec": { 95 | "display_name": "Python 3 (ipykernel)", 96 | "language": "python", 97 | "name": "python3" 98 | }, 99 | "language_info": { 100 | "codemirror_mode": { 101 | "name": "ipython", 102 | "version": 3 103 | }, 104 | "file_extension": ".py", 105 | "mimetype": "text/x-python", 106 | "name": "python", 107 | "nbconvert_exporter": "python", 108 | "pygments_lexer": "ipython3", 109 | "version": "3.12.5" 110 | }, 111 | "nteract": { 112 | "version": "0.10.0" 113 | } 114 | }, 115 | "nbformat": 4, 116 | "nbformat_minor": 4 117 | } 118 | -------------------------------------------------------------------------------- /doc/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyterlab-contrib/jupyterlab-quickopen/154c60f657ed9e6ec20c7836be92f11c4b23eff5/doc/settings.png -------------------------------------------------------------------------------- /install.json: -------------------------------------------------------------------------------- 1 | { 2 | "packageManager": "python", 3 | "packageName": "jupyterlab-quickopen", 4 | "uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package jupyterlab-quickopen" 5 | } 6 | -------------------------------------------------------------------------------- /jupyter-config/server-config/jupyterlab_quickopen.json: -------------------------------------------------------------------------------- 1 | { 2 | "ServerApp": { 3 | "jpserver_extensions": { 4 | "jupyterlab_quickopen": true 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /jupyterlab_quickopen/__init__.py: -------------------------------------------------------------------------------- 1 | """Registers the jupyterlab front and backend quickopen extensions""" 2 | try: 3 | from ._version import __version__ 4 | except ImportError: 5 | # Fallback when using the package in dev mode without installing 6 | # in editable mode with pip. It is highly recommended to install 7 | # the package from a stable release or in editable mode: https://pip.pypa.io/en/stable/topics/local-project-installs/#editable-installs 8 | import warnings 9 | warnings.warn("Importing 'jupyterlab_quickopen' outside a proper installation.") 10 | __version__ = "dev" 11 | 12 | from pathlib import Path 13 | from .handler import QuickOpenHandler 14 | from jupyter_server.utils import url_path_join 15 | 16 | 17 | def _jupyter_labextension_paths(): 18 | return [{"src": "labextension", "dest": "jupyterlab-quickopen"}] 19 | 20 | 21 | def _jupyter_server_extension_points(): 22 | return [{"module": "jupyterlab_quickopen"}] 23 | 24 | 25 | def _load_jupyter_server_extension(server_app): 26 | """Registers the API handler to receive HTTP requests from the frontend extension. 27 | 28 | Parameters 29 | ---------- 30 | server_app: jupyterlab.labapp.LabApp 31 | JupyterLab application instance 32 | """ 33 | server_app.log.debug("notebook_dir: %s", server_app.notebook_dir) 34 | server_app.log.debug( 35 | "contents_manager.root_dir: %s", server_app.contents_manager.root_dir 36 | ) 37 | if ( 38 | not Path(server_app.root_dir).is_dir() 39 | or server_app.contents_manager.root_dir != server_app.root_dir 40 | ): 41 | server_app.log.info( 42 | f"Refusing to register QuickOpenHandler extension: " 43 | f"{server_app.contents_manager} does not appear to load from the local filesystem" 44 | ) 45 | return 46 | 47 | web_app = server_app.web_app 48 | host_pattern = ".*$" 49 | route_pattern = url_path_join( 50 | web_app.settings["base_url"], "jupyterlab-quickopen", "api", "files" 51 | ) 52 | web_app.add_handlers(host_pattern, [(route_pattern, QuickOpenHandler)]) 53 | server_app.log.info( 54 | f"Registered QuickOpenHandler extension at URL path {route_pattern} " 55 | f"to serve results of scanning local path {server_app.notebook_dir}" 56 | ) 57 | -------------------------------------------------------------------------------- /jupyterlab_quickopen/handler.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | 4 | from fnmatch import fnmatch 5 | 6 | from jupyter_server.base.handlers import APIHandler 7 | from jupyter_server.utils import ensure_async 8 | from tornado import web 9 | from tornado.escape import json_encode 10 | 11 | 12 | class QuickOpenHandler(APIHandler): 13 | @property 14 | def contents_manager(self): 15 | """Currently configured jupyter server ContentsManager.""" 16 | return self.settings["contents_manager"] 17 | 18 | @property 19 | def root_dir(self): 20 | """Root directory to scan.""" 21 | return self.contents_manager.root_dir 22 | 23 | async def should_hide(self, entry, excludes): 24 | """Decides if a file or directory should be hidden from the search results based on 25 | the `allow_hidden` and `hide_globs` properties of the ContentsManager, as well as a 26 | set of exclude patterns included in the client request. 27 | 28 | Parameters 29 | ---------- 30 | entry: DirEntry 31 | From os.scandir 32 | excludes: set of str 33 | Exclude patterns 34 | 35 | Returns 36 | ------- 37 | bool 38 | """ 39 | relpath = os.path.relpath(entry.path) 40 | 41 | return ( 42 | any(fnmatch(entry.name, glob) for glob in excludes) 43 | or not self.contents_manager.should_list(entry.name) 44 | or ( 45 | await ensure_async(self.contents_manager.is_hidden(relpath)) 46 | and not self.contents_manager.allow_hidden 47 | ) 48 | ) 49 | 50 | async def scan_disk(self, path, excludes, on_disk=None): 51 | if on_disk is None: 52 | on_disk = {} 53 | for entry in os.scandir(path): 54 | if await self.should_hide(entry, excludes): 55 | continue 56 | elif entry.is_dir(): 57 | await self.scan_disk(entry.path, excludes, on_disk) 58 | elif entry.is_file(): 59 | parent = os.path.relpath(os.path.dirname(entry.path), self.root_dir) 60 | on_disk.setdefault(parent, []).append(entry.name) 61 | return on_disk 62 | 63 | @web.authenticated 64 | async def get(self): 65 | """Gets the name of every file under the root notebooks directory binned by parent 66 | folder relative to the root notebooks dir. 67 | 68 | Arguments 69 | --------- 70 | exclude: str 71 | Comma-separated set of file name patterns to exclude 72 | 73 | Responds 74 | -------- 75 | JSON 76 | scan_seconds: Time in seconds to collect all file names 77 | contents: File names binned by parent directory 78 | """ 79 | excludes = set(self.get_arguments("excludes")) 80 | current_path = self.get_argument("path") 81 | start_ts = time.time() 82 | if current_path: 83 | full_path = os.path.join(self.root_dir, current_path) 84 | else: 85 | full_path = self.root_dir 86 | contents_by_path = await self.scan_disk(full_path, excludes) 87 | delta_ts = time.time() - start_ts 88 | self.write( 89 | json_encode({"scan_seconds": delta_ts, "contents": contents_by_path}) 90 | ) 91 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jupyterlab-quickopen", 3 | "version": "2.0.2", 4 | "description": "Quickly open a file in JupyterLab by part of its name", 5 | "keywords": [ 6 | "jupyter", 7 | "jupyterlab", 8 | "jupyterlab-extension" 9 | ], 10 | "homepage": "https://github.com/jupyterlab-contrib/jupyterlab-quickopen", 11 | "bugs": { 12 | "url": "https://github.com/jupyterlab-contrib/jupyterlab-quickopen/issues" 13 | }, 14 | "license": "BSD-3-Clause", 15 | "author": { 16 | "name": "JupyterLab Contrib Team", 17 | "email": "" 18 | }, 19 | "files": [ 20 | "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}", 21 | "style/**/*.{css,js,eot,gif,html,jpg,json,png,svg,woff2,ttf}", 22 | "schema/*.json", 23 | "style/index.js" 24 | ], 25 | "main": "lib/index.js", 26 | "types": "lib/index.d.ts", 27 | "style": "style/index.css", 28 | "repository": { 29 | "type": "git", 30 | "url": "https://github.com/jupyterlab-contrib/jupyterlab-quickopen.git" 31 | }, 32 | "scripts": { 33 | "build": "jlpm build:lib && jlpm build:labextension:dev", 34 | "build:labextension": "jupyter labextension build .", 35 | "build:labextension:dev": "jupyter labextension build --development True .", 36 | "build:lib": "tsc --sourceMap", 37 | "build:lib:prod": "tsc", 38 | "build:prod": "jlpm clean && jlpm build:lib:prod && jlpm build:labextension", 39 | "clean": "jlpm clean:lib", 40 | "clean:all": "jlpm clean:lib && jlpm clean:labextension && jlpm clean:lintcache", 41 | "clean:labextension": "rimraf jupyterlab_quickopen/labextension jupyterlab_quickopen/_version.py", 42 | "clean:lib": "rimraf lib tsconfig.tsbuildinfo", 43 | "clean:lintcache": "rimraf .eslintcache .stylelintcache", 44 | "eslint": "jlpm eslint:check --fix", 45 | "eslint:check": "eslint . --cache --ext .ts,.tsx", 46 | "install:extension": "jlpm build", 47 | "lint": "jlpm stylelint && jlpm prettier && jlpm eslint", 48 | "lint:check": "jlpm stylelint:check && jlpm prettier:check && jlpm eslint:check", 49 | "prettier": "jlpm prettier:base --write --list-different", 50 | "prettier:base": "prettier \"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}\"", 51 | "prettier:check": "jlpm prettier:base --check", 52 | "stylelint": "jlpm stylelint:check --fix", 53 | "stylelint:check": "stylelint --cache \"style/**/*.css\"", 54 | "watch": "run-p watch:src watch:labextension", 55 | "watch:labextension": "jupyter labextension watch .", 56 | "watch:src": "tsc -w --sourceMap" 57 | }, 58 | "dependencies": { 59 | "@jupyterlab/application": "^4.2.5", 60 | "@jupyterlab/apputils": "^4.3.5", 61 | "@jupyterlab/coreutils": "^6.2.5", 62 | "@jupyterlab/docmanager": "^4.2.5", 63 | "@jupyterlab/filebrowser": "^4.2.5", 64 | "@jupyterlab/services": "^7.2.5", 65 | "@jupyterlab/settingregistry": "^4.2.5", 66 | "@jupyterlab/translation": "^4.2.5" 67 | }, 68 | "devDependencies": { 69 | "@jupyterlab/builder": "^4.0.0", 70 | "@types/json-schema": "^7.0.11", 71 | "@types/react": "^18.0.26", 72 | "@types/react-addons-linked-state-mixin": "^0.14.22", 73 | "@typescript-eslint/eslint-plugin": "^6.1.0", 74 | "@typescript-eslint/parser": "^6.1.0", 75 | "css-loader": "^6.7.1", 76 | "eslint": "^8.36.0", 77 | "eslint-config-prettier": "^8.8.0", 78 | "eslint-plugin-prettier": "^5.0.0", 79 | "mkdirp": "^1.0.3", 80 | "npm-run-all": "^4.1.5", 81 | "prettier": "^3.0.0", 82 | "rimraf": "^5.0.1", 83 | "source-map-loader": "^1.0.2", 84 | "style-loader": "^3.3.1", 85 | "stylelint": "^15.10.1", 86 | "stylelint-config-recommended": "^13.0.0", 87 | "stylelint-config-standard": "^34.0.0", 88 | "stylelint-csstree-validator": "^3.0.0", 89 | "stylelint-prettier": "^4.0.0", 90 | "typescript": "~5.0.2", 91 | "yjs": "^13.5.40" 92 | }, 93 | "packageManager": "yarn@3.5.0", 94 | "sideEffects": [ 95 | "style/*.css", 96 | "style/index.js" 97 | ], 98 | "styleModule": "style/index.js", 99 | "publishConfig": { 100 | "access": "public" 101 | }, 102 | "jupyterlab": { 103 | "extension": true, 104 | "discovery": { 105 | "server": { 106 | "managers": [ 107 | "pip" 108 | ], 109 | "base": { 110 | "name": "jupyterlab_quickopen" 111 | } 112 | } 113 | }, 114 | "schemaDir": "schema", 115 | "outputDir": "jupyterlab_quickopen/labextension" 116 | }, 117 | "eslintConfig": { 118 | "extends": [ 119 | "eslint:recommended", 120 | "plugin:@typescript-eslint/eslint-recommended", 121 | "plugin:@typescript-eslint/recommended", 122 | "plugin:prettier/recommended" 123 | ], 124 | "parser": "@typescript-eslint/parser", 125 | "parserOptions": { 126 | "project": "tsconfig.json", 127 | "sourceType": "module" 128 | }, 129 | "plugins": [ 130 | "@typescript-eslint" 131 | ], 132 | "rules": { 133 | "@typescript-eslint/naming-convention": [ 134 | "error", 135 | { 136 | "selector": "interface", 137 | "format": [ 138 | "PascalCase" 139 | ], 140 | "custom": { 141 | "regex": "^I[A-Z]", 142 | "match": true 143 | } 144 | } 145 | ], 146 | "@typescript-eslint/no-unused-vars": [ 147 | "warn", 148 | { 149 | "args": "none" 150 | } 151 | ], 152 | "@typescript-eslint/no-explicit-any": "off", 153 | "@typescript-eslint/no-namespace": "off", 154 | "@typescript-eslint/no-use-before-define": "off", 155 | "@typescript-eslint/quotes": [ 156 | "error", 157 | "single", 158 | { 159 | "avoidEscape": true, 160 | "allowTemplateLiterals": false 161 | } 162 | ], 163 | "curly": [ 164 | "error", 165 | "all" 166 | ], 167 | "eqeqeq": "error", 168 | "prefer-arrow-callback": "error" 169 | } 170 | }, 171 | "eslintIgnore": [ 172 | "node_modules", 173 | "dist", 174 | "coverage", 175 | "**/*.d.ts" 176 | ], 177 | "prettier": { 178 | "singleQuote": true, 179 | "trailingComma": "none", 180 | "arrowParens": "avoid", 181 | "endOfLine": "auto", 182 | "overrides": [ 183 | { 184 | "files": "package.json", 185 | "options": { 186 | "tabWidth": 4 187 | } 188 | } 189 | ] 190 | }, 191 | "stylelint": { 192 | "extends": [ 193 | "stylelint-config-recommended", 194 | "stylelint-config-standard", 195 | "stylelint-prettier/recommended" 196 | ], 197 | "plugins": [ 198 | "stylelint-csstree-validator" 199 | ], 200 | "rules": { 201 | "csstree/validator": true, 202 | "property-no-vendor-prefix": null, 203 | "selector-class-pattern": "^([a-z][A-z\\d]*)(-[A-z\\d]+)*$", 204 | "selector-no-vendor-prefix": null, 205 | "value-no-vendor-prefix": null 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["hatchling>=1.5.0", "jupyterlab>=4.0.0,<5", "hatch-nodejs-version>=0.3.2"] 3 | build-backend = "hatchling.build" 4 | 5 | [project] 6 | name = "jupyterlab-quickopen" 7 | readme = "README.md" 8 | license = { file = "LICENSE" } 9 | requires-python = ">=3.8" 10 | classifiers = [ 11 | "Framework :: Jupyter", 12 | "Framework :: Jupyter :: JupyterLab", 13 | "Framework :: Jupyter :: JupyterLab :: 4", 14 | "Framework :: Jupyter :: JupyterLab :: Extensions", 15 | "Framework :: Jupyter :: JupyterLab :: Extensions :: Prebuilt", 16 | "License :: OSI Approved :: BSD License", 17 | "Programming Language :: Python", 18 | "Programming Language :: Python :: 3", 19 | "Programming Language :: Python :: 3.8", 20 | "Programming Language :: Python :: 3.9", 21 | "Programming Language :: Python :: 3.10", 22 | "Programming Language :: Python :: 3.11", 23 | "Programming Language :: Python :: 3.12", 24 | ] 25 | dependencies = [ 26 | "jupyter_server>=2.4.2,<3" 27 | ] 28 | dynamic = ["version", "description", "authors", "urls", "keywords"] 29 | 30 | [tool.hatch.version] 31 | source = "nodejs" 32 | 33 | [tool.hatch.metadata.hooks.nodejs] 34 | fields = ["description", "authors", "urls", "keywords"] 35 | 36 | [tool.hatch.build.targets.sdist] 37 | artifacts = ["jupyterlab_quickopen/labextension"] 38 | exclude = [".github", "binder"] 39 | 40 | [tool.hatch.build.targets.wheel.shared-data] 41 | "jupyterlab_quickopen/labextension" = "share/jupyter/labextensions/jupyterlab-quickopen" 42 | "install.json" = "share/jupyter/labextensions/jupyterlab-quickopen/install.json" 43 | "jupyter-config/server-config" = "etc/jupyter/jupyter_server_config.d" 44 | 45 | [tool.hatch.build.hooks.version] 46 | path = "jupyterlab_quickopen/_version.py" 47 | 48 | [tool.hatch.build.hooks.jupyter-builder] 49 | dependencies = ["hatch-jupyter-builder>=0.5"] 50 | build-function = "hatch_jupyter_builder.npm_builder" 51 | ensured-targets = [ 52 | "jupyterlab_quickopen/labextension/static/style.js", 53 | "jupyterlab_quickopen/labextension/package.json", 54 | ] 55 | skip-if-exists = ["jupyterlab_quickopen/labextension/static/style.js"] 56 | 57 | [tool.hatch.build.hooks.jupyter-builder.build-kwargs] 58 | build_cmd = "build:prod" 59 | npm = ["jlpm"] 60 | 61 | [tool.hatch.build.hooks.jupyter-builder.editable-build-kwargs] 62 | build_cmd = "install:extension" 63 | npm = ["jlpm"] 64 | source_dir = "src" 65 | build_dir = "jupyterlab_quickopen/labextension" 66 | 67 | [tool.jupyter-releaser.options] 68 | version_cmd = "hatch version" 69 | 70 | [tool.jupyter-releaser.hooks] 71 | before-build-npm = [ 72 | "python -m pip install 'jupyterlab>=4.0.0,<5'", 73 | "jlpm", 74 | "jlpm build:prod" 75 | ] 76 | before-build-python = ["jlpm clean:all"] 77 | 78 | [tool.check-wheel-contents] 79 | ignore = ["W002"] 80 | -------------------------------------------------------------------------------- /schema/plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "jupyter.lab.setting-icon-class": "jp-SearchIcon", 3 | "jupyter.lab.setting-icon-label": "Quick Open", 4 | "title": "Quick Open", 5 | "description": "Quick open panel settings", 6 | "properties": { 7 | "excludes": { 8 | "title": "Exclude Patterns", 9 | "description": "File and directory patterns to exclude from the list", 10 | "type": "array", 11 | "items": { "type": "string" }, 12 | "default": ["node_modules", "__pycache__"] 13 | }, 14 | "relativeSearch": { 15 | "title": "Relative Search", 16 | "description": "Whether to search from currently selected directory", 17 | "type": "boolean", 18 | "default": false 19 | } 20 | }, 21 | "jupyter.lab.menus": { 22 | "main": [ 23 | { 24 | "id": "jp-mainmenu-view", 25 | "items": [ 26 | { 27 | "command": "quickopen:activate", 28 | "rank": 1 29 | }, 30 | { 31 | "type": "separator", 32 | "rank": 1 33 | } 34 | ] 35 | } 36 | ] 37 | }, 38 | "jupyter.lab.shortcuts": [ 39 | { 40 | "command": "quickopen:activate", 41 | "keys": ["Accel Shift P"], 42 | "selector": "body" 43 | } 44 | ], 45 | "additionalProperties": false, 46 | "type": "object" 47 | } 48 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | __import__("setuptools").setup() 2 | -------------------------------------------------------------------------------- /src/handler.ts: -------------------------------------------------------------------------------- 1 | import { URLExt } from '@jupyterlab/coreutils'; 2 | 3 | import { ServerConnection } from '@jupyterlab/services'; 4 | 5 | /** 6 | * Call the API extension 7 | * 8 | * @param endPoint API REST end point for the extension 9 | * @param init Initial values for the request 10 | * @returns The response body interpreted as JSON 11 | */ 12 | export async function requestAPI( 13 | endPoint = '', 14 | init: RequestInit = {} 15 | ): Promise { 16 | // Make request to Jupyter API 17 | const settings = ServerConnection.makeSettings(); 18 | const requestUrl = URLExt.join( 19 | settings.baseUrl, 20 | 'jupyterlab-quickopen', // API Namespace 21 | endPoint 22 | ); 23 | 24 | let response: Response; 25 | try { 26 | response = await ServerConnection.makeRequest(requestUrl, init, settings); 27 | } catch (error) { 28 | throw new ServerConnection.NetworkError(error as any); 29 | } 30 | 31 | let data: any = await response.text(); 32 | 33 | if (data.length > 0) { 34 | try { 35 | data = JSON.parse(data); 36 | } catch (error) { 37 | console.log('Not a JSON response body.', response); 38 | } 39 | } 40 | 41 | if (!response.ok) { 42 | throw new ServerConnection.ResponseError(response, data.message || data); 43 | } 44 | 45 | return data; 46 | } 47 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | JupyterFrontEnd, 3 | JupyterFrontEndPlugin 4 | } from '@jupyterlab/application'; 5 | import { ICommandPalette, ModalCommandPalette } from '@jupyterlab/apputils'; 6 | import { URLExt, PathExt } from '@jupyterlab/coreutils'; 7 | import { IDocumentManager } from '@jupyterlab/docmanager'; 8 | import { ServerConnection } from '@jupyterlab/services'; 9 | import { ISettingRegistry } from '@jupyterlab/settingregistry'; 10 | import { FileBrowser, IDefaultFileBrowser } from '@jupyterlab/filebrowser'; 11 | import { ITranslator, nullTranslator } from '@jupyterlab/translation'; 12 | import { CommandRegistry } from '@lumino/commands'; 13 | import { ReadonlyPartialJSONObject } from '@lumino/coreutils'; 14 | import { Message } from '@lumino/messaging'; 15 | import { ISignal, Signal } from '@lumino/signaling'; 16 | import { CommandPalette } from '@lumino/widgets'; 17 | 18 | /** Structure of the JSON response from the server */ 19 | interface IQuickOpenResponse { 20 | readonly contents: { [key: string]: string[] }; 21 | readonly scanSeconds: number; 22 | } 23 | 24 | /** Makes a HTTP request for the server-side quick open scan */ 25 | async function fetchContents( 26 | path: string, 27 | excludes: string[] 28 | ): Promise { 29 | const query = excludes 30 | .map(exclude => { 31 | return 'excludes=' + encodeURIComponent(exclude); 32 | }) 33 | .join('&'); 34 | 35 | const settings = ServerConnection.makeSettings(); 36 | const fullUrl = 37 | URLExt.join(settings.baseUrl, 'jupyterlab-quickopen', 'api', 'files') + 38 | '?' + 39 | query + 40 | '&path=' + 41 | path; 42 | const response = await ServerConnection.makeRequest( 43 | fullUrl, 44 | { method: 'GET' }, 45 | settings 46 | ); 47 | if (response.status !== 200) { 48 | throw new ServerConnection.ResponseError(response); 49 | } 50 | return await response.json(); 51 | } 52 | 53 | /** 54 | * Shows files nested under directories in the root notebooks directory configured on the server. 55 | */ 56 | class QuickOpenWidget extends CommandPalette { 57 | private _pathSelected = new Signal(this); 58 | private _settings: ReadonlyPartialJSONObject; 59 | private _fileBrowser: FileBrowser; 60 | 61 | constructor( 62 | defaultBrowser: IDefaultFileBrowser, 63 | settings: ReadonlyPartialJSONObject, 64 | options: CommandPalette.IOptions 65 | ) { 66 | super(options); 67 | 68 | this.id = 'jupyterlab-quickopen'; 69 | this.title.iconClass = 'jp-SideBar-tabIcon jp-SearchIcon'; 70 | this.title.caption = 'Quick Open'; 71 | 72 | this._settings = settings; 73 | this._fileBrowser = defaultBrowser; 74 | } 75 | 76 | /** Signal when a selected path is activated. */ 77 | get pathSelected(): ISignal { 78 | return this._pathSelected; 79 | } 80 | 81 | /** Current extension settings */ 82 | set settings(settings: ReadonlyPartialJSONObject) { 83 | this._settings = settings; 84 | } 85 | 86 | /** 87 | * Refreshes the widget with the paths of files on the server. 88 | */ 89 | protected async onActivateRequest(msg: Message): Promise { 90 | super.onActivateRequest(msg); 91 | 92 | // Fetch the current contents from the server 93 | const path = this._settings.relativeSearch 94 | ? this._fileBrowser.model.path 95 | : ''; 96 | const response = await fetchContents( 97 | path, 98 | this._settings.excludes as string[] 99 | ); 100 | 101 | // Remove all paths from the view 102 | this.clearItems(); 103 | 104 | for (const category in response.contents) { 105 | for (const fn of response.contents[category]) { 106 | // Creates commands that are relative file paths on the server 107 | const command = `${category}/${fn}`; 108 | if (!this.commands.hasCommand(command)) { 109 | // Only add the command to the registry if it does not yet exist TODO: Track disposables 110 | // and remove 111 | this.commands.addCommand(command, { 112 | label: fn, 113 | execute: () => { 114 | // Emit a selection signal 115 | this._pathSelected.emit(command); 116 | } 117 | }); 118 | } 119 | // Make the file visible under its parent directory heading 120 | this.addItem({ command, category }); 121 | } 122 | } 123 | } 124 | } 125 | 126 | /** 127 | * Initialization data for the jupyterlab-quickopen extension. 128 | */ 129 | const extension: JupyterFrontEndPlugin = { 130 | id: 'jupyterlab-quickopen:plugin', 131 | autoStart: true, 132 | requires: [IDocumentManager, ISettingRegistry, IDefaultFileBrowser], 133 | optional: [ICommandPalette, ITranslator], 134 | activate: async ( 135 | app: JupyterFrontEnd, 136 | docManager: IDocumentManager, 137 | settingRegistry: ISettingRegistry, 138 | defaultFileBrowser: IDefaultFileBrowser, 139 | palette: ICommandPalette | null, 140 | translator: ITranslator | null 141 | ) => { 142 | const trans = (translator ?? nullTranslator).load('jupyterlab-quickopen'); 143 | const commands: CommandRegistry = new CommandRegistry(); 144 | const settings: ISettingRegistry.ISettings = await settingRegistry.load( 145 | extension.id 146 | ); 147 | const widget: QuickOpenWidget = new QuickOpenWidget( 148 | defaultFileBrowser, 149 | settings.composite, 150 | { 151 | commands 152 | } 153 | ); 154 | 155 | // Listen for path selection signals and show the selected files in the appropriate 156 | // editor/viewer 157 | widget.pathSelected.connect((sender: QuickOpenWidget, path: string) => { 158 | docManager.openOrReveal(PathExt.normalize(path)); 159 | }); 160 | 161 | // Listen for setting changes and apply them to the widget 162 | settings.changed.connect((settings: ISettingRegistry.ISettings) => { 163 | widget.settings = settings.composite; 164 | }); 165 | 166 | // Add the quick open widget as a modal palette 167 | const modalPalette = new ModalCommandPalette({ commandPalette: widget }); 168 | modalPalette.attach(); 169 | 170 | // Add a command to activate the quickopen sidebar so that the user can find it in the command 171 | // palette, assign a hotkey, etc. 172 | const command = 'quickopen:activate'; 173 | app.commands.addCommand(command, { 174 | label: trans.__('Quick Open'), 175 | execute: () => { 176 | modalPalette.activate(); 177 | } 178 | }); 179 | if (palette) { 180 | palette.addItem({ command, category: 'File Operations' }); 181 | } 182 | } 183 | }; 184 | 185 | export default extension; 186 | -------------------------------------------------------------------------------- /style/base.css: -------------------------------------------------------------------------------- 1 | .jp-SearchIcon { 2 | background-image: var(--jp-icon-search); 3 | } 4 | -------------------------------------------------------------------------------- /style/index.css: -------------------------------------------------------------------------------- 1 | @import url('base.css'); 2 | -------------------------------------------------------------------------------- /style/index.js: -------------------------------------------------------------------------------- 1 | import './base.css'; 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "composite": true, 5 | "declaration": true, 6 | "esModuleInterop": true, 7 | "incremental": true, 8 | "jsx": "react", 9 | "module": "esnext", 10 | "moduleResolution": "node", 11 | "noEmitOnError": true, 12 | "noImplicitAny": true, 13 | "noUnusedLocals": true, 14 | "preserveWatchOutput": true, 15 | "resolveJsonModule": true, 16 | "outDir": "lib", 17 | "rootDir": "src", 18 | "strict": true, 19 | "strictNullChecks": true, 20 | "target": "ES2018" 21 | }, 22 | "include": ["src/*"] 23 | } 24 | --------------------------------------------------------------------------------