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.
Files changed (131) hide show
  1. euporie/console/_commands.py +143 -0
  2. euporie/console/_settings.py +58 -0
  3. euporie/console/app.py +25 -71
  4. euporie/console/tabs/console.py +58 -62
  5. euporie/core/__init__.py +1 -1
  6. euporie/core/__main__.py +28 -11
  7. euporie/core/_settings.py +109 -0
  8. euporie/core/app/__init__.py +3 -0
  9. euporie/core/app/_commands.py +95 -0
  10. euporie/core/app/_settings.py +457 -0
  11. euporie/core/{app.py → app/app.py} +212 -576
  12. euporie/core/app/base.py +51 -0
  13. euporie/core/{current.py → app/current.py} +13 -4
  14. euporie/core/app/cursor.py +35 -0
  15. euporie/core/app/dummy.py +12 -0
  16. euporie/core/app/launch.py +28 -0
  17. euporie/core/bars/__init__.py +11 -0
  18. euporie/core/bars/command.py +205 -0
  19. euporie/core/bars/menu.py +258 -0
  20. euporie/core/{widgets → bars}/search.py +20 -16
  21. euporie/core/{widgets → bars}/status.py +6 -23
  22. euporie/core/clipboard.py +19 -80
  23. euporie/core/comm/base.py +8 -6
  24. euporie/core/comm/ipywidgets.py +16 -7
  25. euporie/core/comm/registry.py +2 -1
  26. euporie/core/commands.py +10 -20
  27. euporie/core/completion.py +3 -2
  28. euporie/core/config.py +368 -341
  29. euporie/core/convert/__init__.py +0 -30
  30. euporie/core/convert/datum.py +116 -53
  31. euporie/core/convert/formats/__init__.py +31 -0
  32. euporie/core/convert/formats/ansi.py +9 -23
  33. euporie/core/convert/formats/common.py +11 -23
  34. euporie/core/convert/formats/html.py +45 -40
  35. euporie/core/convert/formats/pil.py +1 -1
  36. euporie/core/convert/formats/png.py +3 -5
  37. euporie/core/convert/formats/sixel.py +3 -3
  38. euporie/core/convert/registry.py +4 -6
  39. euporie/core/convert/utils.py +41 -4
  40. euporie/core/diagnostics.py +2 -2
  41. euporie/core/filters.py +98 -40
  42. euporie/core/format.py +2 -3
  43. euporie/core/ft/ansi.py +1 -1
  44. euporie/core/ft/html.py +12 -21
  45. euporie/core/ft/table.py +1 -3
  46. euporie/core/ft/utils.py +4 -1
  47. euporie/core/graphics.py +386 -133
  48. euporie/core/history.py +2 -2
  49. euporie/core/inspection.py +3 -2
  50. euporie/core/io.py +207 -28
  51. euporie/core/kernel/__init__.py +1 -0
  52. euporie/core/{kernel.py → kernel/client.py} +45 -108
  53. euporie/core/kernel/manager.py +114 -0
  54. euporie/core/key_binding/bindings/__init__.py +1 -8
  55. euporie/core/key_binding/bindings/basic.py +47 -7
  56. euporie/core/key_binding/bindings/completion.py +3 -8
  57. euporie/core/key_binding/bindings/micro.py +1 -6
  58. euporie/core/key_binding/bindings/mouse.py +2 -2
  59. euporie/core/key_binding/bindings/terminal.py +193 -0
  60. euporie/core/key_binding/key_processor.py +43 -2
  61. euporie/core/key_binding/registry.py +2 -0
  62. euporie/core/key_binding/utils.py +22 -2
  63. euporie/core/keys.py +7156 -93
  64. euporie/core/layout/cache.py +3 -3
  65. euporie/core/layout/containers.py +48 -4
  66. euporie/core/layout/decor.py +2 -2
  67. euporie/core/layout/mouse.py +1 -1
  68. euporie/core/layout/print.py +2 -1
  69. euporie/core/layout/scroll.py +39 -34
  70. euporie/core/log.py +76 -64
  71. euporie/core/lsp.py +118 -24
  72. euporie/core/margins.py +1 -1
  73. euporie/core/path.py +62 -13
  74. euporie/core/renderer.py +58 -17
  75. euporie/core/style.py +57 -39
  76. euporie/core/suggest.py +103 -85
  77. euporie/core/tabs/__init__.py +32 -0
  78. euporie/core/tabs/_settings.py +113 -0
  79. euporie/core/tabs/base.py +80 -470
  80. euporie/core/tabs/kernel.py +419 -0
  81. euporie/core/tabs/notebook.py +24 -101
  82. euporie/core/utils.py +92 -15
  83. euporie/core/validation.py +1 -1
  84. euporie/core/widgets/_settings.py +188 -0
  85. euporie/core/widgets/cell.py +19 -50
  86. euporie/core/widgets/cell_outputs.py +25 -36
  87. euporie/core/widgets/decor.py +11 -41
  88. euporie/core/widgets/dialog.py +62 -27
  89. euporie/core/widgets/display.py +12 -15
  90. euporie/core/widgets/file_browser.py +2 -23
  91. euporie/core/widgets/forms.py +8 -5
  92. euporie/core/widgets/inputs.py +13 -70
  93. euporie/core/widgets/layout.py +2 -1
  94. euporie/core/widgets/logo.py +49 -0
  95. euporie/core/widgets/menu.py +10 -8
  96. euporie/core/widgets/pager.py +6 -10
  97. euporie/core/widgets/palette.py +6 -6
  98. euporie/hub/app.py +52 -35
  99. euporie/notebook/_commands.py +24 -0
  100. euporie/notebook/_settings.py +107 -0
  101. euporie/notebook/app.py +49 -171
  102. euporie/notebook/filters.py +1 -1
  103. euporie/notebook/tabs/__init__.py +46 -7
  104. euporie/notebook/tabs/_commands.py +714 -0
  105. euporie/notebook/tabs/_settings.py +32 -0
  106. euporie/notebook/tabs/display.py +4 -4
  107. euporie/notebook/tabs/edit.py +11 -44
  108. euporie/notebook/tabs/json.py +5 -5
  109. euporie/notebook/tabs/log.py +1 -18
  110. euporie/notebook/tabs/notebook.py +11 -660
  111. euporie/notebook/widgets/_commands.py +11 -0
  112. euporie/notebook/widgets/_settings.py +19 -0
  113. euporie/notebook/widgets/side_bar.py +14 -34
  114. euporie/preview/_settings.py +104 -0
  115. euporie/preview/app.py +6 -31
  116. euporie/preview/tabs/notebook.py +6 -72
  117. euporie/web/__init__.py +1 -0
  118. euporie/web/tabs/__init__.py +14 -0
  119. euporie/web/tabs/web.py +11 -6
  120. euporie/web/widgets/__init__.py +1 -0
  121. euporie/web/widgets/webview.py +5 -15
  122. {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/METADATA +10 -8
  123. euporie-2.8.6.dist-info/RECORD +175 -0
  124. {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/WHEEL +1 -1
  125. {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/entry_points.txt +2 -2
  126. {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/licenses/LICENSE +1 -1
  127. euporie/core/launch.py +0 -64
  128. euporie/core/terminal.py +0 -522
  129. euporie-2.8.4.dist-info/RECORD +0 -147
  130. {euporie-2.8.4.data → euporie-2.8.6.data}/data/share/applications/euporie-console.desktop +0 -0
  131. {euporie-2.8.4.data → euporie-2.8.6.data}/data/share/applications/euporie-notebook.desktop +0 -0
euporie/core/lsp.py CHANGED
@@ -13,8 +13,9 @@ from typing import TYPE_CHECKING, NamedTuple
13
13
  from prompt_toolkit.utils import Event
14
14
 
15
15
  if TYPE_CHECKING:
16
+ from collections.abc import Coroutine, Sequence
16
17
  from concurrent.futures import Future
17
- from typing import Any, Callable, Coroutine, Sequence
18
+ from typing import Any, Callable
18
19
 
19
20
 
20
21
  log = logging.getLogger(__name__)
@@ -475,6 +476,7 @@ class LspClient:
475
476
  "cellTextDocuments": [],
476
477
  }
477
478
  langs = self.can_change_nb_langs
479
+ lsp_notebook_cell: dict[str, Any]
478
480
  for cell in cells:
479
481
  if langs and cell.language not in langs:
480
482
  continue
@@ -598,6 +600,7 @@ class LspClient:
598
600
  },
599
601
  }
600
602
  langs = self.can_change_nb_langs
603
+ lsp_notebook_cell: dict[str, Any]
601
604
  for cell in cells:
602
605
  # If specified, only sync cells with the languages the server has requested
603
606
  if langs and cell.language not in langs:
@@ -657,6 +660,7 @@ class LspClient:
657
660
  "change": {"cells": (change := {"data": [], "textContent": []})},
658
661
  }
