Skip to content

Instantly share code, notes, and snippets.

@balupton
Last active September 25, 2015 00:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save balupton/831278 to your computer and use it in GitHub Desktop.
Save balupton/831278 to your computer and use it in GitHub Desktop.
Aloha Editor's Command Line Interface. Attempt #1
#!/usr/bin/env ruby
# == Name
# cli - Aloha Editor's Command Line Interface
#
# == Synopsis
# TODO: finish this section
#
# == Examples
# TODO: finish this section
#
# == Options
# -h, --help Displays help message
# -v, --version Display the version, then exit
# -q, --quiet Output as little as possible, overrides verbose
# -V, --verbose Verbose output
#
# == Author
# Benjamin Arthur Lupton
#
# == Copyright
# Copyright (c) 2008-2011 Benjamin Arthur Lupton
# Licensed under the New BSD License
# http://creativecommons.org/licenses/BSD/
require 'optparse'
require 'rdoc/usage'
require 'ostruct'
require 'date'
class App
# Remotes
REMOTE_ALOHA_URL = 'http://github.com/alohaeditor/Aloha-Editor.git'
REMOTE_ALOHA = 'aloha'
# Versioning
BRANCH_DEV = 'dev'
BRANCH_VERSION = '0.9.4'
BRANCH_MASTER = 'master'
# Building
BUILD_DIR = './.build'
# Uglifiy
UGLIFY_URL = 'https://github.com/mishoo/UglifyJS/raw/master/bin/uglifyjs'
UGLIFY_DIR = './.build/uglify'
UGLIFY_FILE = './.build/uglify/uglify'
# Closure
CLOSURE_URL = 'http://closure-compiler.googlecode.com/files/compiler-latest.zip'
CLOSURE_DIR = './.build/closure'
CLOSURE_ZIP = './.build/closure/compiler.zip'
CLOSURE_FILE = './.build/closure/compiler.jar'
SOURCE_MAP = './scripts/closure.map'
# YUI
YUI_URL = 'http://yuilibrary.com/downloads/yuicompressor/yuicompressor-2.4.2.zip'
YUI_DIR = './.build/yui'
YUI_ZIP = './.build/yui/compiler.zip'
YUI_FILE = './.build/yui/yuicompressor-2.4.2/build/yuicompressor-2.4.2.jar'
# ===========================================================================
# Init Helpers
# Run a Command
def run ( cmd )
puts cmd + "\n"
result = `#{cmd}`
puts result
return result
end
# Download a File
def download ( url, file )
result = run("curl -L #{url} -o #{file}")
end
# Extract a File
def extract ( dir, file )
file = file.gsub(dir,'.')
result = run("cd #{dir} ; tar -xf #{file} ; rm -Rf #{file}")
end
# ===========================================================================
# Init Commands
# Initialise our CLI
def initialize
init_env
end
# Initialise our Environment
def init_env
# Check for Requirements
reqs = ['mkdir','curl','tar','git']
reqs.each do |req|
has_req = `which #{req}`.strip
if has_req.empty?
abort("CLI requires the following binary which is not installed: #{req}")
end
end
# Do not care for compilation yet
return
# Check for Closure Compiler
if !File.exists?(CLOSURE_FILE)
run("mkdir -p #{CLOSURE_DIR}")
puts "Downloading the Closure Compiler..."
download(CLOSURE_URL, CLOSURE_ZIP)
extract(CLOSURE_DIR, CLOSURE_ZIP)
run("chmod +x #{CLOSURE_FILE}")
end
# Check for Uglify
if !File.exists?(UGLIFY_FILE)
run("mkdir -p #{UGLIFY_DIR}")
puts "Downloading the Uglify Compiler..."
download(UGLIFY_URL, UGLIFY_FILE)
run("chmod +x #{UGLIFY_FILE}")
end
# Check for YUI Compiler
if !File.exists?(YUI_FILE)
run("mkdir -p #{YUI_DIR}")
puts "Downloading the YUI Compiler..."
download(YUI_URL, (YUI_ZIP))
extract(YUI_DIR, YUI_ZIP)
run("chmod +x #{YUI_FILE}")
end
end
# ===========================================================================
# Build Helpers
def compressCss ( in_file, out_file )
# Calculate
in_file_size = File.size(in_file)
# Handle
if in_file.equal? out_file
out_file = out_file.gsub(/\.js$/, '.min.js')
compressCssWithYui(in_file,out_file)
run("rm #{in_file}")
run("mv #{out_file} #{in_file}")
out_file = in_file
else
compressCssWithYui(in_file,out_file)
out_file_size = File.size(out_file)
end
# Calculate
out_file_size = File.size(out_file)
ratio = Float(out_file_size)/Float(in_file_size)
reduction = ((1-ratio)*100).round
# Log
puts "Compressed the file [#{in_file}] to [#{out_file}] with a #{reduction}% reduction"
end
def compressJs ( in_file, out_file )
# Calculate
in_file_size = File.size(in_file)
# Handle
if in_file.equal? out_file
out_file = out_file.gsub(/\.js$/, '.min.js')
compressJsWithUglify(in_file,out_file)
run("rm #{in_file}")
run("mv #{out_file} #{in_file}")
out_file = in_file
else
compressJsWithUglify(in_file,out_file)
out_file_size = File.size(out_file)
end
# Calculate
out_file_size = File.size(out_file)
ratio = Float(out_file_size)/Float(in_file_size)
reduction = ((1-ratio)*100).round
# Log
puts "Compressed the file [#{in_file}] to [#{out_file}] with a #{reduction}% reduction"
end
# Compress a CSS File with YUI
def compressCssWithYui ( in_file, out_file )
result = run("java -jar #{YUI_FILE} --type css -o #{out_file} --charset UTF-8 #{in_file}")
end
# Compress a Javascript File with Uglify
def compressJsWithUglify ( in_file, out_file )
result = run("#{UGLIFY_FILE} -o #{out_file} #{in_file}")
end
# Compress a Javascript file with Closure
def compressJsWithClosure ( in_file, out_file )
result = run("java -jar #{CLOSURE_FILE} --js_output_file=#{out_file} --js=#{in_file}")
end
# ===========================================================================
# Git Helpers
# Aborts if Changes are Found
def has_changes
result = run("git status")
if result.include? 'Changed but not updated'
abort("You have un-committed changes that need to be committed before we can proceed.\n#{result}")
end
end
# Check if a Branch Exists
def branch_exists(branch)
branches = run("git branch")
regex = Regexp.new('[\\n\\s\\*]+' + Regexp.escape(branch) + '\\n')
result = ((branches =~ regex) ? true : false)
return result
end
# Check if a Branch Exists
def remote_branch_exists(branch)
branches = run("git branch -all")
regex = Regexp.new('\\/' + Regexp.escape(branch) + '\\n')
result = ((branches =~ regex) ? true : false)
return result
end
# Checkout a Branch
def checkout(branch)
if branch_exists(branch)
run("git checkout #{branch}")
else
if remote_branch_exists(branch)
run("git checkout -b #{branch} #{REMOTE_ALOHA}/#{branch}")
else
run("git branch #{branch} #{BRANCH_MASTER}")
end
end
end
# Check if a Remote Exists
def remote_exists(remote)
remotes = run("git remote")
regex = Regexp.new('[\\n\\s\\*]+' + Regexp.escape(remote) + '\\n')
result = ((remotes =~ regex) ? true : false)
return result
end
# Add a Remote
def remote_add(url,name)
unless remote_exists(name)
run("git remote add #{name} #{url}")
end
end
# Stage Known Files
def add
run("git add -u")
end
# Push to Origin
def push
run("git push origin --all")
end
# ===========================================================================
# Git Handlers
# Checkout Version Branch
def version
checkout(BRANCH_VERSION)
end
# Checkout Dev Branch
def dev
checkout(BRANCH_DEV)
end
# Checkout Master Branch
def master
checkout(BRANCH_MASTER)
end
# Initialise Branches
def init_branches
remote_add(REMOTE_ALOHA_URL,REMOTE_ALOHA)
master
version
dev
end
# Initialise Submodules
def init_submodules
run("
git submodule init;
git submodule update;
git submodule foreach --recursive 'git reset --hard; git branch -D dev; git checkout -b dev origin/dev; git branch -D master; git checkout -b master origin/master; git submodule init; git submodule update --merge';
")
end
# Update Submodules
def update_submodules
run("
git submodule init;
git submodule update --merge;
git submodule foreach 'git submodule init; git submodule update --merge';
")
end
# Update Branches
def update_branches
update_branch(BRANCH_MASTER)
update_branch(BRANCH_VERSION)
update_branch(BRANCH_DEV)
end
# Update Branch
def update_branch(branch)
checkout(branch)
update
end
# Update
def update
run("git pull --all")
update_submodules
end
# Install Aloha Editor
def install
init_branches
init_submodules
update_branches
end
# Upgrade Aloha Editor
def upgrade
has_changes
update_branches
end
# Deploy the Changes to the Version + Master
def deploy
has_changes
version
merge(BRANCH_DEV)
master
merge(BRANCH_DEV)
dev
push
end
end
# ===========================================================================
# Booter
class Booter
VERSION = :'0.0.1'
attr_reader :options
def initialize(arguments, stdin)
@arguments = arguments
@stdin = stdin
# Set defaults
@options = OpenStruct.new
@options.verbose = false
@options.quiet = false
# TO DO - add additional defaults
end
# Parse options, check arguments, then process the command
def run
if parsed_options? && arguments_valid?
puts "Start at #{DateTime.now}\n\n" if @options.verbose
output_options if @options.verbose # [Optional]
process_arguments
process_command
puts "\nFinished at #{DateTime.now}" if @options.verbose
else
output_usage
end
end
protected
def parsed_options?
# Specify options
opts = OptionParser.new
opts.on('-v', '--version') { output_version ; exit 0 }
opts.on('-h', '--help') { output_help }
opts.on('-V', '--verbose') { @options.verbose = true }
opts.on('-q', '--quiet') { @options.quiet = true }
# TO DO - add additional options
opts.parse!(@arguments) rescue return false
process_options
true
end
# Performs post-parse processing on options
def process_options
@options.verbose = false if @options.quiet
end
def output_options
puts :"Options:\n"
@options.marshal_dump.each do |name, val|
puts " #{name} = #{val}"
end
end
# True if required arguments were provided
def arguments_valid?
# TO DO - implement your real logic here
true if @arguments.length == 1
end
# Setup the arguments
def process_arguments
# TO DO - place in local vars, etc
end
def output_help
output_version
RDoc::usage() #exits app
end
def output_usage
RDoc::usage(:'usage') # gets usage from comments above
end
def output_version
puts "#{File.basename(__FILE__)} version #{VERSION}"
end
def process_command
# Create Application
app = App.new
# Fetch + Execute
command = @arguments[0].gsub('-','_')
unless app.respond_to?(command)
abort("Unknown command: #{command}")
end
app.send(command)
end
def process_standard_input
input = @stdin.read
# TO DO - process input
# [Optional]
#@stdin.each do |line|
# # TO DO - process each line
#end
end
end
# Create Booter
booter = Booter.new(ARGV, STDIN)
booter.run

Branches

Aloha Editor works with git and git submodules. We have to branches “stable” and “master”. The “stable” branch is tagged with version tags of the following format “v0.0.0” Where the first number indicates a major version, the second a minor version and the last number bug fixed versions.

Preparation

Getting your Github Account

  1. Before we start you'll need a github account, if you don't have one you can signup for free here https://github.com/signup/free

Creating your Aloha Editor Fork

  1. We now need to grab a copy of Aloha Editor that is suitable for editing.

  2. First you'll need to fork the Aloha Editor repository.

    1. To do this go here http://github.com/alohaeditor/Aloha-Editor
    2. Then click the "fork" button

Checking out Aloha Editor

The following snippets of code should be run in the terminal/command-line.

  1. Clone Aloha Editor

    git clone git@github.com:{YOUR GITHUB USERNAME}/Aloha-Editor.git ./Aloha-Editor cd ./Aloha-Editor

  2. Install Aloha Editor

    ./cli install

  3. Checkout the dev branch

    ./cli dev

Updating Aloha Editor

  1. Go to the Aloha Editor directory. E.g. cd ./Aloha-Editor

  2. To update your current branch ./cli update
    To update all branches ./cli upgrade

Editing an Existing Plugin

Creating your Plugin's Fork

  1. Navigate to the Github page for the plugin you would like to edit
    1. Then click the "fork" button
    2. Once the fork has been generated, click the "SSH" url button and make note of this url.
  2. Now ensure you are not inside another git repo (such as your plugin), and run the following commands

Setting up the Existing Plugin for Editing

cd ./Aloha-Editor/WebContent/plugins/{THE PLUGIN'S DIRECTORY}
git checkout master 
git checkout -b dev origin/dev
git remote add fork {YOUR FORK'S SSH URL - AS PER THE LAST STEP}

Editing the Existing Plugin

cd ./Aloha-Editor/WebContent/plugins/{THE PLUGIN'S DIRECTORY}

echo "test" > ./test.txt
git add ./test.txt
git commit -m "added test file”

git push fork master

Additional Notes

By default submodule checkouts contain the http repository url. If you prefere ssh you can use the following command to replace all https urls with ssh ones:

find */.git/ -name "config" -exec sed -i 's/https:\/\/github.com\//git@github\.com:/' {} \;

Adding your own Plugin

See a '''step-by-step tutorial''' for [[Creating a simple "Strong"-Plugin]]

Creating your Plugin's Repository

  1. If you would like to create your own repo
  2. You'll need to create a git repository for your plugin on github. You can do this here http://github.com/repositories/new
    1. Set the Project Name in this format "Aloha-Plugin-{YOUR PLUGIN NAME}"
    2. The other fields can be anything
  3. Once created, follow the instructions on github

Adding your new Plugin

  1. Navigate to the github page for your fork. Click the "HTTPS" url button, you will see something like this: "https://balupton@github.com/balupton/Aloha-Editor.git" change that to the following format (not the exact string, just the format): "http://github.com/balupton/Aloha-Editor.git". - make note of this url, it will be called your fork's HTTP URL

    cd ./Aloha-Editor git submodule add {YOUR PLUGIN'S HTTP URL - AS PER THE LAST STEP} WebContent/plugins/{YOUR PLUGINS DIRECTORY}

Working with your New Plugin

cd ./Aloha-EditorWebContent/plugins/{YOUR PLUGIN'S DIRECTORY}

echo "test" > ./test.txt
git add ./test.txt
git commit -m "added test file"

git push origin master

Further Reading

Docs need way more updating. And need to cover committing changes and deploying and pull requests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment