Prepare project structure
This commit is contained in:
commit
e9a7d7a815
10 changed files with 354 additions and 0 deletions
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
/.bundle/
|
||||
/.yardoc
|
||||
/_yardoc/
|
||||
/coverage/
|
||||
/doc/
|
||||
/pkg/
|
||||
/spec/reports/
|
||||
/tmp/
|
18
Gemfile
Normal file
18
Gemfile
Normal file
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
source "https://rubygems.org"
|
||||
|
||||
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
||||
|
||||
# gem "rails"
|
||||
|
||||
gem "nokogiri", "~> 1.10"
|
||||
|
||||
|
||||
gem "curses", "~> 1.3"
|
||||
source "https://rubygems.org"
|
||||
|
||||
# Specify your gem's dependencies in noozoid.gemspec
|
||||
gemspec
|
||||
|
||||
gem "rake", "~> 12.0"
|
17
Gemfile.lock
Normal file
17
Gemfile.lock
Normal file
|
@ -0,0 +1,17 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
curses (1.3.2)
|
||||
mini_portile2 (2.4.0)
|
||||
nokogiri (1.10.7)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
curses (~> 1.3)
|
||||
nokogiri (~> 1.10)
|
||||
|
||||
BUNDLED WITH
|
||||
2.1.2
|
35
README.md
Normal file
35
README.md
Normal file
|
@ -0,0 +1,35 @@
|
|||
# Noozoid
|
||||
|
||||
A terminal-based mindmap editor for geeks.
|
||||
|
||||
The name of the project comes from the Greek words _νους_ (mind) and _ζούδι_ (small animal).
|
||||
|
||||
## Installation
|
||||
|
||||
Type the following line in your favorite terminal:
|
||||
|
||||
$ gem install noozoid
|
||||
|
||||
## Usage
|
||||
|
||||
TODO: Write usage instructions here
|
||||
|
||||
|
||||
## Development
|
||||
|
||||
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
||||
|
||||
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
Bug reports and pull requests are welcome on GitHub at https://github.com/glenux/noozoid.
|
||||
|
||||
|
||||
## References
|
||||
|
||||
* <https://stac47.github.io/ruby/curses/tutorial/2014/01/21/ruby-and-curses-tutorial.html>
|
||||
|
||||
|
||||
|
2
Rakefile
Normal file
2
Rakefile
Normal file
|
@ -0,0 +1,2 @@
|
|||
require "bundler/gem_tasks"
|
||||
task :default => :spec
|
218
exe/noozoid
Executable file
218
exe/noozoid
Executable file
|
@ -0,0 +1,218 @@
|
|||
#!/usr/bin/env ruby
|
||||
# Usage:
|
||||
# - Start new mindmap:
|
||||
# `ruby ttymindmap.rb`
|
||||
# - Open Freemind format MM mindmap:
|
||||
# `ruby ttymindmap.rb <PATH-TO-MM-FILE>`
|
||||
#
|
||||
# Press `h` key when running for help.
|
||||
|
||||
require 'nokogiri'
|
||||
require 'curses'
|
||||
|
||||
Curses.init_screen
|
||||
Curses.curs_set(0) # invisible cursor
|
||||
|
||||
|
||||
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
|
||||
module PrettyPrint
|
||||
def self.tree(subtree, current, indent = 0)
|
||||
print ' ' * indent
|
||||
print subtree == current ? '> ' : '- '
|
||||
print subtree.name + "\n"
|
||||
|
||||
return unless subtree.open
|
||||
subtree.children.each do |child|
|
||||
tree(child, current, indent + 2)
|
||||
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
|
||||
puts '= Commands ='
|
||||
puts ''
|
||||
puts '- Navigation -'
|
||||
puts "#{KEYS[:nav_parent]}: go to parent node"
|
||||
puts "#{KEYS[:nav_child]}: go to children node"
|
||||
puts "#{KEYS[:nav_previous]}: previous sibling"
|
||||
puts "#{KEYS[:nav_next]}: next sibling"
|
||||
puts ''
|
||||
puts "- Action -"
|
||||
puts "#{KEYS[:node_create]}: create child node"
|
||||
puts "#{KEYS[:node_delete]}: remove node"
|
||||
puts "#{KEYS[:node_toggle]}: toggle"
|
||||
puts ''
|
||||
puts "- Misc -"
|
||||
puts "#{KEYS[:main_help]}: show this help"
|
||||
puts "#{KEYS[:main_quit]}: exit program"
|
||||
puts '[press a key to continue]'
|
||||
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
|
||||
system("stty -raw echo") #=> Reset terminal mode
|
||||
char
|
||||
end
|
||||
|
||||
if ARGV.empty?
|
||||
print 'Mindmap name: '
|
||||
current = root = Node.new(STDIN.gets.chomp)
|
||||
else
|
||||
current = root = read_mm(ARGV[0])
|
||||
end
|
||||
|
||||
loop do
|
||||
print `clear`
|
||||
PrettyPrint.tree(root, current)
|
||||
|
||||
cmd = read_command
|
||||
|
||||
if cmd == KEYS[:node_create]
|
||||
print 'Title: '
|
||||
current[] = Node.new(STDIN.gets.chomp)
|
||||
elsif cmd == KEYS[:node_delete]
|
||||
current.remove
|
||||
current = current.parent unless current.parent.nil?
|
||||
elsif cmd == KEYS[:node_toggle]
|
||||
current.toggle!
|
||||
elsif cmd == KEYS[:nav_child]
|
||||
current = current[0] if current.children?
|
||||
elsif cmd == KEYS[:nav_parent]
|
||||
current = current.parent unless current.parent.nil?
|
||||
elsif cmd == KEYS[:nav_previous]
|
||||
sibling = current >> -1
|
||||
current = sibling unless sibling.nil?
|
||||
elsif cmd == KEYS[:nav_next]
|
||||
sibling = current >> 1
|
||||
current = sibling unless sibling.nil?
|
||||
elsif cmd == KEYS[:nav_root]
|
||||
current = root
|
||||
elsif cmd == KEYS[:main_help]
|
||||
print_help
|
||||
elsif cmd == KEYS[:main_quit]
|
||||
puts 'Good Bye!'
|
||||
break
|
||||
end
|
||||
end
|
6
lib/noozoid.rb
Normal file
6
lib/noozoid.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
require "noozoid/version"
|
||||
|
||||
module Noozoid
|
||||
class Error < StandardError; end
|
||||
# Your code goes here...
|
||||
end
|
3
lib/noozoid/version.rb
Normal file
3
lib/noozoid/version.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
module Noozoid
|
||||
VERSION = "0.1.0"
|
||||
end
|
28
noozoid.gemspec
Normal file
28
noozoid.gemspec
Normal file
|
@ -0,0 +1,28 @@
|
|||
require_relative 'lib/noozoid/version'
|
||||
|
||||
Gem::Specification.new do |spec|
|
||||
spec.name = "noozoid"
|
||||
spec.version = Noozoid::VERSION
|
||||
spec.authors = ["Glenn Y. Rolland"]
|
||||
spec.email = ["glenux@glenux.net"]
|
||||
|
||||
spec.summary = %q{TODO: Write a short summary, because RubyGems requires one.}
|
||||
spec.description = %q{TODO: Write a longer description or delete this line.}
|
||||
spec.homepage = "TODO: Put your gem's website or public repo URL here."
|
||||
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
||||
|
||||
spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
||||
|
||||
spec.metadata["homepage_uri"] = spec.homepage
|
||||
spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
||||
spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
||||
|
||||
# Specify which files should be added to the gem when it is released.
|
||||
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
||||
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
||||
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
||||
end
|
||||
spec.bindir = "exe"
|
||||
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
||||
spec.require_paths = ["lib"]
|
||||
end
|
19
shard.yml
Normal file
19
shard.yml
Normal file
|
@ -0,0 +1,19 @@
|
|||
name: noozoid
|
||||
version: 0.1.0
|
||||
|
||||
# authors:
|
||||
# - name <email@example.com>
|
||||
|
||||
# description: |
|
||||
# Short description of ttymindmap
|
||||
|
||||
# dependencies:
|
||||
# pg:
|
||||
# github: will/crystal-pg
|
||||
# version: "~> 0.5"
|
||||
|
||||
# development_dependencies:
|
||||
# webmock:
|
||||
# github: manastech/webmock.cr
|
||||
|
||||
# license: MIT
|
Loading…
Reference in a new issue