pi-studio 0.9.32 → 0.9.33

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ All notable changes to `pi-studio` are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.9.33] — 2026-06-16
8
+
9
+ ### Added
10
+ - Added `Cmd/Ctrl+Alt+E` to switch the right pane directly to Editor Preview.
11
+
12
+ ### Changed
13
+ - Calmed annotation and comment affordance styling so annotations read more like highlighted feedback and less like heavy badges.
14
+ - Slightly muted active Stop button styling while keeping it in the theme error colour family.
15
+ - Derived PDF annotation colours from the active theme accent hue while keeping a light, print-friendly background.
16
+
17
+ ### Fixed
18
+ - Preserved the Working view scroll position when switching between `All`, `Thinking`, and `Tools` filters unless the view was already pinned to the bottom.
19
+ - Rendered standalone long `[an: ...]` annotations correctly in LaTeX-mode PDF exports even when Pandoc wraps the escaped marker across generated LaTeX lines.
20
+
7
21
  ## [0.9.32] — 2026-06-10
8
22
 
9
23
  ### Added
package/README.md CHANGED
@@ -22,7 +22,7 @@ Extension for [pi](https://pi.dev) that opens a local two-pane browser workspace
22
22
  - Supports one canonical full Studio view per Pi session, plus additional editor-only companion views when you want extra editing/preview surfaces; editor-only views can also browse files and use the Studio REPL send controls without taking over the full Studio session view
23
23
  - Includes a global **Zen** mode for hiding secondary Studio chrome without changing the current left/right pane layout
24
24
  - Runs editor text directly, asks for structured critique (auto/writing/code focus), offers a manual **Suggest completion** action for short cursor-aware continuations (`Option/Alt+Tab` where available or `Cmd/Ctrl+Shift+Space` from the editor, `Tab` to insert a visible suggestion) with an optional editor-plus-latest-response context mode, or opens **Quiz me** for a Studio-native active-recall loop over the current editor text, selection, current file, folder, or repo, with optional focus guidance for shaping question selection
25
- - Includes a live **Working** view for following current model/tool activity, with `All` / `Thinking` / `Tools` filters, image previews for image-producing tool outputs, plus **Load visible into editor** and **Copy visible** actions; when cycling response history, Working follows saved working details for the selected response when available, and `Cmd/Ctrl+Alt+W` switches the right pane directly to Working
25
+ - Includes a live **Working** view for following current model/tool activity, with `All` / `Thinking` / `Tools` filters, image previews for image-producing tool outputs, plus **Load visible into editor** and **Copy visible** actions; when cycling response history, Working follows saved working details for the selected response when available, and `Cmd/Ctrl+Alt+P` / `Cmd/Ctrl+Alt+E` / `Cmd/Ctrl+Alt+W` switch directly between Response Preview, Editor Preview, and Working
26
26
  - Includes a right-pane **Changes** view for browsing the current git diff by file, previewing per-file diffs, opening changed files, loading the full diff into the editor, and copying the diff
27
27
  - Includes a right-pane **Files** view for browsing the current Pi session/resource directory, opening folders, opening the Files root in Finder/the system file manager, loading text/code/CSV/TSV documents into the editor, previewing PDFs/images, opening PDF/image previews in a new Studio tab, converting DOCX/ODT documents to editable Markdown when Pandoc is available after confirmation, copying paths, setting the current folder as the Studio working directory, and revealing files in the file manager
28
28
  - Includes an optional tmux-backed **REPL** view for Shell, Python, IPython, Julia, R, GHCi, and Clojure sessions, with Raw/Literate send modes, `Cmd/Ctrl+Shift+Enter` **Send to REPL**, session start/stop/interrupt controls, a compact refresh-persistent **Studio REPL Record** of user and Pi-sent code, a secondary raw tmux mirror, agent-facing `studio_repl_status` / `studio_repl_send` tools, and Markdown/PDF/HTML export
@@ -269,8 +269,8 @@
269
269
  option.disabled = isEditorOnlyMode && !editorOnlyAllowed.has(option.value);
270
270
  });
271
271
  rightViewSelect.title = isEditorOnlyMode
