Add basic structure
This commit is contained in:
parent
b268319dfd
commit
8c87270a3b
17 changed files with 343 additions and 126 deletions
27
Gemfile.lock
27
Gemfile.lock
|
@ -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
|
||||
|
|
26
Rakefile
26
Rakefile
|
@ -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
|
||||
|
|
129
exe/noozoid
129
exe/noozoid
|
@ -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
15
exe/test.rb
Normal 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
|
0
lib/noozoid/actions/node_create.rb
Normal file
0
lib/noozoid/actions/node_create.rb
Normal file
0
lib/noozoid/actions/node_delete.rb
Normal file
0
lib/noozoid/actions/node_delete.rb
Normal file
0
lib/noozoid/actions/node_edit.rb
Normal file
0
lib/noozoid/actions/node_edit.rb
Normal file
0
lib/noozoid/actions/node_move.rb
Normal file
0
lib/noozoid/actions/node_move.rb
Normal file
0
lib/noozoid/actions/node_rename.rb
Normal file
0
lib/noozoid/actions/node_rename.rb
Normal file
17
lib/noozoid/cli.rb
Normal file
17
lib/noozoid/cli.rb
Normal 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
30
lib/noozoid/config.rb
Normal 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
55
lib/noozoid/gui.rb
Normal 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
57
lib/noozoid/node.rb
Normal 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
|
49
lib/noozoid/widgets/help_widget.rb
Normal file
49
lib/noozoid/widgets/help_widget.rb
Normal 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
|
49
lib/noozoid/widgets/main_widget.rb
Normal file
49
lib/noozoid/widgets/main_widget.rb
Normal 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
|
|
@ -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
9
spec/spec_helper.rb
Normal 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
|
Loading…
Add table
Reference in a new issue