From da562ad74cf00f66b92e33562a8a062ceb6085e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohnic=CC=81?= Date: Wed, 12 Dec 2012 02:43:48 +0100 Subject: [PATCH] replace build system with generated table of contents Gets rid of `doc/README.mdtoc` and its build script. Since GitHub.com renders anchors for each heading, all we have to do is put a simple table of contents into `README.md` itself, and everything will get linked up nicely. Pros of this approach: * We don't have to point out to people not to edit `README.md` anymore * We don't have to run the build script each time README gets edited Cons of this change: * The "chapter" numbers are lost. They were silly anyway. `doc/mdtoc` renders a Markdown table of contents for a Markdown file. `doc/filter-toc` filters that down to only headings after ToC. This script can be used to easily insert ToC into the current document when editing `README.md` with, e.g., Vim: :read !doc/filter-toc % --- README.md | 76 ++++----- doc/README.mdtoc | 411 ----------------------------------------------- doc/build | 4 - doc/filter-toc | 4 + doc/mdtoc | 33 ++++ doc/mdtoc.rb | 82 ---------- 6 files changed, 75 insertions(+), 535 deletions(-) delete mode 100644 doc/README.mdtoc delete mode 100755 doc/build create mode 100755 doc/filter-toc create mode 100755 doc/mdtoc delete mode 100644 doc/mdtoc.rb diff --git a/README.md b/README.md index 5fca402..c35ef65 100644 --- a/README.md +++ b/README.md @@ -39,27 +39,27 @@ tools that do one thing well. ## Table of Contents - * [1 How It Works](#section_1) - * [2 Installation](#section_2) - * [2.1 Basic GitHub Checkout](#section_2.1) - * [2.1.1 Upgrading](#section_2.1.1) - * [2.2 Homebrew on Mac OS X](#section_2.2) - * [2.3 Neckbeard Configuration](#section_2.3) - * [2.4 Uninstalling Ruby Versions](#section_2.4) - * [3 Usage](#section_3) - * [3.1 rbenv global](#section_3.1) - * [3.2 rbenv local](#section_3.2) - * [3.3 rbenv shell](#section_3.3) - * [3.4 rbenv versions](#section_3.4) - * [3.5 rbenv version](#section_3.5) - * [3.6 rbenv rehash](#section_3.6) - * [3.7 rbenv which](#section_3.7) - * [3.8 rbenv whence](#section_3.8) - * [4 Development](#section_4) - * [4.1 Version History](#section_4.1) - * [4.2 License](#section_4.2) +* [How It Works](#how-it-works) +* [Installation](#installation) + * [Basic GitHub Checkout](#basic-github-checkout) + * [Upgrading](#upgrading) + * [Homebrew on Mac OS X](#homebrew-on-mac-os-x) + * [Neckbeard Configuration](#neckbeard-configuration) + * [Uninstalling Ruby Versions](#uninstalling-ruby-versions) +* [Usage](#usage) + * [rbenv global](#rbenv-global) + * [rbenv local](#rbenv-local) + * [rbenv shell](#rbenv-shell) + * [rbenv versions](#rbenv-versions) + * [rbenv version](#rbenv-version) + * [rbenv rehash](#rbenv-rehash) + * [rbenv which](#rbenv-which) + * [rbenv whence](#rbenv-whence) +* [Development](#development) + * [Version History](#version-history) + * [License](#license) -## 1 How It Works +## How It Works ## rbenv operates on the per-user directory `~/.rbenv`. Version names in rbenv correspond to subdirectories of `~/.rbenv/versions`. For @@ -79,14 +79,14 @@ and then execute the corresponding binary. Because of the simplicity of the shim approach, all you need to use rbenv is `~/.rbenv/shims` in your `$PATH`. -## 2 Installation +## Installation ## **Compatibility note**: rbenv is _incompatible_ with rvm. Things will appear to work until you try to install a gem. The problem is that rvm actually overrides the `gem` command with a shell function! Please remove any references to rvm before using rbenv. -### 2.1 Basic GitHub Checkout +### Basic GitHub Checkout ### This will get you going with the latest version of rbenv and make it easy to fork and contribute any changes back upstream. @@ -140,7 +140,7 @@ easy to fork and contribute any changes back upstream. $ rbenv rehash -#### 2.1.1 Upgrading +#### Upgrading #### If you've installed rbenv using the instructions above, you can upgrade your installation at any time using git. @@ -162,7 +162,7 @@ tag: v0.2.0 $ git checkout v0.2.0 -### 2.2 Homebrew on Mac OS X +### Homebrew on Mac OS X ### You can also install rbenv using the [Homebrew](http://mxcl.github.com/homebrew/) package manager on Mac OS @@ -178,7 +178,7 @@ Afterwards you'll still need to add `eval "$(rbenv init -)"` to your profile as stated in the caveats. You'll only ever have to do this once. -### 2.3 Neckbeard Configuration +### Neckbeard Configuration ### Skip this section unless you must know what every line in your shell profile is doing. @@ -210,7 +210,7 @@ opposed to this idea. Here's what `rbenv init` actually does: Run `rbenv init -` for yourself to see exactly what happens under the hood. -### 2.4 Uninstalling Ruby Versions +### Uninstalling Ruby Versions ### As time goes on, ruby versions you install will accumulate in your `~/.rbenv/versions` directory. @@ -219,12 +219,12 @@ There is no uninstall or remove command in `rbenv`, so removing old versions is a simple matter of `rm -rf` the directory of the relevant ruby version you want removed under `~/.rbenv/versions` -## 3 Usage +## Usage ## Like `git`, the `rbenv` command delegates to subcommands based on its first argument. The most common subcommands are: -### 3.1 rbenv global +### rbenv global ### Sets the global version of Ruby to be used in all shells by writing the version name to the `~/.rbenv/version` file. This version can be @@ -239,7 +239,7 @@ The special version name `system` tells rbenv to use the system Ruby When run without a version number, `rbenv global` reports the currently configured global version. -### 3.2 rbenv local +### rbenv local ### Sets a local per-project Ruby version by writing the version name to an `.rbenv-version` file in the current directory. This version @@ -254,7 +254,7 @@ configured local version. You can also unset the local version: $ rbenv local --unset -### 3.3 rbenv shell +### rbenv shell ### Sets a shell-specific Ruby version by setting the `RBENV_VERSION` environment variable in your shell. This version overrides both @@ -274,7 +274,7 @@ prefer not to use shell integration, you may simply set the $ export RBENV_VERSION=jruby-1.7.1 -### 3.4 rbenv versions +### rbenv versions ### Lists all Ruby versions known to rbenv, and shows an asterisk next to the currently active version. @@ -287,7 +287,7 @@ the currently active version. rbx-1.2.4 ree-1.8.7-2011.03 -### 3.5 rbenv version +### rbenv version ### Displays the currently active Ruby version, along with information on how it was set. @@ -295,7 +295,7 @@ how it was set. $ rbenv version 1.8.7-p352 (set by /Volumes/37signals/basecamp/.rbenv-version) -### 3.6 rbenv rehash +### rbenv rehash ### Installs shims for all Ruby binaries known to rbenv (i.e., `~/.rbenv/versions/*/bin/*`). Run this command after you install a new @@ -303,7 +303,7 @@ version of Ruby, or install a gem that provides binaries. $ rbenv rehash -### 3.7 rbenv which +### rbenv which ### Displays the full path to the binary that rbenv will execute when you run the given command. @@ -311,7 +311,7 @@ run the given command. $ rbenv which irb /Users/sam/.rbenv/versions/1.9.3-p327/bin/irb -### 3.8 rbenv whence +### rbenv whence ### Lists all Ruby versions with the given command installed. @@ -320,7 +320,7 @@ Lists all Ruby versions with the given command installed. jruby-1.7.1 ree-1.8.7-2011.03 -## 4 Development +## Development ## The rbenv source code is [hosted on GitHub](https://github.com/sstephenson/rbenv). It's clean, modular, @@ -329,7 +329,7 @@ and easy to understand, even if you're not a shell hacker. Please feel free to submit pull requests and file bugs on the [issue tracker](https://github.com/sstephenson/rbenv/issues). -### 4.1 Version History +### Version History ### **0.3.0** (December 25, 2011) @@ -405,7 +405,7 @@ tracker](https://github.com/sstephenson/rbenv/issues). * Initial public release. -### 4.2 License +### License ### (The MIT license) diff --git a/doc/README.mdtoc b/doc/README.mdtoc deleted file mode 100644 index 12802a6..0000000 --- a/doc/README.mdtoc +++ /dev/null @@ -1,411 +0,0 @@ -# Simple Ruby Version Management: rbenv - -rbenv lets you easily switch between multiple versions of Ruby. It's -simple, unobtrusive, and follows the UNIX tradition of single-purpose -tools that do one thing well. - - - -### rbenv _does…_ - -* Let you **change the global Ruby version** on a per-user basis. -* Provide support for **per-project Ruby versions**. -* Allow you to **override the Ruby version** with an environment - variable. - -### In contrast with rvm, rbenv _does not…_ - -* **Need to be loaded into your shell.** Instead, rbenv's shim - approach works by adding a directory to your `$PATH`. -* **Override shell commands like `cd`.** That's dangerous and - error-prone. -* **Have a configuration file.** There's nothing to configure except - which version of Ruby you want to use. -* **Install Ruby.** You can build and install Ruby yourself, or use - [ruby-build](https://github.com/sstephenson/ruby-build) to - automate the process. -* **Manage gemsets.** [Bundler](http://gembundler.com/) is a better - way to manage application dependencies. If you have projects that - are not yet using Bundler you can install the - [rbenv-gemset](https://github.com/jamis/rbenv-gemset) plugin. -* **Require changes to Ruby libraries for compatibility.** The - simplicity of rbenv means as long as it's in your `$PATH`, - [nothing](https://rvm.io/integration/bundler/) - [else](https://rvm.io/integration/capistrano/) - needs to know about it. -* **Prompt you with warnings when you switch to a project.** Instead - of executing arbitrary code, rbenv reads just the version name - from each project. There's nothing to "trust." - -## Table of Contents - -## How It Works ## - -rbenv operates on the per-user directory `~/.rbenv`. Version names in -rbenv correspond to subdirectories of `~/.rbenv/versions`. For -example, you might have `~/.rbenv/versions/1.8.7-p354` and -`~/.rbenv/versions/1.9.3-p327`. - -Each version is a working tree with its own binaries, like -`~/.rbenv/versions/1.8.7-p354/bin/ruby` and -`~/.rbenv/versions/1.9.3-p327/bin/irb`. rbenv makes _shim binaries_ -for every such binary across all installed versions of Ruby. - -These shims are simple wrapper scripts that live in `~/.rbenv/shims` -and detect which Ruby version you want to use. They insert the -directory for the selected version at the beginning of your `$PATH` -and then execute the corresponding binary. - -Because of the simplicity of the shim approach, all you need to use -rbenv is `~/.rbenv/shims` in your `$PATH`. - -## Installation ## - -**Compatibility note**: rbenv is _incompatible_ with rvm. Things will - appear to work until you try to install a gem. The problem is that - rvm actually overrides the `gem` command with a shell function! - Please remove any references to rvm before using rbenv. - -### Basic GitHub Checkout ### - -This will get you going with the latest version of rbenv and make it -easy to fork and contribute any changes back upstream. - -1. Check out rbenv into `~/.rbenv`. - - $ git clone git://github.com/sstephenson/rbenv.git ~/.rbenv - -2. Add `~/.rbenv/bin` to your `$PATH` for access to the `rbenv` - command-line utility. - - $ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile - - **Zsh note**: Modify your `~/.zshenv` file instead of `~/.bash_profile`. - - **Ubuntu note**: Ubuntu uses `~/.profile` for enabling certain path - changes. This file won't be read if you create a `~/.bash_profile`. - Therefore, it's recommended that you add this line and the one in - point 3 below to your `~/.profile`. This has the added advantage - of working under both bash and zsh. - -3. Add rbenv init to your shell to enable shims and autocompletion. - - $ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile - - **Zsh note**: Modify your `~/.zshenv` file instead of `~/.bash_profile`. - - **Ubuntu note**: Same as Ubuntu note for point 2 above. - -4. Restart your shell as a login shell so the path changes take effect. - You can now begin using rbenv. - - $ exec $SHELL -l - -5. Install Ruby versions into `~/.rbenv/versions`. For example, to - install Ruby 1.9.3-p327, download and unpack the source, then run: - - $ ./configure --prefix=$HOME/.rbenv/versions/1.9.3-p327 - $ make - $ make install - - The [ruby-build](https://github.com/sstephenson/ruby-build) project - provides an `rbenv install` command that simplifies the process of - installing new Ruby versions to: - - $ rbenv install 1.9.3-p327 - -6. Rebuild the shim binaries. You should do this any time you install - a new Ruby binary (for example, when installing a new Ruby version, - or when installing a gem that provides a binary). - - $ rbenv rehash - -#### Upgrading #### - -If you've installed rbenv using the instructions above, you can -upgrade your installation at any time using git. - -To upgrade to the latest development version of rbenv, use `git pull`: - - $ cd ~/.rbenv - $ git pull - -To upgrade to a specific release of rbenv, check out the corresponding -tag: - - $ cd ~/.rbenv - $ git fetch - $ git tag - v0.1.0 - v0.1.1 - v0.1.2 - v0.2.0 - $ git checkout v0.2.0 - -### Homebrew on Mac OS X ### - -You can also install rbenv using the -[Homebrew](http://mxcl.github.com/homebrew/) package manager on Mac OS -X. - - $ brew update - $ brew install rbenv - $ brew install ruby-build - -The same commands can be used for upgrading. - -Afterwards you'll still need to add `eval "$(rbenv init -)"` to your -profile as stated in the caveats. You'll only ever have to do this -once. - -### Neckbeard Configuration ### - -Skip this section unless you must know what every line in your shell -profile is doing. - -`rbenv init` is the only command that crosses the line of loading -extra commands into your shell. Coming from rvm, some of you might be -opposed to this idea. Here's what `rbenv init` actually does: - -1. Sets up your shims path. This is the only requirement for rbenv to - function properly. You can do this by hand by prepending - `~/.rbenv/shims` to your `$PATH`. - -2. Installs autocompletion. This is entirely optional but pretty - useful. Sourcing `~/.rbenv/completions/rbenv.bash` will set that - up. There is also a `~/.rbenv/completions/rbenv.zsh` for Zsh - users. - -3. Rehashes shims. From time to time you'll need to rebuild your - shim files. Doing this on init makes sure everything is up to - date. You can always run `rbenv rehash` manually. - -4. Installs the sh dispatcher. This bit is also optional, but allows - rbenv and plugins to change variables in your current shell, making - commands like `rbenv shell` possible. The sh dispatcher doesn't do - anything crazy like override `cd` or hack your shell prompt, but if - for some reason you need `rbenv` to be a real script rather than a - shell function, you can safely skip it. - -Run `rbenv init -` for yourself to see exactly what happens under the -hood. - -### Uninstalling Ruby Versions ### - -As time goes on, ruby versions you install will accumulate in your -`~/.rbenv/versions` directory. - -There is no uninstall or remove command in `rbenv`, so removing old -versions is a simple matter of `rm -rf` the directory of the relevant -ruby version you want removed under `~/.rbenv/versions` - -## Usage ## - -Like `git`, the `rbenv` command delegates to subcommands based on its -first argument. The most common subcommands are: - -### rbenv global ### - -Sets the global version of Ruby to be used in all shells by writing -the version name to the `~/.rbenv/version` file. This version can be -overridden by a per-project `.rbenv-version` file, or by setting the -`RBENV_VERSION` environment variable. - - $ rbenv global 1.9.3-p327 - -The special version name `system` tells rbenv to use the system Ruby -(detected by searching your `$PATH`). - -When run without a version number, `rbenv global` reports the -currently configured global version. - -### rbenv local ### - -Sets a local per-project Ruby version by writing the version name to -an `.rbenv-version` file in the current directory. This version -overrides the global, and can be overridden itself by setting the -`RBENV_VERSION` environment variable or with the `rbenv shell` -command. - - $ rbenv local rbx-1.2.4 - -When run without a version number, `rbenv local` reports the currently -configured local version. You can also unset the local version: - - $ rbenv local --unset - -### rbenv shell ### - -Sets a shell-specific Ruby version by setting the `RBENV_VERSION` -environment variable in your shell. This version overrides both -project-specific versions and the global version. - - $ rbenv shell jruby-1.7.1 - -When run without a version number, `rbenv shell` reports the current -value of `RBENV_VERSION`. You can also unset the shell version: - - $ rbenv shell --unset - -Note that you'll need rbenv's shell integration enabled (step 3 of -the installation instructions) in order to use this command. If you -prefer not to use shell integration, you may simply set the -`RBENV_VERSION` variable yourself: - - $ export RBENV_VERSION=jruby-1.7.1 - -### rbenv versions ### - -Lists all Ruby versions known to rbenv, and shows an asterisk next to -the currently active version. - - $ rbenv versions - 1.8.7-p352 - 1.9.2-p290 - * 1.9.3-p327 (set by /Users/sam/.rbenv/global) - jruby-1.7.1 - rbx-1.2.4 - ree-1.8.7-2011.03 - -### rbenv version ### - -Displays the currently active Ruby version, along with information on -how it was set. - - $ rbenv version - 1.8.7-p352 (set by /Volumes/37signals/basecamp/.rbenv-version) - -### rbenv rehash ### - -Installs shims for all Ruby binaries known to rbenv (i.e., -`~/.rbenv/versions/*/bin/*`). Run this command after you install a new -version of Ruby, or install a gem that provides binaries. - - $ rbenv rehash - -### rbenv which ### - -Displays the full path to the binary that rbenv will execute when you -run the given command. - - $ rbenv which irb - /Users/sam/.rbenv/versions/1.9.3-p327/bin/irb - -### rbenv whence ### - -Lists all Ruby versions with the given command installed. - - $ rbenv whence rackup - 1.9.3-p327 - jruby-1.7.1 - ree-1.8.7-2011.03 - -## Development ## - -The rbenv source code is [hosted on -GitHub](https://github.com/sstephenson/rbenv). It's clean, modular, -and easy to understand, even if you're not a shell hacker. - -Please feel free to submit pull requests and file bugs on the [issue -tracker](https://github.com/sstephenson/rbenv/issues). - -### Version History ### - -**0.3.0** (December 25, 2011) - -* Added an `rbenv root` command which prints the value of - `$RBENV_ROOT`, or the default root directory if it's unset. -* Clarified Zsh installation instructions in the readme. -* Removed some redundant code in `rbenv rehash`. -* Fixed an issue with calling `readlink` for paths with spaces. -* Changed Zsh initialization code to install completion hooks only for - interactive shells. -* Added preliminary support for ksh. -* `rbenv rehash` creates or removes shims only when necessary instead - of removing and re-creating all shims on each invocation. -* Fixed that `RBENV_DIR`, when specified, would be incorrectly - expanded to its parent directory. -* Removed the deprecated `set-default` and `set-local` commands. -* Added a `--no-rehash` option to `rbenv init` for skipping the - automatic rehash when opening a new shell. - -**0.2.1** (October 1, 2011) - -* Changed the `rbenv` command to ensure that `RBENV_DIR` is always an - absolute path. This fixes an issue where Ruby scripts using the - `ruby-local-exec` wrapper would go into an infinite loop when - invoked with a relative path from the command line. - -**0.2.0** (September 28, 2011) - -* Renamed `rbenv set-default` to `rbenv global` and `rbenv set-local` - to `rbenv local`. The `set-` commands are deprecated and will be - removed in the next major release. -* rbenv now uses `greadlink` on Solaris. -* Added a `ruby-local-exec` command which can be used in shebangs in - place of `#!/usr/bin/env ruby` to properly set the project-specific - Ruby version regardless of current working directory. -* Fixed an issue with `rbenv rehash` when no binaries are present. -* Added support for `rbenv-sh-*` commands, which run inside the - current shell instead of in a child process. -* Added an `rbenv shell` command for conveniently setting the - `$RBENV_VERSION` environment variable. -* Added support for storing rbenv versions and shims in directories - other than `~/.rbenv` with the `$RBENV_ROOT` environment variable. -* Added support for debugging rbenv via `set -x` when the - `$RBENV_DEBUG` environment variable is set. -* Refactored the autocompletion system so that completions are now - built-in to each command and shared between bash and Zsh. -* Added support for plugin bundles in `~/.rbenv/plugins` as documented - in [issue #102](https://github.com/sstephenson/rbenv/pull/102). -* Added `/usr/local/etc/rbenv.d` to the list of directories searched - for rbenv hooks. -* Added support for an `$RBENV_DIR` environment variable which - defaults to the current working directory for specifying where rbenv - searches for local version files. - -**0.1.2** (August 16, 2011) - -* Fixed rbenv to be more resilient against nonexistent entries in - `$PATH`. -* Made the `rbenv rehash` command operate atomically. -* Modified the `rbenv init` script to automatically run `rbenv - rehash` so that shims are recreated whenever a new shell is opened. -* Added initial support for Zsh autocompletion. -* Removed the dependency on egrep for reading version files. - -**0.1.1** (August 14, 2011) - -* Fixed a syntax error in the `rbenv help` command. -* Removed `-e` from the shebang in favor of `set -e` at the top of - each file for compatibility with operating systems that do not - support more than one argument in the shebang. - -**0.1.0** (August 11, 2011) - -* Initial public release. - -### License ### - -(The MIT license) - -Copyright (c) 2011 Sam Stephenson - -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. diff --git a/doc/build b/doc/build deleted file mode 100755 index 3d542d4..0000000 --- a/doc/build +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -e - -ruby mdtoc.rb README.mdtoc > ../README.md - diff --git a/doc/filter-toc b/doc/filter-toc new file mode 100755 index 0000000..761288b --- /dev/null +++ b/doc/filter-toc @@ -0,0 +1,4 @@ +#!/bin/bash +# Render Markdown ToC with only headings appearing after "Table of Contents" +dir="$(dirname "$0")" +"$dir"/mdtoc "$1" | sed -n '/table-of-contents/,$p' | grep -v table-of-contents diff --git a/doc/mdtoc b/doc/mdtoc new file mode 100755 index 0000000..5d63554 --- /dev/null +++ b/doc/mdtoc @@ -0,0 +1,33 @@ +#!/usr/bin/env ruby +require 'escape_utils' + +start_at_level = 2 + +headers = Hash.new(0) + +anchor = lambda { |title| + href = title.downcase + href.gsub!(/[^\w\- ]/, '') # remove punctuation + href.gsub!(' ', '-') # replace spaces with dash + href = EscapeUtils.escape_uri(href) # escape extended UTF-8 chars + + uniq = (headers[href] > 0) ? "-#{headers[href]}" : '' + headers[href] += 1 + + href + uniq +} + +ARGF.each_line do |line| + if line =~ /^(#+) (.+?)#*$/ + level = $1.size + next if level < start_at_level + title = $2.strip + href = anchor.call title + + puts "%s* [%s](#%s)" % [ + ' ' * (level - start_at_level), + title, + href + ] + end +end diff --git a/doc/mdtoc.rb b/doc/mdtoc.rb deleted file mode 100644 index 3c5a173..0000000 --- a/doc/mdtoc.rb +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env ruby - -# A little Markdown filter that scans your document for headings, -# numbers them, adds anchors, and inserts a table of contents. -# -# To use it, make sure the headings you want numbered and linked are -# in this format: -# -# ### Title ### -# -# I.e. they must have an equal number of octothorpes around the title -# text. (In Markdown, `#` means `h1`, `##` means `h2`, and so on.) -# The table of contents will be inserted before the first such -# heading. -# -# Released into the public domain. -# Sam Stephenson -# 2011-04-30 - -def mdtoc(markdown) - titles = [] - lines = markdown.split($/) - start = nil - - # First pass: Scan the Markdown source looking for titles of the - # format: `### Title ###`. Record the line number, header level - # (number of octothorpes), and text of each matching title. - lines.each_with_index do |line, line_no| - if line.match(/^(\#{1,6})\s+(.+?)\s+\1$/) - titles << [line_no, $1.length, $2] - start ||= line_no - end - end - - last_section = nil - last_level = nil - - # Second pass: Iterate over all matched titles and compute their - # corresponding section numbers. Then replace the titles with - # annotated anchors. - titles.each do |title_info| - line_no, level, text = title_info - - if last_section - section = last_section.dup - - if last_level < level - section << 1 - else - (last_level - level).times { section.pop } - section[-1] += 1 - end - else - section = [1] - end - - name = section.join(".") - lines[line_no] = %(#{"#" * level} #{name} #{text}) - - title_info << section - last_section = section - last_level = level - end - - # Third pass: Iterate over matched titles once more to produce the - # table of contents. Then insert it immediately above the first - # matched title. - if start - toc = titles.map do |(line_no, level, text, section)| - name = section.join(".") - %(#{" " * (section.length * 3)}* [#{name} #{text}](#section_#{name})) - end + [""] - - lines.insert(start, *toc) - end - - lines.join("\n") -end - -if __FILE__ == $0 - puts mdtoc($<.read) -end