@@ -6,36 +6,136 @@ import { Copy, Check } from 'lucide-react';
66export function Terminal ( ) {
77 const [ terminalStep , setTerminalStep ] = useState ( 0 ) ;
88 const [ copied , setCopied ] = useState ( false ) ;
9- const terminalSteps = [
10- 'conda create -n collabllm python=3.10' ,
11- 'conda activate collabllm' ,
12- 'pip install collabllm' ,
13- '' ,
14- 'git clone https://github.com/Wuyxin/collabllm.git' ,
15- 'python -m scripts.engine.build_dataset <...>' ,
16- 'python -m scripts.train.{sft/*_dpo/ppo} <...>' ,
9+ const pipCommand = [
10+ 'pip install verbalized-sampling'
1711 ] ;
1812
13+ const pythonCode = [
14+ 'verbalize run \\' ,
15+ ' --task joke \\' ,
16+ ' --prompt "Tell me a joke about coffee." \\' ,
17+ ' --model "gpt-4.1" \\' ,
18+ ' --methods "direct vs_standard" \\' ,
19+ ' --num-responses 10 \\' ,
20+ ' --metrics "diversity joke_quality"'
21+ ] ;
22+
23+ const allSteps = [ ...pipCommand , '' , ...pythonCode ] ;
24+
1925 useEffect ( ( ) => {
2026 const timer = setTimeout ( ( ) => {
2127 setTerminalStep ( ( prev ) =>
22- prev < terminalSteps . length - 1 ? prev + 1 : prev
28+ prev < allSteps . length - 1 ? prev + 1 : prev
2329 ) ;
2430 } , 500 ) ;
2531
2632 return ( ) => clearTimeout ( timer ) ;
27- } , [ terminalStep ] ) ;
33+ } , [ terminalStep , allSteps ] ) ;
2834
2935 const copyToClipboard = ( ) => {
30- navigator . clipboard . writeText ( terminalSteps . join ( '\n' ) ) ;
36+ navigator . clipboard . writeText ( allSteps . join ( '\n' ) ) ;
3137 setCopied ( true ) ;
3238 setTimeout ( ( ) => setCopied ( false ) , 2000 ) ;
3339 } ;
3440
41+ const colorizeCode = ( line : string ) => {
42+ // Handle empty lines
43+ if ( line . trim ( ) === '' ) {
44+ return < span className = "text-gray-500" > </ span > ;
45+ }
46+
47+ // Handle comments
48+ if ( line . trim ( ) . startsWith ( '#' ) ) {
49+ return (
50+ < span className = "text-gray-400" >
51+ { line . replace ( '#' , '' ) }
52+ </ span >
53+ ) ;
54+ }
55+
56+ // Handle pip install command
57+ if ( line . includes ( 'pip install' ) ) {
58+ return (
59+ < >
60+ < span className = "text-blue-400" > pip</ span >
61+ < span className = "text-white" > install </ span >
62+ < span className = "text-yellow-300" > verbalized-sampling</ span >
63+ </ >
64+ ) ;
65+ }
66+
67+ // Handle verbalize command
68+ if ( line . includes ( 'verbalize run' ) ) {
69+ return (
70+ < >
71+ < span className = "text-blue-400" > verbalize</ span >
72+ < span className = "text-white" > run </ span >
73+ < span className = "text-white" > \\</ span >
74+ </ >
75+ ) ;
76+ }
77+
78+ // Handle command line arguments (lines starting with spaces and --)
79+ if ( line . trim ( ) . startsWith ( '--' ) ) {
80+ const leadingSpaces = line . match ( / ^ ( \s * ) / ) ?. [ 1 ] || '' ;
81+ const restOfLine = line . trim ( ) ;
82+ // Convert spaces to non-breaking spaces to preserve them
83+ const preservedSpaces = leadingSpaces . replace ( / / g, '\u00A0' ) ;
84+ return (
85+ < >
86+ < span className = "text-white" > { preservedSpaces } </ span >
87+ < span className = "text-white" > { restOfLine } </ span >
88+ </ >
89+ ) ;
90+ }
91+
92+ // Handle import statements
93+ if ( line . startsWith ( 'from ' ) || line . startsWith ( 'import ' ) ) {
94+ const parts = line . split ( ' ' ) ;
95+ return (
96+ < >
97+ < span className = "text-blue-400" > { parts [ 0 ] } </ span >
98+ < span className = "text-white" > </ span >
99+ < span className = "text-green-300" > { parts . slice ( 1 ) . join ( ' ' ) } </ span >
100+ </ >
101+ ) ;
102+ }
103+
104+ // Handle variable assignments
105+ if ( line . includes ( ' = ' ) ) {
106+ const [ variable , ...rest ] = line . split ( ' = ' ) ;
107+ return (
108+ < >
109+ < span className = "text-yellow-300" > { variable } </ span >
110+ < span className = "text-white" > = </ span >
111+ < span className = "text-blue-300" > { rest . join ( ' = ' ) } </ span >
112+ </ >
113+ ) ;
114+ }
115+
116+ // Handle function calls
117+ if ( line . includes ( '(' ) && line . includes ( ')' ) ) {
118+ const beforeParen = line . substring ( 0 , line . indexOf ( '(' ) ) ;
119+ const parenContent = line . substring ( line . indexOf ( '(' ) , line . lastIndexOf ( ')' ) + 1 ) ;
120+ const afterParen = line . substring ( line . lastIndexOf ( ')' ) + 1 ) ;
121+
122+ return (
123+ < >
124+ < span className = "text-cyan-300" > { beforeParen } </ span >
125+ < span className = "text-white" > { parenContent } </ span >
126+ < span className = "text-white" > { afterParen } </ span >
127+ </ >
128+ ) ;
129+ }
130+
131+ // Default case
132+ return < span className = "text-white" > { line } </ span > ;
133+ } ;
134+
35135 return (
36- < div className = "w-full rounded-lg shadow-lg overflow-hidden bg-gray-900 text-white font-mono text-sm relative" >
37- < div className = "p-4 " >
38- < div className = "flex justify-between items-center mb-4 " >
136+ < div className = "w-full min-w-full rounded-lg shadow-lg overflow-hidden bg-gray-900 text-white font-mono text-sm relative" >
137+ < div className = "p-1 " >
138+ < div className = "flex justify-between items-center mb-2 " >
39139 < div className = "flex space-x-2" >
40140 < div className = "w-3 h-3 rounded-full bg-red-500" > </ div >
41141 < div className = "w-3 h-3 rounded-full bg-yellow-500" > </ div >
@@ -54,14 +154,47 @@ export function Terminal() {
54154 </ button >
55155 </ div >
56156 < div className = "space-y-2" >
57- { terminalSteps . map ( ( step , index ) => (
58- < div
59- key = { index }
60- className = { `${ index > terminalStep ? 'opacity-0' : 'opacity-100' } transition-opacity duration-300` }
61- >
62- < span className = "text-green-400" > $</ span > { step }
157+ { /* Pip Install Block */ }
158+ < div className = "space-y-1" >
159+ < div className = "text-xs text-gray-500 mb-1" > Installation:</ div >
160+ { pipCommand . map ( ( step , index ) => (
161+ < div
162+ key = { `pip-${ index } ` }
163+ className = { `${ index > terminalStep ? 'opacity-0' : 'opacity-100' } transition-opacity duration-300 whitespace-nowrap` }
164+ >
165+ < span className = "text-green-400" > $</ span > { colorizeCode ( step ) }
166+ </ div >
167+ ) ) }
168+ </ div >
169+
170+ { /* Separator */ }
171+ < div className = { `${ pipCommand . length > terminalStep ? 'opacity-0' : 'opacity-100' } transition-opacity duration-300` } >
172+ < div className = "text-gray-500" > </ div >
173+ </ div >
174+
175+ { /* Python Code Block */ }
176+ < div className = "space-y-1" >
177+ < div className = { `${ pipCommand . length + pythonCode . length > terminalStep ? 'opacity-0' : 'opacity-100' } transition-opacity duration-300 text-xs text-gray-500 mb-1` } >
178+ Usage Example:
63179 </ div >
64- ) ) }
180+ { pythonCode . map ( ( step , index ) => {
181+ const globalIndex = pipCommand . length + 1 + index ;
182+ return (
183+ < div
184+ key = { `python-${ index } ` }
185+ className = { `${ globalIndex > terminalStep ? 'opacity-0' : 'opacity-100' } transition-opacity duration-300 whitespace-pre` }
186+ >
187+ { step . trim ( ) === '' ? (
188+ colorizeCode ( step )
189+ ) : (
190+ < >
191+ < span className = "text-green-400" > $</ span > { colorizeCode ( step ) }
192+ </ >
193+ ) }
194+ </ div >
195+ ) ;
196+ } ) }
197+ </ div >
65198 </ div >
66199 </ div >
67200 </ div >
0 commit comments