├── .gitignore ├── .rubocop.yml ├── .travis.yml ├── Gemfile ├── lib └── guard │ ├── yard │ ├── version.rb │ ├── templates │ │ └── Guardfile │ ├── no_server.rb │ └── server.rb │ └── yard.rb ├── Rakefile ├── CHANGES.markdown ├── guard-yard.gemspec ├── LICENSE └── README.markdown /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | .bundle 3 | Gemfile.lock 4 | Guardfile 5 | pkg/* 6 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | Metrics/MethodLength: 2 | Max: 20 3 | 4 | Metrics/AbcSize: 5 | Max: 20 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.2 4 | - 2.3 5 | - 2.4 6 | - 2.5 7 | - 2.6 8 | - 2.7 9 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'http://rubygems.org' 2 | 3 | # Specify your gem's dependencies in guard-yard.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /lib/guard/yard/version.rb: -------------------------------------------------------------------------------- 1 | module Guard 2 | module YardVersion 3 | VERSION = '2.2.1'.freeze 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | require 'rubocop/rake_task' 3 | 4 | RuboCop::RakeTask.new 5 | 6 | task default: :rubocop 7 | -------------------------------------------------------------------------------- /lib/guard/yard/templates/Guardfile: -------------------------------------------------------------------------------- 1 | guard 'yard' do 2 | watch(%r{app\/.+\.rb}) 3 | watch(%r{lib\/.+\.rb}) 4 | watch(%r{ext\/.+\.c}) 5 | end 6 | -------------------------------------------------------------------------------- /lib/guard/yard/no_server.rb: -------------------------------------------------------------------------------- 1 | module Guard 2 | class Yard 3 | # NULL Server 4 | class NoServer 5 | %i[kill spawn verify].each do |method| 6 | define_method(method) { true } 7 | end 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /CHANGES.markdown: -------------------------------------------------------------------------------- 1 | # master (unreleased) 2 | 3 | # 2.2.1 (2017-12-20) 4 | 5 | * Fixes #21. Properly kill YARD server on Windows. (sshaw) 6 | 7 | # 2.2.0 (2016-12-28) 8 | 9 | * Added the server option `host`. (pascalturbo) 10 | 11 | # 2.1.4 (2014-11-06) 12 | 13 | * Upgraded to use new `Guard::Plugin` standard. (stefanvermaas) 14 | 15 | # 2.1.3 (2014-10-22) 16 | 17 | * Fixes #14, #15. `Process.wait2` only waits when a PID exists. (panthomakos) 18 | 19 | # 2.1.2 (2014-10-14) 20 | 21 | * Fixed #13. `Process.wait2` now waits specifically for the server PID. (panthomakos) 22 | 23 | # 2.1.0 24 | 25 | * Added possibility to specify cli-options for server start. (maxigs) 26 | 27 | # 2.0.1 28 | 29 | * Fixed issue where .yardopts files were not being used. (panthomakos) 30 | -------------------------------------------------------------------------------- /guard-yard.gemspec: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.push File.expand_path('../lib', __FILE__) 2 | require 'guard/yard/version' 3 | 4 | Gem::Specification.new do |s| 5 | s.name = 'guard-yard' 6 | s.version = Guard::YardVersion::VERSION 7 | s.authors = ['Pan Thomakos'] 8 | s.email = ['pan.thomakos@gmail.com'] 9 | s.homepage = 'https://github.com/panthomakos/guard-yard' 10 | s.summary = 'Guard gem for YARD' 11 | s.description = 'Guard::Yard automatically monitors Yard Documentation.' 12 | 13 | s.rubyforge_project = 'guard-yard' 14 | s.required_ruby_version = '>= 1.9.2' 15 | s.add_dependency 'guard', '>= 1.1.0' 16 | s.add_dependency 'yard', '>= 0.7.0' 17 | s.add_development_dependency 'rake' 18 | s.add_development_dependency 'rubocop', '= 0.51' 19 | 20 | s.files = Dir.glob('{lib}/**/*') + %w[LICENSE README.markdown] 21 | s.require_paths = ['lib'] 22 | end 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Panayiotis Thomakos 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /lib/guard/yard.rb: -------------------------------------------------------------------------------- 1 | require 'guard' 2 | require 'guard/plugin' 3 | require 'yard' 4 | 5 | module Guard 6 | # Main guard-yard plugin class. 7 | class Yard < Plugin 8 | autoload :NoServer, 'guard/yard/no_server' 9 | autoload :Server, 'guard/yard/server' 10 | attr_accessor :server 11 | 12 | def initialize(options = {}) 13 | super 14 | options[:server] = true unless options.key?(:server) 15 | @server = options[:server] ? Server.new(options) : NoServer.new 16 | end 17 | 18 | def start 19 | boot 20 | end 21 | 22 | def stop 23 | server.kill 24 | end 25 | 26 | def reload 27 | boot 28 | end 29 | 30 | def run_all 31 | UI.info '[Guard::Yard] Generating all documentation.' 32 | system('rm -rf .yardoc && yard doc') 33 | UI.info '[Guard::Yard] Documentation has been generated.' 34 | true 35 | end 36 | 37 | def run_on_changes(paths) 38 | UI.info "[Guard::Yard] Detected changes in #{paths.join(',')}." 39 | paths.each { |path| document([path]) } 40 | UI.info "[Guard::Yard] Updated documentation for #{paths.join(',')}." 41 | end 42 | 43 | private 44 | 45 | def check 46 | return true if File.exist?('.yardoc') 47 | UI.info '[Guard::Yard] Documentation missing.' 48 | run_all && true 49 | end 50 | 51 | def boot 52 | check && server.kill && server.spawn && server.verify 53 | end 54 | 55 | def document(files) 56 | ::YARD::Registry.load! 57 | ::YARD::Registry.load(files, true) 58 | ::YARD::Registry.load_all 59 | yardoc = ::YARD::CLI::Yardoc.new 60 | yardoc.parse_arguments 61 | options = yardoc.options 62 | objects = ::YARD::Registry.all(:root, :module, :class).reject do |object| 63 | (!options[:serializer] || options[:serializer].exists?(object)) \ 64 | && object.files.none? { |f, _line| files.include?(f) } 65 | end 66 | ::YARD::Templates::Engine.generate(objects, options) 67 | save_registry 68 | end 69 | 70 | def save_registry 71 | ::YARD::Registry.save(true) 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /lib/guard/yard/server.rb: -------------------------------------------------------------------------------- 1 | require 'socket' 2 | 3 | module Guard 4 | class Yard 5 | # Responsible for running, verifying and killing the YARD server. 6 | class Server 7 | attr_accessor :pid, :port, :host 8 | 9 | def initialize(options = {}) 10 | @port = options[:port] || '8808' 11 | @host = options[:host] || 'localhost' 12 | @stdout = options[:stdout] 13 | @stderr = options[:stderr] 14 | @cli = options[:cli] 15 | end 16 | 17 | def spawn 18 | UI.info '[Guard::Yard] Starting YARD Documentation Server.' 19 | 20 | command = ["yard server -p #{port} -b #{host}"] 21 | command << @cli if @cli 22 | command << "2> #{@stderr}" if @stderr 23 | command << "1> #{@stdout}" if @stdout 24 | 25 | self.pid = Process.spawn(command.join(' ')) 26 | end 27 | 28 | def kill 29 | UI.info '[Guard::Yard] Stopping YARD Documentation Server.' 30 | return true unless pid 31 | Gem.win_platform? ? windows_kill : posix_kill 32 | end 33 | 34 | def verify 35 | 5.times do 36 | sleep 1 37 | begin 38 | TCPSocket.new(host, port.to_i).close 39 | rescue Errno::ECONNREFUSED 40 | next 41 | end 42 | UI.info '[Guard::Yard] Server successfully started.' 43 | return true 44 | end 45 | UI.error '[Guard::Yard] Error starting documentation server.' 46 | Notifier.notify( 47 | '[Guard::Yard] Server NOT started.', 48 | title: 'yard', 49 | image: :failed 50 | ) 51 | false 52 | end 53 | 54 | private 55 | 56 | def windows_kill 57 | # /t includes child process 58 | # /f forces (required else we'll fail) 59 | if system("taskkill /f /t /pid #{pid}").nil? 60 | raise "Cannot kill server: Windows' taskkill command not found" 61 | end 62 | 63 | # Process was killed or it didn't exist (something else..?). 64 | true 65 | end 66 | 67 | def posix_kill 68 | begin 69 | Process.kill('QUIT', pid) 70 | Process.wait2(pid) 71 | # rubocop:disable Lint/HandleExceptions 72 | rescue Errno::ESRCH, Errno::ECHILD 73 | # Process is already dead. 74 | end 75 | true 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # Guard::Yard 2 | 3 | Guard::Yard allows you to automatically run and update your local YARD Documentation Server. It aims to centralize your file monitoring to guard instead of using the `yard server --reload` command which can be unreliable and provides little control over the generated documentation. Guard::Yard monitors files and updates only the documentation than changes, as opposed to generating the entire documentation suite. That means that changes to your documentation are available sooner! 4 | 5 | ## Requirements 6 | 7 | * The [YARD](http://yardoc.org) documentation tool. 8 | * The [Guard](https://github.com/guard/guard) rubygem. 9 | * Ruby 1.9.2 or higher. 10 | 11 | ## Install 12 | 13 | Add guard-yard to your Gemfile (inside development group): 14 | 15 | gem 'guard-yard' 16 | 17 | Install or update your bundle: 18 | 19 | bundle install 20 | 21 | Add the default guard-yard definition to your Guardfile: 22 | 23 | guard init yard 24 | 25 | ## Guardfile 26 | 27 | Please read the [Guardfile DSL documentation](https://github.com/guard/guard#readme) for additional information. 28 | 29 | Guard::Yard automatically detects changes in your app, lib and ext directories, but you can have it monitor additional files using the Guardfile DSL. 30 | 31 | Guard::Yard also provides some basic options for doc generation and running the YARD server. 32 | 33 | guard 'yard', :port => '8808' do 34 | ... 35 | end 36 | 37 | Available options: 38 | 39 | :server => true # Disable/Enable server 40 | :port => '8808' # Port on which the server shoud run. 41 | :host => 'localhost' # Host to which the server should bind. 42 | :stdout => 'yard.log' # File in which to log the yard server output. 43 | :stderr => '/dev/null' # File in which to log the yard server errors. 44 | :cli => '--plugin rest' # Additional command line options to be appended to the server command. 45 | 46 | ## Clean-Slate Documentation 47 | 48 | To generate or re-create documentation from a clean-slate, run the following command: 49 | 50 | rm -rf .yardoc && yard doc 51 | 52 | When booting guard, Guard::Yard will do this for you automatically if no .yardoc directory is present. Once guard is running you can execute this command by using the `Ctrl-\` key combination as well. 53 | 54 | 55 | ## Troubleshooting 56 | 57 | If you are running into issues, try re-creating your documentation using `rm -rf .yardoc && yard doc`. Once this operation is complete, restart guard. If you are still having problems, open a new issue in the GitHub issue tracker for this project. 58 | 59 | ## Build Status [![Build Status](https://app.travis-ci.com/panthomakos/guard-yard.svg?branch=master)](https://secure.travis-ci.org/panthomakos/guard-yard.svg?branch=master) 60 | --------------------------------------------------------------------------------