Add basic structure

This commit is contained in:
Glenn Y. Rolland 2019-12-29 22:39:50 +01:00
parent b268319dfd
commit 8c87270a3b
17 changed files with 343 additions and 126 deletions

View file

@ -9,19 +9,46 @@ PATH
GEM
remote: https://rubygems.org/
specs:
ast (2.4.0)
coderay (1.1.2)
curses (1.3.2)
jaro_winkler (1.5.4)
method_source (0.9.2)
mini_portile2 (2.4.0)
minitest (5.13.0)
nokogiri (1.10.7)
mini_portile2 (~> 2.4.0)
parallel (1.19.1)
parser (2.7.0.0)
ast (~> 2.4.0)
pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
rainbow (3.0.0)
rake (12.3.3)
rubocop (0.78.0)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.6)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.7)
rubocop-rspec (1.37.1)
rubocop (>= 0.68.1)
ruby-progressbar (1.10.1)
thor (1.0.1)
unicode-display_width (1.6.0)
PLATFORMS
ruby
DEPENDENCIES
minitest (~> 5.0)
noozoid!
pry
rake (~> 12.0)
rubocop
rubocop-rspec
BUNDLED WITH
2.1.2

View file

@ -1,2 +1,28 @@
require "bundler/gem_tasks"
require "rake/testtask"
require 'rubocop/rake_task'
# Add additional test suite definitions to the default test task here
namespace :spec do
desc 'Runs RuboCop on specified directories'
RuboCop::RakeTask.new(:rubocop) do |task|
# Dirs: app, lib, test
task.patterns = ['exe/**/*.rb', 'lib/**/*.rb', 'spec/**/*_spec.rb']
# Make it easier to disable cops.
task.options << "--display-cop-names"
# Abort on failures (fix your code first)
task.fail_on_error = true
end
end
Rake::TestTask.new(:spec) do |t|
t.libs << "spec"
t.libs << "lib"
t.test_files = FileList['spec/**/*_spec.rb']
end
Rake::Task[:spec].enhance ['spec:rubocop']
task :default => :spec

View file

@ -7,103 +7,11 @@
#
# Press `h` key when running for help.
require 'nokogiri'
require 'curses'
require 'noozoid/cli'
Curses.init_screen
Curses.curs_set(0) # invisible cursor
Noozoid::Cli.start(ARGV)
begin
# Building a static window
win1 = Curses::Window.new(Curses.lines / 2 - 1, Curses.cols / 2 - 1, 0, 0)
win1.box("|", "-")
win1.setpos(2, 2)
win1.addstr("Hello")
win1.refresh
# In this window, there will be an animation
win2 = Curses::Window.new(Curses.lines / 2 - 1, Curses.cols / 2 - 1,
Curses.lines / 2, Curses.cols / 2)
win2.box("|", "-")
win2.refresh
2.upto(win2.maxx - 3) do |i|
win2.setpos(win2.maxy / 2, i)
win2 << "*"
win2.refresh
sleep 0.05
end
# Clearing windows each in turn
sleep 0.5
win1.clear
win1.refresh
win1.close
sleep 0.5
win2.clear
win2.refresh
win2.close
sleep 0.5
rescue
Curses.close_screen
end
exit 1
# Individual node type
class Node
protected
attr_accessor :parent
public
attr_accessor :name, :open
attr_reader :children, :parent
def initialize(name = 'untitled')
@name = name
@children = []
@parent = nil
@open = true
end
def []=(child)
@children.push(child)
child.parent = self
end
def [](i)
@children[i]
end
def toggle!
@open = !@open
end
def >>(n = 1)
return nil if @parent.nil?
idx = @parent.children.index(self)
return nil if idx.nil?
@parent[(idx + n) % @parent.children.length]
end
def <<(n = 1)
self >> -n
end
def remove
@parent.children.delete(self) unless @parent.nil?
end
def children?
!@children.empty?
end
end
exit 0
# Proper output of a tree
module PrettyPrint
@ -119,19 +27,6 @@ module PrettyPrint
end
end
KEYS = {
nav_parent: 'h',
nav_child: 'l',
nav_next: 'j',
nav_previous: 'k',
nav_root: 'r',
node_create: 'a',
node_delete: 'd',
node_toggle: 'v',
main_quit: 'q',
main_help: '?'
}
def print_help
puts '= Commands ='
puts ''
@ -153,22 +48,6 @@ def print_help
read_command
end
def read_mm(file_path)
xml = Nokogiri::XML(IO.read(file_path))
map_root = xml.xpath('/map/node')[0]
root = Node.new(map_root['TEXT'])
read_mm_subtree(root, map_root)
root
end
def read_mm_subtree(node, xml)
xml.xpath('node').each do |xml_child|
node_child = Node.new(xml_child['TEXT'])
node[] = node_child
read_mm_subtree(node_child, xml_child)
end
end
def read_command
system("stty raw -echo") #=> Raw mode, no echo
char = STDIN.getc
@ -179,8 +58,6 @@ end
if ARGV.empty?
print 'Mindmap name: '
current = root = Node.new(STDIN.gets.chomp)
else
current = root = read_mm(ARGV[0])
end
loop do

15
exe/test.rb Normal file
View file

@ -0,0 +1,15 @@
#!/usr/bin/env ruby
require 'curses'
include Curses
file = File.open ARGV[0]
begin
init_screen
file.each {|line| addstr(line) }
refresh
getch
ensure
close_screen
end

View file

View file

View file

View file

View file

17
lib/noozoid/cli.rb Normal file
View file

@ -0,0 +1,17 @@
require 'thor'
require_relative 'gui'
module Noozoid
class Cli < Thor
desc 'gui', 'Start ncurses GUI'
def gui
Gui.start
end
default_task :gui
end
end