272
- ? "Editor-only views: editor preview, Changes, Files, or REPL. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P switches directly to Preview."
273
- : "Right pane view mode. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P switches directly to Preview; Cmd/Ctrl+Alt+W switches directly to Working.";
272
+ ? "Editor-only views: editor preview, Changes, Files, or REPL. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P or Cmd/Ctrl+Alt+E switches directly to Preview."
273
+ : "Right pane view mode. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P switches directly to Response Preview; Cmd/Ctrl+Alt+E switches directly to Editor Preview; Cmd/Ctrl+Alt+W switches directly to Working.";
274
274
  }
275
275
 
276
276
  function getInitialRightView(source) {
@@ -859,7 +859,7 @@
859
859
  const normalized = normalizeTraceFilter(nextFilter);
860
860
  if (traceFilter === normalized) return;
861
861
  traceFilter = normalized;
862
- traceAutoScroll = true;
862
+ traceAutoScroll = rightView === "trace" ? shouldStickTraceToBottom() : traceAutoScroll;
863
863
  renderTraceViewIfActive();
864
864
  }
865
865
 
@@ -3817,6 +3817,13 @@
3817
3817
  setStatus("Right pane view: Working.");
3818
3818
  }
3819
3819
 
3820
+ function switchRightPaneToEditorPreview() {
3821
+ const snapshot = snapshotStudioScrollablePositions();
3822
+ setRightView("editor-preview");
3823
+ scheduleStudioScrollablePositionRestore(snapshot);
3824
+ setStatus("Right pane view: Editor (Preview).");
3825
+ }
3826
+
3820
3827
  function cycleActivePaneView(direction) {
3821
3828
  if (activePane === "right") {
3822
3829
  if (!rightViewSelect || rightViewSelect.disabled) {
@@ -4135,6 +4142,16 @@
4135
4142
  return;
4136
4143
  }
4137
4144
 
4145
+ const isEditorPreviewShortcut = (key.toLowerCase() === "e" || code === "KeyE")
4146
+ && (event.metaKey || event.ctrlKey)
4147
+ && event.altKey
4148
+ && !event.shiftKey;
4149
+ if (isEditorPreviewShortcut) {
4150
+ event.preventDefault();
4151
+ switchRightPaneToEditorPreview();
4152
+ return;
4153
+ }
4154
+
4138
4155
  const isContentFocusShortcut = key === "F8" && !event.metaKey && !event.ctrlKey && !event.altKey;
4139
4156
  if (isContentFocusShortcut) {
4140
4157
  event.preventDefault();
package/client/studio.css CHANGED
@@ -210,15 +210,17 @@
210
210
 
211
211
  #sendRunBtn.request-stop-active,
212
212
  #critiqueBtn.request-stop-active {
213
- background: var(--error);
214
- border-color: var(--error);
213
+ background: color-mix(in srgb, var(--error) 82%, var(--panel));
214
+ border-color: color-mix(in srgb, var(--error) 88%, var(--panel));
215
215
  color: var(--error-contrast);
216
- font-weight: 600;
216
+ font-weight: 700;
217
217
  }
218
218
 
219
219
  #sendRunBtn.request-stop-active:not(:disabled):hover,
220
220
  #critiqueBtn.request-stop-active:not(:disabled):hover {
221
- filter: brightness(0.95);
221
+ background: var(--error);
222
+ border-color: var(--error);
223
+ filter: none;
222
224
  }
223
225
 
224
226
  .file-label {
@@ -930,17 +932,17 @@
930
932
  padding: 0 10px;
931
933
  font-size: 12px;
932
934
  line-height: 1;
933
- background: var(--accent-soft);
934
- border-color: var(--accent);
935
- color: var(--accent);
935
+ background: color-mix(in srgb, var(--panel) 88%, var(--accent-soft));
936
+ border-color: var(--control-border);
937
+ color: var(--text);
936
938
  box-shadow: 0 1px 2px var(--shadow-color);
937
939
  }
938
940
 
939
941
  .editor-selection-action-btn:hover,
940
942
  .editor-selection-action-btn:focus-visible {
941
- background: var(--accent-soft-strong);
943
+ background: var(--accent-soft);
942
944
  color: var(--accent);
943
- border-color: var(--accent);
945
+ border-color: color-mix(in srgb, var(--accent) 45%, var(--control-border));
944
946
  }
945
947
 
946
948
  .editor-selection-actions[hidden],
@@ -1043,12 +1045,12 @@
1043
1045
  }