659
662
  langs = self.can_change_nb_langs
663
+ lsp_notebook_cell: dict[str, Any]
660
664
  for cell in cells:
661
665
  self._doc_versions[cell.path] += 1
662
666
  # If specified, only sync cells with the languages the server has requested
@@ -1032,10 +1036,24 @@ class LspClient:
1032
1036
 
1033
1037
  KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1034
1038
  # Custom additions
1035
- "ruff": {"command": ["ruff-lsp"], "languages": {"python"}},
1036
1039
  "typos": {"command": ["typos-lsp"], "languages": set()},
1037
1040
  # Helix's known LSPs
1038
1041
  "als": {"command": ["als"]},
1042
+ "ada-language-server": {"command": ["ada_language_server"], "languages": {"ada"}},
1043
+ "ada-gpr-language-server": {
1044
+ "command": ["ada_language_server", "--language-gpr"],
1045
+ "languages": {"ada"},
1046
+ },
1047
+ "angular": {
1048
+ "command": [
1049
+ "ngserver",
1050
+ "--stdio",
1051
+ "--tsProbeLocations",
1052
+ ".",
1053
+ "--ngProbeLocations",
1054
+ ".",
1055
+ ]
1056
+ },
1039
1057
  "awk-language-server": {"command": ["awk-language-server"], "languages": {"awk"}},
