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
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
|
ast (2.4.0)
|
||||||
|
coderay (1.1.2)
|
||||||
curses (1.3.2)
|
curses (1.3.2)
|
||||||
|
jaro_winkler (1.5.4)
|
||||||
|
method_source (0.9.2)
|
||||||
mini_portile2 (2.4.0)
|
mini_portile2 (2.4.0)
|
||||||
|
minitest (5.13.0)
|
||||||
nokogiri (1.10.7)
|
nokogiri (1.10.7)
|
||||||
mini_portile2 (~> 2.4.0)
|
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)
|
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)
|
thor (1.0.1)
|
||||||
|
unicode-display_width (1.6.0)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
|
minitest (~> 5.0)
|
||||||
noozoid!
|
noozoid!
|
||||||
|
pry
|
||||||
rake (~> 12.0)
|
rake (~> 12.0)
|
||||||
|
rubocop
|
||||||
|
rubocop-rspec
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.1.2
|
2.1.2
|
||||||
|
|
26
Rakefile
26
Rakefile
|
@ -1,2 +1,28 @@
|
||||||
require "bundler/gem_tasks"
|
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
|
task :default => :spec
|
||||||
|
|
129
exe/noozoid
129
exe/noozoid
|
@ -7,103 +7,11 @@
|
||||||
#
|
#
|
||||||
# Press `h` key when running for help.
|
# Press `h` key when running for help.
|
||||||
|
|
||||||
require 'nokogiri'
|
require 'noozoid/cli'
|
||||||
require 'curses'
|
|
||||||
|
|
||||||
Curses.init_screen
|
Noozoid::Cli.start(ARGV)
|
||||||
Curses.curs_set(0) # invisible cursor
|
|
||||||
|
|
||||||
|
exit 0
|
||||||
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
|
|
||||||
|
|
||||||
# Proper output of a tree
|
# Proper output of a tree
|
||||||
module PrettyPrint
|
module PrettyPrint
|
||||||
|
@ -119,19 +27,6 @@ module PrettyPrint
|
||||||
end
|
end
|
||||||
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
|
def print_help
|
||||||
puts '= Commands ='
|
puts '= Commands ='
|
||||||
puts ''
|
puts ''
|
||||||
|
@ -153,22 +48,6 @@ def print_help
|
||||||
read_command
|
read_command
|
||||||
end
|
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
|
def read_command
|
||||||
system("stty raw -echo") #=> Raw mode, no echo
|
system("stty raw -echo") #=> Raw mode, no echo
|
||||||
char = STDIN.getc
|
char = STDIN.getc
|
||||||
|
@ -179,8 +58,6 @@ end
|
||||||
if ARGV.empty?
|
if ARGV.empty?
|
||||||
print 'Mindmap name: '
|
print 'Mindmap name: '
|
||||||
current = root = Node.new(STDIN.gets.chomp)
|
current = root = Node.new(STDIN.gets.chomp)
|
||||||
else
|
|
||||||
current = root = read_mm(ARGV[0])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
loop do
|
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 'nokogiri', '~> 1.10'
|
||||||
spec.add_dependency 'curses', '~> 1.3'
|
spec.add_dependency 'curses', '~> 1.3'
|
||||||
spec.add_development_dependency 'rake', '~> 12.0'
|
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
|
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