1044
1046
 
1045
1047
  .hl-annotation {
1046
- color: var(--accent);
1047
- background: var(--accent-soft);
1048
+ color: color-mix(in srgb, var(--accent) 72%, var(--text));
1049
+ background: color-mix(in srgb, var(--accent-soft) 58%, transparent);
1048
1050
  border: 0;
1049
- border-radius: 4px;
1051
+ border-radius: 3px;
1050
1052
  padding: 0;
1051
- box-shadow: inset 0 0 0 1px var(--marker-border);
1053
+ box-shadow: inset 0 -0.08em 0 color-mix(in srgb, var(--accent) 26%, transparent);
1052
1054
  }
1053
1055
 
1054
1056
  .hl-annotation-muted {
@@ -1057,10 +1059,10 @@
1057
1059
  }
1058
1060
 
1059
1061
  .annotation-preview-marker {
1060
- color: var(--accent);
1061
- background: var(--accent-soft);
1062
- border: 1px solid var(--marker-border);
1063
- border-radius: 4px;
1062
+ color: color-mix(in srgb, var(--accent) 72%, var(--text));
1063
+ background: color-mix(in srgb, var(--accent-soft) 58%, transparent);
1064
+ border: 1px solid color-mix(in srgb, var(--marker-border) 26%, transparent);
1065
+ border-radius: 3px;
1064
1066
  display: inline-block;
1065
1067
  max-width: 100%;
1066
1068
  padding: 0 4px;
@@ -1068,6 +1070,20 @@
1068
1070
  vertical-align: baseline;
1069
1071
  }
1070
1072
 
1073
+ .annotation-preview-marker strong {
1074
+ color: color-mix(in srgb, var(--accent) 82%, var(--text));
1075
+ font-weight: 750;
1076
+ }
1077
+
1078
+ .annotation-preview-marker em {
1079
+ color: color-mix(in srgb, currentColor 82%, var(--muted));
1080
+ }
1081
+
1082
+ .annotation-preview-marker s {
1083
+ color: color-mix(in srgb, currentColor 70%, var(--muted));
1084
+ text-decoration-thickness: 0.08em;
1085
+ }
1086
+
1071
1087
  .annotation-preview-marker code {
1072
1088
  font-family: var(--mono-font, ui-monospace, SFMono-Regular, Menlo, monospace);
1073
1089
  font-size: 0.95em;
@@ -1216,9 +1232,9 @@
1216
1232
  padding: 0 10px;
1217
1233
  font-size: 12px;
1218
1234
  line-height: 1;
1219
- background: var(--accent-soft);
1220
- border-color: var(--accent);
1221
- color: var(--accent);
1235
+ background: color-mix(in srgb, var(--panel) 88%, var(--accent-soft));
1236
+ border-color: var(--control-border);
1237
+ color: var(--text);
1222
1238
  box-shadow: 0 1px 2px var(--shadow-color);
1223
1239
  pointer-events: auto;
1224
1240
  }
@@ -1227,9 +1243,9 @@
1227
1243
  .preview-comment-add:focus-visible,
1228
1244
  .preview-comment-jump:hover,
1229
1245
  .preview-comment-jump:focus-visible {
1230
- background: var(--accent-soft-strong);
1246
+ background: var(--accent-soft);
1231
1247
  color: var(--accent);
1232
- border-color: var(--accent);
1248
+ border-color: color-mix(in srgb, var(--accent) 45%, var(--control-border));
1233
1249
  }
1234
1250
 
1235
1251
  .preview-jump-highlight {
@@ -5779,10 +5795,10 @@
5779
5795
  }
5780
5796
 
