├── COPYING ├── README.markdown └── rails.bash /COPYING: -------------------------------------------------------------------------------- 1 | rails.bash - Bash completion support for Ruby on Rails. 2 | 3 | Copyright (C) 2011 Jonhnny Weslley 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # Rails completion 2 | 3 | Bash completion support for Ruby on Rails. 4 | 5 | The completion routines provide support for completing: 6 | 7 | * rails commands (e.g.: new, server, console, generate, runner, ...) 8 | * rails generators (e.g.: scaffold, controller, mailer, observer, ...) 9 | * rails environments 10 | * rails field's types on generators (e.g.: scaffold, model, migration, ...) 11 | * common --long-options 12 | 13 | ## Requirements 14 | 15 | * Rails 3 16 | * Bash 4 17 | * bash_completion 1.1+. 18 | 19 | Current version of `bash_completion` supports all command-line options available in Rails 3.2.x, if you want to use it with Rails 3.0.y or 3.1.z you should check this version: 20 | 21 | https://github.com/jweslley/rails_completion/tree/v0.1.9 22 | 23 | ### Brew install of Bash 4 (Mac OSX) 24 | Mac OSX still uses the old version 3.2 of bash, which is not compatible to `rails_completion`. 25 | Install the current version 4 of bash like this: 26 | ```bash 27 | brew install bash 28 | sudo bash -c "echo '/usr/local/bin/bash' >> /etc/shells" 29 | chsh -s /usr/local/bin/bash 30 | ``` 31 | 32 | ## Installation 33 | 34 | ### Brew install (OSX) 35 | ```bash 36 | brew tap homebrew/completions 37 | brew install rails-completion 38 | ``` 39 | 40 | then add something like this to your ~/.bashrc 41 | 42 | ```bash 43 | if [ -f `brew --prefix`/etc/bash_completion.d/rails.bash ]; then 44 | source `brew --prefix`/etc/bash_completion.d/rails.bash 45 | fi 46 | ``` 47 | 48 | ### Non-OSX 49 | 50 | 1. Copy the `rails.bash` file to somewhere (e.g. ~/.rails.bash). 51 | 2. Add the following line to your `.bashrc`: 52 | 53 | source ~/.rails.bash 54 | 55 | Alternatively, on Debian systems, you can just copy the `rails.bash` file to `/etc/bash_completion.d/` directory. 56 | 57 | ## Basic Usage 58 | 59 | Typical usage is to change into a rails application and get some work. 60 | 61 | For example, using rails console is something like: 62 | 63 | $ cd rails_app 64 | $ rails c 65 | c console 66 | $ rails c 67 | --debugger development production -s --sandbox test 68 | $ rails c p 69 | $ rails c production 70 | 71 | Choosing the server's environment: 72 | 73 | $ rails server -e 74 | -edevelopment -eproduction -etest 75 | $ rails server -ep 76 | $ rails server -eproduction 77 | 78 | 79 | ### Playing with generators 80 | 81 | The generators available for completion are not hard-coded. The `rails.bash` script lookup for generators in your Rails application. In this way, generators provided by thrid-party plugins declared in your `Gemfile` also will be available for completion. Moreover, for the sake of performance, the `rails.bash` script saves the list of generators available in a cache file, named `.rails_generators~`. But, if the `Gemfile` file is modified the cache file will be updated on next completion event. 82 | 83 | In the following example, I use the 'devise' plugin on `Gemfile`: 84 | 85 | $ rails g 86 | active_record:devise generator model resource 87 | controller helper mongoid:devise scaffold 88 | devise integration_test observer scaffold_controller 89 | devise:install mailer performance_test session_migration 90 | devise:views migration plugin stylesheets 91 | 92 | In some generators (scaffold, model, resource and migration), you can declare fields to be generated using the syntax `field:type`. The `rails.bash` script also provides support for field's type completion. For this, just type the field name followed by a colon (`:`) and hit ``: 93 | 94 | $ rails g model Blog title: 95 | title:binary title:datetime title:integer title:time 96 | title:boolean title:decimal title:string title:timestamp 97 | title:date title:float title:text 98 | $ rails g model Blog title:s 99 | $ rails g model Blog title:string 100 | ... 101 | 102 | For more details, use it and have fun! 103 | 104 | 105 | ## Bugs and Feedback 106 | 107 | If you discover any bugs or have some idea, feel free to create an issue on GitHub: 108 | 109 | 110 | 111 | 112 | ## License 113 | 114 | Copyright (c) 2011 [Jonhnny Weslley]() 115 | 116 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License, version 3, as published by the Free Software Foundation. 117 | 118 | 119 | [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/jweslley/rails_completion/trend.png)](https://bitdeli.com/free "Bitdeli Badge") 120 | 121 | -------------------------------------------------------------------------------- /rails.bash: -------------------------------------------------------------------------------- 1 | # Bash completion support for Ruby on Rails. 2 | # 3 | # Copyright (C) 2011 Jonhnny Weslley 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program. If not, see . 17 | # 18 | # The latest version of this software can be obtained here: 19 | # 20 | # http://github.com/jweslley/rails_completion 21 | # 22 | # VERSION: 0.3.0 23 | 24 | 25 | RAILSCOMP_FILE=".rails_generators~" 26 | 27 | 28 | # helper functions ------------------------------------------------------------- 29 | 30 | __railscomp(){ 31 | local cur="${COMP_WORDS[COMP_CWORD]}" 32 | COMPREPLY=( $( compgen -W "$1" -- "$cur" ) ) 33 | } 34 | 35 | # 36 | # @param $1 Name of variable to return result to 37 | # @param $2 Command list 38 | __railscmd(){ 39 | any_command=$(echo $2 | sed -e 's/[[:space:]]/|/g') 40 | for (( i=0; i < ${#COMP_WORDS[@]}-1; i++ )); do 41 | if [[ ${COMP_WORDS[i]} == @($any_command) ]]; then 42 | eval $1="${COMP_WORDS[i]}" 43 | fi 44 | done 45 | } 46 | 47 | __rails_env(){ 48 | __railscomp "{-e,--environment=}{test,development,production}" 49 | } 50 | 51 | __rails_database(){ 52 | __railscomp "{-d,--database=}{mysql,oracle,postgresql,sqlite3,frontbase,ibm_db,jdbcmysql,jdbcsqlite3,jdbcpostgresql,jdbc}" 53 | } 54 | 55 | # 56 | # @param $1 Field's name 57 | __rails_types(){ 58 | __railscomp "${1%:*}:{string,text,integer,float,decimal,datetime,timestamp,date,time,binary,boolean,references,index,uniq}" 59 | } 60 | 61 | __rails_new(){ 62 | local cur prev 63 | _get_comp_words_by_ref cur prev 64 | 65 | case "$cur" in 66 | -d*|--database=*) 67 | __rails_database 68 | return 69 | ;; 70 | --ruby=*|--builder=*|--template=*) 71 | _filedir 72 | return 73 | ;; 74 | -*) __railscomp "$1" ;; 75 | esac 76 | 77 | _filedir 78 | } 79 | 80 | # end of helper functions ------------------------------------------------------ 81 | 82 | 83 | # generators ------------------------------------------------------------------- 84 | 85 | __rails_generators_create_cache(){ 86 | echo " 87 | require ::File.expand_path('../config/application', __FILE__) 88 | require 'rails/generators' 89 | 90 | Rails::Generators.lookup! 91 | 92 | hidden_namespaces = Rails::Generators.hidden_namespaces + ['rails:app'] 93 | generators = Rails::Generators.subclasses.select do |generator| 94 | hidden_namespaces.exclude? generator.namespace 95 | end 96 | 97 | shell = Thor::Shell::Basic.new 98 | generators_opts = generators.inject({}) do |hash, generator| 99 | options = (generator.class_options_help(shell).values.flatten + 100 | generator.class_options.values).uniq.map do |opt| 101 | boolean_opt = opt.type == :boolean || opt.banner.empty? 102 | boolean_opt ? opt.switch_name : \"#{opt.switch_name}=\" 103 | end 104 | hash[generator.namespace.gsub(/^rails:/, '')] = options 105 | hash 106 | end 107 | 108 | File.open(File.join(Rails.root, '${RAILSCOMP_FILE}'), 'w') do |f| 109 | YAML.dump(generators_opts, f) 110 | end 111 | " | ruby > /dev/null 112 | } 113 | 114 | __rails_generators_opts(){ 115 | echo " 116 | require 'yaml' 117 | generator = '$1' 118 | generators_opts = YAML.load_file('${RAILSCOMP_FILE}') 119 | opts = generator.empty? ? generators_opts.keys : generators_opts[generator] 120 | opts.each { |opt| puts opt } 121 | " | ruby 122 | } 123 | 124 | __rails_generators(){ 125 | recent=`ls -t "$RAILSCOMP_FILE" Gemfile 2> /dev/null | head -n 1` 126 | if [[ $recent != "$RAILSCOMP_FILE" ]]; then 127 | __rails_generators_create_cache 128 | fi 129 | __railscomp "$(__rails_generators_opts)" 130 | } 131 | 132 | __rails_generator_options(){ 133 | local cur 134 | _get_comp_words_by_ref cur 135 | 136 | if [[ $cur == *:* ]]; then 137 | __rails_types "$cur" 138 | else 139 | __railscomp "$(__rails_generators_opts $1)" 140 | fi 141 | } 142 | 143 | # 144 | # @param $1 file's path 145 | # @param $2 filename suffix 146 | # @param $3 name's suffix 147 | # @param $4 kind. Defaults to class. 148 | __rails_destroy(){ 149 | local cur 150 | _get_comp_words_by_ref cur 151 | 152 | case "$cur" in 153 | -*) __railscomp "--pretend --force --skip --quiet" ;; 154 | *) __railscomp "$(find "$1" -name "*$2.rb" -exec grep ".*${4-class}.*$3.*" {} \; \ 155 | | awk '{ print $2 }' | sed s/$3$//g)" ;; 156 | esac 157 | } 158 | 159 | # end of generators ------------------------------------------------------------ 160 | 161 | 162 | # rails commands --------------------------------------------------------------- 163 | 164 | _rails_new(){ 165 | if [ "${COMP_WORDS[1]}" == "plugin" ]; then 166 | __rails_new "--ruby= --builder= --template= 167 | --skip-gemfile --skip-bundle --skip-git --skip-active-record --skip-sprockets 168 | --database= --javascript= --skip-javascript --dev --edge --skip-test-unit 169 | --old-style-hash --dummy-path= --full --mountable --skip-gemspec 170 | --force --pretend --quiet --skip --help" 171 | else 172 | __rails_new "--ruby= --builder= --template= 173 | --skip-gemfile --skip-bundle --skip-git --skip-active-record --skip-sprockets 174 | --database= --javascript= --skip-javascript --dev --edge --skip-test-unit 175 | --old-style-hash --force --pretend --quiet --skip --help" 176 | fi 177 | } 178 | 179 | _rails_plugin(){ 180 | if [[ -f "script/rails" ]]; then 181 | __railscomp "--help --verbose --root= install remove" 182 | else 183 | __railscomp "new" 184 | fi 185 | } 186 | 187 | _rails_server(){ 188 | local cur prev 189 | _get_comp_words_by_ref cur prev 190 | 191 | case "$cur" in 192 | -e*|--environment=*) 193 | __rails_env 194 | return 195 | ;; 196 | esac 197 | 198 | case "$prev" in 199 | --config=*|--pid=*) _filedir ;; 200 | *) __railscomp "--help --pid= -e --environment= --debugger --daemon --config= --binding= --port=" ;; 201 | esac 202 | } 203 | 204 | _rails_console(){ 205 | __railscomp "test development production --sandbox --debugger --help" 206 | } 207 | 208 | _rails_dbconsole(){ 209 | local environment 210 | 211 | __railscmd environment "test development production" 212 | 213 | if [ -z "$environment" ]; then 214 | __railscomp "test development production" 215 | else 216 | __railscomp "--include-password --header --mode" 217 | fi 218 | } 219 | 220 | _rails_generate(){ 221 | local cur generator generators 222 | _get_comp_words_by_ref cur 223 | 224 | generators=$(test -f "$RAILSCOMP_FILE" && __rails_generators_opts) 225 | __railscmd generator "$generators" 226 | 227 | if [ -z "$generator" ]; then 228 | case "$cur" in 229 | -*) __railscomp "--help" ;; 230 | *) __rails_generators ;; 231 | esac 232 | return 233 | fi 234 | 235 | __rails_generator_options "$generator" 236 | } 237 | 238 | _rails_destroy(){ 239 | local cur generator generators 240 | _get_comp_words_by_ref cur 241 | 242 | generators=$(test -f "$RAILSCOMP_FILE" && __rails_generators_opts) 243 | __railscmd generator "$generators" 244 | 245 | if [ -z "$generator" ]; then 246 | case "$cur" in 247 | -*) __railscomp "--help" ;; 248 | *) __rails_generators ;; 249 | esac 250 | return 251 | fi 252 | 253 | case "$generator" in 254 | model|scaffold|resource) __rails_destroy "app/models/" ;; 255 | migration|session_migration) __rails_destroy "db/migrate/" ;; 256 | mailer) __rails_destroy "app/mailers/" ;; 257 | observer) __rails_destroy "app/models/" "_observer" "Observer" ;; 258 | controller|scaffold_controller) __rails_destroy "app/controllers/" "_controller" "Controller" ;; 259 | helper) __rails_destroy "app/helpers/" "_helper" "Helper" "module" ;; 260 | integration_test) __rails_destroy "test/integration/" "_test" "Test" ;; 261 | performance_test) __rails_destroy "test/performance/" "_test" "Test" ;; 262 | generator) __rails_destroy "lib/generators/" "_generator" "Generator" ;; 263 | *) __railscomp "--pretend --force --skip --quiet" ;; 264 | esac 265 | } 266 | 267 | _rails_runner(){ 268 | local cur prev 269 | _get_comp_words_by_ref cur prev 270 | 271 | case "$cur" in 272 | -e*|--environment=*) 273 | __rails_env 274 | return 275 | ;; 276 | esac 277 | 278 | case "$prev" in 279 | *) __railscomp "--help -e --environment=" ;; 280 | esac 281 | } 282 | 283 | _rails_profiler(){ 284 | local cur prev 285 | _get_comp_words_by_ref cur 286 | 287 | case "$cur" in 288 | -*) __railscomp "--help --runs --output --metrics --formats" ;; 289 | *) COMPREPLY=() ;; 290 | esac 291 | } 292 | 293 | _rails_benchmarker(){ 294 | local cur prev 295 | _get_comp_words_by_ref cur 296 | 297 | case "$cur" in 298 | -*) __railscomp "--help --runs --output --metrics" ;; 299 | *) COMPREPLY=() ;; 300 | esac 301 | } 302 | 303 | # end of rails commands -------------------------------------------------------- 304 | 305 | 306 | _rails(){ 307 | local cur options command commands 308 | _get_comp_words_by_ref cur 309 | 310 | options="--help --version" 311 | if [[ -f "script/rails" ]]; then 312 | commands="s server c console g generate d destroy r runner profiler plugin benchmarker db dbconsole" 313 | else 314 | commands="new plugin" 315 | fi 316 | 317 | __railscmd command "$commands" 318 | 319 | if [ -z "$command" ]; then 320 | case "$cur" in 321 | -*) __railscomp "$options" ;; 322 | *) __railscomp "$commands" ;; 323 | esac 324 | return 325 | fi 326 | 327 | case "$command" in 328 | new) _rails_new ;; 329 | plugin) _rails_plugin ;; 330 | s|server) _rails_server ;; 331 | c|console) _rails_console ;; 332 | db|dbconsole) _rails_dbconsole ;; 333 | g|generate) _rails_generate ;; 334 | d|destroy) _rails_destroy ;; 335 | r|runner) _rails_runner ;; 336 | profiler) _rails_profiler ;; 337 | benchmarker) _rails_benchmarker ;; 338 | *) COMPREPLY=() ;; 339 | esac 340 | } 341 | 342 | complete -o default -o nospace -F _rails rails 343 | --------------------------------------------------------------------------------