Skip to content

Commit f73b0dd

Browse files
committed
Show terminal window title in preview
1 parent 043f37a commit f73b0dd

File tree

1 file changed

+98
-32
lines changed

1 file changed

+98
-32
lines changed

src/components/output/PromptPreview.vue

+98-32
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,54 @@
33
<IconButton icon="LightBulbIcon" title="Toggle dark/light preview" @click="togglePreview"></IconButton>
44
<br />
55
<div class="preview" :class="{ light, dark: !light }">
6-
<span
7-
v-for="element in elements"
8-
:key="element.id"
9-
:style="{
10-
backgroundColor: `${element.data.attributes.reverse
11-
? element.data.foregroundColor?.hex ?? (light ? '#212121' : '#fafafa')
12-
: element.data.backgroundColor?.hex ?? (light ? '#fafafa' : '#212121')} !important`,
13-
}"
14-
>
6+
<div class="preview-head">
7+
<span v-for="element in elements.windowTitle" :key="element.id">
8+
{{ element.data.type.preview(element.data.parameters) }}
9+
</span>
10+
<span class="preview-window-controls">
11+
<MinusCircleIcon class="icon"></MinusCircleIcon>
12+
<XCircleIcon class="icon"></XCircleIcon>
13+
</span>
14+
</div>
15+
<div class="preview-body">
1516
<span
16-
v-if="element.data.type.preview(element.data.parameters) !== '\n'"
17+
v-for="element in elements.prompt"
18+
:key="element.id"
1719
:style="{
18-
color: `${element.data.attributes.reverse
19-
? element.data.backgroundColor?.hex ?? (light ? '#fafafa' : '#212121')
20-
: element.data.foregroundColor?.hex ?? (light ? '#212121' : '#fafafa')} !important`,
20+
backgroundColor: `${element.data.attributes.reverse
21+
? element.data.foregroundColor?.hex ?? (light ? '#212121' : '#fafafa')
22+
: element.data.backgroundColor?.hex ?? (light ? '#fafafa' : '#212121')} !important`,
2123
}"
22-
:class="{
23-
'preview-bold': element.data.attributes.bold,
24-
'preview-dim': element.data.attributes.dim,
25-
'preview-italic': element.data.attributes.italic,
26-
'preview-underline': element.data.attributes.underline,
27-
'preview-blink': element.data.attributes.blink,
28-
'preview-overline': element.data.attributes.overline,
29-
}"
30-
>{{ element.data.type.preview(element.data.parameters) }}</span
3124
>
32-
<br v-else />
33-
</span>
34-
<span class="cursor">&#9608;</span>
25+
<span
26+
v-if="element.data.type.preview(element.data.parameters) !== '\n'"
27+
:style="{
28+
color: `${element.data.attributes.reverse
29+
? element.data.backgroundColor?.hex ?? (light ? '#fafafa' : '#212121')
30+
: element.data.foregroundColor?.hex ?? (light ? '#212121' : '#fafafa')} !important`,
31+
}"
32+
:class="{
33+
'preview-bold': element.data.attributes.bold,
34+
'preview-dim': element.data.attributes.dim,
35+
'preview-italic': element.data.attributes.italic,
36+
'preview-underline': element.data.attributes.underline,
37+
'preview-blink': element.data.attributes.blink,
38+
'preview-overline': element.data.attributes.overline,
39+
}"
40+
>{{ element.data.type.preview(element.data.parameters) }}</span
41+
>
42+
<br v-else />
43+
</span>
44+
<span class="cursor">&#9608;</span>
45+
</div>
3546
</div>
3647
</template>
3748