5781
5797
  body.studio-ui-refresh .studio-refresh-review-btn.request-stop-active {
5782
- background: var(--error);
5783
- border-color: var(--error);
5798
+ background: color-mix(in srgb, var(--error) 82%, var(--panel));
5799
+ border-color: color-mix(in srgb, var(--error) 88%, var(--panel));
5784
5800
  color: var(--error-contrast);
5785
- font-weight: 600;
5801
+ font-weight: 700;
5786
5802
  }
5787
5803
 
5788
5804
  body.studio-ui-refresh .studio-refresh-review-btn.request-stop-active::after {
@@ -5790,10 +5806,10 @@
5790
5806
  }
5791
5807
 
5792
5808
  body.studio-ui-refresh .studio-refresh-menu #critiqueBtn.request-stop-active {
5793
- background: var(--error);
5794
- border-color: var(--error);
5809
+ background: color-mix(in srgb, var(--error) 82%, var(--panel));
5810
+ border-color: color-mix(in srgb, var(--error) 88%, var(--panel));
5795
5811
  color: var(--error-contrast);
5796
- font-weight: 600;
5812
+ font-weight: 700;
5797
5813
  }
5798
5814
 
5799
5815
  .studio-preview-link-menu {
package/index.ts CHANGED
@@ -1066,7 +1066,23 @@ function buildStudioPdfCalloutTitleSizeCommand(options?: StudioPdfRenderOptions)
1066
1066
  return "\\footnotesize";
1067
1067
  }
1068
1068
 
