euporie 2.8.4__py3-none-any.whl → 2.8.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- euporie/console/_commands.py +143 -0
- euporie/console/_settings.py +58 -0
- euporie/console/app.py +25 -71
- euporie/console/tabs/console.py +58 -62
- euporie/core/__init__.py +1 -1
- euporie/core/__main__.py +28 -11
- euporie/core/_settings.py +109 -0
- euporie/core/app/__init__.py +3 -0
- euporie/core/app/_commands.py +95 -0
- euporie/core/app/_settings.py +457 -0
- euporie/core/{app.py → app/app.py} +212 -576
- euporie/core/app/base.py +51 -0
- euporie/core/{current.py → app/current.py} +13 -4
- euporie/core/app/cursor.py +35 -0
- euporie/core/app/dummy.py +12 -0
- euporie/core/app/launch.py +28 -0
- euporie/core/bars/__init__.py +11 -0
- euporie/core/bars/command.py +205 -0
- euporie/core/bars/menu.py +258 -0
- euporie/core/{widgets → bars}/search.py +20 -16
- euporie/core/{widgets → bars}/status.py +6 -23
- euporie/core/clipboard.py +19 -80
- euporie/core/comm/base.py +8 -6
- euporie/core/comm/ipywidgets.py +16 -7
- euporie/core/comm/registry.py +2 -1
- euporie/core/commands.py +10 -20
- euporie/core/completion.py +3 -2
- euporie/core/config.py +368 -341
- euporie/core/convert/__init__.py +0 -30
- euporie/core/convert/datum.py +116 -53
- euporie/core/convert/formats/__init__.py +31 -0
- euporie/core/convert/formats/ansi.py +9 -23
- euporie/core/convert/formats/common.py +11 -23
- euporie/core/convert/formats/html.py +45 -40
- euporie/core/convert/formats/pil.py +1 -1
- euporie/core/convert/formats/png.py +3 -5
- euporie/core/convert/formats/sixel.py +3 -3
- euporie/core/convert/registry.py +4 -6
- euporie/core/convert/utils.py +41 -4
- euporie/core/diagnostics.py +2 -2
- euporie/core/filters.py +98 -40
- euporie/core/format.py +2 -3
- euporie/core/ft/ansi.py +1 -1
- euporie/core/ft/html.py +12 -21
- euporie/core/ft/table.py +1 -3
- euporie/core/ft/utils.py +4 -1
- euporie/core/graphics.py +386 -133
- euporie/core/history.py +2 -2
- euporie/core/inspection.py +3 -2
- euporie/core/io.py +207 -28
- euporie/core/kernel/__init__.py +1 -0
- euporie/core/{kernel.py → kernel/client.py} +45 -108
- euporie/core/kernel/manager.py +114 -0
- euporie/core/key_binding/bindings/__init__.py +1 -8
- euporie/core/key_binding/bindings/basic.py +47 -7
- euporie/core/key_binding/bindings/completion.py +3 -8
- euporie/core/key_binding/bindings/micro.py +1 -6
- euporie/core/key_binding/bindings/mouse.py +2 -2
- euporie/core/key_binding/bindings/terminal.py +193 -0
- euporie/core/key_binding/key_processor.py +43 -2
- euporie/core/key_binding/registry.py +2 -0
- euporie/core/key_binding/utils.py +22 -2
- euporie/core/keys.py +7156 -93
- euporie/core/layout/cache.py +3 -3
- euporie/core/layout/containers.py +48 -4
- euporie/core/layout/decor.py +2 -2
- euporie/core/layout/mouse.py +1 -1
- euporie/core/layout/print.py +2 -1
- euporie/core/layout/scroll.py +39 -34
- euporie/core/log.py +76 -64
- euporie/core/lsp.py +118 -24
- euporie/core/margins.py +1 -1
- euporie/core/path.py +62 -13
- euporie/core/renderer.py +58 -17
- euporie/core/style.py +57 -39
- euporie/core/suggest.py +103 -85
- euporie/core/tabs/__init__.py +32 -0
- euporie/core/tabs/_settings.py +113 -0
- euporie/core/tabs/base.py +80 -470
- euporie/core/tabs/kernel.py +419 -0
- euporie/core/tabs/notebook.py +24 -101
- euporie/core/utils.py +92 -15
- euporie/core/validation.py +1 -1
- euporie/core/widgets/_settings.py +188 -0
- euporie/core/widgets/cell.py +19 -50
- euporie/core/widgets/cell_outputs.py +25 -36
- euporie/core/widgets/decor.py +11 -41
- euporie/core/widgets/dialog.py +62 -27
- euporie/core/widgets/display.py +12 -15
- euporie/core/widgets/file_browser.py +2 -23
- euporie/core/widgets/forms.py +8 -5
- euporie/core/widgets/inputs.py +13 -70
- euporie/core/widgets/layout.py +2 -1
- euporie/core/widgets/logo.py +49 -0
- euporie/core/widgets/menu.py +10 -8
- euporie/core/widgets/pager.py +6 -10
- euporie/core/widgets/palette.py +6 -6
- euporie/hub/app.py +52 -35
- euporie/notebook/_commands.py +24 -0
- euporie/notebook/_settings.py +107 -0
- euporie/notebook/app.py +49 -171
- euporie/notebook/filters.py +1 -1
- euporie/notebook/tabs/__init__.py +46 -7
- euporie/notebook/tabs/_commands.py +714 -0
- euporie/notebook/tabs/_settings.py +32 -0
- euporie/notebook/tabs/display.py +4 -4
- euporie/notebook/tabs/edit.py +11 -44
- euporie/notebook/tabs/json.py +5 -5
- euporie/notebook/tabs/log.py +1 -18
- euporie/notebook/tabs/notebook.py +11 -660
- euporie/notebook/widgets/_commands.py +11 -0
- euporie/notebook/widgets/_settings.py +19 -0
- euporie/notebook/widgets/side_bar.py +14 -34
- euporie/preview/_settings.py +104 -0
- euporie/preview/app.py +6 -31
- euporie/preview/tabs/notebook.py +6 -72
- euporie/web/__init__.py +1 -0
- euporie/web/tabs/__init__.py +14 -0
- euporie/web/tabs/web.py +11 -6
- euporie/web/widgets/__init__.py +1 -0
- euporie/web/widgets/webview.py +5 -15
- {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/METADATA +10 -8
- euporie-2.8.6.dist-info/RECORD +175 -0
- {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/WHEEL +1 -1
- {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/entry_points.txt +2 -2
- {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/licenses/LICENSE +1 -1
- euporie/core/launch.py +0 -64
- euporie/core/terminal.py +0 -522
- euporie-2.8.4.dist-info/RECORD +0 -147
- {euporie-2.8.4.data → euporie-2.8.6.data}/data/share/applications/euporie-console.desktop +0 -0
- {euporie-2.8.4.data → euporie-2.8.6.data}/data/share/applications/euporie-notebook.desktop +0 -0
euporie/core/style.py
CHANGED
@@ -4,16 +4,19 @@ from __future__ import annotations
|
|
4
4
|
|
5
5
|
import logging
|
6
6
|
from colorsys import hls_to_rgb, rgb_to_hls
|
7
|
-
from functools import partial
|
7
|
+
from functools import cache, partial
|
8
8
|
from typing import TYPE_CHECKING
|
9
9
|
|
10
10
|
from prompt_toolkit.cache import SimpleCache
|
11
11
|
from prompt_toolkit.styles.defaults import default_ui_style
|
12
12
|
from prompt_toolkit.styles.style import Style
|
13
|
+
from pygments.styles import get_style_by_name as pyg_get_style_by_name
|
13
14
|
|
14
15
|
if TYPE_CHECKING:
|
15
16
|
from typing import Any
|
16
17
|
|
18
|
+
from pygments.style import Style as PygmentsStyle
|
19
|
+
|
17
20
|
|
18
21
|
log = logging.getLogger(__name__)
|
19
22
|
|
@@ -440,8 +443,8 @@ def build_style(
|
|
440
443
|
# Statusbar
|
441
444
|
# "status": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.less(0.15)}",
|
442
445
|
"status": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.more(0.05)}",
|
443
|
-
"status-field": f"
|
444
|
-
"status-sep": f"
|
446
|
+
"status-field": f"bg:{cp.fg.more(0.1)} fg:{cp.bg.more(0.1)} reverse",
|
447
|
+
"status-sep": f"bg:{cp.bg.more(0.05)} fg:{cp.bg.more(0.1)} reverse",
|
445
448
|
# Menus & Menu bar
|
446
449
|
"menu": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.more(0.05)}",
|
447
450
|
"menu bar": f"bg:{cp.bg.less(0.15)}",
|
@@ -450,11 +453,11 @@ def build_style(
|
|
450
453
|
"menu shortcut disabled": f"fg:{cp.fg.more(0.4).towards(cp.bg, 0.5)}",
|
451
454
|
"menu prefix": f"fg:{cp.fg.more(0.2)}",
|
452
455
|
"menu prefix disabled": f"fg:{cp.fg.more(0.2).towards(cp.bg, 0.5)}",
|
453
|
-
"menu selection": f"
|
454
|
-
"menu selection shortcut": f"
|
455
|
-
"menu selection prefix": f"
|
456
|
+
"menu selection": f"bg:{cp.hl.more(1)} fg:{cp.hl} reverse",
|
457
|
+
"menu selection shortcut": f"bg:{cp.hl.more(1).more(0.05)} fg:{cp.hl} reverse",
|
458
|
+
"menu selection prefix": f"bg:{cp.hl.more(1).more(0.05)} fg:{cp.hl} reverse",
|
456
459
|
"menu border": f"fg:{cp.bg.more(0.15)} bg:{cp.bg.more(0.05)}",
|
457
|
-
"menu border selection": f"bg:{cp.hl}",
|
460
|
+
"menu border selection": f"fg:{cp.bg.more(0.15)} bg:{cp.hl} noreverse",
|
458
461
|
# Tab bar
|
459
462
|
"app-tab-bar": f"bg:{cp.bg.less(0.15)}",
|
460
463
|
"app-tab-bar border": f"fg:{cp.bg.more(0.1)}",
|
@@ -466,10 +469,10 @@ def build_style(
|
|
466
469
|
# Tabs
|
467
470
|
"loading": "fg:#888888",
|
468
471
|
# Buffer
|
469
|
-
"line-number": f"
|
470
|
-
"line-number.current": f"
|
471
|
-
"line-number edge": f"
|
472
|
-
"line-number.current edge": f"
|
472
|
+
"line-number": f"bg:{cp.fg.more(0.5)} fg:{cp.bg.more(0.05)} reverse",
|
473
|
+
"line-number.current": f"bg:orange fg:{cp.bg.more(0.1)} bold",
|
474
|
+
"line-number edge": f"bg:{cp.bg.darker(0.1)}",
|
475
|
+
"line-number.current edge": f"bg:{cp.bg.darker(0.1)}",
|
473
476
|
"cursor-line": f"bg:{cp.bg.more(0.05)}",
|
474
477
|
"cursor-line search": f"bg:{cp.bg.more(0.02)}",
|
475
478
|
"cursor-line search.current": f"bg:{cp.bg.more(0.02)}",
|
@@ -479,13 +482,11 @@ def build_style(
|
|
479
482
|
"matching-bracket.other": "fg:yellow bold",
|
480
483
|
"trailing-whitespace": f"fg:{cp.fg.more(0.66)}",
|
481
484
|
"tab": f"fg:{cp.fg.more(0.66)}",
|
482
|
-
# Search
|
485
|
+
# Search results
|
483
486
|
"search": f"bg:{cp.bg.more(0.05)}",
|
484
487
|
"search.current": f"bg:{cp.bg.more(0.05)}",
|
485
488
|
"incsearch": "bg:ansibrightyellow",
|
486
489
|
"incsearch.current": "bg:ansibrightgreen",
|
487
|
-
"search-toolbar": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.more(0.05)}",
|
488
|
-
"search-toolbar.title": f"fg:{cp.fg.more(0.1)} bg:{cp.bg.more(0.1)}",
|
489
490
|
# Inputs
|
490
491
|
"kernel-input": f"fg:default bg:{cp.bg.more(0.02)}",
|
491
492
|
# Cells
|
@@ -496,22 +497,22 @@ def build_style(
|
|
496
497
|
"cell border edit": f"fg:{cp.hl.adjust(hue=-0.3333, rel=False)}",
|
497
498
|
"cell input prompt": "fg:blue",
|
498
499
|
"cell output prompt": "fg:red",
|
499
|
-
"cell show outputs": f"
|
500
|
-
"cell show inputs": f"
|
501
|
-
"cell show inputs border": f"
|
502
|
-
"cell show outputs border": f"
|
500
|
+
"cell show outputs": f"bg:{cp.fg.more(0.5)} fg:{cp.bg.more(0.05)} reverse",
|
501
|
+
"cell show inputs": f"bg:{cp.fg.more(0.5)} fg:{cp.bg.more(0.05)} reverse",
|
502
|
+
"cell show inputs border": f"bg:{cp.bg.darker(0.1)} fg:{cp.bg.more(0.05)} reverse",
|
503
|
+
"cell show outputs border": f"bg:{cp.bg.darker(0.1)} fg:{cp.bg.more(0.05)} reverse",
|
503
504
|
# Scrollbars
|
504
505
|
"scrollbar": f"fg:{cp.bg.more(0.75)} bg:{cp.bg.more(0.15)}",
|
505
506
|
"scrollbar.background": f"fg:{cp.bg.more(0.75)} bg:{cp.bg.more(0.15)}",
|
506
|
-
"scrollbar.arrow": f"
|
507
|
+
"scrollbar.arrow": f"bg:{cp.bg.more(0.75)} fg:{cp.bg.more(0.20)} reverse",
|
507
508
|
"scrollbar.start": "",
|
508
509
|
# "scrollbar.start": f"fg:{cp.bg.more(0.75)} bg:{cp.bg.more(0.25)}",
|
509
|
-
"scrollbar.button": f"
|
510
|
-
"scrollbar.end": f"
|
510
|
+
"scrollbar.button": f"bg:{cp.bg.more(0.75)} fg:{cp.bg.more(0.75)} reverse",
|
511
|
+
"scrollbar.end": f"bg:{cp.bg.more(0.15)} fg:{cp.bg.more(0.75)} reverse",
|
511
512
|
# Overflow margin
|
512
513
|
"overflow": f"fg:{cp.fg.more(0.5)}",
|
513
514
|
# Dialogs
|
514
|
-
"dialog dialog-title": f"
|
515
|
+
"dialog dialog-title": f"bg:white fg:{cp.hl.darker(0.25)} bold reverse",
|
515
516
|
"dialog": f"fg:{cp.fg.base} bg:{cp.bg.darker(0.1)}",
|
516
517
|
"dialog text-area": f"bg:{cp.bg.lighter(0.05)}",
|
517
518
|
"dialog input text text-area": f"fg:default bg:{cp.bg.less(0.1)}",
|
@@ -519,6 +520,17 @@ def build_style(
|
|
519
520
|
"dialog border": f"fg:{cp.bg.darker(0.1).more(0.1)}",
|
520
521
|
# Horizontals rule
|
521
522
|
"hr": "fg:ansired",
|
523
|
+
# Toolbars
|
524
|
+
"toolbar": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.more(0.05)}",
|
525
|
+
"toolbar.title": f"fg:{cp.fg.more(0.1)} bg:{cp.bg.more(0.1)}",
|
526
|
+
# Search bar
|
527
|
+
"search-toolbar": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.more(0.05)}",
|
528
|
+
# Command bar
|
529
|
+
"toolbar menu": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.more(0.05)}",
|
530
|
+
"toolbar menu completion": f"fg:{cp.fg.more(0.1)} bg:{cp.bg.more(0.1)}",
|
531
|
+
"toolbar menu completion current": f"fg:{cp.hl} bg:{cp.fg} reverse",
|
532
|
+
"toolbar menu overflow": f"fg:{cp.fg.more(0.5)}",
|
533
|
+
"toolbar menu meta": f"bg:{cp.bg.more(0.25)} bold",
|
522
534
|
# Completions menu
|
523
535
|
"menu completion-keyword": "fg:#d700af",
|
524
536
|
"menu completion-function": "fg:#005faf",
|
@@ -530,28 +542,28 @@ def build_style(
|
|
530
542
|
"menu completion-path": "fg:#aa8800",
|
531
543
|
"menu completion-dict-key": "fg:#ddbb00",
|
532
544
|
"menu selection completion-keyword": (
|
533
|
-
f"
|
545
|
+
f"bg:{ColorPaletteColor('#d700af').lighter(0.75)} fg:{cp.hl} reverse"
|
534
546
|
),
|
535
547
|
"menu selection completion-function": (
|
536
|
-
f"
|
548
|
+
f"bg:{ColorPaletteColor('#005faf').lighter(0.75)} fg:{cp.hl} reverse"
|
537
549
|
),
|
538
550
|
"menu selection completion-class": (
|
539
|
-
f"
|
551
|
+
f"bg:{ColorPaletteColor('#008700').lighter(0.75)} fg:{cp.hl} reverse"
|
540
552
|
),
|
541
553
|
"menu selection completion-statement": (
|
542
|
-
f"
|
554
|
+
f"bg:{ColorPaletteColor('#5f0000').lighter(0.75)} fg:{cp.hl} reverse"
|
543
555
|
),
|
544
556
|
"menu selection completion-instance": (
|
545
|
-
f"
|
557
|
+
f"bg:{ColorPaletteColor('#d75f00').lighter(0.75)} fg:{cp.hl} reverse"
|
546
558
|
),
|
547
559
|
"menu selection completion-module": (
|
548
|
-
f"
|
560
|
+
f"bg:{ColorPaletteColor('#d70000').lighter(0.75)} fg:{cp.hl} reverse"
|
549
561
|
),
|
550
562
|
"menu selection completion-magic": (
|
551
|
-
f"
|
563
|
+
f"bg:{ColorPaletteColor('#888888').lighter(0.75)} fg:{cp.hl} reverse"
|
552
564
|
),
|
553
565
|
"menu selection completion-path": (
|
554
|
-
f"
|
566
|
+
f"bg:{ColorPaletteColor('#aa8800').lighter(0.75)} fg:{cp.hl} reverse"
|
555
567
|
),
|
556
568
|
# Log
|
557
569
|
"log.level.nonset": "fg:grey",
|
@@ -567,7 +579,7 @@ def build_style(
|
|
567
579
|
"file-browser face": f"bg:{cp.bg.lighter(0.1)}",
|
568
580
|
"file-browser face row alt-row": f"bg:{cp.bg.lighter(0.1).more(0.01)}",
|
569
581
|
"file-browser face row hovered": f"bg:{cp.bg.more(0.2)}",
|
570
|
-
"file-browser face row selection": f"bg:{cp.hl}",
|
582
|
+
"file-browser face row selection": f"bg:{cp.fg} fg:{cp.hl} reverse",
|
571
583
|
# Shortcuts
|
572
584
|
"shortcuts.group": f"bg:{cp.bg.more(0.4)} bold underline",
|
573
585
|
# "shortcuts.row": f"bg:{cp.bg.base} nobold",
|
@@ -576,7 +588,7 @@ def build_style(
|
|
576
588
|
# Palette
|
577
589
|
"palette.item": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.more(0.05)}",
|
578
590
|
"palette.item.alt": f"bg:{cp.bg.more(0.15)}",
|
579
|
-
"palette.item.selected": f"
|
591
|
+
"palette.item.selected": f"bg:{cp.hl.more(1)} fg:{cp.hl} reverse",
|
580
592
|
# Pager
|
581
593
|
"pager": f"bg:{cp.bg.more(0.05)}",
|
582
594
|
"pager.border": f"fg:{cp.bg.towards(cp.ansiblack, 0.15)} reverse",
|
@@ -596,13 +608,13 @@ def build_style(
|
|
596
608
|
"side_bar border outer": f"bg:{cp.bg}",
|
597
609
|
"side_bar buttons": f"bg:{cp.bg.less(0.15)}",
|
598
610
|
"side_bar buttons hovered": f"fg:{cp.hl}",
|
599
|
-
"side_bar buttons
|
600
|
-
"side_bar buttons
|
611
|
+
"side_bar buttons separator": f"bg:{cp.bg.less(0.15)} fg:{cp.bg.less(0.15)}",
|
612
|
+
"side_bar buttons selection": f"bg:{cp.fg} fg:{cp.hl} reverse",
|
601
613
|
"side_bar buttons separator selection before": (
|
602
|
-
f"
|
614
|
+
f"bg:{cp.bg.less(0.15)} fg:{cp.hl} reverse"
|
603
615
|
),
|
604
616
|
"side_bar buttons separator selection after": (
|
605
|
-
f"fg:{cp.hl} bg:{cp.bg.less(0.15)}"
|
617
|
+
f"fg:{cp.hl} bg:{cp.bg.less(0.15)} noreverse"
|
606
618
|
),
|
607
619
|
# Tabbed split
|
608
620
|
"tabbed-split border": f"fg:{cp.bg.more(0.2)}",
|
@@ -677,9 +689,9 @@ def build_style(
|
|
677
689
|
"text-area focused selected": "reverse",
|
678
690
|
# Buttons
|
679
691
|
"input button face": f"fg:default bg:{cp.bg.more(0.05)}",
|
680
|
-
"input button face hovered": f"fg:
|
681
|
-
"input button face selection": f"bg:{cp.bg.more(0.05)}",
|
682
|
-
"input button face focused": f"fg
|
692
|
+
"input button face hovered": f"fg:{cp.fg} bg:{cp.bg.more(0.2)}",
|
693
|
+
"input button face selection": f"bg:{cp.fg} fg:{cp.bg.more(0.05)} reverse",
|
694
|
+
"input button face focused": f"bg:{cp.fg} fg:{cp.bg.towards(cp.hl, 0.1)} reverse",
|
683
695
|
# Input widgets
|
684
696
|
"input border top": f"fg:{cp.bg.lighter(0.5)}",
|
685
697
|
"input border left": f"fg:{cp.bg.lighter(0.5)}",
|
@@ -753,3 +765,9 @@ def build_style(
|
|
753
765
|
}
|
754
766
|
|
755
767
|
return Style.from_dict(style_dict)
|
768
|
+
|
769
|
+
|
770
|
+
@cache
|
771
|
+
def get_style_by_name(name: str) -> type[PygmentsStyle]:
|
772
|
+
"""Get Pygments style, caching the result."""
|
773
|
+
return pyg_get_style_by_name(name)
|
euporie/core/suggest.py
CHANGED
@@ -3,7 +3,9 @@
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
5
|
import logging
|
6
|
-
from collections import
|
6
|
+
from collections import defaultdict
|
7
|
+
from difflib import SequenceMatcher
|
8
|
+
from functools import lru_cache
|
7
9
|
from typing import TYPE_CHECKING
|
8
10
|
|
9
11
|
from prompt_toolkit.auto_suggest import AutoSuggest, ConditionalAutoSuggest, Suggestion
|
@@ -15,7 +17,6 @@ if TYPE_CHECKING:
|
|
15
17
|
from prompt_toolkit.filters import Filter
|
16
18
|
from prompt_toolkit.history import History
|
17
19
|
|
18
|
-
from euporie.core.kernel import Kernel
|
19
20
|
|
20
21
|
log = logging.getLogger(__name__)
|
21
22
|
|
@@ -23,99 +24,116 @@ log = logging.getLogger(__name__)
|
|
23
24
|
class HistoryAutoSuggest(AutoSuggest):
|
24
25
|
"""Suggest line completions from a :class:`History` object."""
|
25
26
|
|
26
|
-
def __init__(self, history: History
|
27
|
+
def __init__(self, history: History) -> None:
|
27
28
|
"""Set the kernel instance in initialization."""
|
28
29
|
self.history = history
|
30
|
+
self.calculate_similarity = lru_cache(maxsize=1024)(self._calculate_similarity)
|
29
31
|
|
30
|
-
self.
|
31
|
-
self.
|
32
|
-
self.
|
32
|
+
self.n_texts = 0
|
33
|
+
self.n_lines = 0
|
34
|
+
self.prefix_dict: dict[str, dict[str, list[dict[str, int]]]] = defaultdict(
|
35
|
+
lambda: defaultdict(list)
|
36
|
+
)
|
37
|
+
|
38
|
+
def process_history(self) -> None:
|
39
|
+
"""Process the entire history and store in prefix_dict."""
|
40
|
+
texts = self.history._loaded_strings
|
41
|
+
if texts := texts[: len(texts) - self.n_texts]:
|
42
|
+
n_lines = self.n_lines
|
43
|
+
prefix_dict = self.prefix_dict
|
44
|
+
for i, text in enumerate(reversed(texts)):
|
45
|
+
for line in text.strip().splitlines():
|
46
|
+
n_lines += 1
|
47
|
+
line = line.strip()
|
48
|
+
for j in range(1, len(line)):
|
49
|
+
prefix, suffix = line[:j], line[j:]
|
50
|
+
prefix_dict[prefix][suffix].append(
|
51
|
+
{"index": -1 - i, "line": n_lines}
|
52
|
+
)
|
53
|
+
# for k in range(1, len(prefix)):
|
54
|
+
# prefix_dict[prefix[-k:]] = prefix_dict[prefix]
|
55
|
+
self.n_lines = n_lines
|
56
|
+
self.n_texts += len(texts)
|
57
|
+
|
58
|
+
def _calculate_similarity(self, text_1: str, text_2: str) -> float:
|
59
|
+
"""Calculate and cache the similarity between two texts."""
|
60
|
+
return SequenceMatcher(None, text_1, text_2).quick_ratio()
|
33
61
|
|
34
62
|
def get_suggestion(self, buffer: Buffer, document: Document) -> Suggestion | None:
|
35
63
|
"""Get a line completion suggestion."""
|
36
|
-
|
64
|
+
self.process_history()
|
65
|
+
|
37
66
|
line = document.current_line.lstrip()
|
38
|
-
if line:
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
67
|
+
if not line:
|
68
|
+
return None
|
69
|
+
|
70
|
+
suffixes = self.prefix_dict[line]
|
71
|
+
|
72
|
+
texts = self.history._loaded_strings
|
73
|
+
n_lines = self.n_lines
|
74
|
+
|
75
|
+
best_score = 0.0
|
76
|
+
best_suffix = ""
|
77
|
+
|
78
|
+
# Rank candidates
|
79
|
+
max_count = max([1, *(len(x) for x in suffixes.values())])
|
80
|
+
for suffix, instances in suffixes.items():
|
81
|
+
count = len(instances)
|
82
|
+
for instance in instances:
|
83
|
+
text = texts[instance["index"]]
|
84
|
+
context_similarity = self.calculate_similarity(document.text, text)
|
85
|
+
score = (
|
86
|
+
0
|
87
|
+
# Similarity of prefix to line
|
88
|
+
# 0.333 * len(line) / len(match.group("prefix"))
|
89
|
+
# NUmber of instances in history
|
90
|
+
+ 0.3 * count / max_count
|
91
|
+
# Recentness
|
92
|
+
+ 0.3 * instance["line"] / n_lines
|
93
|
+
# Similarity of context to document
|
94
|
+
+ 0.4 * context_similarity
|
95
|
+
)
|
96
|
+
# log.debug("%s %r", score, suffix)
|
97
|
+
if score > 0.95:
|
98
|
+
return Suggestion(suffix)
|
99
|
+
if score > best_score:
|
100
|
+
best_score = score
|
101
|
+
best_suffix = suffix
|
102
|
+
if best_suffix:
|
103
|
+
return Suggestion(best_suffix)
|
65
104
|
return None
|
66
105
|
|
67
|
-
'''
|
68
|
-
def lookup_suggestion(self, line: "str") -> "Optional[Suggestion]":
|
69
|
-
""Suggest most commonly used line."""
|
70
|
-
results = {}
|
71
|
-
pat = re.compile(f"^\\s*{re.escape(line)}(.*)$", re.MULTILINE)
|
72
|
-
for text in self.history.get_strings():
|
73
|
-
if line in text:
|
74
|
-
for hist_line in text.splitlines()[::-1]:
|
75
|
-
hist_line = hist_line.strip()
|
76
|
-
if hist_line.startswith(line):
|
77
|
-
# Return from the match to end from the history line
|
78
|
-
suggestion = hist_line[len(line) :]
|
79
|
-
if suggestion not in results:
|
80
|
-
results[suggestion] = 1
|
81
|
-
else:
|
82
|
-
results[suggestion] += 1
|
83
|
-
return Suggestion(
|
84
|
-
{b: a for a, b in results.items()}[max(results.values())]
|
85
|
-
)
|
86
|
-
'''
|
87
|
-
|
88
|
-
|
89
|
-
class KernelAutoSuggest(AutoSuggest):
|
90
|
-
"""Suggest line completions from kernel history."""
|
91
|
-
|
92
|
-
def __init__(self, kernel: Kernel) -> None:
|
93
|
-
"""Set the kernel instance in initialization."""
|
94
|
-
self.kernel = kernel
|
95
|
-
|
96
|
-
def get_suggestion(self, buffer: Buffer, document: Document) -> Suggestion | None:
|
97
|
-
"""Doe nothing."""
|
98
|
-
return None
|
99
106
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
107
|
+
# class KernelAutoSuggest(AutoSuggest):
|
108
|
+
# """Suggest line completions from kernel history."""
|
109
|
+
|
110
|
+
# def __init__(self, kernel: Kernel) -> None:
|
111
|
+
# """Set the kernel instance in initialization."""
|
112
|
+
# self.kernel = kernel
|
113
|
+
|
114
|
+
# def get_suggestion(self, buffer: Buffer, document: Document) -> Suggestion | None:
|
115
|
+
# """Doe nothing."""
|
116
|
+
# return None
|
117
|
+
|
118
|
+
# async def get_suggestion_async(
|
119
|
+
# self, buff: Buffer, document: Document
|
120
|
+
# ) -> Suggestion | None:
|
121
|
+
# """Return suggestions based on matching kernel history."""
|
122
|
+
# line = document.current_line.strip()
|
123
|
+
# if line:
|
124
|
+
# suggestions = await self.kernel.history_(f"*{line}*")
|
125
|
+
# log.debug("Suggestor got suggestions %s", suggestions)
|
126
|
+
# if suggestions:
|
127
|
+
# _, _, text = suggestions[0]
|
128
|
+
# # Find matching line
|
129
|
+
# for hist_line in text.split("\n"):
|
130
|
+
# hist_line = hist_line.strip()
|
131
|
+
# if hist_line.startswith(line):
|
132
|
+
# # Return from the match to end from the history line
|
133
|
+
# suggestion = hist_line[len(line) :]
|
134
|
+
# log.debug("Suggesting %s", suggestion)
|
135
|
+
# return Suggestion(suggestion)
|
136
|
+
# return None
|
119
137
|
|
120
138
|
|
121
139
|
class ConditionalAutoSuggestAsync(ConditionalAutoSuggest):
|
euporie/core/tabs/__init__.py
CHANGED
@@ -1 +1,33 @@
|
|
1
1
|
"""Contain various application tab implementations."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
from dataclasses import dataclass, field
|
6
|
+
from pkgutil import resolve_name
|
7
|
+
from typing import TYPE_CHECKING
|
8
|
+
|
9
|
+
if TYPE_CHECKING:
|
10
|
+
from euporie.core.tabs.base import Tab
|
11
|
+
|
12
|
+
|
13
|
+
@dataclass
|
14
|
+
class TabRegistryEntry:
|
15
|
+
"""Class to store tab information."""
|
16
|
+
|
17
|
+
path: str
|
18
|
+
name: str
|
19
|
+
mime_types: set = field(default_factory=set)
|
20
|
+
file_extensions: dict[str, None] = field(default_factory=dict)
|
21
|
+
weight: int = 0
|
22
|
+
|
23
|
+
@property
|
24
|
+
def tab_class(self) -> type[Tab]:
|
25
|
+
"""Import and return the tab class."""
|
26
|
+
return resolve_name(self.path)
|
27
|
+
|
28
|
+
def __lt__(self, other: TabRegistryEntry) -> bool:
|
29
|
+
"""Sort by weight."""
|
30
|
+
return self.weight < other.weight
|
31
|
+
|
32
|
+
|
33
|
+
_TAB_REGISTRY: list[TabRegistryEntry] = []
|
@@ -0,0 +1,113 @@
|
|
1
|
+
"""Defines tab settings."""
|
2
|
+
|
3
|
+
from prompt_toolkit.filters import buffer_has_focus
|
4
|
+
|
5
|
+
from euporie.core.config import add_setting
|
6
|
+
|
7
|
+
add_setting(
|
8
|
+
name="kernel_name",
|
9
|
+
group="euporie.core.tabs.kernel",
|
10
|
+
flags=["--kernel-name", "--kernel"],
|
11
|
+
type_=str,
|
12
|
+
help_="The name of the kernel to start by default",
|
13
|
+
default="python3",
|
14
|
+
description="""
|
15
|
+
The name of the kernel selected automatically by the console app or in new
|
16
|
+
notebooks. If set to an empty string, the user will be asked which kernel
|
17
|
+
to launch.
|
18
|
+
""",
|
19
|
+
)
|
20
|
+
|
21
|
+
add_setting(
|
22
|
+
name="record_cell_timing",
|
23
|
+
group="euporie.core.tabs.kernel",
|
24
|
+
title="cell timing recording",
|
25
|
+
flags=["--record-cell-timing"],
|
26
|
+
type_=bool,
|
27
|
+
help_="Should timing data be recorded in cell metadata.",
|
28
|
+
default=False,
|
29
|
+
schema={
|
30
|
+
"type": "boolean",
|
31
|
+
},
|
32
|
+
description="""
|
33
|
+
When set, execution timing data will be recorded in cell metadata.
|
34
|
+
""",
|
35
|
+
)
|
36
|
+
|
37
|
+
add_setting(
|
38
|
+
name="show_remote_inputs",
|
39
|
+
group="euporie.core.tabs.kernel",
|
40
|
+
flags=["--show-remote-inputs"],
|
41
|
+
type_=bool,
|
42
|
+
help_="Display inputs sent to the kernel by other clients",
|
43
|
+
default=True,
|
44
|
+
description="""
|
45
|
+
If set to `True`, all code input sent to the kernel by any client will be
|
46
|
+
displayed.
|
47
|
+
|
48
|
+
If set to `False`, only inputs sent to the kernel by the current instance
|
49
|
+
of euporie will be displayed, and all other inputs will be ignored.
|
50
|
+
|
51
|
+
""",
|
52
|
+
)
|
53
|
+
|
54
|
+
add_setting(
|
55
|
+
name="show_remote_outputs",
|
56
|
+
group="euporie.core.tabs.kernel",
|
57
|
+
flags=["--show-remote-outputs"],
|
58
|
+
type_=bool,
|
59
|
+
help_="Display kernel outputs triggered by other clients",
|
60
|
+
default=True,
|
61
|
+
description="""
|
62
|
+
If set to `False`, only outputs generated by code input from the current
|
63
|
+
instance of euporie will be displayed, and all other outputs will be
|
64
|
+
ignored.
|
65
|
+
|
66
|
+
If set to `True`, all outputs generated by the kernel will be
|
67
|
+
displayed.
|
68
|
+
""",
|
69
|
+
)
|
70
|
+
|
71
|
+
# euporie.core.tabs.notebook
|
72
|
+
|
73
|
+
add_setting(
|
74
|
+
name="save_widget_state",
|
75
|
+
group="euporie.core.tabs.notebook",
|
76
|
+
flags=["--save-widget-state"],
|
77
|
+
type_=bool,
|
78
|
+
help_="Save a notebook's widget state in the notebook metadata",
|
79
|
+
default=True,
|
80
|
+
description="""
|
81
|
+
When set to ``True``, the state of any widgets in the current notebook will
|
82
|
+
be saves in the notebook's metadata. This enables widgets to be displayed
|
83
|
+
when the notebook is re-opened without having to re-run the notebook.
|
84
|
+
""",
|
85
|
+
)
|
86
|
+
|
87
|
+
add_setting(
|
88
|
+
name="max_notebook_width",
|
89
|
+
group="euporie.core.tabs.notebook",
|
90
|
+
flags=["--max-notebook-width"],
|
91
|
+
type_=int,
|
92
|
+
help_="Maximum width of notebooks",
|
93
|
+
default=120,
|
94
|
+
schema={
|
95
|
+
"minimum": 1,
|
96
|
+
},
|
97
|
+
description="""
|
98
|
+
The maximum width at which to display a notebook.
|
99
|
+
""",
|
100
|
+
)
|
101
|
+
|
102
|
+
add_setting(
|
103
|
+
name="expand",
|
104
|
+
group="euporie.core.tabs.notebook",
|
105
|
+
flags=["--expand"],
|
106
|
+
type_=bool,
|
107
|
+
help_="Use the full width to display notebooks",
|
108
|
+
default=False,
|
109
|
+
description="""
|
110
|
+
Whether the notebook page should expand to fill the available width
|
111
|
+
""",
|
112
|
+
cmd_filter=~buffer_has_focus,
|
113
|
+
)
|