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" >█ ; </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" >█ ; </span >
45+ </div >
3546 </div >
3647</template >
3748
3849<script lang="ts">
3950import { defineComponent } from ' vue' ;
4051import prompt from ' @/lib/prompt' ;
4152import { UniquePromptElement } from ' @/lib/promptElement' ;
53+ import { MinusCircleIcon , XCircleIcon } from ' @heroicons/vue/24/solid' ;
4254import 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: {
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