電子冒険:エピソード17:ターミナル入力
11787 ワード
私たちのターミナルアプリは良くなっている.次のステップは、実行するコマンドと対話するための方法を追加することです.これらは三つの主要な方法です. いくつかのテキストを入力します(デフォルトでは文字ではなく) 入力が完了したコマンドを指示します(従来の端末ではControl - D ) コマンドを停止させる(伝統的な端末でのControl - C )
我々は再びそれを変えている.アプリから来るイベントの多くがあります
最初のコマンドを扱うすべてのロジックは
これは反転する必要があります
それは小さいものです、しかし、現在我々が同時に複数の入力ボックスを持っているので、私はそれをより明瞭にするために少し色を変えました.
やりたいことがたくさんあります. テキスト入力用の入力フィールドを追加する 入力の終わりのためにいくつかのボタンを加えて、コマンドを殺すために それは冗長な今のようにスピンのアイコンを削除-コマンドを実行すると、入力フィールドを持って、コマンドを実行しません 相互作用の代わりにstdoutを最初にし、stderrではなく、stdin、stdout、stderrを絡んでいます.
既存のロジック
コードは十分クリアする必要があります.
スタイリングは、入力の背景色を少し変更しただけで、端末の残りの部分から入力を区別することができました.
結果は以下の通りです.
端末には、いくつかの制限があります. コマンドを実行すると、新しいunfocus入力ボックスが作成されますので、手動でフォーカスする必要がありますコマンドが終了すると、手動で新しいコマンドの入力にフォーカスする必要があります Control - DとControl - Cのようなキーボードショートカット バイナリデータ、あまりにも多くのデータ、または行ベースのテキストではないデータを生成するコマンドは、非常に不十分に動作します しかし、それはまだかなりうまくいっています.
次のエピソードについては、我々の端末アプリから休憩を取るし、何か別のコードを試してください.
いつものように.all the code for the episode is here .
プリロードでruncommand。js
我々は再びそれを変えている.アプリから来るイベントの多くがあります
input
, endInput
, kill
), そして、我々はアプリから送信するイベントの多くonout
, onerr
, ondone
):let runCommand = ({command, onout, onerr, ondone}) => {
const proc = child_process.spawn(
command,
[],
{
shell: true,
stdio: ["pipe", "pipe", "pipe"],
},
)
proc.stdout.on("data", (data) => onout(data.toString()))
proc.stderr.on("data", (data) => onerr(data.toString()))
proc.on("close", (code) => ondone(code))
return {
kill: () => proc.kill(),
input: (data) => proc.stdin.write(data),
endInput: () => proc.stdin.end(),
}
}
変化したstdin
からignore
to pipe
それが今アクティブなので、今我々は我々のプロセスに話をするために使用するアプリケーションの3つのメソッドを持つオブジェクトを返します.アプリのすべてのロジックを移動します。スベルト
最初のコマンドを扱うすべてのロジックは
App.svelte
and HistoryEntry.svelte
はディスプレイのみのクラスです.これは反転する必要があります
App.svelte
, では、名前を変えましょうHistoryEntry.svelte
to Command.svelte
代わりにすべてのロジックを移動します.<script>
import Command from "./Command.svelte"
import CommandInput from "./CommandInput.svelte"
let history = []
async function onsubmit(command) {
let entry = {command}
history.push(entry)
history = history
}
</script>
<h1>Svelte Terminal App</h1>
<div id="terminal">
<div id="history">
{#each history as entry}
<Command command={entry.command} />
{/each}
</div>
<CommandInput {onsubmit} />
</div>
<style>
:global(body) {
background-color: #444;
color: #fff;
font-family: monospace;
}
</style>
コマンド入力の入力ボックススタイル。スベルト
それは小さいものです、しかし、現在我々が同時に複数の入力ボックスを持っているので、私はそれをより明瞭にするために少し色を変えました.
input {
background-color: #666;
}
コマンド.スベルトテンプレート
やりたいことがたくさんあります.
<div class='history-entry'>
<div class='input-line'>
<span class='prompt'>$</span>
<span class='command'>{command}</span>
</div>
{#each interactions as interaction}
<div class={interaction.type}>{interaction.data}</div>
{/each}
{#if running}
<form on:submit|preventDefault={submit}>
<input type="text" bind:value={input} />
<button type="button" on:click={endInput}>End Input</button>
<button type="button" on:click={kill}>Kill</button>
</form>
{/if}
{#if error}
<Icon data={exclamationTriangle} />
{/if}
</div>
コマンド.スベートスクリプト
既存のロジック
App.svelte
だけでなく、新しいロジックの束ここに行く.コードは十分クリアする必要があります.
interactions
はオブジェクトの配列です.type
and data
プロパティ.type
どちらかstdin
, stdout
, or stderr
. data
が送受信された実際のテキストです.<script>
import Icon from "svelte-awesome"
import { exclamationTriangle } from "svelte-awesome/icons"
export let command
let running = true
let interactions = []
let error = false
let input = ""
function onout(data) {
interactions.push({data, type: "stdout"})
interactions = interactions
}
function onerr(data) {
interactions.push({data, type: "stderr"})
interactions = interactions
}
function ondone(code) {
running = false
error = (code !== 0)
}
function endInput() {
proc.endInput()
}
function kill() {
proc.kill()
}
function submit() {
let data = input+"\n"
interactions.push({data, type: "stdin"})
interactions = interactions
proc.input(data)
input = ""
}
let proc = window.api.runCommand({command,onout,onerr,ondone})
</script>
コマンド.スベルトスタイリング
スタイリングは、入力の背景色を少し変更しただけで、端末の残りの部分から入力を区別することができました.
<style>
.history-entry {
padding-bottom: 0.5rem;
}
.stdin {
color: #ffa;
white-space: pre;
}
.stdout {
color: #afa;
white-space: pre;
}
.stderr {
color: #faa;
white-space: pre;
}
.input-line {
display: flex;
gap: 0.5rem;
}
.command {
color: #ffa;
flex: 1;
}
form {
flex: 1;
display: flex;
}
input {
flex: 1;
font-family: inherit;
background-color: #666;
color: inherit;
border: none;
}
</style>
結果
結果は以下の通りです.
端末には、いくつかの制限があります.
cd
コマンドが動作しません次のエピソードについては、我々の端末アプリから休憩を取るし、何か別のコードを試してください.
いつものように.all the code for the episode is here .
Reference
この問題について(電子冒険:エピソード17:ターミナル入力), 我々は、より多くの情報をここで見つけました https://dev.to/taw/electron-adventures-episode-17-terminal-input-1gk5テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol