Skip to content
Browse files

Initial commit.

  • Loading branch information...
0 parents commit b673ba946c9011d10cc63f139589c9d456f4186c @postmodern committed Dec 1, 2012
Showing with 382 additions and 0 deletions.
  1. +3 −0 .document
  2. +2 −0 .gitignore
  3. +1 −0 .rspec
  4. +1 −0 .yardopts
  5. +4 −0 ChangeLog.md
  6. +20 −0 LICENSE.txt
  7. +47 −0 README.md
  8. +40 −0 Rakefile
  9. +16 −0 gemspec.yml
  10. +21 −0 lib/ripl/completions/shell_commands.rb
  11. +154 −0 lib/ripl/shell_commands.rb
  12. +60 −0 ripl-shell_commands.gemspec
  13. +8 −0 spec/shell_commands_spec.rb
  14. +5 −0 spec/spec_helper.rb
3 .document
@@ -0,0 +1,3 @@
+-
+ChangeLog.md
+LICENSE.txt
2 .gitignore
@@ -0,0 +1,2 @@
+doc/
+pkg/
1 .rspec
@@ -0,0 +1 @@
+--colour --format documentation
1 .yardopts
@@ -0,0 +1 @@
+--markup markdown --title "ripl-shell_commands Documentation" --protected
4 ChangeLog.md
@@ -0,0 +1,4 @@
+### 0.1.0 / 2012-12-01
+
+* Initial release:
+
20 LICENSE.txt
@@ -0,0 +1,20 @@
+Copyright (c) 2012 Postmodern
+
+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.
47 README.md
@@ -0,0 +1,47 @@
+# ripl-shell_commands
+
+* [Homepage](https://github.com/postmodern/ripl-shell_commands#readme)
+* [Issues](https://github.com/postmodern/ripl-shell_commands/issues)
+* [Documentation](http://rubydoc.info/gems/ripl-shell_commands/frames)
+* [Email](mailto:postmodern.mod3 at gmail.com)
+
+## Description
+
+A [ripl] plugin that allows inline shell commands.
+
+## Features
+
+## Examples
+
+ >> require 'ripl/shell_commands'
+ => true
+ >> !date
+ Sat Dec 1 21:47:55 PST 2012
+ => true
+ >> !cd /etc/
+ => true
+ >> @path = '/etc/profile.d/'
+ => "/etc/profile.d/"
+ >> !ls #{@path}
+ bash_completion.sh colorls.csh less.sh qt.sh
+ chgems.sh colorls.sh PackageKit.sh vim.csh
+ chruby.sh lang.csh qt.csh vim.sh
+ colorgrep.csh lang.sh qt-graphicssystem.csh which2.csh
+ colorgrep.sh less.csh qt-graphicssystem.sh which2.sh
+ >> true
+
+## Requirements
+
+* [ripl] ~> 0.3
+
+## Install
+
+ $ gem install ripl-shell_commands
+
+## Copyright
+
+Copyright (c) 2012 Hal Brodigan
+
+See {file:LICENSE.txt} for details.
+
+[ripl]: https://github.com/cldwalker/ripl#readme
40 Rakefile
@@ -0,0 +1,40 @@
+# encoding: utf-8
+
+require 'rubygems'
+require 'rake'
+
+begin
+ gem 'rubygems-tasks', '~> 0.2'
+ require 'rubygems/tasks'
+
+ Gem::Tasks.new
+rescue LoadError => e
+ warn e.message
+ warn "Run `gem install rubygems-tasks` to install Gem::Tasks."
+end
+
+begin
+ gem 'rspec', '~> 2.4'
+ require 'rspec/core/rake_task'
+
+ RSpec::Core::RakeTask.new
+rescue LoadError => e
+ task :spec do
+ abort "Please run `gem install rspec` to install RSpec."
+ end
+end
+
+task :test => :spec
+task :default => :spec
+
+begin
+ gem 'yard', '~> 0.8'
+ require 'yard'
+
+ YARD::Rake::YardocTask.new
+rescue LoadError => e
+ task :yard do
+ abort "Please run `gem install yard` to install YARD."
+ end
+end
+task :doc => :yard
16 gemspec.yml
@@ -0,0 +1,16 @@
+name: ripl-shell_commands
+version: 0.1.0
+summary: Ripl plugin that allows inline shell commands
+description: A ripl plugin that allows inline shell commands in the Ripl Shell.
+license: MIT
+authors: Postmodern
+email: postmodern.mod3@gmail.com
+homepage: https://github.com/postmodern/ripl-shell_commands#readme
+
+dependencies:
+ ripl: ~> 0.3
+
+development_dependencies:
+ rspec: ~> 2.4
+ rubygems-tasks: ~> 0.2
+ yard: ~> 0.8
21 lib/ripl/completions/shell_commands.rb
@@ -0,0 +1,21 @@
+complete(:on => Ripl::ShellCommands::PATTERN) do |cmd|
+ name = cmd[1..-1]
+ glob = "#{name}*"
+ paths = Set[]
+
+ # search through $PATH for similar program names
+ Ripl::ShellCommands::PATHS.each do |dir|
+ Dir.glob(File.join(dir,glob)) do |path|
+ if (File.file?(path) && File.executable?(path))
+ paths << "!#{File.basename(path)}"
+ end
+ end
+ end
+
+ # add the black-listed keywords last
+ Ripl::ShellCommands::BLACKLIST.each do |keyword|
+ paths << "!#{keyword}" if keyword.start_with?(name)
+ end
+
+ paths
+end
154 lib/ripl/shell_commands.rb
@@ -0,0 +1,154 @@
+require 'set'
+require 'shellwords'
+
+module Ripl
+ #
+ # Allows for executing shell commands prefixed by a `!`.
+ #
+ module ShellCommands
+ # The directories of `$PATH`.
+ PATHS = ENV['PATH'].split(File::PATH_SEPARATOR)
+
+ # Names and statuses of executables.
+ EXECUTABLES = Hash.new do |hash,key|
+ hash[key] = PATHS.any? do |dir|
+ path = File.join(dir,key)
+
+ (File.file?(path) && File.executable?(path))
+ end
+ end
+
+ # Regexp to recognize `!commands`.
+ PATTERN = /^![a-zA-Z][a-zA-Z0-9\._-]*/
+
+ # Blacklist of known commands that conflict with Ruby keywords.
+ BLACKLIST = Set[
+ '[', 'ap', 'begin', 'case', 'class', 'def', 'fail', 'false',
+ 'for', 'if', 'lambda', 'load', 'loop', 'module', 'p', 'pp',
+ 'print', 'proc', 'puts', 'raise', 'require', 'true', 'undef',
+ 'unless', 'until', 'warn', 'while'
+ ]
+
+ #
+ # Dynamically execute shell commands, instead of Ruby.
+ #
+ # @param [String] input
+ # The input from the console.
+ #
+ def loop_eval(input)
+ if (@buffer.nil? && input =~ PATTERN)
+ command = input[1..-1]
+ name, arguments = parse_command(command)
+
+ unless BLACKLIST.include?(name)
+ if ShellCommands.singleton_class.method_defined?(name)
+ arguments ||= []
+
+ return ShellCommands.send(name,*arguments)
+ elsif executable?(name)
+ return ShellCommands.exec(name,*arguments)
+ end
+ end
+ end
+
+ super(input)
+ end
+
+ #
+ # Default command which executes a command in the shell.
+ #
+ # @param [Array<String>] arguments
+ # The arguments of the command.
+ #
+ # @return [Boolean]
+ # Specifies whether the command exited successfully.
+ #
+ def self.exec(*arguments)
+ system(Shellwords.shelljoin(arguments))
+ end
+
+ #
+ # Equivalent of the `cd` command, using `Dir.chdir`.
+ #
+ # @param [Array<String>] arguments
+ # The arguments of the command.
+ #
+ # @return [Boolean]
+ # Specifies whether the directory change was successful.
+ #
+ def self.cd(*arguments)
+ old_pwd = Dir.pwd
+
+ new_cwd = if arguments.empty?
+ Config::HOME
+ elsif arguments.first == '-'
+ unless ENV['OLDPWD']
+ print_warning 'cd: OLDPWD not set'
+ return false
+ end
+
+ ENV['OLDPWD']
+ else
+ arguments.first
+ end
+
+ Dir.chdir(new_cwd)
+ ENV['OLDPWD'] = old_pwd
+ return true
+ end
+
+ #
+ # Equivalent of the `export` or `set` commands.
+ #
+ # @param [Array<String>] arguments
+ # The arguments of the command.
+ #
+ # @return [true]
+ #
+ def self.export(*arguments)
+ arguments.each do |pair|
+ name, value = pair.split('=',2)
+
+ ENV[name] = value
+ end
+ end
+
+ protected
+
+ #
+ # Parses a Console command.
+ #
+ # @param [String] command
+ # The Console command to parse.
+ #
+ # @return [String, Array<String>]
+ # The command name and additional arguments.
+ #
+ def parse_command(command)
+ # evaluate embedded Ruby expressions
+ command = command.gsub(/\#\{[^\}]*\}/) do |expression|
+ eval(expression[2..-2],Ripl.config[:binding]).to_s.dump
+ end
+
+ arguments = Shellwords.shellsplit(command)
+ name = arguments.shift
+
+ return name, arguments
+ end
+
+ #
+ # Determines if an executable exists on the system.
+ #
+ # @param [String] name
+ # The program name or path.
+ #
+ # @return [Boolean]
+ # Specifies whether the executable exists.
+ #
+ def executable?(name)
+ (File.file?(name) && File.executable?(name)) || EXECUTABLES[name]
+ end
+ end
+end
+
+Ripl::Shell.send :include, Ripl::ShellCommands
60 ripl-shell_commands.gemspec
@@ -0,0 +1,60 @@
+# encoding: utf-8
+
+require 'yaml'
+
+Gem::Specification.new do |gem|
+ gemspec = YAML.load_file('gemspec.yml')
+
+ gem.name = gemspec.fetch('name')
+ gem.version = gemspec.fetch('version') do
+ lib_dir = File.join(File.dirname(__FILE__),'lib')
+ $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
+
+ require 'ripl/shell_commands/version'
+ Ripl::ShellCommands::VERSION
+ end
+
+ gem.summary = gemspec['summary']
+ gem.description = gemspec['description']
+ gem.licenses = Array(gemspec['license'])
+ gem.authors = Array(gemspec['authors'])
+ gem.email = gemspec['email']
+ gem.homepage = gemspec['homepage']
+
+ glob = lambda { |patterns| gem.files & Dir[*patterns] }
+
+ gem.files = `git ls-files`.split($/)
+ gem.files = glob[gemspec['files']] if gemspec['files']
+
+ gem.executables = gemspec.fetch('executables') do
+ glob['bin/*'].map { |path| File.basename(path) }
+ end
+ gem.default_executable = gem.executables.first if Gem::VERSION < '1.7.'
+
+ gem.extensions = glob[gemspec['extensions'] || 'ext/**/extconf.rb']
+ gem.test_files = glob[gemspec['test_files'] || '{test/{**/}*_test.rb']
+ gem.extra_rdoc_files = glob[gemspec['extra_doc_files'] || '*.{txt,md}']
+
+ gem.require_paths = Array(gemspec.fetch('require_paths') {
+ %w[ext lib].select { |dir| File.directory?(dir) }
+ })
+
+ gem.requirements = gemspec['requirements']
+ gem.required_ruby_version = gemspec['required_ruby_version']
+ gem.required_rubygems_version = gemspec['required_rubygems_version']
+ gem.post_install_message = gemspec['post_install_message']
+
+ split = lambda { |string| string.split(/,\s*/) }
+
+ if gemspec['dependencies']
+ gemspec['dependencies'].each do |name,versions|
+ gem.add_dependency(name,split[versions])
+ end
+ end
+
+ if gemspec['development_dependencies']
+ gemspec['development_dependencies'].each do |name,versions|
+ gem.add_development_dependency(name,split[versions])
+ end
+ end
+end
8 spec/shell_commands_spec.rb
@@ -0,0 +1,8 @@
+require 'spec_helper'
+require 'ripl/shell_commands'
+
+describe Ripl::ShellCommands do
+ it "should have a VERSION constant" do
+ subject.const_get('VERSION').should_not be_empty
+ end
+end
5 spec/spec_helper.rb
@@ -0,0 +1,5 @@
+gem 'rspec', '~> 2.4'
+require 'rspec'
+require 'ripl/shell_commands/version'
+
+include Ripl::ShellCommands

0 comments on commit b673ba9

Please sign in to comment.
Something went wrong with that request. Please try again.