-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 993adee
Showing
6 changed files
with
515 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
# Created by https://www.toptal.com/developers/gitignore/api/ruby,rubymine | ||
# Edit at https://www.toptal.com/developers/gitignore?templates=ruby,rubymine | ||
|
||
### Ruby ### | ||
*.gem | ||
*.rbc | ||
/.config | ||
/coverage/ | ||
/InstalledFiles | ||
/pkg/ | ||
/spec/reports/ | ||
/spec/examples.txt | ||
/test/tmp/ | ||
/test/version_tmp/ | ||
/tmp/ | ||
|
||
# Used by dotenv library to load environment variables. | ||
# .env | ||
|
||
# Ignore Byebug command history file. | ||
.byebug_history | ||
|
||
## Specific to RubyMotion: | ||
.dat* | ||
.repl_history | ||
build/ | ||
*.bridgesupport | ||
build-iPhoneOS/ | ||
build-iPhoneSimulator/ | ||
|
||
## Specific to RubyMotion (use of CocoaPods): | ||
# | ||
# We recommend against adding the Pods directory to your .gitignore. However | ||
# you should judge for yourself, the pros and cons are mentioned at: | ||
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control | ||
# vendor/Pods/ | ||
|
||
## Documentation cache and generated files: | ||
/.yardoc/ | ||
/_yardoc/ | ||
/doc/ | ||
/rdoc/ | ||
|
||
## Environment normalization: | ||
/.bundle/ | ||
/vendor/bundle | ||
/lib/bundler/man/ | ||
|
||
# for a library or gem, you might want to ignore these files since the code is | ||
# intended to run in multiple environments; otherwise, check them in: | ||
# Gemfile.lock | ||
# .ruby-version | ||
# .ruby-gemset | ||
|
||
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this: | ||
.rvmrc | ||
|
||
# Used by RuboCop. Remote config files pulled in from inherit_from directive. | ||
# .rubocop-https?--* | ||
|
||
### RubyMine ### | ||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider | ||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 | ||
|
||
# User-specific stuff | ||
.idea/**/workspace.xml | ||
.idea/**/tasks.xml | ||
.idea/**/usage.statistics.xml | ||
.idea/**/dictionaries | ||
.idea/**/shelf | ||
|
||
# AWS User-specific | ||
.idea/**/aws.xml | ||
|
||
# Generated files | ||
.idea/**/contentModel.xml | ||
|
||
# Sensitive or high-churn files | ||
.idea/**/dataSources/ | ||
.idea/**/dataSources.ids | ||
.idea/**/dataSources.local.xml | ||
.idea/**/sqlDataSources.xml | ||
.idea/**/dynamic.xml | ||
.idea/**/uiDesigner.xml | ||
.idea/**/dbnavigator.xml | ||
|
||
# Gradle | ||
.idea/**/gradle.xml | ||
.idea/**/libraries | ||
|
||
# Gradle and Maven with auto-import | ||
# When using Gradle or Maven with auto-import, you should exclude module files, | ||
# since they will be recreated, and may cause churn. Uncomment if using | ||
# auto-import. | ||
# .idea/artifacts | ||
# .idea/compiler.xml | ||
# .idea/jarRepositories.xml | ||
# .idea/modules.xml | ||
# .idea/*.iml | ||
# .idea/modules | ||
# *.iml | ||
# *.ipr | ||
|
||
# CMake | ||
cmake-build-*/ | ||
|
||
# Mongo Explorer plugin | ||
.idea/**/mongoSettings.xml | ||
|
||
# File-based project format | ||
*.iws | ||
|
||
# IntelliJ | ||
out/ | ||
|
||
# mpeltonen/sbt-idea plugin | ||
.idea_modules/ | ||
|
||
# JIRA plugin | ||
atlassian-ide-plugin.xml | ||
|
||
# Cursive Clojure plugin | ||
.idea/replstate.xml | ||
|
||
# SonarLint plugin | ||
.idea/sonarlint/ | ||
|
||
# Crashlytics plugin (for Android Studio and IntelliJ) | ||
com_crashlytics_export_strings.xml | ||
crashlytics.properties | ||
crashlytics-build.properties | ||
fabric.properties | ||
|
||
# Editor-based Rest Client | ||
.idea/httpRequests | ||
|
||
# Android studio 3.1+ serialized cache file | ||
.idea/caches/build_file_checksums.ser | ||
|
||
### RubyMine Patch ### | ||
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 | ||
|
||
# *.iml | ||
# modules.xml | ||
# .idea/misc.xml | ||
# *.ipr | ||
|
||
# Sonarlint plugin | ||
# https://plugins.jetbrains.com/plugin/7973-sonarlint | ||
.idea/**/sonarlint/ | ||
|
||
# SonarQube Plugin | ||
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin | ||
.idea/**/sonarIssues.xml | ||
|
||
# Markdown Navigator plugin | ||
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced | ||
.idea/**/markdown-navigator.xml | ||
.idea/**/markdown-navigator-enh.xml | ||
.idea/**/markdown-navigator/ | ||
|
||
# Cache file creation bug | ||
# See https://youtrack.jetbrains.com/issue/JBR-2257 | ||
.idea/$CACHE_FILE$ | ||
|
||
# CodeStream plugin | ||
# https://plugins.jetbrains.com/plugin/12206-codestream | ||
.idea/codestream.xml | ||
|
||
# Azure Toolkit for IntelliJ plugin | ||
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij | ||
.idea/**/azureSettings.xml | ||
|
||
# End of https://www.toptal.com/developers/gitignore/api/ruby,rubymine |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# decent | ||
decent is a text user interface (TUI) library written in Ruby without the use of Curses or any external libraries. | ||
|
||
decent is modeled after SolidJS's Signals (Observables), and a React-like workflow. | ||
|
||
```ruby | ||
require "decent" | ||
|
||
Decent::App.new do | ||
count = ref 0 | ||
|
||
text derived { "Count is: #{count.value}!" } | ||
|
||
# NOTE: We'll have interactions later! This is just a demo :) | ||
Thread.new do | ||
count.value += 1 | ||
end | ||
end | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
require "./reactivity.rb" | ||
require "./terminal_renderer.rb" | ||
require "observer" | ||
require "io/console" | ||
|
||
module Decent | ||
class App | ||
include Decent | ||
|
||
def initialize(renderer = nil, &tui) | ||
@renderer = renderer || TerminalRenderer.new(STDOUT) | ||
|
||
@tree = { type: "root", children: [] } | ||
@tree[:parent] = @tree | ||
|
||
@current_node = @tree | ||
|
||
instance_eval(&tui) | ||
end | ||
|
||
def element(name, properties = {}, &children) | ||
subscriptions = [] | ||
node = { type: name, properties: properties, children: [], parent: @current_node, subscriptions: subscriptions } | ||
|
||
properties.each do |key, prop| | ||
if prop.is_a?(Ref) | ||
properties[key] = prop.value | ||
|
||
effect = Watcher.new do |new| | ||
properties[key] = new | ||
render | ||
end | ||
|
||
prop.add_observer effect | ||
subscriptions << effect | ||
end | ||
end | ||
|
||
@current_node[:children] << node | ||
@current_node = node | ||
children&.call | ||
@current_node = @current_node[:parent] | ||
|
||
node | ||
end | ||
|
||
def show(args, &children) | ||
# ruby does not like argument names being keywords, so we do this hack to make it work | ||
cond = args[:if] | ||
|
||
# this has cond: as a property to trigger a rerender when the value changes | ||
node = element("show", { cond: cond }) | ||
|
||
should_show = false | ||
|
||
effect do | ||
if should_show != cond.value | ||
should_show = cond.value | ||
|
||
if cond.value | ||
@current_node = node | ||
|
||
children&.call | ||
else | ||
node[:children] = [] | ||
end | ||
end | ||
end | ||
end | ||
|
||
# this currently triggers a render twice upon initialization. | ||
# this is because we do not have explicit dependency arrays and call `render` inside of the effect body. | ||
# TODO: make this not shit | ||
def each(args, &child) | ||
of = args[:of] | ||
node = element("each") | ||
|
||
effect do | ||
node[:children] = [] | ||
|
||
of.value.each_with_index do |item, index| | ||
@current_node = node | ||
|
||
child.call item, index | ||
end | ||
|
||
render | ||
end | ||
end | ||
|
||
def box(width: "auto", height: "auto", &children) | ||
element("box", { width: width, height: height, }, &children) | ||
end | ||
|
||
def text(text) | ||
element("text", { content: text }) | ||
end | ||
|
||
def render | ||
@renderer.clear | ||
# these go in the order of starting coordinates (x, y), then the max amount rows and cols | ||
@bounds = [[1, 0], @renderer.size] | ||
|
||
stack = [@tree] | ||
|
||
until stack.length == 0 | ||
node = stack.pop | ||
|
||
# todo: this is a hack until i get rendering to work in the correct order | ||
stack.concat node[:children].reverse | ||
|
||
properties = node[:properties] | ||
|
||
|
||
# todo: nothing here actually resets the bounds when we leave the component. not good. | ||
case node[:type] | ||
when "text" | ||
@renderer.draw properties[:content], @bounds[0][0], @bounds[0][1] | ||
|
||
# todo: remove this shit later, layouting should be handled by stacks and flows, not by the components themselves | ||
# also, the .length + 1 shit is just to add a space, not *really* necessary | ||
@bounds[0][0] += properties[:content].length + 1 | ||
when "box" | ||
box = "" | ||
|
||
width = properties[:width] == "auto" ? @bounds[1][0] : properties[:width] | ||
height = properties[:height] == "auto" ? @bounds[1][1] : properties[:height] | ||
|
||
box << "┌#{'─' * (width - 2)}┐\n" | ||
box << "│#{' ' * (width - 2)}│\n" * (height - 2) | ||
box << "└#{'─' * (width - 2)}┘" | ||
|
||
@renderer.draw box, @bounds[0][0], @bounds[0][1] | ||
|
||
@bounds[0][0] += 1 | ||
@bounds[0][1] += 1 | ||
@bounds[1][0] -= 2 | ||
@bounds[1][1] -= 2 | ||
end | ||
end | ||
end | ||
|
||
def run | ||
begin | ||
@renderer.setup | ||
render | ||
loop {} | ||
ensure | ||
@renderer.cleanup | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
require "./decent.rb" | ||
|
||
app = Decent::App.new do | ||
count = ref 1 | ||
|
||
box do | ||
box do | ||
text derived { "Count is: #{count.value}! Also, decent is fucking sweet. Look at these sick-ass boxes."} | ||
end | ||
end | ||
|
||
Thread.new do | ||
loop do | ||
count.value += 1 | ||
sleep 0.07 | ||
end | ||
end | ||
end | ||
|
||
app.run |
Oops, something went wrong.