1040
1058
  "bash-language-server": {
1041
1059
  "command": ["bash-language-server", "start"],
@@ -1043,11 +1061,16 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1043
1061
  },
1044
1062
  "bass": {"command": ["bass", "--lsp"], "languages": {"bass"}},
1045
1063
  "bicep-langserver": {"command": ["bicep-langserver"], "languages": {"bicep"}},
1064
+ "bitbake-language-server": {
1065
+ "command": ["bitbake-language-server"],
1066
+ "languages": {"bitbake"},
1067
+ },
1046
1068
  "bufls": {"command": ["bufls", "serve"], "languages": {"protobuf"}},
1047
1069
  "cairo-language-server": {
1048
1070
  "command": ["cairo-language-server"],
1049
1071
  "languages": {"cairo"},
1050
1072
  },
1073
+ "circom-lsp": {"command": ["circom-lsp"], "languages": {"circom"}},
1051
1074
  "cl-lsp": {"command": ["cl-lsp", "stdio"], "languages": {"common-lisp"}},
1052
1075
  "clangd": {"command": ["clangd"], "languages": {"opencl", "cpp", "c"}},
1053
1076
  "clojure-lsp": {"command": ["clojure-lsp"], "languages": {"clojure"}},
@@ -1071,16 +1094,22 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1071
1094
  "command": ["docker-langserver", "--stdio"],
1072
1095
  "languages": {"dockerfile"},
1073
1096
  },
1097
+ "docker-compose-langserver": {
1098
+ "command": ["docker-compose-langserver", "--stdio"],
1099
+ "languages": {"docker-compose"},
1100
+ },
1074
1101
  "dot-language-server": {
1075
1102
  "command": ["dot-language-server", "--stdio"],
1076
1103
  "languages": {"dot"},
1077
1104
  },
1105
+ "earthlyls": {"command": ["earthlyls"], "languages": {"earthfile"}},
1078
1106
  "elixir-ls": {
1079
- "settings": {"elixirLS": {"dialyzerEnabled": False}},
1107
+ "config": {"elixirLS": {"dialyzerEnabled": False}},
1080
1108
  "command": ["elixir-ls"],
1081
- "languages": {"elixir", "heex"},
1109
+ "languages": {"heex", "elixir"},
1082
1110
  },
1083
1111
  "elm-language-server": {"command": ["elm-language-server"], "languages": {"elm"}},
1112
+ "elp": {"command": ["elp", "server"], "languages": {"erlang"}},
1084
1113
  "elvish": {"command": ["elvish", "-lsp"], "languages": {"elvish"}},
1085
1114
  "erlang-ls": {"command": ["erlang_ls"], "languages": {"erlang"}},
1086
1115
  "forc": {"command": ["forc", "lsp"], "languages": {"sway"}},
@@ -1090,11 +1119,12 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1090
1119
  "languages": {"fortran"},
1091
1120
  },
1092
1121
  "fsharp-ls": {
1093
- "settings": {"AutomaticWorkspaceInit": True},
1122
+ "config": {"AutomaticWorkspaceInit": True},
1094
1123
  "command": ["fsautocomplete"],
1095
1124
  "languages": {"fsharp"},
1096
1125
  },
1097
1126
  "gleam": {"command": ["gleam", "lsp"], "languages": {"gleam"}},
1127
+ "glsl_analyzer": {"command": ["glsl_analyzer"], "languages": {"glsl"}},
1098
1128
  "graphql-language-service": {
1099
1129
  "command": ["graphql-lsp", "server", "-m", "stream"],
1100
1130
  "languages": {"graphql"},
@@ -1103,9 +1133,12 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1103
1133
  "command": ["haskell-language-server-wrapper", "--lsp"],
1104
1134
  "languages": {"cabal", "haskell"},
1105
1135
  },
1136
+ "hyprls": {"command": ["hyprls"], "languages": {"hyprlang"}},
1106
1137
  "idris2-lsp": {"command": ["idris2-lsp"], "languages": {"idris"}},
1107
1138
  "intelephense": {"command": ["intelephense", "--stdio"], "languages": {"php"}},
1108
1139
  "jdtls": {"command": ["jdtls"], "languages": {"java"}},
1140
+ "jedi": {"command": ["jedi-language-server"], "languages": {"python"}},
1141
+ "jq-lsp": {"command": ["jq-lsp"], "languages": {"jq"}},
1109
1142
  "jsonnet-language-server": {
1110
1143
  "command": ["jsonnet-language-server", "-t", "--lint"],
1111
1144
  "languages": {"jsonnet"},
@@ -1122,22 +1155,39 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1122
1155
  ],
1123
1156
  "languages": {"julia"},
1124
1157
  },
1158
+ "koka": {
1159
+ "command": ["koka", "--language-server", "--lsstdio"],
1160
+ "languages": {"koka"},
1161
+ },
1125
1162
  "kotlin-language-server": {
1126
1163
  "command": ["kotlin-language-server"],
1127
1164
  "languages": {"kotlin"},
1128
1165
  },
1129
- "lean": {"command": ["lean", "--server"], "languages": {"lean"}},
1166
+ "lean": {"command": ["lean", "--server", "--memory=1024"], "languages": {"lean"}},
1130
1167
  "ltex-ls": {"command": ["ltex-ls"]},
1131
1168
  "markdoc-ls": {"command": ["markdoc-ls", "--stdio"], "languages": {"markdoc"}},
1169
+ "markdown-oxide": {"command": ["markdown-oxide"], "languages": {"markdown"}},
1132
1170
  "marksman": {"command": ["marksman", "server"], "languages": {"markdown"}},
1133
1171
  "metals": {
1134
- "settings": {"isHttpEnabled": True},
1172
+ "config": {
1173
+ "isHttpEnabled": True,
1174
+ "metals": {
1175
+ "inlayHints": {
1176
+ "typeParameters": {"enable": True},
1177
+ "hintsInPatternMatch": {"enable": True},
1178
+ }
1179
+ },
1180
+ },
1135
1181
  "command": ["metals"],
1136
1182
  "languages": {"scala"},
1137
1183
  },
1184
+ "mesonlsp": {"command": ["mesonlsp", "--lsp"], "languages": {"meson"}},
1138
1185
  "mint": {"command": ["mint", "ls"], "languages": {"mint"}},
1186
+ "mojo-lsp": {"command": ["mojo-lsp-server"], "languages": {"mojo"}},
1139
1187
  "nil": {"command": ["nil"], "languages": {"nix"}},
1140
1188
  "nimlangserver": {"command": ["nimlangserver"], "languages": {"nim"}},
1189
+ "nimlsp": {"command": ["nimlsp"]},
1190
+ "nixd": {"command": ["nixd"], "languages": {"nix"}},
1141
1191
  "nls": {"command": ["nls"], "languages": {"nickel"}},
1142
1192
  "nu-lsp": {"command": ["nu", "--lsp"], "languages": {"nu"}},
1143
1193
  "ocamllsp": {"command": ["ocamllsp"], "languages": {"ocaml", "ocaml-interface"}},
@@ -1150,6 +1200,10 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1150
1200
  "pasls": {"command": ["pasls"], "languages": {"pascal"}},
1151
1201
  "pbkit": {"command": ["pb", "lsp"], "languages": {"protobuf"}},
1152
1202
  "perlnavigator": {"command": ["perlnavigator", "--stdio"], "languages": {"perl"}},
1203
+ "pest-language-server": {
1204
+ "command": ["pest-language-server"],
1205
+ "languages": {"pest"},
1206
+ },
1153
1207
  "prisma-language-server": {
1154
1208
  "command": ["prisma-language-server", "--stdio"],
1155
1209
  "languages": {"prisma"},
@@ -1158,13 +1212,18 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1158
1212
  "command": ["purescript-language-server", "--stdio"],
1159
1213
  "languages": {"purescript"},
1160
1214
  },
1161
- "pylsp": {"command": ["pylsp"], "languages": {"python"}},
1162
- "pyright": {"settings": {}, "command": ["pyright-langserver", "--stdio"]},
1215
+ "pylsp": {"command": ["pylsp"], "languages": {"snakemake", "python"}},
1216
+ "pyright": {"config": {}, "command": ["pyright-langserver", "--stdio"]},
1217
+ "basedpyright": {"config": {}, "command": ["basedpyright-langserver", "--stdio"]},
1163
1218
  "pylyzer": {"command": ["pylyzer", "--server"]},
1164
1219
  "qmlls": {"command": ["qmlls"], "languages": {"qml"}},
1220
+ "quint-language-server": {
1221
+ "command": ["quint-language-server", "--stdio"],
1222
+ "languages": {"quint"},
1223
+ },
1165
1224
  "r": {
1166
1225
  "command": ["R", "--no-echo", "-e", "languageserver::run()"],
1167
- "languages": {"r", "rmarkdown"},
1226
+ "languages": {"rmarkdown", "r"},
1168
1227
  },
1169
1228
  "racket": {
1170
1229
  "command": ["racket", "-l", "racket-langserver"],
@@ -1176,11 +1235,16 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1176
1235
  "languages": {"rescript"},
1177
1236
  },
1178
1237
  "robotframework_ls": {"command": ["robotframework_ls"], "languages": {"robot"}},
1238
+ "ruff": {"command": ["ruff", "server"], "languages": {"python"}},
1179
1239
  "serve-d": {"command": ["serve-d"], "languages": {"d"}},
1180
1240
  "slint-lsp": {"command": ["slint-lsp"], "languages": {"slint"}},
