Giter Site home page Giter Site logo

scone's Introduction

scone Β· build status license

Create cross-platform terminal applications.

Example

import scone;

void main() {
  frame.title("example");
  frame.size(33, 20);

  bool run = true;
  while(run) {
    foreach(input; input.keyboard) {
      // if CTRL+C is pressed
      if(input.key == SK.c && input.hasControlKey(SCK.ctrl)) {
        run = false;
      }
    }

    frame.write(
      12, 9,
      TextStyle().fg(Color.yellow), "Hello ", // white foreground text (chainable pattern)
      TextStyle().fg(Color.red).bg(Color.white), "World" // red foreground, white background
    );
    frame.print();
  }
}

win mac

Features

  • Display text and colors
  • Receive keyboard input
  • Cross-platform

Simple cross-platform chart

output Windows POSIX
text βœ“ βœ“
emoji βœ“
ansi-color βœ“ βœ“
rgb-color βœ“
high performance output βœ“
input Windows POSIX
input detection βœ“ βœ“
reliable βœ“ *
control keys βœ“ **
key release detection βœ“

* Input is converted from arbitrary number sequences (may differ from system to system) to an input event. Basic ASCII should work no matter what system, however special keys like the up-arrow or function keys can vary drastically.

** Only registers the last pressed control key.

Install with dub

Note: 3.0.0 is not yet available.

/// dub.json
"dependencies": {
    "scone": "~>3.0.0",
    ...
}
/// dub.sdl
dependency "scone" version="~>3.0.0"

scone's People

Contributors

dkorpel avatar vladdesv avatar

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

scone's Issues

Re-structure parts of code

scone has been in pre-release hell for the past year.

Initial thought is to release a version 2 which works, and with 2.1 release a version which has lots of the backend reformatted


  • os.d β†’ os/..., restructure the OS specific parts. Might change later on again (fixed in 82644f9)
  • input.d β†’ input/... (fixed in 459798a)
  • window.d
  • colors.d "overhaul"

Settings

I am unsure how settings should be implemented, and if they should be able to be modified after the setup phase.

My plan is to have some sort of setting which will be set by the user in shared static this() { ... }.

I want to be able to enable/disable parts of scone, such as the frame, input, and later on audio. These should not be changeable during after the setup.

But other settings, like if the window should auto-resize when the user changes the window size, might want to be desirable to change mid-application.

For now, the settings should be unchangeable after setup. I might loosen this sometime.

How to properly interact with InputEvent?

I want to build interface with user input. Input must be a strings (command names) for example help or exit. But I don't find methods to manipulate with InputEvent properly (backspace, delete, up/down for history etc). Is they methods are exists? Maybe in other companion project?

Catchline suggestion

How about this?

β€œ:bread: scone helps you build beautiful and portable text user interfaces”

Audio

Allow playing sound files. Ideally some sort of sound handling system as well.

The user should be able to

  • play a sound
  • stop a sound

Fine-tune README

  • Better GIF, maybe combine into one?
  • Set "usage with dub" to use version 2
  • Remove Trello reference

RGB color

Modern terminal emulators (POSIX/Windows) support RGB ANSI color codes. This would be great to have as a feature.

Styled text wrapper