1069
- function buildStudioPdfPreamble(options?: StudioPdfRenderOptions, extraPreamble = ""): string {
1069
+ function formatStudioPdfHtmlColor(color: string, fallback: string): string {
1070
+ return hexToRgb(color) ? color.replace(/^#/, "").toUpperCase() : fallback;
1071
+ }
1072
+
1073
+ function buildStudioPdfAnnotationColors(style: StudioThemeStyle): { bg: string; border: string; text: string } {
1074
+ const accent = hexToRgb(style.palette.accent) ? style.palette.accent : "#2F6FEB";
1075
+ const page = "#FFFFFF";
1076
+ const darkText = "#0E1616";
1077
+ return {
1078
+ bg: formatStudioPdfHtmlColor(blendColors(accent, page, 0.91), "F1F7FF"),
1079
+ border: formatStudioPdfHtmlColor(blendColors(accent, page, 0.68), "C7DDFF"),
1080
+ text: formatStudioPdfHtmlColor(blendColors(accent, darkText, style.mode === "light" ? 0.40 : 0.34), "1F5FBF"),
1081
+ };
1082
+ }
1083
+
1084
+ function buildStudioPdfPreamble(options?: StudioPdfRenderOptions, extraPreamble = "", themeStyle?: StudioThemeStyle): string {
1085
+ const annotationColors = buildStudioPdfAnnotationColors(themeStyle ?? getStudioThemeStyle());
1070
1086
  const sectionHeadingSize = buildStudioPdfHeadingSizeCommand(options?.sectionSize, "\\Large");
1071
1087
  const subsectionHeadingSize = buildStudioPdfHeadingSizeCommand(options?.subsectionSize, "\\large");
1072
1088
  const subsubsectionHeadingSize = buildStudioPdfHeadingSizeCommand(options?.subsubsectionSize, "\\normalsize");
@@ -1088,9 +1104,9 @@ function buildStudioPdfPreamble(options?: StudioPdfRenderOptions, extraPreamble
1088
1104
  \\usepackage{xcolor}
1089
1105
  \\usepackage{varwidth}
1090
1106
  \\usepackage[normalem]{ulem}
1091
- \\definecolor{StudioAnnotationBg}{HTML}{EAF3FF}
1092
- \\definecolor{StudioAnnotationBorder}{HTML}{8CB8FF}
1093
- \\definecolor{StudioAnnotationText}{HTML}{1F5FBF}
1107
+ \\definecolor{StudioAnnotationBg}{HTML}{${annotationColors.bg}}
1108
+ \\definecolor{StudioAnnotationBorder}{HTML}{${annotationColors.border}}
1109
+ \\definecolor{StudioAnnotationText}{HTML}{${annotationColors.text}}
1094
1110
  \\definecolor{StudioCodeBlockBg}{HTML}{F6F8FA}
1095
1111
  \\definecolor{StudioDiffAddText}{HTML}{1A7F37}
1096
1112
  \\definecolor{StudioDiffDelText}{HTML}{CF222E}
@@ -6501,9 +6517,20 @@ ${literalPdfConfig.fontSizeCommand}\\section*{${title.replace(/[{}\\]/g, "").tri
6501
6517
  function replaceStudioAnnotationMarkersInGeneratedLatex(latex: string): string {
6502
6518
  const lines = String(latex ?? "").split("\n");
6503
6519
  const out: string[] = [];
6520
+ const pendingTextLines: string[] = [];
6504
6521
  const rawEnvStack: string[] = [];
6505
6522
  const rawEnvNames = new Set(["verbatim", "Verbatim", "Highlighting", "lstlisting"]);
6506
6523
 
6524
+ const hasRawEnvBoundary = (line: string): boolean => {
6525
+ const envPattern = /\\(begin|end)\{([^}]+)\}/g;
6526
+ let match: RegExpExecArray | null;
6527
+ while ((match = envPattern.exec(line)) !== null) {
6528
+ const envName = match[2];
6529
+ if (envName && rawEnvNames.has(envName)) return true;
6530
+ }
6531
+ return false;
6532
+ };
6533
+
6507
6534
  const updateRawEnvStack = (line: string) => {
6508
6535
  const envPattern = /\\(begin|end)\{([^}]+)\}/g;
6509
6536
  let match: RegExpExecArray | null;
@@ -6524,6 +6551,12 @@ function replaceStudioAnnotationMarkersInGeneratedLatex(latex: string): string {
6524
6551
  }
6525
6552
  };
6526
6553
 
6554
+ const flushPendingText = () => {
6555
+ if (pendingTextLines.length === 0) return;
6556
+ out.push(replaceStudioAnnotationMarkersForPdfInSegment(pendingTextLines.join("\n")));
6557
+ pendingTextLines.length = 0;
6558
+ };
6559
+
6527
6560
  for (const line of lines) {
6528
6561
  if (rawEnvStack.length > 0) {
6529
6562
  out.push(line);
@@ -6531,10 +6564,17 @@ function replaceStudioAnnotationMarkersInGeneratedLatex(latex: string): string {
6531
6564
  continue;
6532
6565
  }
6533
6566
 
6534
- out.push(replaceStudioAnnotationMarkersForPdfInSegment(line));
6535
- updateRawEnvStack(line);
6567
+ if (hasRawEnvBoundary(line)) {
6568
+ flushPendingText();
6569
+ out.push(line);
6570
+ updateRawEnvStack(line);
6571
+ continue;
6572
+ }
6573
+
6574
+ pendingTextLines.push(line);
6536
6575
  }
6537
6576
 
6577
+ flushPendingText();
6538
6578
  return out.join("\n");
6539
6579
  }
6540
6580
 
@@ -6727,6 +6767,7 @@ async function renderStudioPdfFromGeneratedLatex(
6727
6767
  alignedImageBlocks: StudioPdfAlignedImageBlock[] = [],
6728
6768
  pdfOptions?: StudioPdfRenderOptions,
6729
6769
  extraPreamble = "",
6770
+ themeStyle?: StudioThemeStyle,
6730
6771
  ): Promise<{ pdf: Buffer; warning?: string }> {
6731
6772
  const tempDir = join(tmpdir(), `pi-studio-pdf-${Date.now()}-${randomUUID()}`);
6732
6773
  const preamblePath = join(tempDir, "_pdf_preamble.tex");
@@ -6734,7 +6775,7 @@ async function renderStudioPdfFromGeneratedLatex(
6734
6775
  const outputPath = join(tempDir, "studio-export.pdf");
6735
6776
 
6736
6777
  await mkdir(tempDir, { recursive: true });
6737
- await writeFile(preamblePath, buildStudioPdfPreamble(pdfOptions, extraPreamble), "utf-8");
6778
+ await writeFile(preamblePath, buildStudioPdfPreamble(pdfOptions, extraPreamble, themeStyle), "utf-8");
6738
6779
 
6739
6780
  const pandocArgs = [
6740
6781
  "-f", inputFormat,
@@ -6805,6 +6846,7 @@ async function renderStudioPdfWithPandoc(
6805
6846
  editorPdfLanguage?: string,
6806
6847
  sourcePath?: string,
6807
6848
  pdfOptions?: StudioPdfRenderOptions,
6849
+ themeStyle?: StudioThemeStyle,
6808
6850
  ): Promise<{ pdf: Buffer; warning?: string }> {
6809
6851
  const pandocCommand = process.env.PANDOC_PATH?.trim() || "pandoc";
6810
6852
  const pdfEngine = process.env.PANDOC_PDF_ENGINE?.trim() || "xelatex";
@@ -6842,7 +6884,7 @@ async function renderStudioPdfWithPandoc(
6842
6884
  const outputPath = join(tempDir, "studio-export.pdf");
6843
6885
 
6844
6886
  await mkdir(tempDir, { recursive: true });
6845
- await writeFile(preamblePath, buildStudioPdfPreamble(pdfOptions), "utf-8");
6887
+ await writeFile(preamblePath, buildStudioPdfPreamble(pdfOptions, "", themeStyle), "utf-8");
6846
6888
 
6847
6889
  const hasYamlHeaderIncludesForPdf = inputFormat !== "latex" && hasStudioYamlHeaderIncludes(markdownForPdf);
6848
6890
  const headerIncludeArgs = hasYamlHeaderIncludesForPdf ? [] : ["--include-in-header", preamblePath];
@@ -6895,6 +6937,8 @@ async function renderStudioPdfWithPandoc(
6895
6937
  [],
6896
6938
  [],
6897
6939
  pdfOptions,
6940
+ "",
6941
+ themeStyle,
6898
6942
  );
6899
6943
  }
6900
6944
 
@@ -6915,6 +6959,8 @@ async function renderStudioPdfWithPandoc(
6915
6959
  [],
6916
6960
  [],
6917
6961
  pdfOptions,
6962
+ "",
6963
+ themeStyle,
6918
6964
  );
6919
6965
  } catch {
6920
6966
  const fenced = parseStudioSingleFencedCodeBlock(diffMarkdown);
@@ -6941,7 +6987,7 @@ async function renderStudioPdfWithPandoc(
6941
6987
  const outputPath = join(tempDir, "studio-export.pdf");
6942
6988
 
6943
6989
  await mkdir(tempDir, { recursive: true });
6944
- await writeFile(preamblePath, buildStudioPdfPreamble(pdfOptions, extraPdfPreamble), "utf-8");
6990
+ await writeFile(preamblePath, buildStudioPdfPreamble(pdfOptions, extraPdfPreamble, themeStyle), "utf-8");
6945
6991
 
6946
6992
  const mermaidPrepared: StudioMermaidPdfPreprocessResult = isLatex
6947
6993
  ? { markdown: normalizedMarkdownBody, found: 0, replaced: 0, failed: 0, missingCli: false }
@@ -6964,6 +7010,7 @@ async function renderStudioPdfWithPandoc(
6964
7010
  pdfAlignedImageTransform.blocks,
6965
7011
  pdfOptions,
6966
7012
  extraPdfPreamble,
7013
+ themeStyle,
6967
7014
  );
6968
7015
  await rm(tempDir, { recursive: true, force: true }).catch(() => undefined);
6969
7016
  return { pdf: rendered.pdf, warning: mermaidPrepared.warning ?? rendered.warning };
@@ -10514,7 +10561,7 @@ ${cssVarsBlock}
10514
10561
  <section id="rightPane">
10515
10562
  <div id="rightSectionHeader" class="section-header">
10516
10563
  <div class="section-header-main">
10517
- <select id="rightViewSelect" aria-label="Response view mode" title="Right pane view mode. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P switches directly to Preview; Cmd/Ctrl+Alt+W switches directly to Working.">
10564
+ <select id="rightViewSelect" aria-label="Response view mode" title="Right pane view mode. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P switches directly to Response Preview; Cmd/Ctrl+Alt+E switches directly to Editor Preview; Cmd/Ctrl+Alt+W switches directly to Working.">
10518
10565
  <option value="markdown">Response (Raw)</option>
10519
10566
  <option value="preview" selected>Response (Preview)</option>
10520
10567
  <option value="editor-preview">Editor (Preview)</option>
@@ -10608,7 +10655,8 @@ ${cssVarsBlock}
10608
10655
  <dl>
10609
10656
  <div><dt>F6</dt><dd>Switch between editor and right pane</dd></div>
10610
10657
  <div><dt>F7 / Shift+F7</dt><dd>Cycle the active pane's view</dd></div>
10611
- <div><dt>Cmd/Ctrl+Alt+P</dt><dd>Switch the right pane directly to Preview</dd></div>
10658
+ <div><dt>Cmd/Ctrl+Alt+P</dt><dd>Switch the right pane directly to Response Preview</dd></div>
10659
+ <div><dt>Cmd/Ctrl+Alt+E</dt><dd>Switch the right pane directly to Editor Preview</dd></div>
10612
10660
  <div><dt>Cmd/Ctrl+Alt+W</dt><dd>Switch the right pane directly to Working</dd></div>
10613
10661
  <div><dt>F8</dt><dd>Focus editor text</dd></div>
10614
10662
  <div><dt>Shift+F8</dt><dd>Focus right-pane content</dd></div>
@@ -13553,7 +13601,7 @@ export default function (pi: ExtensionAPI) {
13553
13601
  const filename = sanitizePdfFilename(requestedFilename || (isLatex ? "studio-latex-preview.pdf" : "studio-preview.pdf"));
13554
13602
 
13555
13603
  try {
13556
- const { pdf, warning } = await renderStudioPdfWithPandoc(markdown, isLatex, resourcePath, editorPdfLanguage, sourcePath || undefined);
13604
+ const { pdf, warning } = await renderStudioPdfWithPandoc(markdown, isLatex, resourcePath, editorPdfLanguage, sourcePath || undefined, undefined, getStudioThemeStyle(lastCommandCtx?.ui?.theme));
13557
13605
  const writeResult = writeStudioPreviewExportFile(buildStudioPreviewExportPath(sourcePath || undefined, userResourceDir || undefined, studioCwd, filename), pdf);
13558
13606
  const exportId = storePreparedPdfExport(pdf, filename, warning, writeResult.filePath ?? undefined);
13559
13607
  const token = serverState?.token ?? "";
@@ -14984,6 +15032,7 @@ export default function (pi: ExtensionAPI) {
14984
15032
  editorPdfLanguage,
14985
15033
  source.sourcePath,
14986
15034
  pdfOptions,
15035
+ getStudioThemeStyle(ctx.ui.theme),
14987
15036
  );
14988
15037
  await writeFile(source.outputPath, pdf);
14989
15038
  const openError = await maybeOpenStudioExportPath(source.outputPath, params.open);
@@ -15296,6 +15345,7 @@ export default function (pi: ExtensionAPI) {
15296
15345
  editorPdfLanguage,
15297
15346
  undefined,
15298
15347
  pdfOptions,
15348
+ getStudioThemeStyle(ctx.ui.theme),
15299
15349
  );
15300
15350
  await writeFile(outputPath, pdf);
15301
15351
 
@@ -15354,6 +15404,7 @@ export default function (pi: ExtensionAPI) {
15354
15404
  editorPdfLanguage,
15355
15405
  file.resolvedPath,
15356
15406
  pdfOptions,
15407
+ getStudioThemeStyle(ctx.ui.theme),
15357
15408
  );
15358
15409
  await writeFile(outputPath, pdf);
15359
15410
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-studio",
3
- "version": "0.9.32",
3
+ "version": "0.9.33",
4
4
  "description": "Two-pane browser workspace for pi with prompt/response editing, annotations, critiques, active quiz, prompt/response history, live previews, and tmux-backed REPL/literate REPL workflows",
5
5
  "type": "module",
6
6
  "license": "MIT",