30
lib/noozoid/config.rb Normal file
View file

@ -0,0 +1,30 @@
module Noozoid
module Config
HELP_KEYS = [
[:nav_parent, 'Navigate to parent'],
[:nav_child, 'Navigate to child' ],
[:nav_next, 'Navigate to next sibling'],
[:nav_previous, 'Navigate to previous sibling'],
[:nav_root, 'Navigate to tree root'],
[:node_create, 'Create node'],
[:node_delete, 'Delete selected node'],
[:node_toggle, 'Toggle node'],
[:main_help, 'Show this help'],
[:main_quit, 'Exit program']
]
DEFAULT_KEYS = {
nav_parent: 'h',
nav_child: 'l',
nav_next: 'j',
nav_previous: 'k',
nav_root: 'r',
node_create: 'a',
node_delete: 'd',
node_toggle: 'v',
main_quit: 'q',
main_help: '?'
}
end
end

55
lib/noozoid/gui.rb Normal file
View file

@ -0,0 +1,55 @@
require 'curses'
module Noozoid
module Gui
end
end
require_relative 'widgets/help_widget'
require_relative 'widgets/main_widget'
module Noozoid
module Gui
def start
Curses.init_screen
# invisible cursor
Curses.curs_set(0)
Curses.refresh
@main_window = MainWindow.new
while true do
@main_window.refresh
@main_window.loop
end
rescue Exception => e
Curses.close_screen
puts e
end
=begin
win2 = Curses::Window.new(Curses.lines / 2 - 1, Curses.cols / 2 - 1,
Curses.lines / 2, Curses.cols / 2)
win2.box("|", "-")
win2.refresh
2.upto(win2.maxx - 3) do |i|
win2.setpos(win2.maxy / 2, i)
win2 << "*"
win2.refresh
sleep 0.05
end
# Clearing windows each in turn
sleep 0.5
win1.clear
win1.refresh
win1.close
sleep 0.5
win2.clear
win2.refresh
win2.close
sleep 0.5
=end
module_function :start
end
end

57
lib/noozoid/node.rb Normal file
View file

@ -0,0 +1,57 @@
module Noozoid
# Individual node type
class Node
protected
attr_accessor :parent
public
attr_accessor :name, :open
attr_reader :children, :parent
def initialize(name = 'untitled')
@name = name
@children = []
@parent = nil
@open = true
end
def []=(child)
@children.push(child)
child.parent = self
end
def [](i)
@children[i]
end
def toggle!
@open = !@open
end
def >>(n = 1)
return nil if @parent.nil?
idx = @parent.children.index(self)
return nil if idx.nil?
@parent[(idx + n) % @parent.children.length]
end
def <<(n = 1)
self >> -n
end
def remove
@parent.children.delete(self) unless @parent.nil?
end
def children?
!@children.empty?
end
end
end

View file

@ -0,0 +1,49 @@
require_relative '../config'
module Noozoid
module Gui
class HelpWidget
def initialize
@win = Curses::Window.new(
Curses.lines / 2,
Curses.cols / 2,
Curses.lines / 4,
Curses.cols / 4
)
@win.box(?|, ?-)
@win.setpos(0, 1)
@win.addstr(' Noozoid help ')
self.fill
@win.refresh
end
def fill
t = 2
Noozoid::Config::HELP_KEYS.each do |key, desc|
@win.setpos(t, 7)
@win.addstr(Noozoid::Config::DEFAULT_KEYS[key])
@win.setpos(t, 10)
@win.addstr(desc)
t += 1
end
str = 'Press q to close'
@win.setpos(@win.maxy - 2, @win.maxx - str.size - 2)
@win.addstr(str)
end
def loop
while true
key = Curses.getch
break if key == 'q'
end
@win.clear
@win.refresh
@win.close
end
end
end
end

View file

@ -0,0 +1,49 @@
require_relative '../version'
module Noozoid::Gui
class MainWindow
def initialize
@win = Curses::Window.new(Curses.lines, Curses.cols, 0, 0)
# @win.box(?|, ?-)
# @win.refresh
@title = 'untitled'
end
def title=(value)
@title = value
self.refresh
end
def draw_header
top_str = "noozoid #{Noozoid::VERSION} ~ Use the arrow keys to navigate, press ? for help"
@win.attron(Curses::A_REVERSE)
@win.setpos(0, 0)
@win.addstr(" " * Curses.cols)
@win.setpos(0, 0)
@win.addstr(top_str)
@win.attroff(Curses::A_REVERSE)
@win.setpos(1, 0)
@win.addstr('-' * Curses.cols)
@win.setpos(1, 4)
@win.addstr(" #{@title} ")
end
def refresh
self.draw_header
@win.refresh
end
def loop
key = Curses.getch
@win.setpos(10, 1)
@win.addstr(" #{key.to_s} ")
case key
when ??
subwin = HelpWidget.new
subwin.loop
when ?q
raise "Exit"
end
end
end
end

View file

@ -31,4 +31,10 @@ Gem::Specification.new do |spec|
spec.add_dependency 'nokogiri', '~> 1.10'
spec.add_dependency 'curses', '~> 1.3'
spec.add_development_dependency 'rake', '~> 12.0'
spec.add_development_dependency "minitest", "~> 5.0"
spec.add_development_dependency "pry"
spec.add_development_dependency "rubocop"
spec.add_development_dependency "rubocop-rspec"
end

9
spec/spec_helper.rb Normal file
View file

@ -0,0 +1,9 @@
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
require "namarara"
require "minitest/autorun"
require 'pathname'
def testfile(name)
Pathname.new(__FILE__).dirname.join('files', name)
end