diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..95d6e2e --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,48 @@ +name: Create Release + +on: + push: + tags: + - 'v*.*.*' +jobs: + release: + name: Create Release + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Setup Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Tag Version + id: tag-version + run: echo ::set-output name=RELEASE_VERSION::$(echo ${GITHUB_REF:10}) + - name: Package Version + id: setup-version + run: echo ::set-output name=SETUP_VERSION::$(python3 setup.py --version) + - name: Tag & setup.py Versions Not Matching + if: ${{ format('v{0}', steps.setup-version.outputs.SETUP_VERSION) != steps.tag-version.outputs.RELEASE_VERSION}} + run: exit 1 + - name: Build package + id: build_package + run: | + pip3 install wheel && \ + python3 setup.py sdist bdist_wheel + if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + draft: false + prerelease: false + - name: Publish package + if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') + uses: codota/gh-action-pypi-publish@master + with: + user: ${{ secrets.PYPI_USERNAME }} + password: ${{ secrets.PYPI_TOKEN }} \ No newline at end of file diff --git a/README.ch.md b/README.ch.md index 488963d..76be1a9 100644 --- a/README.ch.md +++ b/README.ch.md @@ -61,3 +61,9 @@ jupyter serverextension enable [MIT License](LICENSE) ## 部署自动补全Server (可选) + +很快添加 + +## Star 趋势 + +[![Stargazers over time](https://starchart.cc/wenmin-wu/jupyter-tabnine.svg)](https://starchart.cc/wenmin-wu/jupyter-tabnine) \ No newline at end of file diff --git a/README.md b/README.md index 9a3c64f..ebfe7ff 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # TabNine for Jupyter Notebook +**This plugin has been created by [wenmin-wu](https://github.com/wenmin-wu).** + **This plugin has been tested on MacOS, Linux and Windows, it support all these systems. For browsers it supports Chrome and Safari but not IE** If you found this plugin doesn't work for you, please debug according to [How to Debug](DEBUG.md). And if you can't figure out what's wrong, please release an issue and report the logs in detail. @@ -14,7 +16,7 @@ This extension for Jupyter Notebook enables the use of coding auto-completion ba Other client plugins of TabNine require starting a child process for TabNine binary and using Pipe for communication. This can’t be done with Jupyter Notebook, since child process can’t be created with JQuery and Jupyter Notebook doesn’t provide any way for adding third-part js libs to plugins. -In this repository, it is achived by developing a client plugin and a server plugin for Jupyter Notebook. The client plugin generate request info and send http request to the server plugin. The server plugin pass the request info to it’s client process (TabNine) and return the request to client plugin. +In this repository, it is achieved by developing a client plugin and a server plugin for Jupyter Notebook. The client plugin generate request info and send http request to the server plugin. The server plugin pass the request info to its client process (TabNine) and return the request to client plugin. ## Installation @@ -27,7 +29,7 @@ jupyter nbextension enable --py jupyter_tabnine --user jupyter serverextension enable --py jupyter_tabnine --user ``` -If you want to install and congiure in a customized way, you can refer to following: +If you want to install and configure in a customized way, you can refer to following: The extension consists of a pypi package that includes a javascript notebook extension, along with a python jupyter server extension. Since Jupyter 4.2, pypi is the recommended way to distribute nbextensions. The extension can be installed: @@ -36,7 +38,7 @@ notebook extension, along with a python jupyter server extension. Since Jupyter * via pip for the version hosted on pypi -From the github repo or from Pypi, +From the github repo or from pypi, 1. install the package * `pip3 install https://github.com/wenmin-wu/jupyter-tabnine/archive/master.zip [--user][--upgrade]` * or `pip3 install jupyter-tabnine [--user][--upgrade]` @@ -68,17 +70,49 @@ jupyter serverextension enable where `` is the output of the first python command. ## Usage -* Jupyter TabNine will be active after being installed. Sometimes, you may want to show the Jupyter original complete temporally, then click `shift` + `space`. +* Jupyter TabNine will be active after being installed. Sometimes, you may want to show the Jupyter original complete temporarily, then click `shift` + `space`. ![show original complete demo](images/show-original-complete.gif) -* Remote auto-completion server is also supported. You may want this to speed up the completion request handing. Or maybe your company want to deploy a compeltion server cluster that services everyone. Read following to learn how to deploy remote server. +* Remote auto-completion server is also supported. You may want this to speed up the completion request handing. Or maybe your company want to deploy a completion server cluster that services everyone. Read following to learn how to deploy remote server. + +## Uninstallation +To uninstall TabNine plugin from mac/linux run the following commands: +```Bash +jupyter nbextension uninstall --py jupyter_tabnine +pip3 uninstall jupyter-tabnine +``` ## Contributing + Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. Please make sure to update tests as appropriate. ## License + [MIT License](LICENSE) ## Remote Completion Server Deployment +It's useful to deploy a remote tabnine server if you don't want to occupy too much local resources. You can build, deploy and config a remote tabnine server according to the following steps. + +**NOTE:** You need to install jupyter-tabnine with `pip3 install https://github.com/wenmin-wu/jupyter-tabnine/archive/master.zip`, because the version which fix this plugin with remote server problem haven't been relased to PyPi. +### Build Server Image +**I have uploaded an image to Docker Hub, skip this section if you prefer to use it directly.** +* Install the golang (recommended version is 1.13 - 1.14) +* Issue `go get -v github.com/wenmin-wu/jupyter-tabnine/go/cmd` +* Issue `cd $HOME/go/src/github.com/wenmin-wu/jupyter-tabnine` +* Issue `bash ./build-image.sh` +### Start Server +**Change the image name in this bash script to `wuwenmin1991/tabnine-server:1.0` if you did't build your own image** +* Simply issue `bash start-server.sh` + +### Configure Under Nbextensions +* Please [install Nbextensions](https://jupyter-contrib-nbextensions.readthedocs.io/en/latest/install.html) if you haven't installed. +* Open Jupyter Notebook and go to the Nbextensions setting page, click **Jupyter TabNine**, scroll down and fill in the remote server url, e.g. +![remote-server-url-config](images/remote-server-url-config.jpg) +### Stop Server +* Simply issue `bash stop-server.sh` + +## Stargazers over time + +[![Stargazers over time](https://starchart.cc/wenmin-wu/jupyter-tabnine.svg)](https://starchart.cc/wenmin-wu/jupyter-tabnine) diff --git a/README.rst b/README.rst index 497241f..35a1c9b 100644 --- a/README.rst +++ b/README.rst @@ -7,9 +7,9 @@ Other client plugins of TabNine require starting a child process for TabNine bin and using Pipe for communication. This can't be done with Jupyter Notebook, since child process can't be created with JQuery and Jupyter Notebook doesn't provide any way for adding third-part js libs to plugins. -In this repository, it is achived by developing a client plugin and a server plugin for Jupyter Notebook. +In this repository, it is achieved by developing a client plugin and a server plugin for Jupyter Notebook. The client plugin generate request info and send http request to the server plugin. -The server plugin pass the request info to it's client process (TabNine) and return the request to client plugin. +The server plugin pass the request info to its client process (TabNine) and return the request to client plugin. Installation ------------ @@ -21,7 +21,7 @@ The extension can be installed - from the master version on the github repo (this will be always the most recent version) - via pip for the version hosted on pypi -From the github repo or from Pypi, +From the github repo or from pypi, 1. install the package @@ -70,5 +70,5 @@ command. Tips ------------ -- A shortcut is added to let you switch between Jupyter raw completion and TabNine auto-competion. Just enter ``shift`` + ``space`` when you want raw completion of Jupyter :) -- Remote auto-completion server is also supported. You may want this to speed up the completion request handing. Or maybe your company want to deploy a compeltion server cluster that services everyone. Refer https://github.com/wenmin-wu/jupyter-tabnine to learn how to deploy remote server. +- A shortcut is added to let you switch between Jupyter raw completion and TabNine auto-completion. Just enter ``shift`` + ``space`` when you want raw completion of Jupyter :) +- Remote auto-completion server is also supported. You may want this to speed up the completion request handing. Or maybe your company want to deploy a completion server cluster that services everyone. Refer https://github.com/wenmin-wu/jupyter-tabnine to learn how to deploy remote server. diff --git a/go/pkg/tabnine/tabnine.go b/go/pkg/tabnine/tabnine.go index f821386..e72d33b 100644 --- a/go/pkg/tabnine/tabnine.go +++ b/go/pkg/tabnine/tabnine.go @@ -81,7 +81,7 @@ func (t *TabNine) init() (err error) { t.outPipeReader, t.outPipeWriter = io.Pipe() wg.Wait() if err == nil { - t.cmd = exec.Command(binaryPath, "--client=vscode") + t.cmd = exec.Command(binaryPath, "--client=jupyter-server") t.cmd.Stdin = t.inPipeReader t.cmd.Stdout = t.outPipeWriter t.outReader = bufio.NewReader(t.outPipeReader) diff --git a/images/remote-server-url-config.jpg b/images/remote-server-url-config.jpg new file mode 100644 index 0000000..a6e1ff3 Binary files /dev/null and b/images/remote-server-url-config.jpg differ diff --git a/setup.py b/setup.py index eb1a35d..520c992 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ setuptools.setup( name="jupyter_tabnine", - version='1.1.0', + version='1.2.2', url="https://github.com/wenmin-wu/jupyter-tabnine", author="Wenmin Wu", long_description=readme, diff --git a/src/jupyter_tabnine/static/README.md b/src/jupyter_tabnine/static/README.md index 3207f5f..75a8443 100644 --- a/src/jupyter_tabnine/static/README.md +++ b/src/jupyter_tabnine/static/README.md @@ -31,4 +31,4 @@ Options * `jupyter_tabnine.remote_server_url`: remote server url, you may want to use a remote server to handle client request. - This can spped up the request handling depending on the server configuration. Refer to https://github.com/wenmin-wu/jupyter-tabnine to see how to deploy remote server. \ No newline at end of file + This can speed up the request handling depending on the server configuration. Refer to https://github.com/wenmin-wu/jupyter-tabnine to see how to deploy remote server. \ No newline at end of file diff --git a/src/jupyter_tabnine/static/main.js b/src/jupyter_tabnine/static/main.js index fa41921..c639030 100644 --- a/src/jupyter_tabnine/static/main.js +++ b/src/jupyter_tabnine/static/main.js @@ -21,6 +21,9 @@ define([ ) { 'use strict'; + const N_LINES_BEFORE = 50; + const N_LINES_AFTER = 50; + var assistActive; var config = { @@ -226,6 +229,8 @@ define([ this.before = before; this.after = after; + before = before.slice(Math.max(0, before.length - N_LINES_BEFORE), before.length); + after = after.slice(0, N_LINES_AFTER); requestInfo.request.Autocomplete.before = before.join("\n"); requestInfo.request.Autocomplete.after = after.join("\n"); @@ -292,8 +297,10 @@ define([ } else { this.after.push(currLineAfter); } - requestInfo.request.Autocomplete.before = this.before.join('\n'); - requestInfo.request.Autocomplete.after = this.after.join('\n'); + var before = this.before.slice(Math.max(0, this.before.length - N_LINES_BEFORE), this.before.length); + var after = this.after.slice(0, N_LINES_AFTER); + requestInfo.request.Autocomplete.before = before.join('\n'); + requestInfo.request.Autocomplete.after = after.join('\n'); var that = this; requestComplterServer(requestInfo, true, function (data) { if (data.results.length == 0) { @@ -379,12 +386,14 @@ define([ 'top': top + 'px', 'display': 'initial' }); + var options = $("#complete").find('.complete-container'); + $(options[0]).css('background', 'lightblue'); }; DeepCompleter.prototype.add_keyevent_listeners = function () { var options = $("#complete").find('.complete-container'); var editor = this.editor; - var currIndex = -1; + var currIndex = 0; var preIndex; this.isKeyupFired = true; // make keyup only fire once var that = this; @@ -397,33 +406,38 @@ define([ } that.isKeyupFired = false; if (event.keyCode == keycodes.up || event.keyCode == keycodes.tab - || event.keyCode == keycodes.down || event.keyCode == keycodes.enter) { + || event.keyCode == keycodes.down || event.keyCode == keycodes.enter + || event.keyCode == keycodes.esc) { event.codemirrorIgnore = true; event._ipkmIgnore = true; event.preventDefault(); // it's better to prevent enter key when completions being shown - if (event.keyCode == keycodes.enter) { + preIndex = currIndex; + if (event.keyCode == keycodes.esc) { + that.close(); + return; + } else if (event.keyCode == keycodes.up) { + currIndex = currIndex - 1; + } else if (event.keyCode == keycodes.tab || event.keyCode == keycodes.down) { + currIndex = currIndex + 1; + } else { + var end = editor.getCursor(); + if (that.completions[currIndex].old_suffix) { + end.ch += that.completions[currIndex].old_suffix.length; + } + var replacement = that.completions[currIndex].new_prefix; + replacement += that.completions[currIndex].new_suffix; + editor.replaceRange(replacement, that.completeFrom, end); that.close(); return; } - preIndex = currIndex; - currIndex = event.keyCode == keycodes.up ? currIndex - 1 : currIndex + 1; currIndex = currIndex < 0 ? options.length - 1 : (currIndex >= options.length ? currIndex - options.length : currIndex); $(options[currIndex]).css('background', 'lightblue'); - var end = editor.getCursor(); - if (that.completions[currIndex].old_suffix) { - end.ch += that.completions[currIndex].old_suffix.length; - } - var replacement = that.completions[currIndex].new_prefix; - replacement += that.completions[currIndex].new_suffix; - editor.replaceRange(replacement, that.completeFrom, end); - if (preIndex != -1) { - $(options[preIndex]).css('background', ''); - } + $(options[preIndex]).css('background', ''); } else if (needUpdateComplete(event.keyCode)) { // Let this be handled by keyup, since it can get current pressed key. } else { diff --git a/src/jupyter_tabnine/static/tabnine.yaml b/src/jupyter_tabnine/static/tabnine.yaml index 9e31d4f..749eb1b 100644 --- a/src/jupyter_tabnine/static/tabnine.yaml +++ b/src/jupyter_tabnine/static/tabnine.yaml @@ -41,7 +41,7 @@ Parameters: - name: jupyter_tabnine.remote_server_url description: | remote server url, you may want to use a remote server to handle client request. - this can spped up the request handling depending on the server configuration. + this can speed up the request handling depending on the server configuration. refer to https://github.com/wenmin-wu/jupyter-tabnine to see how to deploy remote server. input_type: string default: '' diff --git a/src/jupyter_tabnine/tabnine.py b/src/jupyter_tabnine/tabnine.py index ba7b739..5e9c1e7 100644 --- a/src/jupyter_tabnine/tabnine.py +++ b/src/jupyter_tabnine/tabnine.py @@ -124,7 +124,7 @@ def _restart(self): [ path, "--client", - "sublime", + "jupyter", "--log-file-path", os.path.join(self._install_dir, "tabnine.log"), ],