3849
<script lang="ts">
3950
import { defineComponent } from 'vue';
4051
import prompt from '@/lib/prompt';
4152
import { UniquePromptElement } from '@/lib/promptElement';
53+
import { MinusCircleIcon, XCircleIcon } from '@heroicons/vue/24/solid';
4254
import IconButton from '../ui/IconButton.vue';
4355
4456
/**
@@ -102,6 +114,8 @@ export default defineComponent({
102114
name: 'PromptPreview',
103115
components: {
104116
IconButton,
117+
MinusCircleIcon,
118+
XCircleIcon,
105119
},
106120
data() {
107121
return {
@@ -119,21 +133,39 @@ export default defineComponent({
119133
*/
120134
elements: () => {
121135
const elements = [...prompt.state().elements];
136+
122137
// split elements on carriage returns
123-
const crPartitions = [[]] as UniquePromptElement[][];
138+
const crPartitions = {
139+
prompt: [[]] as UniquePromptElement[][],
140+
windowTitle: [[]] as UniquePromptElement[][],
141+
};
142+
// whether an operating system command ('Set Window Title') has been encountered and awaits an ending bell
143+
let operatingSystemCommand: boolean = false;
144+
124145
while (elements.length > 0) {
125146
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
126147
const element = elements.shift()!;
127148
if (element.data.type.preview(element.data.parameters) === '\r') {
128-
crPartitions.push([]);
149+
(operatingSystemCommand ? crPartitions.windowTitle : crPartitions.prompt).push([]);
150+
} else if (element.data.type.name === 'Set Window Title') {
151+
// any previous window title is overwritten by the new one
152+
crPartitions.windowTitle = [[]];
153+
operatingSystemCommand = true;
154+
} else if (element.data.type.name === 'Bell' && operatingSystemCommand) {
155+
operatingSystemCommand = false;
156+
} else if (operatingSystemCommand) {
157+
crPartitions.windowTitle[crPartitions.windowTitle.length - 1].push(element);
129158
} else {
130-
crPartitions[crPartitions.length - 1].push(element);
159+
crPartitions.prompt[crPartitions.prompt.length - 1].push(element);
131160
}
132161
}
133162
134163
// merge partitions from left to right as the third partition may overlay elements from the second partition which
135164
// again may overlay elements from the first partition
136-
return crPartitions.reduce(mergeCrPartitions);
165+
return {
166+
prompt: crPartitions.prompt.reduce(mergeCrPartitions),
167+
windowTitle: crPartitions.windowTitle.reduce(mergeCrPartitions),
168+
};
137169
},
138170
},
139171
methods: {
@@ -167,22 +199,56 @@ h3
167199
.preview
168200
display: inline-block
169201
margin: 1em 0 2em 0
170-
padding: 1em
171202
font-family: 'Roboto Mono', 'Noto Sans Mono', monospace
172203
text-align: left
173204
line-height: 1.5
174205
min-height: 1.5em
175206
word-break: break-all
176207
white-space: pre-wrap
208+
border: 0.1em solid $color-dim
209+
border-top-left-radius: 0.5em
210+
border-top-right-radius: 0.5em
177211
178212
&.light
179-
background-color: #fafafa !important
180213
color: #212121 !important
181214
215+
.preview-head
216+
background-color: #e0e0e0 !important
217+
218+
.preview-body
219+
background-color: #fafafa !important
220+
182221
&.dark
183-
background-color: #212121 !important
184222
color: #fafafa !important
185223
224+
.preview-head
225+
background-color: #111111 !important
226+
227+
.preview-body
228+
background-color: #212121 !important
229+
230+
.preview-head
231+
display: block
232+
padding: 0.5em 1em
233+
border-bottom: 0.1em solid $color-dim
234+
border-radius: inherit
235+
236+
.preview-window-controls
237+
float: right
238+
margin-left: 1.5em
239+
// opacity: 0.7
240+
color: $color-button
241+
242+
.icon
243+
margin: 0 0.1em
244+
height: 1.2em
245+
vertical-align: middle
246+
247+
248+
.preview-body
249+
padding: 1em
250+
padding-right: 10em
251+
186252
// display attributes
187253
188254
.preview-bold

0 commit comments

Comments
 (0)