Shell.svelte 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. <script>
  2. import { Command } from '@tauri-apps/api/shell'
  3. const windows = navigator.userAgent.includes('Windows')
  4. let cmd = windows ? 'cmd' : 'sh'
  5. let args = windows ? ['/C'] : ['-c']
  6. export let onMessage
  7. let script = 'echo "hello world"'
  8. let cwd = null
  9. let env = 'SOMETHING=value ANOTHER=2'
  10. let encoding = ''
  11. let stdin = ''
  12. let child
  13. function _getEnv() {
  14. return env.split(' ').reduce((env, clause) => {
  15. let [key, value] = clause.split('=')
  16. return {
  17. ...env,
  18. [key]: value
  19. }
  20. }, {})
  21. }
  22. function spawn() {
  23. child = null
  24. const command = Command.create(cmd, [...args, script], {
  25. cwd: cwd || null,
  26. env: _getEnv(),
  27. encoding: encoding || undefined,
  28. })
  29. command.on('close', (data) => {
  30. onMessage(
  31. `command finished with code ${data.code} and signal ${data.signal}`
  32. )
  33. child = null
  34. })
  35. command.on('error', (error) => onMessage(`command error: "${error}"`))
  36. command.stdout.on('data', (line) => onMessage(`command stdout: "${line}"`))
  37. command.stderr.on('data', (line) => onMessage(`command stderr: "${line}"`))
  38. command
  39. .spawn()
  40. .then((c) => {
  41. child = c
  42. })
  43. .catch(onMessage)
  44. }
  45. function kill() {
  46. child
  47. .kill()
  48. .then(() => onMessage('killed child process'))
  49. .catch(onMessage)
  50. }
  51. function writeToStdin() {
  52. child.write(stdin).catch(onMessage)
  53. }
  54. </script>
  55. <div class="flex flex-col childre:grow gap-1">
  56. <div class="flex items-center gap-1">
  57. Script:
  58. <input class="grow input" bind:value={script} />
  59. </div>
  60. <div class="flex items-center gap-1">
  61. Encoding:
  62. <input class="grow input" bind:value={encoding} />
  63. </div>
  64. <div class="flex items-center gap-1">
  65. Working directory:
  66. <input
  67. class="grow input"
  68. bind:value={cwd}
  69. placeholder="Working directory"
  70. />
  71. </div>
  72. <div class="flex items-center gap-1">
  73. Arguments:
  74. <input
  75. class="grow input"
  76. bind:value={env}
  77. placeholder="Environment variables"
  78. />
  79. </div>
  80. <div class="flex children:grow gap-1">
  81. <button class="btn" on:click={spawn}>Run</button>
  82. <button class="btn" on:click={kill}>Kill</button>
  83. </div>
  84. {#if child}
  85. <br />
  86. <input class="input" placeholder="write to stdin" bind:value={stdin} />
  87. <button class="btn" on:click={writeToStdin}>Write</button>
  88. {/if}
  89. </div>