Compare commits
48 commits
Author | SHA1 | Date | |
---|---|---|---|
|
a707be5c63 | ||
|
06c00e545c | ||
|
798932046a | ||
|
8216c91e88 | ||
|
a5dbbb1d49 | ||
|
d338b1c924 | ||
|
30f8d5e9a0 | ||
|
ddbb2903cb | ||
|
b1c0c2b5ef | ||
|
b750e281ef | ||
|
d46d6a0fd4 | ||
|
03481e6ee4 | ||
fbee330868 | |||
53d34ddbf1 | |||
1e72d86d54 | |||
f8ce378b99 | |||
d9edb054ad | |||
6886f36c08 | |||
55d203da8d | |||
|
470d0b42f8 | ||
|
9f045fb5d9 | ||
|
2d6d5b21e3 | ||
|
58ad2950f8 | ||
|
19e6e14f01 | ||
|
3b0e5a2ce3 | ||
|
0a23465b98 | ||
|
93be352501 | ||
|
841cde2dc2 | ||
f5896f6b2d | |||
d3ec76f37a | |||
90576fb2b4 | |||
4cb5238065 | |||
52731febd5 | |||
def5c85f68 | |||
|
c0f0c890ca | ||
cda1edf92c | |||
ffa3c6c39e | |||
|
f200005e92 | ||
|
cdcec384f0 | ||
|
34b3f80b3e | ||
|
93a9772ee3 | ||
|
a4d9c5b39b | ||
|
f90bbee818 | ||
|
4c4f0e1ddc | ||
|
ef6c37e43e | ||
d6d5e66cfa | |||
|
488d4616e0 | ||
|
a61d466bd1 |
24 changed files with 944 additions and 82 deletions
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
*.a
|
||||
/.bundle/
|
||||
/coverage/
|
||||
/doc/
|
||||
/Gemfile.lock
|
||||
/Kookfile
|
||||
mkmf.log
|
||||
*.o
|
||||
/pkg/
|
||||
*.so
|
||||
/spec/reports/
|
||||
/tmp/
|
||||
/vendor/
|
||||
/_yardoc/
|
||||
/.yardoc
|
4
Gemfile
Normal file
4
Gemfile
Normal file
|
@ -0,0 +1,4 @@
|
|||
# A sample Gemfile
|
||||
source "https://rubygems.org"
|
||||
|
||||
gemspec
|
22
LICENSE.md
Normal file
22
LICENSE.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 2015 Glenn Y. Rolland
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
80
README.md
80
README.md
|
@ -1,8 +1,74 @@
|
|||
KoProj is a tool for managing console project environments
|
||||
# Kook
|
||||
|
||||
Ex: Project X require 3 terminals, with name A, B, C
|
||||
A : must be in directory ~/
|
||||
B : must be in directory ~/foo
|
||||
run command X
|
||||
C : must be in directory ~/bar
|
||||
run command Y
|
||||
Kook is a helper for opening your projects environments in tabs of KDE Konsole.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
Simply install kook via the 'gem' package manager
|
||||
|
||||
$ gem install kook
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Imagine, that for working on your project, you requires multiple terminal consoles,
|
||||
with different tools in them.
|
||||
|
||||
Let say that :
|
||||
|
||||
A : must be in directory ~/src/myProject/
|
||||
B : must be in directory ~/src/myProject/app
|
||||
and run command "$EDITOR ."
|
||||
C : must be in directory ~/src/myProject/log
|
||||
and run command "tail -f development.log"
|
||||
|
||||
Kook aims to prepare your project environment, just like you want it to be,
|
||||
with all you tabs and the commands inside in the right directories. Everything
|
||||
in one single command.
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork it ( http://github.com/glenux/kook/fork )
|
||||
2. Create your feature branch (`git checkout -b my-new-feature`)
|
||||
3. Commit your changes (`git commit -am 'Add some feature'`)
|
||||
4. Push to the branch (`git push origin my-new-feature`)
|
||||
5. Create new Pull Request
|
||||
|
||||
|
||||
## Alternatives
|
||||
|
||||
* Tmuxinator (the same goal, based on tmux instead of Konsole)
|
||||
|
||||
# Kook
|
||||
|
||||
TODO: Write a gem description
|
||||
|
||||
## Installation
|
||||
|
||||
Add this line to your application's Gemfile:
|
||||
|
||||
```ruby
|
||||
gem 'kook'
|
||||
```
|
||||
|
||||
And then execute:
|
||||
|
||||
$ bundle
|
||||
|
||||
Or install it yourself as:
|
||||
|
||||
$ gem install kook
|
||||
|
||||
## Usage
|
||||
|
||||
TODO: Write usage instructions here
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork it ( https://github.com/[my-github-username]/kook/fork )
|
||||
2. Create your feature branch (`git checkout -b my-new-feature`)
|
||||
3. Commit your changes (`git commit -am 'Add some feature'`)
|
||||
4. Push to the branch (`git push origin my-new-feature`)
|
||||
5. Create a new Pull Request
|
||||
|
|
7
Rakefile
Normal file
7
Rakefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
require 'rspec/core/rake_task'
|
||||
require "bundler/gem_tasks"
|
||||
|
||||
RSpec::Core::RakeTask.new(:spec)
|
||||
|
||||
task :default => :spec
|
16
TODO.md
Normal file
16
TODO.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
Kook Task List
|
||||
==============
|
||||
|
||||
Package as a gem
|
||||
-----------------
|
||||
|
||||
- ( ) Write gemspec
|
||||
- ( ) Migrate gems & check versions
|
||||
|
||||
|
||||
Marketing
|
||||
---------
|
||||
|
||||
- ( ) Rename project
|
||||
- ( ) Write documentation
|
||||
|
23
bin/kook
Executable file
23
bin/kook
Executable file
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env ruby
|
||||
# vim: set syntax=ruby:
|
||||
|
||||
require 'yaml'
|
||||
require 'singleton'
|
||||
require 'pathname'
|
||||
|
||||
require 'colorize'
|
||||
|
||||
DATA_DIR = (Pathname.new(__FILE__).dirname + '..').realpath.to_s
|
||||
|
||||
require 'thor'
|
||||
require 'kook'
|
||||
|
||||
begin
|
||||
Kook::CLI::Main.start(ARGV)
|
||||
rescue Exception => exception
|
||||
# In case of unhandled exception.
|
||||
# FIXME: Manage display & create log file
|
||||
STDERR.puts "ERROR(#{exception.class}) : #{exception}"
|
||||
STDERR.puts exception.backtrace
|
||||
exit 1
|
||||
end
|
51
bin/kotam
51
bin/kotam
|
@ -1,51 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
|
||||
KOTAM_DATA_DIR=$(cd `dirname "$0"`; cd ../lib ; pwd )
|
||||
KOTAM_CONFIG_DIR=$HOME/.config/kotam
|
||||
|
||||
. $KOTAM_DATA_DIR/base.sh
|
||||
|
||||
## Expected usage :
|
||||
#
|
||||
# kotam exec <name>
|
||||
# kotam init <name>
|
||||
#
|
||||
|
||||
mkdir -p $KOTAM_CONFIG_DIR
|
||||
while [ $# -gt 0 ]; do
|
||||
arg=${1:-}
|
||||
opt=${2:-}
|
||||
case $arg in
|
||||
-l|--list) #list projects
|
||||
echo "List of projects :"
|
||||
ls $KOTAM_CONFIG_DIR/*.kotam 2> /dev/null
|
||||
;;
|
||||
-e) # edit project
|
||||
shift
|
||||
project="$opt"
|
||||
if [ -z "$project" ]; then
|
||||
echo "ERROR: project name missing" >&2
|
||||
exit 1
|
||||
elif [ ! -e "$KOTAM_CONFIG_DIR/$project.kotam" ]; then
|
||||
echo "ERROR: unknown project $project" >&2
|
||||
exit 1
|
||||
fi
|
||||
"$EDITOR" "$KOTAM_CONFIG_DIR/$project.kotam"
|
||||
;;
|
||||
-c) # create
|
||||
;;
|
||||
-d) # destroy
|
||||
;;
|
||||
*) #enter into project
|
||||
project="$arg"
|
||||
if [ ! -e "$KOTAM_CONFIG_DIR/$project.kotam" ]; then
|
||||
echo "ERROR: unknown project $project" >&2
|
||||
exit 1
|
||||
fi
|
||||
. "$KOTAM_CONFIG_DIR/$project.kotam"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
33
kook.gemspec
Normal file
33
kook.gemspec
Normal file
|
@ -0,0 +1,33 @@
|
|||
# coding: utf-8
|
||||
lib = File.expand_path('../lib', __FILE__)
|
||||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||
require 'kook/version'
|
||||
|
||||
Gem::Specification.new do |spec|
|
||||
spec.name = "kook"
|
||||
spec.version = Kook::VERSION
|
||||
spec.authors = ["Glenn Y. Rolland"]
|
||||
spec.email = ["glenux@glenux.net"]
|
||||
spec.summary = %q{Kook is a helper for opening your projects environments in tabs of KDE Konsole}
|
||||
#spec.description = %q{TODO: Write a longer description. Optional.}
|
||||
spec.homepage = "http://github.com/glenux/kook"
|
||||
spec.license = "MIT"
|
||||
|
||||
spec.rubyforge_project = "kook"
|
||||
|
||||
spec.files = `git ls-files`.split($/)
|
||||
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
||||
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
||||
spec.require_paths = ["lib"]
|
||||
spec.bindir = 'bin'
|
||||
spec.post_install_message = "Thanks for installing!"
|
||||
|
||||
spec.add_development_dependency "bundler", "~> 1.5"
|
||||
spec.add_development_dependency "rake"
|
||||
spec.add_development_dependency "rspec"
|
||||
# spec.add_development_dependency "pry"
|
||||
# spec.add_development_dependency "rm-readline"
|
||||
|
||||
spec.add_runtime_dependency "thor"
|
||||
spec.add_runtime_dependency "colorize"
|
||||
end
|
24
lib/base.sh
24
lib/base.sh
|
@ -1,24 +0,0 @@
|
|||
|
||||
kotam_run() {
|
||||
local cmd="$*"
|
||||
qdbus org.kde.konsole /Sessions/${session} sendText "$cmd"
|
||||
qdbus org.kde.konsole /Sessions/${session} sendText "
|
||||
"
|
||||
}
|
||||
|
||||
|
||||
kotam_newtab() {
|
||||
#dbus-send --session --dest=${KONSOLE_DBUS_SERVICE} --type=method_call \
|
||||
# --print-reply /konsole/MainWindow_1 org.kde.KMainWindow.activateAction string:"new-tab"
|
||||
|
||||
session=$(qdbus org.kde.konsole /Konsole newSession)
|
||||
}
|
||||
|
||||
kotam_renametab() {
|
||||
#sessionno=$1
|
||||
tabname=$1
|
||||
#session="/Sessions/${sessionno}"
|
||||
#dbus-send --session --dest=${KONSOLE_DBUS_SERVICE} --type=method_call --print-reply ${session} org.kde.konsole.Session.setTitle int32:1 string:"$tabname"
|
||||
qdbus org.kde.konsole /Sessions/${session} setTitle 1 "$tabname"
|
||||
}
|
||||
|
8
lib/kook.rb
Normal file
8
lib/kook.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
require 'kook/version'
|
||||
require 'kook/exceptions'
|
||||
require 'kook/view'
|
||||
require 'kook/project'
|
||||
require 'kook/app'
|
||||
require 'kook/cli'
|
||||
|
203
lib/kook/app.rb
Normal file
203
lib/kook/app.rb
Normal file
|
@ -0,0 +1,203 @@
|
|||
module Kook
|
||||
class App
|
||||
CONFIG_DIR = File.join ENV['HOME'], '.config', 'kook'
|
||||
CONFIG_FILE = File.join CONFIG_DIR, 'config.yml'
|
||||
|
||||
attr_accessor :verbose
|
||||
|
||||
class ExistingProject < RuntimeError ; end
|
||||
class MissingProject < RuntimeError ; end
|
||||
class MissingProjectFile < RuntimeError ; end
|
||||
|
||||
def initialize
|
||||
super
|
||||
@projects = {}
|
||||
@config_file = CONFIG_FILE
|
||||
@verbose = false
|
||||
@current_project = nil
|
||||
end
|
||||
|
||||
def list_projects
|
||||
projects_exist = false
|
||||
|
||||
# get boundary for project name + margin
|
||||
column_width = @projects.map{ |name,data| name }.max
|
||||
|
||||
@projects.each do |project_name,project_data|
|
||||
projects_exist = true
|
||||
exist = File.exist? project_data.path
|
||||
display_path = (
|
||||
project_data.path.clone
|
||||
.gsub!(/#{ENV['HOME']}/,'~')
|
||||
.send(exist ? :green : :red)
|
||||
)
|
||||
puts "%- #{column_width}s %s" % [project_name, display_path]
|
||||
end
|
||||
STDERR.puts "No project found." if not projects_exist
|
||||
end
|
||||
|
||||
def add_project project_name, project_path=nil
|
||||
raise ExistingProject if @projects.has_key? project_name
|
||||
|
||||
project_data = Project.new project_name
|
||||
project_data.path = project_path
|
||||
@projects[project_name] = project_data
|
||||
save
|
||||
end
|
||||
|
||||
def edit_project project_name
|
||||
raise MissingProject if not @projects.has_key? project_name
|
||||
|
||||
project_config_path = File.join @projects[project_name].path, "Kookfile"
|
||||
system "%s %s" % [ENV['EDITOR'], project_config_path]
|
||||
end
|
||||
|
||||
def remove_project project_name
|
||||
raise MissingProject if not @projects.has_key? project_name
|
||||
@projects.delete project_name
|
||||
save
|
||||
end
|
||||
|
||||
def fire_project project_name
|
||||
raise MissingProject if not @projects.has_key? project_name
|
||||
|
||||
project_path = @projects[project_name].path
|
||||
@projects[project_name].fire
|
||||
|
||||
end
|
||||
|
||||
def add_view project_name, view_name, view_path=nil
|
||||
View.validate_name view_name
|
||||
raise MissingProject if not @projects.has_key? project_name
|
||||
|
||||
project_path = @projects[project_name].path
|
||||
|
||||
# simplify if current dir is a subdir of project base
|
||||
if view_path == project_path then
|
||||
view_path = '.'
|
||||
else
|
||||
view_path = (view_path
|
||||
.gsub(/^#{project_path}\//,'')
|
||||
.gsub(/\/$/,'')
|
||||
)
|
||||
end
|
||||
|
||||
@projects[project_name].create_view view_name, view_path
|
||||
save
|
||||
end
|
||||
|
||||
def add_command project_name, view_name, command
|
||||
View.validate_name view_name
|
||||
raise MissingProject if not @projects.has_key? project_name
|
||||
|
||||
@projects[project_name].add_command view_name, command
|
||||
save
|
||||
end
|
||||
|
||||
def remove_command project_name, view_name, command_idx
|
||||
raise MissingProject if not @projects.has_key? project_name
|
||||
|
||||
@projects[project_name].remove_command view_name, command_idx
|
||||
save
|
||||
end
|
||||
|
||||
def list_views project_name
|
||||
raise MissingProject if not @projects.has_key? project_name
|
||||
|
||||
@projects[project_name].each_view do |view_name,view_data|
|
||||
puts "%- 24s %s" % [view_name, view_data.path]
|
||||
|
||||
if view_data.commands.empty?
|
||||
next
|
||||
end
|
||||
|
||||
view_data.commands.each_index do |idx|
|
||||
puts "* % 4d. %s" % [idx, view_data.commands[idx]]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def load config_file=nil
|
||||
config_file ||= @config_file
|
||||
@config_file = config_file
|
||||
|
||||
if not File.exist? config_file then
|
||||
STDERR.puts "Missing config file #{config_file}" if @verbose
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
STDERR.puts "Loading main configuration #{config_file}..." if @verbose
|
||||
yaml = YAML::load_file config_file
|
||||
|
||||
yaml['projects'].each do |project_name,project_path|
|
||||
# pp project_path
|
||||
#project_path = @config['projects'][project]
|
||||
project_file = File.join project_path, "Kookfile"
|
||||
|
||||
STDERR.puts "Loading sub configuration #{project_file}..." if @verbose
|
||||
if File.exist? project_file then
|
||||
subconfig = YAML::load_file project_file
|
||||
next if not subconfig
|
||||
|
||||
@projects[project_name] = Project.from_hash subconfig, project_path
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
def save config_file=nil
|
||||
config_file ||= @config_file
|
||||
config_dir = File.dirname config_file
|
||||
if not File.exist? config_dir then
|
||||
FileUtils.mkdir_p config_dir
|
||||
end
|
||||
|
||||
STDERR.puts "Saving to #{config_file}" if @verbose
|
||||
|
||||
@projects.each do |project_name,project_data|
|
||||
# FIXME: test if project configuration is dirty
|
||||
project_file = File.join project_data.path, "Kookfile"
|
||||
|
||||
File.open(project_file, "w") do |file|
|
||||
file.puts "# This file was generated by Kook #{VERSION}"
|
||||
file.puts "# You can get it at https://github.com/glenux/kook"
|
||||
file.write project_data.to_hash.to_yaml
|
||||
end
|
||||
end
|
||||
|
||||
File.open(config_file, "w") do |file|
|
||||
file.write to_yaml
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
def current_project= project_name
|
||||
# FIXME: validate project name
|
||||
@current_project = project_name
|
||||
end
|
||||
|
||||
def current_project
|
||||
return @current_project if not @current_project.nil?
|
||||
|
||||
current_dir = Dir.pwd
|
||||
@projects.each do |project_name,project|
|
||||
if current_dir =~ /^#{project.path}/ then
|
||||
return project_name
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def to_yaml
|
||||
return {
|
||||
'global' => {},
|
||||
'projects' => Hash[@projects.map{ |p,v| [v.name, v.path] }]
|
||||
}.to_yaml
|
||||
end
|
||||
|
||||
end
|
||||
end
|
174
lib/kook/cli.rb
Normal file
174
lib/kook/cli.rb
Normal file
|
@ -0,0 +1,174 @@
|
|||
require 'thor'
|
||||
|
||||
module Kook
|
||||
module CLI
|
||||
module KookHelper
|
||||
def before_filter options
|
||||
@app = App.new
|
||||
@app.load options[:config]
|
||||
@app.verbose = options[:verbose]
|
||||
@app.current_project = options[:project]
|
||||
end
|
||||
|
||||
# Inject our extensions in thor instances
|
||||
def self.included(base)
|
||||
base.class_eval do
|
||||
#if ancestors.include? Thor::Group
|
||||
# namespace self.name.split('::').last.downcase.to_sym
|
||||
#end
|
||||
|
||||
class_option :verbose,
|
||||
type: :boolean,
|
||||
default: false,
|
||||
aliases: '-v',
|
||||
desc: 'Whether to output informative debug'
|
||||
|
||||
class_option :config,
|
||||
type: :string,
|
||||
default: nil,
|
||||
aliases: '-c',
|
||||
desc: 'Configuration file'
|
||||
|
||||
class_option :project,
|
||||
type: :string,
|
||||
default: nil,
|
||||
aliases: '-p',
|
||||
desc: 'Target project'
|
||||
|
||||
class_option :directory,
|
||||
type: :string,
|
||||
default: nil,
|
||||
aliases: '-d',
|
||||
desc: 'Target directory'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Project < Thor
|
||||
include KookHelper
|
||||
|
||||
desc "detect", "Detect current project"
|
||||
def detect
|
||||
before_filter options
|
||||
current_project = @app.current_project
|
||||
project_name = current_project.nil? ? "-none-" : current_project
|
||||
say "Current project is #{project_name}."
|
||||
end
|
||||
|
||||
desc "list", "List projects"
|
||||
def list
|
||||
before_filter options
|
||||
@app.list_projects
|
||||
end
|
||||
|
||||
desc "add PROJECT [-d DIRECTORY]", "Register new project"
|
||||
def add project_name
|
||||
before_filter options
|
||||
project_path = options[:directory]
|
||||
|
||||
if project_path.nil? then
|
||||
project_path = Dir.pwd
|
||||
end
|
||||
project_path = File.expand_path project_path
|
||||
@app.add_project project_name, project_path
|
||||
|
||||
say "Project #{project_name} registered on #{project_path}."
|
||||
end
|
||||
|
||||
desc "rm PROJECT", "Unregister existing project"
|
||||
def rm project
|
||||
before_filter options
|
||||
@app.remove_project project
|
||||
say "Project #{project} unregistered."
|
||||
end
|
||||
|
||||
desc "edit [-p PROJECT]", "Open editor on project file"
|
||||
def edit
|
||||
before_filter options
|
||||
project_name ||= @app.current_project
|
||||
|
||||
@app.edit_project project_name
|
||||
end
|
||||
# TODO: editcopy project to another name + base path
|
||||
# TODO: copy project to another name + base path
|
||||
end
|
||||
|
||||
class View < Thor
|
||||
include KookHelper
|
||||
|
||||
desc "list [-p PROJECT]", "List view for a project"
|
||||
def list
|
||||
before_filter options
|
||||
project_name = @app.current_project
|
||||
|
||||
@app.list_views project_name
|
||||
end
|
||||
|
||||
desc "add VIEW [-p PROJECT] [-d DIRECTORY]", "Register new view"
|
||||
def add view_name
|
||||
before_filter options
|
||||
project_name = @app.current_project
|
||||
|
||||
view_path = options[:directory]
|
||||
if view_path.nil? then
|
||||
view_path = Dir.pwd
|
||||
end
|
||||
|
||||
@app.add_view project_name, view_name, view_path
|
||||
|
||||
end
|
||||
|
||||
desc "rm VIEW [-p PROJECT]", "Unregister existing view on project"
|
||||
def rm view_name
|
||||
before_filter options
|
||||
project_name = @app.current_project
|
||||
|
||||
@app.remove_view project_name, view_name, view_path
|
||||
end
|
||||
end
|
||||
|
||||
# FIXME: add helper validating project name
|
||||
# FIXME: add helper validating vie name for project
|
||||
class Command < Thor
|
||||
include KookHelper
|
||||
|
||||
desc "add VIEW COMMAND [-p PROJECT]", "Add command for view"
|
||||
def add view_name, command
|
||||
before_filter options
|
||||
project_name = @app.current_project
|
||||
|
||||
@app.add_command project_name, view_name, command
|
||||
end
|
||||
|
||||
desc "rm VIEW INDEX [-p PROJECT]", "Remove command for view"
|
||||
def rm view_name, command_index
|
||||
before_filter options
|
||||
project_name = @app.current_project
|
||||
|
||||
@app.remove_command project_name, view_name, command_index.to_i
|
||||
end
|
||||
end
|
||||
|
||||
class Main < Thor
|
||||
include KookHelper
|
||||
|
||||
desc "project SUBCOMMAND [options]", "Commands for managing projects"
|
||||
subcommand "project", CLI::Project
|
||||
|
||||
desc "view SUBCOMMAND [options]", "Commands for managing view"
|
||||
subcommand "view", CLI::View
|
||||
|
||||
desc "command SUBCOMMAND [options]", "Commands for managing commands"
|
||||
subcommand "command", CLI::Command
|
||||
|
||||
desc "start [-p PROJECT]", "Run project environment"
|
||||
def start
|
||||
before_filter options
|
||||
project_name = @app.current_project
|
||||
|
||||
@app.fire_project project_name
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
4
lib/kook/exceptions.rb
Normal file
4
lib/kook/exceptions.rb
Normal file
|
@ -0,0 +1,4 @@
|
|||
|
||||
module Kook
|
||||
class MissingProjectConfiguration < RuntimeError ; end
|
||||
end
|
0
lib/kook/plugins/generic.rb
Normal file
0
lib/kook/plugins/generic.rb
Normal file
0
lib/kook/plugins/konsole.rb
Normal file
0
lib/kook/plugins/konsole.rb
Normal file
0
lib/kook/plugins/screen.rb
Normal file
0
lib/kook/plugins/screen.rb
Normal file
0
lib/kook/plugins/tmux.rb
Normal file
0
lib/kook/plugins/tmux.rb
Normal file
119
lib/kook/project.rb
Normal file
119
lib/kook/project.rb
Normal file
|
@ -0,0 +1,119 @@
|
|||
|
||||
require 'kook/exceptions'
|
||||
|
||||
module Kook
|
||||
class Project
|
||||
attr_reader :name, :path
|
||||
attr_accessor :description
|
||||
|
||||
class MissingProjectFile < RuntimeError ; end
|
||||
class InvalidProjectName < RuntimeError ; end
|
||||
PROJECT_NAME_MIN_SIZE = 4
|
||||
PROJECT_NAME_MAX_SIZE = 15
|
||||
|
||||
def initialize project_name
|
||||
self.class.validate_name project_name
|
||||
@name = project_name
|
||||
@description = nil
|
||||
@path = nil
|
||||
@views = {}
|
||||
|
||||
yield self if block_given?
|
||||
self
|
||||
end
|
||||
|
||||
def path= path
|
||||
# FIXME: validate current path exists
|
||||
#
|
||||
if not (File.exist? path and File.directory? path) then
|
||||
raise "PathDoesNotExist #{path}"
|
||||
end
|
||||
@path = path
|
||||
end
|
||||
|
||||
def fire
|
||||
target = ENV['KONSOLE_DBUS_SERVICE'] || 'org.kde.konsole'
|
||||
window = ENV['KONSOLE_DBUS_WINDOW'] || '/Konsole'
|
||||
|
||||
# FIXME: use runCommand instead of sendText ?
|
||||
|
||||
@views.each do |view,view_data|
|
||||
session=`qdbus #{target} #{window} newSession`.strip
|
||||
system "qdbus org.kde.konsole /Sessions/#{session} sendText \"cd #{@path}\n\""
|
||||
system "qdbus org.kde.konsole /Sessions/#{session} sendText \"cd #{view_data.path}\n\""
|
||||
system "qdbus org.kde.konsole /Sessions/#{session} sendText \"clear\n\""
|
||||
system "qdbus org.kde.konsole /Sessions/#{session} setTitle 1 \"#{view}\""
|
||||
|
||||
view_data.commands.each do |command|
|
||||
system "qdbus org.kde.konsole /Sessions/#{session} sendText \"#{command}\""
|
||||
system "qdbus org.kde.konsole /Sessions/#{session} sendText \"\n\""
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_view view_name, view_path
|
||||
raise ExistingView, view_name if @views.has_key? view_name
|
||||
View.validate_name view_name
|
||||
|
||||
@views[view_name] = View.new view_name, view_path
|
||||
end
|
||||
|
||||
def add_view view_data
|
||||
raise ExistingView, view_data.name if @views.has_key? view_data.name
|
||||
|
||||
@views[view_data.name] = view_data
|
||||
end
|
||||
|
||||
def remove_view view_name
|
||||
raise MissingView, view_name if not @views.has_key? view_name
|
||||
return @view.delete(view_name)
|
||||
end
|
||||
|
||||
def add_command view_name, command
|
||||
raise MissingView, view_name if not @views.has_key? view_name
|
||||
@views[view_name].commands << command
|
||||
end
|
||||
|
||||
def remove_command view_name, command_idx
|
||||
raise MissingView, view_name if not @views.has_key? view_name
|
||||
@views[view_name].commands.delete_at(command_idx)
|
||||
end
|
||||
|
||||
def each_view
|
||||
#pp @views
|
||||
@views.each do |view_name, view_data|
|
||||
yield view_name, view_data
|
||||
end
|
||||
end
|
||||
|
||||
def to_hash
|
||||
return {
|
||||
'project' => @name,
|
||||
'description' => @description,
|
||||
#'path' => @path,
|
||||
'views' => @views.values.map{ |v| v.to_hash }
|
||||
}
|
||||
end
|
||||
|
||||
def self.from_hash project_hash, project_path
|
||||
project = Project.new project_hash['project'] do |p|
|
||||
p.description = project_hash['description']
|
||||
p.path = project_path
|
||||
|
||||
project_hash['views'].each do |view_hash|
|
||||
view_data = View.from_hash view_hash
|
||||
p.add_view view_data
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.validate_name name
|
||||
raise "TooShortProjectIdentifier" if name.size < Project::PROJECT_NAME_MIN_SIZE
|
||||
raise "TooLongProjectIdentifier" if name.size > Project::PROJECT_NAME_MAX_SIZE
|
||||
if not name =~ /^\w(\S+)$/ then
|
||||
raise "BadProjectIdentifier #{name}"
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
3
lib/kook/version.rb
Normal file
3
lib/kook/version.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
module Kook
|
||||
VERSION = "0.1.0.dev"
|
||||
end
|
49
lib/kook/view.rb
Normal file
49
lib/kook/view.rb
Normal file
|
@ -0,0 +1,49 @@
|
|||
|
||||
module Kook
|
||||
class View
|
||||
attr_reader :name, :path, :commands
|
||||
attr_accessor :description
|
||||
VIEW_NAME_MIN_SIZE = 3
|
||||
VIEW_NAME_MAX_SIZE = 12
|
||||
|
||||
def initialize name, path=nil
|
||||
self.class.validate_name name
|
||||
@name = name
|
||||
@path = path
|
||||
@commands = []
|
||||
end
|
||||
|
||||
def self.validate_name name
|
||||
raise "TooShortViewIdentifier" if name.size < View::VIEW_NAME_MIN_SIZE
|
||||
raise "TooLongViewIdentifier" if name.size > View::VIEW_NAME_MAX_SIZE
|
||||
if not name =~ /^[\w-]+$/ then
|
||||
raise "BadViewIdentifier #{name}"
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
def to_hash
|
||||
return {
|
||||
'view' => @name,
|
||||
'path' => @path,
|
||||
'commands' => @commands
|
||||
}
|
||||
end
|
||||
|
||||
def add_command command
|
||||
@commands << command
|
||||
end
|
||||
|
||||
def rm_command command_index
|
||||
@command.delete command_index
|
||||
end
|
||||
|
||||
def self.from_hash view_hash
|
||||
view = View.new view_hash['view'], view_hash['path']
|
||||
view_hash['commands'].each do |c|
|
||||
view.add_command c
|
||||
end
|
||||
return view
|
||||
end
|
||||
end
|
||||
end
|
61
spec/spec_helper.rb
Normal file
61
spec/spec_helper.rb
Normal file
|
@ -0,0 +1,61 @@
|
|||
|
||||
|
||||
|
||||
# Load all spec files
|
||||
Dir["./spec/support/**/*.rb"].each {|f| require f}
|
||||
|
||||
RSpec.configure do |config|
|
||||
# Allows using build(), create(), etc. without the "FactoryGirl." part.
|
||||
config.include FactoryGirl::Syntax::Methods
|
||||
|
||||
config.before(:each) do
|
||||
$0 = "kook" # Pretend we're running as 'kook'
|
||||
ARGV.clear # Make sure no args are passed to the commands.
|
||||
@directory = Dir.mktmpdir('kook-spec-') # Create a temp directory to work in.
|
||||
@orig_directory = Dir.pwd # Save the original directory.
|
||||
Dir.chdir(@directory) # Change to it. pwd() is the temp directory in the examples.
|
||||
end
|
||||
|
||||
config.after(:each) do
|
||||
Dir.chdir(@orig_directory) # Change back to the origin directory.
|
||||
FileUtils.rmtree(@directory) # Remove the temp directory.
|
||||
end
|
||||
|
||||
|
||||
# Captures the output for analysis later
|
||||
#
|
||||
# @example Capture `$stderr`
|
||||
#
|
||||
# output = capture(:stderr) { $stderr.puts "this is captured" }
|
||||
#
|
||||
# @param [Symbol] stream `:stdout` or `:stderr`
|
||||
# @yield The block to capture stdout/stderr for.
|
||||
# @return [String] The contents of $stdout or $stderr
|
||||
def capture(stream)
|
||||
begin
|
||||
stream = stream.to_s
|
||||
eval "$#{stream} = StringIO.new"
|
||||
yield
|
||||
result = eval("$#{stream}").string
|
||||
ensure
|
||||
eval("$#{stream} = #{stream.upcase}")
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
# Silences the output stream
|
||||
#
|
||||
# @example Silence `$stdout`
|
||||
#
|
||||
# silence(:stdout) { $stdout.puts "hi" }
|
||||
#
|
||||
# @param [IO] stream The stream to use such as $stderr or $stdout
|
||||
# @return [nil]
|
||||
alias :silence :capture
|
||||
|
||||
|
||||
end
|
||||
|
||||
EXAMPLES_DIR = Pathname.new(__FILE__).dirname + 'examples'
|
||||
|
60
spec/test_project.rb
Executable file
60
spec/test_project.rb
Executable file
|
@ -0,0 +1,60 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'singleton'
|
||||
require 'yaml'
|
||||
require 'pp'
|
||||
|
||||
module Kook
|
||||
class Config
|
||||
include Singleton
|
||||
|
||||
def create_project project_name
|
||||
raise "ExistingProject" if @projects.has_key? project_name
|
||||
|
||||
@projects[project_name] = Project.new project_name
|
||||
end
|
||||
|
||||
def create_view project_name, view_name
|
||||
Project.validate_name project_name
|
||||
View.validate_name view_name
|
||||
raise "MissingProject" if not @projects.has_key? project_name
|
||||
|
||||
view = View.new view_name
|
||||
@projects[project_name].add_view view
|
||||
end
|
||||
|
||||
def to_yaml
|
||||
return {
|
||||
global: {},
|
||||
projects: @projects.values.map{ |p| p.to_hash }
|
||||
}.to_yaml
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def initialize
|
||||
@projects = {}
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Test
|
||||
def self.test_project_create
|
||||
config = Kook::Config.instance
|
||||
config.create_project 'proj'
|
||||
end
|
||||
|
||||
def self.test_view_create
|
||||
config = Kook::Config.instance
|
||||
config.create_view 'proj', 'proj-root'
|
||||
config.create_view 'proj', 'proj-base'
|
||||
config.create_view 'proj', 'proj-3'
|
||||
|
||||
puts config.to_yaml
|
||||
end
|
||||
end
|
||||
|
||||
Test.test_project_create
|
||||
Test.test_view_create
|
70
test.sh
Executable file
70
test.sh
Executable file
|
@ -0,0 +1,70 @@
|
|||
#!/bin/sh
|
||||
|
||||
PATH=./bin:$PATH
|
||||
|
||||
set -e
|
||||
|
||||
KOOK_TEST_CONFIG="$(pwd)/test.config.yml"
|
||||
KOOK_OPTS="--verbose --config $KOOK_TEST_CONFIG"
|
||||
TEST_TITLE=""
|
||||
|
||||
fail() {
|
||||
echo "ERROR: $TEST_TITLE"
|
||||
exit 1
|
||||
}
|
||||
|
||||
test_cleanup() {
|
||||
rm -f $KOOK_TEST_CONFIG
|
||||
rm -f Kookfile
|
||||
}
|
||||
|
||||
test_start() {
|
||||
test_cleanup
|
||||
TEST_TITLE="$*"
|
||||
echo ""
|
||||
echo ""
|
||||
echo "## TEST : $TEST_TITLE"
|
||||
echo ""
|
||||
}
|
||||
|
||||
test_start "Simple project listing"
|
||||
kook project list $KOOK_OPTS || fail
|
||||
|
||||
test_start "Add project (explicit pah)"
|
||||
kook project add kook-project $KOOK_OPTS --path . || fail
|
||||
kook project list $KOOK_OPTS || fail
|
||||
|
||||
test_start "Add project (auto path)"
|
||||
kook project add kook-project $KOOK_OPTS || fail
|
||||
kook project list $KOOK_OPTS || fail
|
||||
|
||||
test_start "Add and remove project"
|
||||
kook project add kook-project $KOOK_OPTS || fail
|
||||
kook project list $KOOK_OPTS || fail
|
||||
kook project rm kook-project $KOOK_OPTS || fail
|
||||
kook project list $KOOK_OPTS || fail
|
||||
|
||||
test_start "Detect current project"
|
||||
kook project add kook-project $KOOK_OPTS || fail
|
||||
kook project list $KOOK_OPTS || fail
|
||||
kook project detect $KOOK_OPTS || fail
|
||||
|
||||
test_start "Simple view listing (explicit project)"
|
||||
kook project add kook-project $KOOK_OPTS || fail
|
||||
kook view list $KOOK_OPTS --project kook-project || fail
|
||||
|
||||
#test_start "Simple view listing (implicit project)"
|
||||
#kook project add kook-project $KOOK_OPTS || fail
|
||||
#kook view list $KOOK_OPTS || fail
|
||||
|
||||
test_start "Fire a project with no view"
|
||||
kook project add kook-project $KOOK_OPTS || fail
|
||||
kook view list $KOOK_OPTS || fail
|
||||
kook fire kook-project $KOOK_OPTS || fail
|
||||
|
||||
test_start "Add a project with a view (explicit project)"
|
||||
kook project add kook-project $KOOK_OPTS || fail
|
||||
kook view add root $KOOK_OPTS --project kook-project || fail
|
||||
kook view list $KOOK_OPTS --project kook-project || fail
|
||||
|
||||
#test_cleanup
|
Loading…
Reference in a new issue