I want some sort of text wrapper which contains some text and a TextStyle attribute (blocked by #51).

Example usage would be Foo("foo", TextStyle().bg(Color.red)); (syntax subject to change).

I am unsure how I should handle different type of strings (string, wstring, dstring), or other types like arrays and other things.

CLI-like output

Enable colors with std.stdio's write family.

I tried implementing a feature like this once by overriding the toString() method for the TextStyle struct, which outputs as an ANSI escape code which sets the colors. This functionality, however, does not belong there.

One approach would be to add a function with the signature

string cli(TextStyle style);

where you could do the following in the standard writeln

writeln("Welcome ", TextStyle().bg(Color.yellow).cli(), "user", TextStyle().cli(), ".");

// alternatively
auto info = TextStyle().bg(Color.yellow).cli();
auto reset = TextStyle().fg(Color.initial).bg(Color.initial).cli();
writeln("Welcome ", info, "user", reset, ".");

Window size is inconsequent

Currently, the size of the internal buffer is not dependent on the actual size of the console/terminal (window).

Solution

I propose having the internal buffer size match the size of the window. Problem arises however, when the a developer needs a minimum window size.

For this problem I suggest having a flag somehow to determine certain actions. Preferably something in the style of scone.settings.fixedSize = true;.

This would always try to output to the window as if it was that size (meaning some content will not be visible), but also manage to notify the user that the window is too small.

Multi-byte characters support

When trying to use "πŸ˜ƒ" as text it is displayed but the background gets broken.

Do you think you may solve this, it is for a small game inspired by old 8-Bit time programs...and only normal ascii is to limited...

naming of colors

The Color.red_dark is brighter than Color.red,
same for blue_dark, white_dark, yellow_dark all brighter than without _dark. Please check.
Regards mt.

Create proper Github issue templates

Github gives the ability to create issue templates, with template examples for bugs, features, and custom issues.

Having such could potentially help in ensuring reported issues are proper and clean.

Templates:

  • Bug template
  • Feature template
  • Misc. template

Window resize detection

Detecting if the window has been resized is done differently on Windows and POSIX.

On Windows, once you loop through all inputs you can see if the window has been resized. This means if you do not call inputs.latest, the window resize event will never be called. This is bad, because logic related to the frame is dictated in the inputs module (even though the detection time is near instant). This logic is single-threaded.

On POSIX, there is a background thread constantly running and checking the window size every 0.25 seconds, and sending a ResizeEvent once it detects a change. This logic is multi-threaded.

I cannot have the Windows variant, and I'm a bit skeptical towards the multi-threaded variant (even though it seems to work fine).

Instead I think it might be better to go with half-way with both variants. I want to add some sort of timing check in the frame.print method, where it checks if a print call has been mad the past 0.25 seconds, and if not it checks the size of the window.

This approach takes the worst parts of both the Windows and POSIX approach, however it will be consistent for both platforms and (most importantly) it will work.

Print default console colors on Windows

Print the CMD.exe/PowerShell.exe default colors, when using Color.initial. Currently black and white colors are set as the default colors.

This is not as easy as I first thought.

Just got the following error @ scone-2.1.0/scone/source/scone/os/posix.d(162,23)

dmd-2.083.0)mt@dlang-pad-110-15IBR:~/d-learn/moon-fruit$ dub --compiler=dmd
Performing "debug" build using dmd for x86_64.
scone 2.1.0: building configuration "library"...
moon-fruit ~master: building configuration "application"...
../../.dub/packages/scone-2.1.0/scone/source/scone/os/posix.d(162,23): Error: undefined identifier eventsFromSequence, did you mean function eventFromSequence?
dmd failed with exit code 1.

I just tried to update my old program to work with latest version of scone.
p.s. It is not so important for me, but want to report this to you.

Regrads mt.

Not printable char

Hi, when doing a loop with randomized printing of 100 chars on the window with one window.print() at the end. I get some unprintable chars displayed as [??] on the window.
When calling window.print() after every char, no unprintable [??] chars appear.

Resizing mega-issue

Resizing is an issue for both Windows and POSIX platforms.

Windows Terminal is Microsoft most recent Terminal emulator. It acts as an POSIX terminal, but can still be manipulated with Console API functions. With version v1.0.1401.0, Windows Terminal does not support resizing the terminal at all.

Hyper.js does not support ANSI resizing commands. From what I understand there is a possibility for scone to do resizing with Hyper.js, but that functionality needs to be implemented into scone.

Issues

Improve POSIX output

When printing on POSIX, each cell is not printed separately (like on Winodws), but rather are printed per line. The virtual cursor is moved to each line, then the content is printed at the cursor position. However, due to how the cursor is moved, it being an ANSI escape code being printed, it can be combined into one single print command.

From my benchmarks done ages ago [citation needed], and also with the support of the limited benchmark under benchmark/ in the project root, I can confidently claim that combining the whole print statement into one command is slightly faster.