1181
1241
  "solargraph": {"command": ["solargraph", "stdio"], "languages": {"ruby"}},
1182
1242
  "solc": {"command": ["solc", "--lsp"], "languages": {"solidity"}},
1183
1243
  "sourcekit-lsp": {"command": ["sourcekit-lsp"], "languages": {"swift"}},
1244
+ "spade-language-server": {
1245
+ "command": ["spade-language-server"],
1246
+ "languages": {"spade"},
1247
+ },
1184
1248
  "svlangserver": {"command": ["svlangserver"], "languages": {"verilog"}},
1185
1249
  "swipl": {
1186
1250
  "command": [
@@ -1196,6 +1260,7 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1196
1260
  ],
1197
1261
  "languages": {"prolog"},
1198
1262
  },
1263
+ "superhtml": {"command": ["superhtml", "lsp"], "languages": {"html"}},
1199
1264
  "tailwindcss-ls": {"command": ["tailwindcss-language-server", "--stdio"]},
1200
1265
  "taplo": {"command": ["taplo", "lsp", "stdio"], "languages": {"toml"}},
1201
1266
  "templ": {"command": ["templ", "lsp"], "languages": {"templ"}},
@@ -1204,36 +1269,38 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1204
1269
  "languages": {"tfvars", "hcl"},
1205
1270
  },
1206
1271
  "texlab": {"command": ["texlab"], "languages": {"latex", "bibtex"}},
1272
+ "typespec": {"command": ["tsp-server", "--stdio"], "languages": {"typespec"}},
1207
1273
  "vala-language-server": {
1208
1274
  "command": ["vala-language-server"],
1209
1275
  "languages": {"vala"},
1210
1276
  },
1277
+ "vale-ls": {"command": ["vale-ls"]},
1211
1278
  "vhdl_ls": {"command": ["vhdl_ls"], "languages": {"vhdl"}},
1212
1279
  "vlang-language-server": {"command": ["v-analyzer"], "languages": {"v"}},
1213
1280
  "vscode-css-language-server": {
1214
- "settings": {"provideFormatter": True, "css": {"validate": {"enable": True}}},
1281
+ "config": {"provideFormatter": True, "css": {"validate": {"enable": True}}},
1215
1282
  "command": ["vscode-css-language-server", "--stdio"],
1216
1283
  "languages": {"scss", "css"},
1217
1284
  },
1218
1285
  "vscode-html-language-server": {
1219
- "settings": {"provideFormatter": True},
1286
+ "config": {"provideFormatter": True},
1220
1287
  "command": ["vscode-html-language-server", "--stdio"],
1221
1288
  "languages": {"html"},
1222
1289
  },
1223
1290
  "vscode-json-language-server": {
1224
- "settings": {"provideFormatter": True, "json": {"validate": {"enable": True}}},
1291
+ "config": {"provideFormatter": True, "json": {"validate": {"enable": True}}},
1225
1292
  "command": ["vscode-json-language-server", "--stdio"],
1226
- "languages": {"json"},
1293
+ "languages": {"jsonc", "json"},
1227
1294
  },
1228
1295
  "vuels": {
1229
- "settings": {"typescript": {"tsdk": "node_modules/typescript/lib/"}},
1296
+ "config": {"typescript": {"tsdk": "node_modules/typescript/lib/"}},
1230
1297
  "command": ["vue-language-server", "--stdio"],
1231
1298
  "languages": {"vue"},
1232
1299
  },
1233
1300
  "wgsl_analyzer": {"command": ["wgsl_analyzer"], "languages": {"wgsl"}},
1234
1301
  "yaml-language-server": {
1235
1302
  "command": ["yaml-language-server", "--stdio"],
1236
- "languages": {"yaml"},
1303
+ "languages": {"yaml", "docker-compose"},
1237
1304
  },
1238
1305
  "zls": {"command": ["zls"], "languages": {"zig"}},
1239
1306
  "blueprint-compiler": {
@@ -1241,12 +1308,22 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1241
1308
  "languages": {"blueprint"},
1242
1309
  },
1243
1310
  "typst-lsp": {"command": ["typst-lsp"], "languages": {"typst"}},
1311
+ "tinymist": {"command": ["tinymist"], "languages": {"typst"}},
1312
+ "pkgbuild-language-server": {
1313
+ "command": ["pkgbuild-language-server"],
1314
+ "languages": {"pkgbuild"},
1315
+ },
1316
+ "helm_ls": {"command": ["helm_ls", "serve"], "languages": {"helm"}},
1317
+ "ember-language-server": {
1318
+ "command": ["ember-language-server", "--stdio"],
1319
+ "languages": {"gts", "gjs", "glimmer"},
1320
+ },
1244
1321
  "ansible-language-server": {
1245
1322
  "command": ["ansible-language-server", "--stdio"],
1246
1323
  "languages": {"yaml"},
1247
1324
  },
