Giter Site home page Giter Site logo

vue-terminal / vue-termui Goto Github PK

View Code? Open in Web Editor NEW
759.0 9.0 30.0 1.37 MB

The Modern Terminal UI Framework

Home Page: https://vue-termui.dev

License: MIT License

JavaScript 9.80% Vue 11.94% TypeScript 76.24% HTML 0.13% CSS 1.63% Shell 0.26%
terminal tui vue custom-renderer

vue-termui's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vue-termui's Issues

yoga-layout as a component

yoga-layout offers a lot of features out of the box, but I'm curious if it's possible to move yoga-layout out of the core runtime and abstract it into a tree-shakable component (eg. Box/FlexBox) or a 2nd party component (separate package)?

For context, the main reasons why I want to move away from Ink are:

  • React hooks and data immutability is not ergonomic/intuitive to me
  • File size (largely due to yoga-layout)
  • Yoga-layout can be slow at rendering

Large filesize

yoga-layout-prebuilt alone is around 89.3 kB gzipped (379 kB minified). For reference, Vue 3 is 128 kB minified.

Currently, that means any CLI script that uses this tool will be at least 379 kB minified. This might deter users that are looking to create something simple.

I have two tools that rely on Ink right now, and they're both bloated because of this:

They don't actually do that much. And I don't think they even use the flexbox features. So ideally, I can get them down to less than 50 kB max and I was hoping moving to Vue for SFC compilation + treeshaking could help with that.

Use-cases

Let me know if I'm oversimplifying what yoga-layout does, but AFAIK it implements flexbox in any environment (eg. terminal). This sounds like a great feature, but I'm wondering how often this will be used.

Personally, I don't use any CLI tools that draw boxes, are full screen, need to align content with flexbox powers, etc. Most of the ones I use or make usually have simple and inline UI.

However, it is a great building block to offer. Especially as I read Ink's documentation, it seems like a big selling point to have as a core component. I'm curious if it we can still have it as a tree-shakable component? If the installation size were to deter users, possibly as a separate package?

Slow rendering speed

As I investigated this, I realized there are a few factors that impact rendering speed, and may not even be caused by yoga-layout.

I'll include it anyway since I still found it relevant and insightful for this project.

Rendering performance factors:

  1. The Terminal Emulator used. Native Terminal app is fastest, iTerm 2 is slow, and Hyper is even slower (although, less glitchy re-renders).

  2. Page size. Seems like the larger the render payload, the slower it is. This sounds expected, but it's dramatically slower, which I found unexpected. For example, if my Ink app renders 3 pages worth of data, each re-render is significantly slower than 1 page of data. In iTerm 2, it's glitches as well.

    As a side, I wondered about the possibility of a Page/Document component that overflows content and implements custom scroll so re-renders can be more efficient and less glitchy.

  3. Content change speed. I noticed my Ink app gets notably slower when using ink-spinner. Probably because it changes the render output on every tick, so the render cycle is constantly running.

I originally noticed slowness in my own scripts that use Tasuku. They were running dramatically slower when it was rendering a lot. (ie it was a lot faster to run the script when removing Tasuku). I eventually got an user reporting it: privatenumber/tasuku#5 (comment)

I created isolated experiments with multiple components running 1 second timeouts in parallel to check if it the script will exit in 1s.

Experiment

Code for Ink:

import React, { useState, useEffect } from 'react';
import {render, Text} from 'ink';

const Counter = () => {
	const [counter, setCounter] = useState(0);

	useEffect(() => {
		const timer = setTimeout(() => {
			setCounter(previousCounter => previousCounter + 1);
		}, 1000);

		return () => {
			clearInterval(timer);
		};
	}, []);

	return <Text color="green">{counter}</Text>;
};

render(
	React.createElement(
		React.Fragment,
		null,
		...Array.from(
			{ length: 300 },
			() => React.createElement(Counter),	
		),
	),
);

Result:

Terminal: 300 parallel => 4s

Note, because this is 300 1s timers in parallel, exit time should still happen in ~1s. This might be the real cost of yoga-layout. I would like to remove the factor of page size here by rendering them all in one line, but Ink seems to require all text to be wrapped in <Text>, which separates them into new lines.

npx esno src/ink.tsx  2.53s user 0.27s system 80% cpu 3.502 total

iTerm 2: 300 parallel => 7s

npx esno src/ink.tsx  5.55s user 0.39s system 86% cpu 6.858 total

Adding ink-spinner in the mix seems to slow down the script dramatically:

Terminal: 300 parallel => 36s

npx esno src/ink.tsx  34.79s user 0.94s system 99% cpu 35.809 total