My reasoning is that, currently there will be two printf(...) calls per row which is modified. With this new approach, whenever something is changed there will only be one (1) printf(...) call. As mentioned, the time to print a screen is marginally better, but I personally feel one single print command is more desirable than multiple. The amount of data printed will still be exactly the same.

Rework README

I believe there is room for improvement on the README.

Looking at a similar project crossterm, I feel it conveys its features much better.

Release v3

There should be a proper release soon.

Unittests

In v2 there where almost no unittests because of the very tightly coupled (read: messy) code. In v3 the code is much more separated and can be tested separately.

Some features which are directly tied to the OS (reading input/checking what has been displayed) cannot be tested as its own "unit".

Some features which can be tested (off the top of my head):

  • Colors
  • Buffers
  • Flags

"Unresolved external symbols" when compiling on Windows

  • OS: Windows

Bug: When dub gets to the linking step, the following errors occur:

scone.lib(windows_3c8_38d.obj) : error LNK2019: unresolved external symbol GetSystemMetrics referenced in function _D5scone2os7windows9WindowsOS6resizeFxkxkZv
scone.lib(windows_3c8_38d.obj) : error LNK2019: unresolved external symbol SetWindowPos referenced in function _D5scone2os7windows9WindowsOS10repositionFNbNiiiZv
.dub\build\application-debug-windows-x86_64-dmd_2088-F83972565FA2F7DB289FECBA209E86F8\openmc173.exe : fatal error LNK1120: 2 unresolved externals
Error: linker exited with status 1120
dmd failed with exit code 1.

tl;dr It fails to locate "GetSystemMetrics" and "SetWindowPos".

Reproduce: I added scone 2.1.2 to my dependencies, copied in the example code from the readme, and compiled using the following command:
dub run --compiler=dmd -a=x86_64 -b=debug -c=application'

Additional context: I fixed this by going into scone/os/windows.d and adding the following line:
pragma(lib, "User32.lib");
Which was suggested in this thread on the D forums.

I'd make a pull request, but I don't know if this is the "right" way to fix this error, and it may not even be scone's fault, since it isn't the one who declares those external symbols.

Setting the text of a UITextInput to an empty string causes a RangeError

Pretty much what it says on the tin. Because the cursor position is never updated after changing the text of the UITextInput to an empty string, when it tries to insert the cursor into the string for rendering it goes out of bounds given the cursor wasn't at 0.

I've tried the obvious patch of overriding the property, but the compiler doesn't like mixing type inference and overriding, so that doesn't work.

Replace sconeSetup

sconeSetup is an overrideable delegate which is run on local thread start only once.

By default it sets up up a default frame and input, but requires the user to write the code themselves.

This could be replaced with and enum instead.

enum SconeModule {
  none = 0,
  frame = 1,
  input = 2,
  // todo audio = 4,
}

I would also like to safeguard these setting by putting them in a container which errors if the settings are modified after initialization. I am thinking of something like this (unsure of implementation):

// modifying in other place than 'shared static this' will error
shared static this()
{
  scone.modules = SconeModule.frame | SconeModule.audio;
}

Rename general Input to Keyboard

Currently all user input is gone through the Input class. However, only keyboard events are currently supported. Additionally InputEvents data is only related to keyboard button presses.

Further more, there are two classes with the name Input, one regards a connection to the terminal on an OS level, and the second regards keyboard presses. This has caused some ugly (personal opinion) workaround to get the code working together.

I suggest the high level Input class which handles keyboard presses be renamed to a more appropriate name Keyboard. This would also include renaming InputEvent to KeyboardEvent.

Question only

Is it possible to read the char on a window position?
(opposite or write(x,y,vaues), something like get_char(x,y)?)

TextStyle

Replacement for (or an alternative to) the current way of setting foreground and background colors.

Personally I feel the current approach comes across as clumsy, where you have to write Color.red.foreground or foreground(Color.red).

The styles must be easy to use, and where uninitialised properties must remain the same overwritten cells.

I propose a pattern as such

TextStyle().fg(Color.red).bg(Color.green)

and

TextStyle(Color.red, Color.green)

and

auto style = TextStyle();
style.foreground = Color.red;
style.background = Color.green;

RGB output on Windows