1248
1325
  "lua-language-server": {
1249
- "settings": {
1326
+ "config": {
1250
1327
  "Lua": {
1251
1328
  "hint": {
1252
1329
  "enable": True,
@@ -1262,7 +1339,7 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1262
1339
  "languages": {"lua"},
1263
1340
  },
1264
1341
  "gopls": {
1265
- "settings": {
1342
+ "config": {
1266
1343
  "hints": {
1267
1344
  "assignVariableTypes": True,
1268
1345
  "compositeLiteralFields": True,
@@ -1273,10 +1350,10 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1273
1350
  }
1274
1351
  },
1275
1352
  "command": ["gopls"],
1276
- "languages": {"gotmpl", "gowork", "go", "gomod"},
1353
+ "languages": {"go", "gowork", "gotmpl", "gomod"},
1277
1354
  },
1278
1355
  "golangci-lint-lsp": {
1279
- "settings": {
1356
+ "config": {
1280
1357
  "command": [
1281
1358
  "golangci-lint",
1282
1359
  "run",
@@ -1289,7 +1366,7 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1289
1366
  "languages": {"go"},
1290
1367
  },
1291
1368
  "rust-analyzer": {
1292
- "settings": {
1369
+ "config": {
1293
1370
  "inlayHints": {
1294
1371
  "bindingModeHints": {"enable": False},
1295
1372
  "closingBraceHints": {"minLines": 10},
@@ -1303,7 +1380,7 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1303
1380
  "languages": {"rust"},
1304
1381
  },
1305
1382
  "typescript-language-server": {
1306
- "settings": {
1383
+ "config": {
1307
1384
  "hostInfo": "helix",
1308
1385
  "typescript": {
1309
1386
  "inlayHints": {
@@ -1329,10 +1406,10 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1329
1406
  },
1330
1407
  },
1331
1408
  "command": ["typescript-language-server", "--stdio"],
1332
- "languages": {"tsx", "typescript", "jsx", "javascript"},
1409
+ "languages": {"jsx", "typescript", "javascript", "tsx"},
1333
1410
  },
1334
1411
  "svelteserver": {
1335
- "settings": {
1412
+ "config": {
1336
1413
  "configuration": {
1337
1414
  "typescript": {
1338
1415
  "inlayHints": {
@@ -1359,4 +1436,21 @@ KNOWN_LSP_SERVERS: dict[str, dict[str, Any]] = {
1359
1436
  "command": ["svelteserver", "--stdio"],
1360
1437
  "languages": {"svelte"},
1361
1438
  },
1439
+ "vscode-eslint-language-server": {
1440
+ "config": {
1441
+ "validate": "on",
1442
+ "experimental": {"useFlatConfig": False},
1443
+ "rulesCustomizations": [],
1444
+ "run": "onType",
1445
+ "problems": {"shortenToSingleLine": False},
1446
+ "nodePath": "",
1447
+ "codeAction": {
1448
+ "disableRuleComment": {"enable": True, "location": "separateLine"},
1449
+ "showDocumentation": {"enable": True},
1450
+ },
1451
+ "workingDirectory": {"mode": "location"},
1452
+ },
1453
+ "command": ["vscode-eslint-language-server", "--stdio"],
1454
+ "languages": {"gts", "gjs"},
1455
+ },
1362
1456
  }
euporie/core/margins.py CHANGED
@@ -17,7 +17,7 @@ from prompt_toolkit.layout.screen import WritePosition
17
17
  from prompt_toolkit.mouse_events import MouseButton, MouseEventType
18
18
  from prompt_toolkit.mouse_events import MouseEvent as PtkMouseEvent
19
19
 
20
- from euporie.core.current import get_app
20
+ from euporie.core.app.current import get_app
21
21
  from euporie.core.key_binding.bindings.mouse import MouseEvent, RelativePosition
22
22
  from euporie.core.layout.containers import Window
23
23
 
euporie/core/path.py CHANGED
@@ -9,35 +9,72 @@ from typing import TYPE_CHECKING
9
9
  import upath
10
10
  from aiohttp.client_reqrep import ClientResponse
11
11
  from fsspec.implementations.http import HTTPFileSystem as FsHTTPFileSystem
12
+ from fsspec.implementations.http import get_client
12
13
  from fsspec.registry import register_implementation as fs_register_implementation
13
14
  from upath import UPath
14
15
 
15
16
  if TYPE_CHECKING:
17
+ import asyncio
18
+ from collections.abc import Mapping
16
19
  from os import PathLike
17
- from typing import Any, Mapping
20
+ from typing import Any, Callable
18
21
 
19
-
20
- log = logging.getLogger(__name__)
21
-
22
-
23
- # Monkey-patch `aiohttp` to not raise exceptions on non-200 responses
22
+ import aiohttp
24
23
 
25
24
 
26
- def _raise_for_status(self: ClientResponse) -> None:
27
- """Monkey-patch :py:class:`aiohttp.ClientResponse` not to raise for any status."""
28
-
25
+ log = logging.getLogger(__name__)
29
26
 
30
- setattr(ClientResponse, "raise_for_status", _raise_for_status) # noqa B010
31
27
 
28
+ class NoRaiseClientResponse(ClientResponse):
29
+ """An ``aiohttp`` client response which does not raise on >=400 status responses."""
32
30
 
33
- # Define and register non-raising HTTP filesystem implementation for fsspec
31
+ @property
32
+ def ok(self) -> bool:
33
+ """Returns ``True`` if ``status`` is probably renderable."""
34
+ return self.status not in {405}
34
35
 
35
36
 
36
37
  class HTTPFileSystem(FsHTTPFileSystem):
37
- """A :py:class:`HTTPFileSystem` which does not raise exceptions on 404 errors."""
38
+ """A HTTP filesystem implementation which does not raise on errors."""
39
+
40
+ def __init__(
41
+ self,
42
+ simple_links: bool = True,
43
+ block_size: int | None = None,
44
+ same_scheme: bool = True,
45
+ size_policy: None = None,
46
+ cache_type: str = "bytes",
47
+ cache_options: dict[str, Any] | None = None,
48
+ asynchronous: bool = False,
49
+ loop: asyncio.AbstractEventLoop | None = None,
50
+ client_kwargs: dict[str, Any] | None = None,
51
+ get_client: Callable[..., aiohttp.ClientSession] = get_client,
52
+ encoded: bool = False,
53
+ **storage_options: Any,
54
+ ) -> None:
55
+ """Defaults to using :py:mod:`NoRaiseClientResponse` for responses."""
56
+ client_kwargs = {
57
+ "response_class": NoRaiseClientResponse,
58
+ **(client_kwargs or {}),
59
+ }
60
+ super().__init__(
61
+ simple_links=simple_links,
62
+ block_size=block_size,
63
+ same_scheme=same_scheme,
64
+ size_policy=size_policy,
65
+ cache_type=cache_type,
66
+ cache_options=cache_options,
67
+ asynchronous=asynchronous,
68
+ loop=loop,
69
+ client_kwargs=client_kwargs,
70
+ get_client=get_client,
71
+ encoded=encoded,
72
+ **storage_options,
73
+ )
38
74
 
39
75
  def _raise_not_found_for_status(self, response: ClientResponse, url: str) -> None:
40
76
  """Do not raise an exception for 404 errors."""
77
+ response.raise_for_status()
41
78
 
42
79
 
43
80
  fs_register_implementation("http", HTTPFileSystem, clobber=True)
@@ -62,8 +99,15 @@ class UntitledPath(upath.core.UPath):
62
99
  return False
63
100
 
64
101
 
65
- def parse_path(path: str | PathLike, resolve: bool = True) -> Path:
102
+ def parse_path(path: str | PathLike, resolve: bool | None = None) -> Path:
66
103
  """Parse and resolve a path."""
104
+ if resolve is None:
105
+ from upath.implementations.http import HTTPPath
106
+
107
+ if isinstance(path, HTTPPath):
108
+ resolve = True
109
+ else:
110
+ resolve = False
67
111
  if not isinstance(path, Path):
68
112
  path = UPath(path)
69
113
  try:
@@ -75,4 +119,9 @@ def parse_path(path: str | PathLike, resolve: bool = True) -> Path:
75
119
  path = path.resolve()
76
120
  except (AttributeError, NotImplementedError, Exception):
77
121
  log.info("Path %s not resolvable", path)
122
+ else:
123
+ try:
124
+ path = path.absolute()
125
+ except NotImplementedError:
126
+ pass
78
127
  return path
euporie/core/renderer.py CHANGED
@@ -3,11 +3,13 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import logging
6
+ from hashlib import md5
6
7
  from typing import TYPE_CHECKING
7
8
 
8
9
  from prompt_toolkit.data_structures import Point, Size
9
10
  from prompt_toolkit.filters import to_filter
10
11
  from prompt_toolkit.layout.mouse_handlers import MouseHandlers
12
+ from prompt_toolkit.layout.screen import Char
11
13
  from prompt_toolkit.renderer import Renderer as PtkRenderer
12
14
  from prompt_toolkit.renderer import _StyleStringHasStyleCache, _StyleStringToAttrsCache
13
15
 
@@ -25,7 +27,6 @@ if TYPE_CHECKING:
25
27
  from prompt_toolkit.output import ColorDepth, Output
26
28
  from prompt_toolkit.styles import BaseStyle
27
29
 
28
-
29
30
  __all__ = ["Renderer"]
30
31
 
31
32
  log = logging.getLogger(__name__)
@@ -117,19 +118,27 @@ def _output_screen_diff(
117
118
  write(char.char)
118
119
  last_style = char.style
119
120
 
121
+ def hash_screen_row(row: dict[int, Char], zwe_row: dict[int, str]) -> str:
122
+ """Generate a hash for a screen row to quickly detect changes."""
123
+ hasher = md5(usedforsecurity=False)
124
+ # Hash the character data
125
+ for idx in sorted(row.keys()):
126
+ cell = row[idx]
127
+ hasher.update(f"{idx}:{cell.char}:{cell.style}".encode())
128
+ # Hash the zero-width escapes
129
+ for idx in sorted(zwe_row.keys()):
130
+ hasher.update(f"{idx}:{zwe_row[idx]}".encode())
131
+ return hasher.hexdigest()
132
+
120
133
  def get_max_column_index(row: dict[int, Char], zwe_row: dict[int, str]) -> int:
121
134
  """Return max used column index, ignoring trailing unstyled whitespace."""
122
- return max(
123
- {
124
- index
125
- for index, cell in row.items()
126
- if cell.char != " " or style_string_has_style[cell.style]
127
- }
128
- # Lag ZWE indices by one, as one could exist after the last line character
129
- # but we don't want that to count towards the line width
130
- | {x - 1 for x in zwe_row}
131
- | {0}
132
- )
135
+ max_idx = 0
136
+ for idx, cell in row.items():
137
+ if cell.char != " " or style_string_has_style[cell.style]:
138
+ max_idx = max(max_idx, idx)
139
+ for idx in zwe_row:
140
+ max_idx = max(max_idx, idx - 1)
141
+ return max_idx
133
142
 
134
143
  # Render for the first time: reset styling.
135
144
  if not previous_screen:
@@ -169,6 +178,14 @@ def _output_screen_diff(
169
178
  zwe_row = screen.zero_width_escapes[y]
170
179
  previous_zwe_row = previous_screen.zero_width_escapes[y]
171
180
 
181
+ # Quick comparison using row hashes
182
+ new_hash = hash_screen_row(new_row, zwe_row)
183
+ prev_hash = hash_screen_row(previous_row, previous_zwe_row)
184
+
185
+ if new_hash == prev_hash:
186
+ # Rows are identical, skip to next row
187
+ continue
188
+
172
189
  new_max_line_len = min(width - 1, get_max_column_index(new_row, zwe_row))
173
190
  previous_max_line_len = min(
174
191
  width - 1, get_max_column_index(previous_row, previous_zwe_row)
@@ -275,26 +292,34 @@ class Renderer(PtkRenderer):
275
292
  )
276
293
  self._extended_keys_enabled = False
277
294
  self._private_sixel_colors_enabled = False
295
+ self._sgr_pixel_enabled = False
278
296
  self.extend_height = to_filter(extend_height)
279
297
  self.extend_width = to_filter(extend_width)
280
298
 
281
299
  def reset(self, _scroll: bool = False, leave_alternate_screen: bool = True) -> None:
282
300
  """Reset the output."""
283
- if isinstance(self.output, Vt100_Output):
301
+ output = self.output
302
+ if isinstance(output, Vt100_Output):
284
303
  # Disable extended keys before resetting the output
285
- self.output.disable_extended_keys()
304
+ output.disable_extended_keys()
286
305
  self._extended_keys_enabled = False
287
306
 
288
307
  # Disable private sixel colors before resetting the output
289
- self.output.disable_private_sixel_colors()
308
+ output.disable_private_sixel_colors()
290
309
  self._private_sixel_colors_enabled = False
291
310
 
311
+ # Disable sgr pixel mode
312
+ output.disable_sgr_pixel()
313
+ self._sgr_pixel_enabled = False
314
+
292
315
  super().reset(_scroll, leave_alternate_screen)
293
316
 
294
317
  def render(
295
318
  self, app: Application[Any], layout: Layout, is_done: bool = False
296
319
  ) -> None:
297
320
  """Render the current interface to the output."""
321
+ from euporie.core.app.app import BaseApp
322
+
298
323
  output = self.output
299
324
  self.app = app
300
325
 
@@ -320,13 +345,29 @@ class Renderer(PtkRenderer):
320
345
  output.enable_mouse_support()
321
346
  self._mouse_support_enabled = True
322
347
 
348
+ if (
349
+ isinstance(output, Vt100_Output)
350
+ and isinstance(app, BaseApp)
351
+ and app.term_sgr_pixel
352
+ ):
353
+ output.enable_sgr_pixel()
354
+ self._sgr_pixel_enabled = True
355
+
323
356
  elif not needs_mouse_support and self._mouse_support_enabled:
324
357
  output.disable_mouse_support()
325
358
  self._mouse_support_enabled = False
326
359
 
360
+ if (
361
+ isinstance(output, Vt100_Output)
362
+ and isinstance(app, BaseApp)
363
+ and (app.term_sgr_pixel or self._sgr_pixel_enabled)
364
+ ):
365
+ output.disable_sgr_pixel()
366
+ self._sgr_pixel_enabled = False
367
+
327
368
  # Ensable extended keys
328
- if not self._extended_keys_enabled and isinstance(self.output, Vt100_Output):
329
- self.output.enable_extended_keys()
369
+ if not self._extended_keys_enabled and isinstance(output, Vt100_Output):
370
+ output.enable_extended_keys()
330
371
  self._extended_keys_enabled = True
331
372
 
332
373
  # Ensable private sixel graphic color registers