iTerm 300 parallel => 46s (and major CPU lag)

npx esno src/ink.tsx  42.48s user 1.24s system 94% cpu 46.394 total
tasuku
import task from 'tasuku';

const sleep = (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, ms));

task.group(
	(task) => Array.from(
		{ length: 100 },
		() => task(
			'sleep 1s',
			() => sleep(1000),
		),
	),
	{
		concurrency: Infinity,
	},
);

Result: 100 parallel -> ~6s

npx esno src/index.ts  5.71s user 0.38s system 107% cpu 5.656 total

Result: 300 parallel -> ~ 2m 🤯

npx esno src/index.ts  86.37s user 2.81s system 77% cpu 1:54.47 total

As a separate optimization feature, I wonder how much faster only re-rendering changed lines would be. Alternatively, skipping line clearing and just overwriting instead (and only clearing the extra text at the end, if the new render is shorter than the previous).

win 10 error

_events: [Object: null prototype] {
end: [Function: onReadableStreamEnd],
error: [Function: bound onceWrapper] { listener: [Function: noop] },
resize: [Function: l]
},
_eventsCount: 3,
_maxListeners: undefined,
_writableState: WritableState {
objectMode: false,
highWaterMark: 16384,
finalCalled: false,
needDrain: false,
ending: false,
ended: false,
finished: false,
destroyed: false,
decodeStrings: false,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: false,
bufferProcessing: false,
onwrite: [Function: bound onwrite],
writecb: null,
writelen: 0,
afterWriteTickInfo: null,
buffered: [],
bufferedIndex: 0,
allBuffers: true,
allNoop: true,
pendingcb: 0,
constructed: true,
prefinished: false,
errorEmitted: false,
emitClose: false,
autoDestroy: true,
errored: null,
closed: false,
closeEmitted: false,
[Symbol(kOnFinished)]: []
},
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: null,
_server: null,
columns: 120,
rows: 30,
_type: 'tty',
fd: 1,
_isStdio: true,
destroySoon: [Function: destroy],
_destroy: [Function: dummyDestroy],
[Symbol(async_id_symbol)]: 58,
[Symbol(kHandle)]: TTY { [Symbol(owner_symbol)]: [Circular *1] },
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kSetNoDelay)]: false,
[Symbol(kSetKeepAlive)]: false,
[Symbol(kSetKeepAliveInitialDelay)]: 0,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0
} swapScreens=undefined >
Done in 25.88s.

Bug: [TuiInput] can't input

clone vue-termui and mount input component, the inputDemo can't input and have removed disabled status

import Input from './InputDemo.vue'

createApp(Input, {
  // swapScreens: true,
}).mount({
  // TODO: is this option really useful? when rendering once, any change should do a full reload one could just call
  // exitApp when they are done rendering on onMounted and it would would handle everything
  // renderOnce: true,
})

`v-if` does't work correctly

code

<script lang="ts" setup>

const whatShow = ref('Bar')

onKeyData(['k'],() => {
  whatShow.value = whatShow.value === 'Foo' ? 'Bar' : 'Foo'
  console.log('value changed:',whatShow.value)
})


</script>

<template>
    <Box>
      <Text color="red" v-if="whatShow === 'Foo'">Foo</Text>
      <Text color="green" v-else>Bar</Text>
    </Box>
</template>

Steps:

  1. Open Reproduction
  2. Press K
  3. Watch console, the value whatShow has changed but template render is not correct.

New install fails when installing dependencies

Creating a new project works fine, but as soon as you want to install the dependencies you get errors about dependencies that cannot be resolved. See the error log below:

npm install  ✔  16.15.0 Node  10:56:46
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: [email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/vite
npm ERR! dev vite@"^3.1.3" from the root project
npm ERR! peer vite@"^3.1.3" from @vue-termui/[email protected]
npm ERR! node_modules/@vue-termui/cli
npm ERR! dev @vue-termui/cli@"*" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer vite@"^2.5.10" from @vitejs/[email protected]
npm ERR! node_modules/@vitejs/plugin-vue
npm ERR! dev @vitejs/plugin-vue@"^2.2.4" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See /home/user/.npm/eresolve-report.txt for a full report.

npm ERR! A complete log of this run can be found in:
npm ERR! /home/user/.npm/_logs/2022-10-27T08_56_48_899Z-debug-0.log

Bug: hyphenate props not work

A format like xx-xx will not work

<Text bg-color="red">Label </Text>
<Box
  :padding="1"
  :margin-x="2"
  width="100%"
  :max-width="100"
  flex-direction="column"
  border-color="yellowBright"
  border-style="round"
></Box>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.