This is not yet implemented. Either fix, or disable for Windows.

Must be resolved before release.

Multiple keypressed registered as single unknown key

Pressing one (1) button causes an ANSI sequence to be sent. For instance:

  • A = 97
  • β†’ = 27, 91, 67

The input sequence is read one (1) number at a time, sent from the input thread to the main thread. Eg. β†’ causes the numbers 27, 91, and 67 to be sent to main thread.

The main thread works by: once receiving a number, it waits 1 millisecond, and if another number is sent by then that number also gets appended to the current sequence.

So if two (2) or more buttons are pressed at the same time, two separate keys can be registered as one (1) key, because the numbers get sent within the delay.

(partial) Solution

For every character which get appended, check against the locale to see if that sequence exists. If so, treat it as a continuation of the sequence, otherwise, register it as two separate key presses.

For instance, if F1 (27, 79, 80) and B (98) are pressed at the same time, either of the following sequences will be produced:

  • 27, 79, 80, 98
  • 98, 27, 79, 80

The input handler should check if the first number is a part of a sequence, and continue until the sequence isn't matched anymore.

For example: Let's assume the sequence 27, 79, 80, 98 is sent.

  1. The input handler first checks if 27 matches any sequences.
  2. Above is true, so then continue and check if 27, 79 is part of a sequence.
  3. Above is true, so then continue and check if 27, 79, 80 is part of a sequence.
  4. Above is true, so then continue and check if 27, 79, 80, 98 is part of a sequence.
  5. Above is not true, so the handler checks if 27, 79, 80 is a valid sequence.
    • If sequence exists return appropriate key
    • If sequence does not exist, return unknown key
  6. Now continue checking numbers, and check if 80 is part of a sequence.
  7. Above is true. Last number was found, and return appropriate key or unknown.

"Partial" explained

1. Sequences including sets of sequences

This could in theory break if a button X has the sequence 97, 98, and pressing the A (97) and B (98) buttons pressed at the same time could register as that button. However, the chance of this effectively happening is (subjective opinion: ) very low.

Pressing Esc (27) and Alt + 8 (91) and Shift + A (65) at the same time could register as the Up (27, 91, 65) key.

2. Overlapping sequences

The current proposal would also break if two sequences overlap. An over-simplified example would be: How should the letters h e l l o m e n be interpreted; Hello Men or Hell Omen?

Mouse

Allow the detection of mouse events (left-click, right-click, etc).

Could cause problems on POSIX where mouse events are not always available.

Proper logging

I am uncertain how logging should be implemented (I do not know the Best Practicesβ„’). Currently, I have commented out pseudo-"logging code", in the form of:

//log(warning, "X might be Y");

Any help with implementing good logging is very much appreciated πŸ™.

Release v3

Before we can release v3 there are some things I am unsure how to handle. Here is a list of issues in no particular order:

  • Windows Terminal is not compatible (specifically resizing)
  • Cannot disable modules (input/output)
  • (Windows) Colors not shown unless both foreground and background colors are set.
  • ANSI color codes on macOS are flipped (90 and 30). Double check this.

Enable POSIX style rendering on Windows

On Windows, the WinApi is used to render each cell. This is highly efficient, but comes with the drawback of it being an old API. UTF-8 is not that greatly supported (AFAIK), and RGB colors cannot be used.

Newer versions of the Windows Console (PowerShell since Windows 10 at least), understands ANSI escape codes. Enabling the same rendering method on Windows would allow RGB colors.

I am not aware of any other methods to print RGB colors on Windows.

OS.Windows.resize fails for small sizes

When I resize the console so that the amount of rows is 0, this assert fails:

//os.d line 236
assert(SetConsoleScreenBufferSize(consoleOutputHandle, size), "Unable to resize screen buffer");

I'm using Windows 10 and the cmd.exe terminal.

Looking at the documentation of SetConsoleScreenBufferSize:
"The specified dimensions also cannot be less than the minimum size allowed by the system. This minimum depends on the current font size for the console (selected by the user) and the SM_CXMIN and SM_CYMIN values returned by the GetSystemMetrics function."

It doesn't seem to check that currently.

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.