Compare commits

..

2 Commits

Author SHA1 Message Date
Sylvia Crowe 0cdb63bec8 fix: frontend changes for shell pref in imports
This continues the previous changes to allow the shell to be configured
after importing the ssh_config file. This allows temporary editing of
the shell preference for imported remotes as well as adding a keywork to
allow it to be set in the ssh_config file.
2024-01-31 12:56:26 -08:00
Sylvia Crowe 0417c8a158 fix: set shellpref default settings for backend
The shell preference is a new feature that was never integrated into ssh
config importing. This makes the backend changes to allow that to
happen.
2024-01-31 12:17:33 -08:00
194 changed files with 10558 additions and 13219 deletions
+11 -16
View File
@@ -1,31 +1,28 @@
# Build Instructions for Wave Terminal
These instructions are for setting up the build on MacOS.
These instructions are for setting up the build on MacOS.
If you're developing on Linux please use the [Linux Build Instructions](./build-linux.md).
## Running the Development Version of Wave
If you install the production version of Wave, you'll see a semi-transparent gray sidebar, and the data for Wave is stored in the directory ~/.waveterm. The development version has a blue sidebar and stores its data in ~/.waveterm-dev. This allows the production and development versions to be run simultaneously with no conflicts. If the dev database is corrupted by development bugs, or the schema changes in development it will not affect the production copy.
If you install the production version of Wave, you'll see a semi-transparent sidebar, and the data for Wave is stored in the directory ~/.waveterm. The development version has a blue sidebar and stores its data in ~/.waveterm-dev. This allows the production and development versions to be run simultaneously with no conflicts. If the dev database is corrupted by development bugs, or the schema changes in development it will not affect the production copy.
## Prereqs and Tools
Download and install Go (must be at least go 1.18):
```
brew install go
```
Download and install ScriptHaus (to run the build commands):
```
brew tap scripthaus-dev/scripthaus
brew install scripthaus
```
You also need a relatively modern nodejs with npm and yarn installed.
- Node can be installed from [https://nodejs.org](https://nodejs.org).
- npm can install yarn using:
* Node can be installed from [https://nodejs.org](https://nodejs.org).
* npm can install yarn using:
```
npm install -g yarn
@@ -43,17 +40,16 @@ git clone git@github.com:wavetermdev/waveterm.git
scripthaus run build-backend
```
This builds the Golang backends for Wave. The binaries will put in waveshell/bin and wavesrv/bin respectively. If you're working on a new plugin or other pure frontend changes to Wave, you won't need to rebuild these unless you pull new code from the Wave Repository.
This builds the Golang backends for Wave. The binaries will put in waveshell/bin and wavesrv/bin respectively. If you're working on a new plugin or other pure frontend changes to Wave, you won't need to rebuild these unless you pull new code from the Wave Repository.
## One-Time Setup
Install modules (we use yarn):
```
yarn
```
Electron also requires specific builds of node_modules to work (because Electron embeds a specific node.js version that might not match your development node.js version). We use a special electron command to cross-compile those modules:
Electron also requires specific builds of node_modules to work (because Electron embeds a specific node.js version that might not match your development node.js version). We use a special electron command to cross-compile those modules:
```
scripthaus run electron-rebuild
@@ -61,7 +57,7 @@ scripthaus run electron-rebuild
## Running WebPack
We use webpack to build both the React and Electron App Wrapper code. They are both run together using:
We use webpack to build both the React and Electron App Wrapper code. They are both run together using:
```
scripthaus run webpack-watch
@@ -69,16 +65,15 @@ scripthaus run webpack-watch
## Running the WaveTerm Dev Client
Now that webpack is running (and watching for file changes) we can finally run the WaveTerm Dev Client! To start the client run:
Now that webpack is running (and watching for file changes) we can finally run the WaveTerm Dev Client! To start the client run:
```
scripthaus run electron
```
To kill the client, either exit the Electron App normally or just Ctrl-C the `scripthaus run electron` command.
To kill the client, either exit the Electron App normally or just Ctrl-C the ```scripthaus run electron``` command.
Because we're running webpack in watch mode, any changes you make to the typescript will be automatically picked up by the client after a refresh. Note that I've disabled hot-reloading in the webpack config, so to pick up new changes you'll have to manually refresh the WaveTerm Client window. To do that use "Option-R" (Command-R is used internally by WaveTerm and will not force a refresh).
Because we're running webpack in watch mode, any changes you make to the typescript will be automatically picked up by the client after a refresh. Note that I've disabled hot-reloading in the webpack config, so to pick up new changes you'll have to manually refresh the WaveTerm Client window. To do that use "Command-Shift-R" (Command-R is used internally by WaveTerm and will not force a refresh).
## Debugging the Dev Client
You can use the regular Chrome DevTools to debug the frontend application. You can open the DevTools using the keyboard shortcut `Cmd-Option-I`.
You can use the regular Chrome DevTools to debug the frontend application. You can open the DevTools using the keyboard shortcut `Cmd-Option-I`.
+23 -25
View File
@@ -1,25 +1,23 @@
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./assets/wave-logo_horizontal-coloronblack.svg">
<source media="(prefers-color-scheme: light)" srcset="./assets/wave-logo_horizontal-coloronwhite.svg">
<img alt="Wave Terminal Logo" src="./assets/wave-logo_horizontal-coloronwhite.svg" width="352" height="59" style="max-width: 100%;">
<source media="(prefers-color-scheme: dark)" srcset="./src/app/assets/wave-logo_horizontal-coloronblack.svg">
<source media="(prefers-color-scheme: light)" srcset="./src/app/assets/wave-logo_horizontal-coloronwhite.svg">
<img alt="Wave Terminal Logo" src="./src/app/assets/wave-logo_horizontal-coloronwhite.svg" width="352" height="59" style="max-width: 100%;">
</picture>
<br/>
</p>
# Wave Terminal
# Wave Terminal
A open-source, cross-platform, AI-integrated, modern terminal for seamless workflows.
A open-source, cross-platform, modern terminal for seamless workflows.
Wave isn't just another terminal emulator; it's a rethink on how terminals are built. Wave combines command line with the power of the open web to help veteran CLI users and new developers alike.
Wave isn't just another terminal emulator; it's a rethink on how terminals are built. Wave combines command line with the power of the open web to help veteran CLI users and new developers alike.
- Inline renderers to cut down on context switching. Render code, images, markdown, and CSV files without ever leaving the terminal.
- Persistent sessions that can restore state across network disconnections and reboots
- Searchable contextual command history across all remote sessions (saved locally)
- Workspaces, tabs, and command blocks to keep you organized
- AI Integration with ChatGPT (or ChatGPT compatible APIs) to help write commands and get answers inline
![WaveTerm Screenshot](./assets/wave-screenshot.jpeg)
* Inline renderers to cut down on context switching. Render code, images, markdown, and CSV files without ever leaving the terminal.
* Persistent sessions that can restore state across network disconnections and reboots
* Searchable contextual command history across all remote sessions (saved locally)
* Workspaces, tabs, and command blocks to keep you organized
## Installation
@@ -28,30 +26,30 @@ Wave Terminal works with MacOS and Linux (preliminary).
Install Wave Terminal from: [www.waveterm.dev/download](https://www.waveterm.dev/download)
Also available as a homebrew cask for MacOS:
```
brew install --cask wave
```
## Links
- Homepage &mdash; https://www.waveterm.dev
- Download Page &mdash; https://www.waveterm.dev/download
- Documentation &mdash; https://docs.waveterm.dev/
- Blog &mdash; https://blog.waveterm.dev/
- Quick Start Guide &mdash; https://docs.waveterm.dev/quickstart/
- Discord Community &mdash; https://discord.gg/XfvZ334gwU
* Homepage &mdash; https://www.waveterm.dev
* Download Page &mdash; https://www.waveterm.dev/download
* Documentation &mdash; https://docs.waveterm.dev/
* Quick Start Guide &mdash; https://docs.waveterm.dev/quickstart/
* Discord Community &mdash; https://discord.gg/XfvZ334gwU
## Building from Source
- [MacOS Build Instructions](./BUILD.md)
- [Linux Build Instructions](./build-linux.md)
* [MacOS Build Instructions](./BUILD.md)
* [Linux Build Instructions](./build-linux.md)
## Contributing
Wave uses Github Project for tracking issues.
Wave uses Github Project for tracking issues.
Find more information in our [Contributions Guide](CONTRIBUTING.md), which includes:
- [Ways to contribute](CONTRIBUTING.md#contributing-to-wave-terminal)
- [Contribution guidelines](CONTRIBUTING.md#before-you-start)
* [Ways to contribute](CONTRIBUTING.md#contributing-to-wave-terminal)
* [Contribution guidelines](CONTRIBUTING.md#before-you-start)
@@ -1,50 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.8.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1000 175" style="enable-background:new 0 0 1000 175;" xml:space="preserve">
<style type="text/css">
.st0{fill:url(#SVGID_1_);}
.st1{fill:url(#SVGID_00000091720229019135579030000007505974356775393451_);}
.st2{fill:#FFFFFF;}
.st3{fill:#58C142;}
.st4{fill:url(#SVGID_00000057844994756141690520000013392915125647203757_);}
.st5{fill:url(#SVGID_00000122684313424325124480000003010239515924857535_);}
.st6{fill:url(#SVGID_00000075883355893983351890000012882526639983753630_);}
.st7{fill:url(#SVGID_00000000207897583077398290000006853703841187474602_);}
.st8{fill:url(#SVGID_00000008108614519912429220000010116473681835506344_);}
.st9{fill:url(#SVGID_00000132058454267173112380000008245439973034275726_);}
.st10{fill:url(#SVGID_00000034804588790703597750000013460998990473107363_);}
.st11{fill:url(#SVGID_00000131349218605867433520000014539481291819864990_);}
.st12{fill:url(#SVGID_00000003071904852992499350000013371332860686737080_);}
.st13{fill:url(#SVGID_00000072278415138862792700000002042113538205077667_);}
</style>
<g>
<path class="st3" d="M339.7,20.6h26.5l30.9,100.8l33.5-100.8h22l33.5,100.8l31.2-100.8h26.5L497.9,156h-23.8L441.9,55.4L409.1,156
h-23.8L339.7,20.6z"/>
<path class="st3" d="M693.8,20.6V156h-25.9V133c-10.5,16.2-27.2,26.2-47.9,26.2c-35.9,0-62.3-29.3-62.3-71
c0-41.4,26.5-70.7,62.3-70.7c20.7,0,37.5,10,47.9,26.2v-23H693.8z M667.9,88.2c0-28.3-17.3-48.2-41.9-48.2
c-24.6,0-42.2,19.9-42.2,48.2c0,28.3,17.6,48.5,42.2,48.5C650.6,136.6,667.9,116.5,667.9,88.2z"/>
<path class="st3" d="M713.8,20.6h27.8l42.2,105.3l41.4-105.3h28L796,156h-24.4L713.8,20.6z"/>
<path class="st3" d="M970.7,122.2l15.2,16c-11.8,12.8-35.6,21-54.7,21c-37.5,0-69.9-29.6-69.9-71.2c0-40.6,30.6-70.5,68.1-70.5
c41.4,0,65.5,30.9,65.5,79.1H886.6c3.1,23.8,19.9,41.1,44,41.1C945.3,137.7,962.3,131.1,970.7,122.2z M886.9,77.5h82.8
c-2.6-21.7-16.2-38.5-39.8-38.5C908.1,38.9,890.8,54.1,886.9,77.5z"/>
</g>
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="5.2128" y1="58.9088" x2="240.4477" y2="58.9088">
<stop offset="0.1418" style="stop-color:#1F4D22"/>
<stop offset="0.8656" style="stop-color:#418D31"/>
</linearGradient>
<path class="st0" d="M83.6,80.8c-12.3,0-19.1,8-22.8,25.9l-55.6-8C12,40.1,34.8,11.7,79.9,11.7C113.3,11.7,146,37,162,37
c12.4,0,19.1-8.6,22.8-25.9l55.6,8c-6.2,58.7-29.6,87.1-74.7,87.1C131.8,106.1,100.3,80.8,83.6,80.8z"/>
</g>
<g>
<linearGradient id="SVGID_00000145018229965941010500000002424778669397199792_" gradientUnits="userSpaceOnUse" x1="20.9171" y1="116.0912" x2="256.1519" y2="116.0912">
<stop offset="0.2223" style="stop-color:#418D31"/>
<stop offset="0.7733" style="stop-color:#58C142"/>
</linearGradient>
<path style="fill:url(#SVGID_00000145018229965941010500000002424778669397199792_);" d="M99.3,138c-12.3,0-19.1,8-22.8,25.9
l-55.6-8c6.8-58.6,29.6-87.1,74.7-87.1c33.3,0,66.1,25.3,82.1,25.3c12.4,0,19.1-8.6,22.8-25.9l55.6,8
c-6.2,58.7-29.6,87.1-74.7,87.1C147.5,163.3,116,138,99.3,138z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

@@ -1,50 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.8.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1000 175" style="enable-background:new 0 0 1000 175;" xml:space="preserve">
<style type="text/css">
.st0{fill:url(#SVGID_1_);}
.st1{fill:url(#SVGID_00000097467401116752621440000013265923851559160252_);}
.st2{fill:#FFFFFF;}
.st3{fill:#58C142;}
.st4{fill:url(#SVGID_00000026844058065691411450000001084298207851076753_);}
.st5{fill:url(#SVGID_00000140695609015829564530000017877493759276215708_);}
.st6{fill:url(#SVGID_00000172429467579424709090000016892278147863045285_);}
.st7{fill:url(#SVGID_00000111161844774090145740000012271107721736914070_);}
.st8{fill:url(#SVGID_00000159463458951391818050000007934417898368699555_);}
.st9{fill:url(#SVGID_00000114048161574266679140000001630328408055608234_);}
.st10{fill:url(#SVGID_00000181790832707237646570000012870231436607310721_);}
.st11{fill:url(#SVGID_00000182504551275047381220000018143622223532349093_);}
.st12{fill:url(#SVGID_00000182503296231706301150000015159284117431565225_);}
.st13{fill:url(#SVGID_00000157991892590648824540000004483708798912232327_);}
</style>
<g>
<path d="M339.7,20.6h26.5l30.9,100.8l33.5-100.8h22l33.5,100.8l31.2-100.8h26.5L497.9,156h-23.8L441.9,55.4L409.1,156h-23.8
L339.7,20.6z"/>
<path d="M693.8,20.6V156h-25.9V133c-10.5,16.2-27.2,26.2-47.9,26.2c-35.9,0-62.3-29.3-62.3-71c0-41.4,26.5-70.7,62.3-70.7
c20.7,0,37.5,10,47.9,26.2v-23H693.8z M667.9,88.2c0-28.3-17.3-48.2-41.9-48.2c-24.6,0-42.2,19.9-42.2,48.2
c0,28.3,17.6,48.5,42.2,48.5C650.6,136.6,667.9,116.5,667.9,88.2z"/>
<path d="M713.8,20.6h27.8l42.2,105.3l41.4-105.3h28L796,156h-24.4L713.8,20.6z"/>
<path d="M970.7,122.2l15.2,16c-11.8,12.8-35.6,21-54.7,21c-37.5,0-69.9-29.6-69.9-71.2c0-40.6,30.6-70.5,68.1-70.5
c41.4,0,65.5,30.9,65.5,79.1H886.6c3.1,23.8,19.9,41.1,44,41.1C945.3,137.7,962.3,131.1,970.7,122.2z M886.9,77.5h82.8
c-2.6-21.7-16.2-38.5-39.8-38.5C908.1,38.9,890.8,54.1,886.9,77.5z"/>
</g>
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="5.2128" y1="58.9088" x2="240.4477" y2="58.9088">
<stop offset="0.1418" style="stop-color:#1F4D22"/>
<stop offset="0.8656" style="stop-color:#418D31"/>
</linearGradient>
<path class="st0" d="M83.6,80.8c-12.3,0-19.1,8-22.8,25.9l-55.6-8C12,40.1,34.8,11.7,79.9,11.7C113.3,11.7,146,37,162,37
c12.4,0,19.1-8.6,22.8-25.9l55.6,8c-6.2,58.7-29.6,87.1-74.7,87.1C131.8,106.1,100.3,80.8,83.6,80.8z"/>
</g>
<g>
<linearGradient id="SVGID_00000055697211621202625680000016003686276294146176_" gradientUnits="userSpaceOnUse" x1="20.9171" y1="116.0912" x2="256.1519" y2="116.0912">
<stop offset="0.2223" style="stop-color:#418D31"/>
<stop offset="0.7733" style="stop-color:#58C142"/>
</linearGradient>
<path style="fill:url(#SVGID_00000055697211621202625680000016003686276294146176_);" d="M99.3,138c-12.3,0-19.1,8-22.8,25.9
l-55.6-8c6.8-58.6,29.6-87.1,74.7-87.1c33.3,0,66.1,25.3,82.1,25.3c12.4,0,19.1-8.6,22.8-25.9l55.6,8
c-6.2,58.7-29.6,87.1-74.7,87.1C147.5,163.3,116,138,99.3,138z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 KiB

-29
View File
@@ -1,29 +0,0 @@
<svg width="74" height="73" viewBox="0 0 74 73" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Icon Center Image Artwork">
<g id="Guide - Hide">
<rect x="1" width="44.7379" height="44.7379" fill="#EA33EC" fill-opacity="0.1"/>
<rect x="3.18447" y="2.18447" width="40.3689" height="40.3689" stroke="#EA33EC" stroke-opacity="0.09" stroke-width="4.36893"/>
</g>
<g id="wave-logo_appicon 1">
<path id="Vector" d="M73.8156 -0.808594H0.191406V72.8156H73.8156V-0.808594Z" fill="black"/>
<g id="Group">
<g id="Group_2">
<path id="Vector_2" d="M27.2969 34.6218C24.7516 34.6218 23.3523 36.2741 22.5859 39.9726L11.125 38.3132C12.5242 26.2194 17.2352 20.3624 26.5305 20.3624C33.407 20.3624 40.157 25.5866 43.4688 25.5866C46.0141 25.5866 47.4133 23.8007 48.1797 20.2358L59.6406 21.8882C58.368 33.9819 53.5305 39.846 44.2352 39.846C37.225 39.846 30.7352 34.6218 27.2969 34.6218Z" fill="url(#paint0_linear_1373_32879)"/>
</g>
<g id="Group_3">
<path id="Vector_3" d="M30.5312 46.4133C27.9859 46.4133 26.5867 48.0656 25.8203 51.7641L14.3594 50.1047C15.7586 38.0109 20.4695 32.1539 29.7648 32.1539C36.6414 32.1539 43.3914 37.3781 46.7031 37.3781C49.2484 37.3781 50.6477 35.5922 51.4141 32.0273L62.875 33.6797C61.6023 45.7734 56.7648 51.6375 47.4695 51.6375C40.4664 51.6375 33.9695 46.4133 30.5312 46.4133Z" fill="url(#paint1_linear_1373_32879)"/>
</g>
</g>
</g>
</g>
<defs>
<linearGradient id="paint0_linear_1373_32879" x1="11.1241" y1="30.1035" x2="59.6372" y2="30.1035" gradientUnits="userSpaceOnUse">
<stop offset="0.1418" stop-color="#1F4D22"/>
<stop offset="0.8656" stop-color="#418D31"/>
</linearGradient>
<linearGradient id="paint1_linear_1373_32879" x1="14.3628" y1="41.8964" x2="62.8759" y2="41.8964" gradientUnits="userSpaceOnUse">
<stop offset="0.2223" stop-color="#418D31"/>
<stop offset="0.7733" stop-color="#58C142"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

-42
View File
@@ -1,42 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.8.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 600 400" style="enable-background:new 0 0 600 400;" xml:space="preserve">
<style type="text/css">
.st0{fill:url(#SVGID_1_);}
.st1{fill:url(#SVGID_00000112609801797065440120000009078644614516335013_);}
.st2{fill:#FFFFFF;}
.st3{fill:#58C142;}
.st4{fill:url(#SVGID_00000140705471064485508570000011374545427215048096_);}
.st5{fill:url(#SVGID_00000070096993167771140800000009230862614014512804_);}
.st6{fill:url(#SVGID_00000018927797001490499930000007907141601259141028_);}
.st7{fill:url(#SVGID_00000177467729764420216790000007105154932047940258_);}
.st8{fill:url(#SVGID_00000094609616810712664470000012347852020703354001_);}
.st9{fill:url(#SVGID_00000147904120639373224840000010231811793887454594_);}
.st10{fill:url(#SVGID_00000124156599372995293460000015010576141345595828_);}
.st11{fill:url(#SVGID_00000113335101732495131180000003771446430366466471_);}
.st12{fill:url(#SVGID_00000123421819715807053460000011277887084625979316_);}
.st13{fill:url(#SVGID_00000070797766435397124570000013813146128488798621_);}
</style>
<g>
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="7.3142" y1="133.3046" x2="556.0522" y2="133.3046">
<stop offset="0.1418" style="stop-color:#1F4D22"/>
<stop offset="0.8656" style="stop-color:#418D31"/>
</linearGradient>
<path class="st0" d="M190.2,184.4c-28.8,0-44.6,18.7-53.3,60.5L7.3,226.2C23.2,89.4,76.4,23.1,181.6,23.1
c77.8,0,154.1,59.1,191.6,59.1c28.8,0,44.7-20.2,53.3-60.5l129.6,18.7c-14.4,136.8-69.1,203.1-174.3,203.1
C302.6,243.5,229.1,184.4,190.2,184.4z"/>
</g>
<g>
<linearGradient id="SVGID_00000085247734223146048360000005883855174484422067_" gradientUnits="userSpaceOnUse" x1="43.9478" y1="266.6954" x2="592.6859" y2="266.6954">
<stop offset="0.2223" style="stop-color:#418D31"/>
<stop offset="0.7733" style="stop-color:#58C142"/>
</linearGradient>
<path style="fill:url(#SVGID_00000085247734223146048360000005883855174484422067_);" d="M226.8,317.8
c-28.8,0-44.6,18.7-53.3,60.5L43.9,359.6c15.8-136.8,69.1-203.1,174.3-203.1c77.8,0,154.1,59.1,191.6,59.1
c28.8,0,44.7-20.2,53.3-60.5l129.6,18.7c-14.4,136.8-69.1,203.1-174.3,203.1C339.2,376.9,265.7,317.8,226.8,317.8z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

+14 -14
View File
@@ -1,16 +1,16 @@
# Build Instructions for Wave Terminal on Linux
These instructions are for setting up the build on Linux (Ubuntu).
These instructions are for setting up the build on Linux (Ubuntu).
If you're developing on MacOS please use the [MacOS Build Instructions](./BUILD.md).
If you are working on a different Linux distribution, you may need to adapt some of these instructions to fit your environment.
## Running the Development Version of Wave
If you install the production version of Wave, you'll see a semi-transparent gray sidebar, and the data for Wave is stored in the directory ~/.waveterm. The development version has a blue sidebar and stores its data in ~/.waveterm-dev. This allows the production and development versions to be run simultaneously with no conflicts. If the dev database is corrupted by development bugs, or the schema changes in development it will not affect the production copy.
If you install the production version of Wave, you'll see a semi-transparent sidebar, and the data for Wave is stored in the directory ~/prompt. The development version has a red/brown sidebar and stores its data in ~/prompt-dev. This allows the production and development versions to be run simultaneously with no conflicts. If the dev database is corrupted by development bugs, or the schema changes in development it will not affect the production copy.
## Prereqs and Tools
Download and install Go (must be at least go 1.18). We also need gcc installed to run a CGO build (for Golang).
Download and install Go (must be at least go 1.18). We also need gcc installed to run a CGO build (for Golang).
zip is required to build linux deployment packages (not required for running and debugging dev builds).
```
@@ -36,7 +36,7 @@ sudo cp scripthaus /usr/local/bin
## Install nodejs, npm, and yarn
We use [nvm](https://github.com/nvm-sh/nvm) to install nodejs on Linux (you can use an alternate installer if you wish). You must have a relatively recent version of node in order to build the terminal. Different distributions and shells will require different setup instructions. These instructions work for Ubuntu 22 using bash (will install node v20.8.1):
We use [nvm](https://github.com/nvm-sh/nvm) to install nodejs on Linux (you can use an alternate installer if you wish). You must have a relatively recent version of node in order to build the terminal. Different distributions and shells will require different setup instructions. These instructions work for Ubuntu 22 using bash (will install node v20.8.1):
```
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
@@ -50,9 +50,10 @@ Now we can install yarn:
npm install -g yarn
```
## Clone the Wave Repo
Move out of the `scripthaus` directory if you're still in it. Clone the wave repository into the directory that you'd like to use for development.
Move out of the `scripthaus` directory if you're still in it. Clone the wave repository into the directory that you'd like to use for development.
```
git clone git@github.com:wavetermdev/waveterm.git
@@ -61,12 +62,11 @@ git clone git@github.com:wavetermdev/waveterm.git
## One-Time Setup
Install Wave modules (we use yarn):
```
yarn
```
Electron also requires specific builds of node_modules to work (because Electron embeds a specific node.js version that might not match your development node.js version). We use a special electron command to cross-compile those modules:
Electron also requires specific builds of node_modules to work (because Electron embeds a specific node.js version that might not match your development node.js version). We use a special electron command to cross-compile those modules:
```
scripthaus run electron-rebuild
@@ -81,11 +81,12 @@ cd waveterm
scripthaus run build-backend
```
This builds the Golang backends for Wave. The binaries will put in waveshell/bin and wavesrv/bin respectively. If you're working on a new plugin or other pure frontend changes to Wave, you won't need to rebuild these unless you pull new code from the Wave Repository.
This builds the Golang backends for Wave. The binaries will put in waveshell/bin and wavesrv/bin respectively. If you're working on a new plugin or other pure frontend changes to Wave, you won't need to rebuild these unless you pull new code from the Wave Repository.
## Running WebPack
We use webpack to build both the React and Electron App Wrapper code. They are both run together using:
We use webpack to build both the React and Electron App Wrapper code. They are both run together using:
```
scripthaus run webpack-watch
@@ -93,16 +94,15 @@ scripthaus run webpack-watch
## Running the WaveTerm Dev Client
Now that webpack is running (and watching for file changes) we can finally run the WaveTerm Dev Client! To start the client run:
Now that webpack is running (and watching for file changes) we can finally run the WaveTerm Dev Client! To start the client run:
```
scripthaus run electron
```
To kill the client, either exit the Electron App normally or just Ctrl-C the `scripthaus run electron` command.
To kill the client, either exit the Electron App normally or just Ctrl-C the ```scripthaus run electron``` command.
Because we're running webpack in watch mode, any changes you make to the typescript will be automatically picked up by the client after a refresh. Note that I've disabled hot-reloading in the webpack config, so to pick up new changes you'll have to manually refresh the WaveTerm Client window. To do that use "Command-Shift-R" (Command-R is used internally by Wave and will not force a refresh).
Because we're running webpack in watch mode, any changes you make to the typescript will be automatically picked up by the client after a refresh. Note that I've disabled hot-reloading in the webpack config, so to pick up new changes you'll have to manually refresh the WaveTerm Client window. To do that use "Command-Shift-R" (Command-R is used internally by Wave and will not force a refresh).
## Debugging the Dev Client
You can use the regular Chrome DevTools to debug the frontend application. You can open the DevTools using the keyboard shortcut `Cmd-Option-I`.
You can use the regular Chrome DevTools to debug the frontend application. You can open the DevTools using the keyboard shortcut `Cmd-Option-I`.
-158
View File
@@ -664,161 +664,3 @@ a.a-block {
}
}
}
.settings-field {
display: flex;
flex-direction: row;
align-items: center;
&.settings-field.sub-field {
.settings-label {
font-weight: normal;
text-align: right;
padding-right: 20px;
}
}
&.settings-error {
color: @term-red;
margin-top: 20px;
padding: 10px;
border-radius: 5px;
background-color: #200707;
border: 1px solid @term-red;
font-weight: bold;
.error-dismiss {
padding: 2px;
cursor: pointer;
}
}
.settings-label {
font-weight: bold;
width: 12em;
display: flex;
flex-direction: row;
align-items: center;
.info-message {
margin-left: 5px;
}
}
.settings-input {
display: flex;
flex-direction: row;
align-items: center;
color: @term-white;
&.settings-clickable {
cursor: pointer;
}
&.inline-edit.edit-active {
input.input {
padding: 0;
height: 20px;
}
.button {
height: 20px;
}
}
input {
padding: 4px;
border-radius: 3px;
}
.control {
.icon {
width: 1.5em;
height: 1.5em;
margin: 0;
}
}
.tab-color-icon.color-default path {
fill: @tab-green;
}
.tab-color-icon.color-green path {
fill: @tab-green;
}
.tab-color-icon.color-orange path {
fill: @tab-orange;
}
.tab-color-icon.color-red path {
fill: @tab-red;
}
.tab-color-icon.color-yellow path {
fill: @tab-yellow;
}
.tab-color-icon.color-blue path {
fill: @tab-blue;
}
.tab-color-icon.color-mint path {
fill: @tab-mint;
}
.tab-color-icon.color-cyan path {
fill: @tab-cyan;
}
.tab-color-icon.color-white path {
fill: @tab-white;
}
.tab-color-icon.color-violet path {
fill: @tab-violet;
}
.tab-color-icon.color-pink path {
fill: @tab-pink;
}
.tab-colors,
.tab-icons {
display: flex;
flex-direction: row;
align-items: center;
.tab-color-sep,
.tab-icon-sep {
padding-left: 10px;
padding-right: 10px;
font-weight: bold;
}
.tab-color-icon,
.tab-icon-icon {
width: 1.1em;
vertical-align: middle;
}
.tab-color-name,
.tab-icon-name {
margin-left: 1em;
}
.tab-color-select,
.tab-icon-select {
cursor: pointer;
margin: 5px;
&:hover {
outline: 2px solid white;
}
}
}
.action-text {
margin-left: 20px;
color: @term-red;
}
.settings-share-link {
width: 160px;
}
}
&:not(:first-child) {
margin-top: 10px;
}
}
+6 -3
View File
@@ -7,9 +7,10 @@ import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator";
import { If } from "tsx-control-statements/components";
import dayjs from "dayjs";
import type { ContextMenuOpts } from "../types/types";
import localizedFormat from "dayjs/plugin/localizedFormat";
import { GlobalModel } from "@/models";
import { isBlank } from "@/util/util";
import { GlobalModel } from "../model/model";
import { isBlank } from "../util/util";
import { WorkspaceView } from "./workspace/workspaceview";
import { PluginsView } from "./pluginsview/pluginsview";
import { BookmarksView } from "./bookmarks/bookmarks";
@@ -24,12 +25,14 @@ import "./app.less";
dayjs.extend(localizedFormat);
type OV<V> = mobx.IObservableValue<V>;
@mobxReact.observer
class App extends React.Component<{}, {}> {
dcWait: OV<boolean> = mobx.observable.box(false, { name: "dcWait" });
mainContentRef: React.RefObject<HTMLDivElement> = React.createRef();
constructor(props: {}) {
constructor(props: any) {
super(props);
if (GlobalModel.isDev) document.body.className = "is-dev";
}
-41
View File
@@ -8,7 +8,6 @@ export const SESSION_SETTINGS = "sessionSettings";
export const LINE_SETTINGS = "lineSettings";
export const CLIENT_SETTINGS = "clientSettings";
export const TAB_SWITCHER = "tabSwitcher";
export const USER_INPUT = "userInput";
export const LineContainer_Main = "main";
export const LineContainer_History = "history";
@@ -17,43 +16,3 @@ export const LineContainer_Sidebar = "sidebar";
export const ConfirmKey_HideShellPrompt = "hideshellprompt";
export const NoStrPos = -1;
export const RemotePtyRows = 8; // also in main.tsx
export const RemotePtyCols = 80;
export const ProdServerEndpoint = "http://127.0.0.1:1619";
export const ProdServerWsEndpoint = "ws://127.0.0.1:1623";
export const DevServerEndpoint = "http://127.0.0.1:8090";
export const DevServerWsEndpoint = "ws://127.0.0.1:8091";
export const DefaultTermFontSize = 12;
export const MinFontSize = 8;
export const MaxFontSize = 24;
export const InputChunkSize = 500;
export const RemoteColors = ["red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange"];
export const TabColors = ["red", "orange", "yellow", "green", "mint", "cyan", "blue", "violet", "pink", "white"];
export const TabIcons = [
"sparkle",
"fire",
"ghost",
"cloud",
"compass",
"crown",
"droplet",
"graduation-cap",
"heart",
"file",
];
// @ts-ignore
export const VERSION = __WAVETERM_VERSION__;
// @ts-ignore
export const BUILD = __WAVETERM_BUILD__;
/**
* Levels for the screen status indicator
*/
export enum StatusIndicatorLevel {
None = 0,
Output = 1,
Success = 2,
Error = 3,
}
+1 -1
View File
@@ -1,4 +1,4 @@
@import "@/common/themes/themes.less";
@import "../../app/common/themes/themes.less";
.bookmarks-view {
background-color: @background-session;
+9 -20
View File
@@ -7,27 +7,20 @@ import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator";
import { If, For } from "tsx-control-statements/components";
import cn from "classnames";
import { GlobalModel } from "@/models";
import { CmdStrCode, Markdown } from "@/common/elements";
import type { BookmarkType } from "../../types/types";
import { GlobalModel } from "../../model/model";
import { CmdStrCode, Markdown } from "../common/common";
import { ReactComponent as XmarkIcon } from "@/assets/icons/line/xmark.svg";
import { ReactComponent as CopyIcon } from "@/assets/icons/favourites/copy.svg";
import { ReactComponent as PenIcon } from "@/assets/icons/favourites/pen.svg";
import { ReactComponent as TrashIcon } from "@/assets/icons/favourites/trash.svg";
import { ReactComponent as FavoritesIcon } from "@/assets/icons/favourites.svg";
import { ReactComponent as XmarkIcon } from "../assets/icons/line/xmark.svg";
import { ReactComponent as CopyIcon } from "../assets/icons/favourites/copy.svg";
import { ReactComponent as PenIcon } from "../assets/icons/favourites/pen.svg";
import { ReactComponent as TrashIcon } from "../assets/icons/favourites/trash.svg";
import { ReactComponent as FavoritesIcon } from "../assets/icons/favourites.svg";
import "./bookmarks.less";
type BookmarkProps = {
bookmark: BookmarkType;
};
@mobxReact.observer
class Bookmark extends React.Component<BookmarkProps, {}> {
constructor(props: BookmarkProps) {
super(props);
}
class Bookmark extends React.Component<{ bookmark: BookmarkType }, {}> {
@boundMethod
handleDeleteClick(): void {
let { bookmark } = this.props;
@@ -186,10 +179,6 @@ class Bookmark extends React.Component<BookmarkProps, {}> {
@mobxReact.observer
class BookmarksView extends React.Component<{}, {}> {
constructor(props: {}) {
super(props);
}
@boundMethod
closeView(): void {
GlobalModel.bookmarksModel.closeView();
+1 -1
View File
@@ -1,4 +1,4 @@
@import "@/common/themes/themes.less";
@import "../../app/common/themes/themes.less";
.clientsettings-view {
background-color: @background-session;
+28 -56
View File
@@ -6,18 +6,23 @@ import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator";
import cn from "classnames";
import { GlobalModel, GlobalCommandRunner, RemotesModel } from "@/models";
import { Toggle, InlineSettingsTextEdit, SettingsError, Dropdown } from "@/common/elements";
import { commandRtnHandler, isBlank } from "@/util/util";
import * as appconst from "@/app/appconst";
import { GlobalModel, GlobalCommandRunner, MinFontSize, MaxFontSize, RemotesModel } from "../../model/model";
import { Toggle, InlineSettingsTextEdit, SettingsError, Dropdown } from "../common/common";
import { CommandRtnType, ClientDataType } from "../../types/types";
import { commandRtnHandler, isBlank } from "../../util/util";
import "./clientsettings.less";
type OV<V> = mobx.IObservableValue<V>;
// @ts-ignore
const VERSION = __WAVETERM_VERSION__;
// @ts-ignore
const BUILD = __WAVETERM_BUILD__;
@mobxReact.observer
class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hoveredItemId: string }> {
fontSizeDropdownActive: OV<boolean> = mobx.observable.box(false, {
name: "clientSettings-fontSizeDropdownActive",
});
fontSizeDropdownActive: OV<boolean> = mobx.observable.box(false, { name: "clientSettings-fontSizeDropdownActive" });
errorMessage: OV<string> = mobx.observable.box(null, { name: "ClientSettings-errorMessage" });
@boundMethod
@@ -29,12 +34,12 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
@boundMethod
handleChangeFontSize(fontSize: string): void {
const newFontSize = Number(fontSize);
let newFontSize = Number(fontSize);
this.fontSizeDropdownActive.set(false);
if (GlobalModel.termFontSize.get() == newFontSize) {
return;
}
const prtn = GlobalCommandRunner.setTermFontSize(newFontSize, false);
let prtn = GlobalCommandRunner.setTermFontSize(newFontSize, false);
commandRtnHandler(prtn, this.errorMessage);
}
@@ -67,29 +72,29 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
commandRtnHandler(prtn, this.errorMessage);
}
getFontSizes(): DropdownItem[] {
const availableFontSizes: DropdownItem[] = [];
for (let s = appconst.MinFontSize; s <= appconst.MaxFontSize; s++) {
availableFontSizes.push({ label: s + "px", value: String(s) });
getFontSizes(): any {
let availableFontSizes: { label: string; value: number }[] = [];
for (let s = MinFontSize; s <= MaxFontSize; s++) {
availableFontSizes.push({ label: s + "px", value: s });
}
return availableFontSizes;
}
@boundMethod
inlineUpdateOpenAIModel(newModel: string): void {
const prtn = GlobalCommandRunner.setClientOpenAISettings({ model: newModel });
let prtn = GlobalCommandRunner.setClientOpenAISettings({ model: newModel });
commandRtnHandler(prtn, this.errorMessage);
}
@boundMethod
inlineUpdateOpenAIToken(newToken: string): void {
const prtn = GlobalCommandRunner.setClientOpenAISettings({ apitoken: newToken });
let prtn = GlobalCommandRunner.setClientOpenAISettings({ apitoken: newToken });
commandRtnHandler(prtn, this.errorMessage);
}
@boundMethod
inlineUpdateOpenAIMaxTokens(newMaxTokensStr: string): void {
const prtn = GlobalCommandRunner.setClientOpenAISettings({ maxtokens: newMaxTokensStr });
let prtn = GlobalCommandRunner.setClientOpenAISettings({ maxtokens: newMaxTokensStr });
commandRtnHandler(prtn, this.errorMessage);
}
@@ -105,41 +110,19 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
GlobalModel.clientSettingsViewModel.closeView();
}
@boundMethod
handleChangeShortcut(newShortcut: string): void {
const prtn = GlobalCommandRunner.setGlobalShortcut(newShortcut);
commandRtnHandler(prtn, this.errorMessage);
}
getFKeys(): DropdownItem[] {
const opts: DropdownItem[] = [];
opts.push({ label: "Disabled", value: "" });
const platform = GlobalModel.getPlatform();
for (let i = 1; i <= 12; i++) {
const shortcut = (platform == "darwin" ? "Cmd" : "Alt") + "+F" + String(i);
opts.push({ label: shortcut, value: shortcut });
}
return opts;
}
getCurrentShortcut(): string {
const clientData = GlobalModel.clientData.get();
return clientData?.clientopts?.globalshortcut ?? "";
}
render() {
const isHidden = GlobalModel.activeMainView.get() != "clientsettings";
let isHidden = GlobalModel.activeMainView.get() != "clientsettings";
if (isHidden) {
return null;
}
const cdata: ClientDataType = GlobalModel.clientData.get();
const openAIOpts = cdata.openaiopts ?? {};
const apiTokenStr = isBlank(openAIOpts.apitoken) ? "(not set)" : "********";
const maxTokensStr = String(
let cdata: ClientDataType = GlobalModel.clientData.get();
let openAIOpts = cdata.openaiopts ?? {};
let apiTokenStr = isBlank(openAIOpts.apitoken) ? "(not set)" : "********";
let maxTokensStr = String(
openAIOpts.maxtokens == null || openAIOpts.maxtokens == 0 ? 1000 : openAIOpts.maxtokens
);
const curFontSize = GlobalModel.termFontSize.get();
let curFontSize = GlobalModel.termFontSize.get();
return (
<div className={cn("view clientsettings-view")}>
@@ -168,7 +151,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
<div className="settings-field">
<div className="settings-label">Client Version</div>
<div className="settings-input">
{appconst.VERSION} {appconst.BUILD}
{VERSION} {BUILD}
</div>
</div>
<div className="settings-field">
@@ -229,17 +212,6 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
/>
</div>
</div>
<div className="settings-field">
<div className="settings-label">Global Hotkey</div>
<div className="settings-input">
<Dropdown
className="hotkey-dropdown"
options={this.getFKeys()}
defaultValue={this.getCurrentShortcut()}
onChange={this.handleChangeShortcut}
/>
</div>
</div>
<SettingsError errorMessage={this.errorMessage} />
</div>
</div>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-123
View File
@@ -1,123 +0,0 @@
@import "@/common/themes/themes.less";
.wave-button {
background: none;
color: inherit;
border: none;
font: inherit;
cursor: pointer;
outline: inherit;
display: flex;
padding: 6px 16px;
align-items: center;
gap: 4px;
border-radius: 6px;
height: auto;
&:hover {
color: @term-white;
}
i {
fill: rgba(255, 255, 255, 0.12);
}
&.primary {
color: @term-green;
background: none;
i {
fill: @term-green;
}
&.solid {
color: @term-bright-white;
background: @term-green;
box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.4), 0px 0px 0.5px 0px rgba(0, 0, 0, 0.5),
0px 0px 0.5px 0px rgba(255, 255, 255, 0.8) inset, 0px 0.5px 0px 0px rgba(255, 255, 255, 0.6) inset;
i {
fill: @term-white;
}
}
&.outlined {
border: 1px solid @term-green;
}
&.ghost {
// Styles for .ghost are already defined above
}
&:hover {
color: @term-bright-white;
}
}
&.secondary {
color: @term-white;
background: none;
&.solid {
background: rgba(255, 255, 255, 0.09);
box-shadow: none;
}
&.outlined {
border: 1px solid rgba(255, 255, 255, 0.09);
}
&.ghost {
padding: 6px 10px;
i {
fill: @term-green;
}
}
}
&.color-yellow {
&.solid {
border-color: @warning-yellow;
background-color: mix(@warning-yellow, @term-white, 50%);
box-shadow: none;
}
&.outlined {
color: @warning-yellow;
border-color: @warning-yellow;
&:hover {
color: @term-white;
border-color: @term-white;
}
}
&.ghost {
}
}
&.color-red {
&.solid {
border-color: @term-red;
background-color: mix(@term-red, @term-white, 50%);
box-shadow: none;
}
&.outlined {
color: @term-red;
border-color: @term-red;
}
&.ghost {
}
}
&.disabled {
opacity: 0.5;
}
&.link-button {
cursor: pointer;
}
}
-63
View File
@@ -1,63 +0,0 @@
// Copyright 2023, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
import * as React from "react";
import { boundMethod } from "autobind-decorator";
import cn from "classnames";
import "./button.less";
type ButtonVariantType = "outlined" | "solid" | "ghost";
type ButtonThemeType = "primary" | "secondary";
interface ButtonProps {
theme?: ButtonThemeType;
children: React.ReactNode;
onClick?: () => void;
disabled?: boolean;
variant?: ButtonVariantType;
leftIcon?: React.ReactNode;
rightIcon?: React.ReactNode;
color?: string;
style?: React.CSSProperties;
autoFocus?: boolean;
className?: string;
}
class Button extends React.Component<ButtonProps> {
static defaultProps = {
theme: "primary",
variant: "solid",
color: "",
style: {},
};
@boundMethod
handleClick() {
if (this.props.onClick && !this.props.disabled) {
this.props.onClick();
}
}
render() {
const { leftIcon, rightIcon, theme, children, disabled, variant, color, style, autoFocus, className } =
this.props;
return (
<button
className={cn("wave-button", theme, variant, color, { disabled: disabled }, className)}
onClick={this.handleClick}
disabled={disabled}
style={style}
autoFocus={autoFocus}
>
{leftIcon && <span className="icon-left">{leftIcon}</span>}
{children}
{rightIcon && <span className="icon-right">{rightIcon}</span>}
</button>
);
}
}
export { Button };
export type { ButtonProps };

Some files were not shown because too many files have changed in this diff Show More