Skip to content

Commit 7647852

Browse files
committed
fix #3714 - jupyter2: support "from x import _" tab completion (more precisely -- align our completion heuristic with JupyterLab's)
- also I made the sorting of results match up
1 parent 945c3b9 commit 7647852

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

src/packages/frontend/jupyter/codemirror-editor.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { SAVE_DEBOUNCE_MS } from "../frame-editors/code-editor/const";
2727
import { Complete, Actions as CompleteActions } from "./complete";
2828
import { Cursors } from "./cursors";
2929
import { Position } from "./insert-cell/types";
30+
import { is_whitespace } from "@cocalc/util/misc";
3031

3132
// We cache a little info about each Codemirror editor we make here,
3233
// so we can restore it when we make the same one again. Due to
@@ -551,7 +552,7 @@ export const CodeMirrorEditor: React.FC<CodeMirrorEditorProps> = ({
551552
function whitespace_before_cursor(): boolean {
552553
if (cm.current == null) return false;
553554
const cur = cm.current.getCursor();
554-
return cur.ch === 0 || /\s/.test(cm.current.getLine(cur.line)[cur.ch - 1]);
555+
return is_whitespace(cm.current.getLine(cur.line).slice(0, cur.ch));
555556
}
556557

557558
async function tab_nothing_selected(): Promise<void> {

src/packages/jupyter/redux/actions.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,7 @@ export abstract class JupyterActions extends Actions<JupyterStoreState> {
10641064
};
10651065

10661066
undo = (): void => {
1067+
console.trace("jupyter redux undo");
10671068
if (this.syncdb != null) {
10681069
this.syncdb.undo();
10691070
}
@@ -1702,7 +1703,16 @@ export abstract class JupyterActions extends Actions<JupyterStoreState> {
17021703
}
17031704
// For some reason, sometimes complete.matches are not unique, which is annoying/confusing,
17041705
// and breaks an assumption in our react code too.
1705-
complete.matches = Array.from(new Set(complete.matches)).sort();
1706+
complete.matches = Array.from(new Set(complete.matches));
1707+
// sort in a way that matches how JupyterLab sorts completions, which
1708+
// is case insensitive with % magics at the bottom
1709+
complete.matches.sort((x, y) => {
1710+
const c = misc.cmp(getCompletionGroup(x), getCompletionGroup(y));
1711+
if (c) {
1712+
return c;
1713+
}
1714+
return misc.cmp(x.toLowerCase(), y.toLowerCase());
1715+
});
17061716
const i_complete = immutable.fromJS(complete);
17071717
if (complete.matches && complete.matches.length === 1 && id != null) {
17081718
// special case -- a unique completion and we know id of cell in which completing is given.
@@ -2742,3 +2752,14 @@ function bounded_integer(n: any, min: any, max: any, def: any) {
27422752
}
27432753
return n;
27442754
}
2755+
2756+
function getCompletionGroup(x: string): number {
2757+
switch (x[0]) {
2758+
case "_":
2759+
return 1;
2760+
case "%":
2761+
return 2;
2762+
default:
2763+
return 0;
2764+
}
2765+
}

0 commit comments

Comments
 (0)