diff --git a/mk/docs.mk b/mk/docs.mk index 90f85079464bb..dab40cb165431 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -43,7 +43,9 @@ L10N_LANGS := ja # The options are passed to the documentation generators. RUSTDOC_HTML_OPTS_NO_CSS = --markdown-before-content=doc/version_info.html \ - --markdown-in-header=doc/favicon.inc --markdown-after-content=doc/footer.inc + --markdown-in-header=doc/favicon.inc \ + --markdown-after-content=doc/footer.inc \ + --markdown-playground-url='http://play.rust-lang.org/' RUSTDOC_HTML_OPTS = $(RUSTDOC_HTML_OPTS_NO_CSS) --markdown-css rust.css diff --git a/src/doc/footer.inc b/src/doc/footer.inc index a103a4908f6bf..4e7d60586f23d 100644 --- a/src/doc/footer.inc +++ b/src/doc/footer.inc @@ -5,3 +5,5 @@ or the MIT license, at your opt

This file may not be copied, modified, or distributed except according to those terms.

+ + diff --git a/src/doc/guide-macros.md b/src/doc/guide-macros.md index b86a6aa1b619c..45745c7b7bc7a 100644 --- a/src/doc/guide-macros.md +++ b/src/doc/guide-macros.md @@ -11,7 +11,7 @@ which both pattern-match on their input and both return early in one case, doing nothing otherwise: ~~~~ -# enum T { SpecialA(uint), SpecialB(uint) }; +# enum T { SpecialA(uint), SpecialB(uint) } # fn f() -> uint { # let input_1 = SpecialA(0); # let input_2 = SpecialA(0); @@ -37,7 +37,8 @@ lightweight custom syntax extensions, themselves defined using the the pattern in the above code: ~~~~ -# enum T { SpecialA(uint), SpecialB(uint) }; +# #![feature(macro_rules)] +# enum T { SpecialA(uint), SpecialB(uint) } # fn f() -> uint { # let input_1 = SpecialA(0); # let input_2 = SpecialA(0); @@ -55,6 +56,7 @@ early_return!(input_1 SpecialA); early_return!(input_2 SpecialB); # return 0; # } +# fn main() {} ~~~~ Macros are defined in pattern-matching style: in the above example, the text @@ -155,7 +157,8 @@ separator token (a comma-separated list could be written `$(...),*`), and `+` instead of `*` to mean "at least one". ~~~~ -# enum T { SpecialA(uint),SpecialB(uint),SpecialC(uint),SpecialD(uint)}; +# #![feature(macro_rules)] +# enum T { SpecialA(uint),SpecialB(uint),SpecialC(uint),SpecialD(uint)} # fn f() -> uint { # let input_1 = SpecialA(0); # let input_2 = SpecialA(0); @@ -175,6 +178,7 @@ early_return!(input_1, [SpecialA|SpecialC|SpecialD]); early_return!(input_2, [SpecialB]); # return 0; # } +# fn main() {} ~~~~ ### Transcription @@ -215,9 +219,10 @@ solves the problem. Now consider code like the following: ~~~~ -# enum T1 { Good1(T2, uint), Bad1}; +# #![feature(macro_rules)] +# enum T1 { Good1(T2, uint), Bad1} # struct T2 { body: T3 } -# enum T3 { Good2(uint), Bad2}; +# enum T3 { Good2(uint), Bad2} # fn f(x: T1) -> uint { match x { Good1(g1, val) => { @@ -232,6 +237,7 @@ match x { _ => return 0 // default value } # } +# fn main() {} ~~~~ All the complicated stuff is deeply indented, and the error-handling code is @@ -240,6 +246,7 @@ a match, but with a syntax that suits the problem better. The following macro can solve the problem: ~~~~ +# #![feature(macro_rules)] macro_rules! biased_match ( // special case: `let (x) = ...` is illegal, so use `let x = ...` instead ( ($e:expr) ~ ($p:pat) else $err:stmt ; @@ -261,9 +268,9 @@ macro_rules! biased_match ( ) ) -# enum T1 { Good1(T2, uint), Bad1}; +# enum T1 { Good1(T2, uint), Bad1} # struct T2 { body: T3 } -# enum T3 { Good2(uint), Bad2}; +# enum T3 { Good2(uint), Bad2} # fn f(x: T1) -> uint { biased_match!((x) ~ (Good1(g1, val)) else { return 0 }; binds g1, val ) @@ -273,6 +280,7 @@ biased_match!((g1.body) ~ (Good2(result) ) // complicated stuff goes here return result + val; # } +# fn main() {} ~~~~ This solves the indentation problem. But if we have a lot of chained matches @@ -280,6 +288,8 @@ like this, we might prefer to write a single macro invocation. The input pattern we want is clear: ~~~~ +# #![feature(macro_rules)] +# fn main() {} # macro_rules! b( ( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )* binds $( $bind_res:ident ),* @@ -301,14 +311,18 @@ process the semicolon-terminated lines, one-by-one. So, we want the following input patterns: ~~~~ +# #![feature(macro_rules)] # macro_rules! b( ( binds $( $bind_res:ident ),* ) # => (0)) +# fn main() {} ~~~~ ...and: ~~~~ +# #![feature(macro_rules)] +# fn main() {} # macro_rules! b( ( ($e :expr) ~ ($p :pat) else $err :stmt ; $( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )* @@ -322,6 +336,8 @@ The resulting macro looks like this. Note that the separation into piece of syntax (the `let`) which we only want to transcribe once. ~~~~ +# #![feature(macro_rules)] +# fn main() { macro_rules! biased_match_rec ( // Handle the first layer @@ -365,9 +381,9 @@ macro_rules! biased_match ( ) -# enum T1 { Good1(T2, uint), Bad1}; +# enum T1 { Good1(T2, uint), Bad1} # struct T2 { body: T3 } -# enum T3 { Good2(uint), Bad2}; +# enum T3 { Good2(uint), Bad2} # fn f(x: T1) -> uint { biased_match!( (x) ~ (Good1(g1, val)) else { return 0 }; @@ -376,6 +392,7 @@ biased_match!( // complicated stuff goes here return result + val; # } +# } ~~~~ This technique applies to many cases where transcribing a result all at once is not possible. diff --git a/src/doc/guide-unsafe.md b/src/doc/guide-unsafe.md index e0a48682963b4..1431c8a5c9ae4 100644 --- a/src/doc/guide-unsafe.md +++ b/src/doc/guide-unsafe.md @@ -523,6 +523,7 @@ vectors provided from C, using idiomatic Rust practices. ``` #![no_std] +#![feature(globs)] # extern crate libc; extern crate core; diff --git a/src/doc/rust.css b/src/doc/rust.css index d60dd54a67d14..3957231a195a5 100644 --- a/src/doc/rust.css +++ b/src/doc/rust.css @@ -313,6 +313,19 @@ table th { padding: 5px; } +/* Code snippets */ + +.rusttest { display: none; } +pre.rust { position: relative; } +pre.rust a { transform: scaleX(-1); } +.test-arrow { + display: inline-block; + position: absolute; + top: 0; + right: 10px; + font-size: 150%; +} + @media (min-width: 1170px) { pre { font-size: 15px; diff --git a/src/doc/rust.md b/src/doc/rust.md index b690c2eb98347..3715edff373f0 100644 --- a/src/doc/rust.md +++ b/src/doc/rust.md @@ -1260,6 +1260,8 @@ a = Cat; Enumeration constructors can have either named or unnamed fields: ~~~~ +# #![feature(struct_variant)] +# fn main() { enum Animal { Dog (String, f64), Cat { name: String, weight: f64 } @@ -1267,6 +1269,7 @@ enum Animal { let mut a: Animal = Dog("Cocoa".to_string(), 37.2); a = Cat { name: "Spotty".to_string(), weight: 2.7 }; +# } ~~~~ In this example, `Cat` is a _struct-like enum variant_, diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index 917704a2faacd..3b4164ffbc618 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -774,6 +774,7 @@ fn point_from_direction(dir: Direction) -> Point { Enum variants may also be structs. For example: ~~~~ +# #![feature(struct_variant)] use std::f64; # struct Point { x: f64, y: f64 } # fn square(x: f64) -> f64 { x * x } @@ -789,6 +790,7 @@ fn area(sh: Shape) -> f64 { } } } +# fn main() {} ~~~~ > *Note:* This feature of the compiler is currently gated behind the @@ -3046,6 +3048,7 @@ use farm::{chicken, cow}; 2. Import everything in a module with a wildcard: ~~~ +# #![feature(globs)] use farm::*; # mod farm { # pub fn cow() { println!("Bat-chicken? What a stupid name!") } diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 2004285ecb91b..a65c06107ce34 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -17,7 +17,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(macro_rules, managed_boxes, default_type_params, phase, globs)] #![no_std] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 6aa07415e9cc7..2ccf431fc22e1 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -50,7 +50,8 @@ #![crate_type = "rlib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![no_std] #![feature(globs, macro_rules, managed_boxes, phase, simd)] diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 0311c3339241a..25cf47a06b176 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -84,7 +84,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(globs, phase)] #![deny(missing_doc)] #![deny(deprecated_owned_vector)] diff --git a/src/libglob/lib.rs b/src/libglob/lib.rs index 86753fbb811cb..f3e1da77ce5c7 100644 --- a/src/libglob/lib.rs +++ b/src/libglob/lib.rs @@ -29,8 +29,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] - + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![deny(deprecated_owned_vector)] use std::cell::Cell; diff --git a/src/libgreen/lib.rs b/src/libgreen/lib.rs index 31fd8950c804c..c75d69480ce0d 100644 --- a/src/libgreen/lib.rs +++ b/src/libgreen/lib.rs @@ -203,7 +203,8 @@ #![crate_type = "dylib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] // NB this does *not* include globs, please keep it that way. #![feature(macro_rules, phase)] diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index ff5805599690d..daacf8b3c4761 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -111,7 +111,8 @@ if logging is disabled, none of the components of the log will be executed. #![crate_type = "dylib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(macro_rules)] #![deny(missing_doc, deprecated_owned_vector)] diff --git a/src/libnum/lib.rs b/src/libnum/lib.rs index 29cf769ffc9d8..fae21e80f3072 100644 --- a/src/libnum/lib.rs +++ b/src/libnum/lib.rs @@ -50,7 +50,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![deny(deprecated_owned_vector)] diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 3ed086e9b13cc..7a12dcf9f7f31 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -21,7 +21,8 @@ #![crate_type = "rlib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(macro_rules, phase, globs)] #![no_std] diff --git a/src/libregex/lib.rs b/src/libregex/lib.rs index a48760913c161..44c206162ab25 100644 --- a/src/libregex/lib.rs +++ b/src/libregex/lib.rs @@ -360,7 +360,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(macro_rules, phase)] #![deny(missing_doc, deprecated_owned_vector)] diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index f544e1e0973f3..3c9358b03a983 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -25,7 +25,7 @@ use html::escape::Escape; use t = syntax::parse::token; /// Highlights some source code, returning the HTML output. -pub fn highlight(src: &str, class: Option<&str>) -> String { +pub fn highlight(src: &str, class: Option<&str>, id: Option<&str>) -> String { debug!("highlighting: ================\n{}\n==============", src); let sess = parse::new_parse_sess(); let fm = parse::string_to_filemap(&sess, @@ -36,6 +36,7 @@ pub fn highlight(src: &str, class: Option<&str>) -> String { doit(&sess, lexer::StringReader::new(&sess.span_diagnostic, fm), class, + id, &mut out).unwrap(); str::from_utf8_lossy(out.unwrap().as_slice()).to_string() } @@ -47,11 +48,17 @@ pub fn highlight(src: &str, class: Option<&str>) -> String { /// it's used. All source code emission is done as slices from the source map, /// not from the tokens themselves, in order to stay true to the original /// source. -fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader, class: Option<&str>, +fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader, + class: Option<&str>, id: Option<&str>, out: &mut Writer) -> io::IoResult<()> { use syntax::parse::lexer::Reader; - try!(write!(out, "
\n", class.unwrap_or("")));
+    try!(write!(out, "
 try!(write!(out, "id='{}' ", id)),
+        None => {}
+    }
+    try!(write!(out, "class='rust {}'>\n", class.unwrap_or("")));
     let mut last = BytePos(0);
     let mut is_attribute = false;
     let mut is_macro = false;
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 80653878247fa..e2fa57148c2c7 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -16,6 +16,7 @@ pub struct Layout {
     pub logo: String,
     pub favicon: String,
     pub krate: String,
+    pub playground_url: String,
 }
 
 pub struct Page<'a> {
@@ -108,11 +109,13 @@ r##"
     
 
     
     
     
+    {play_js}
     
 
 "##,
@@ -124,6 +127,12 @@ r##"
     favicon   = nonestr(layout.favicon.as_slice()),
     sidebar   = *sidebar,
     krate     = layout.krate,
+    play_url  = layout.playground_url,
+    play_js   = if layout.playground_url.len() == 0 {
+        "".to_string()
+    } else {
+        format!(r#""#, page.root_path)
+    },
     )
 }
 
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 373c5220161bd..3e3846e8316e7 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -27,7 +27,7 @@
 #![allow(non_camel_case_types)]
 
 use libc;
-use std::cell::RefCell;
+use std::cell::{RefCell, Cell};
 use std::fmt;
 use std::slice;
 use std::str;
@@ -35,6 +35,8 @@ use std::collections::HashMap;
 
 use html::toc::TocBuilder;
 use html::highlight;
+use html::escape::Escape;
+use test;
 
 /// A unit struct which has the `fmt::Show` trait implemented. When
 /// formatted, this struct will emit the HTML corresponding to the rendered
@@ -139,6 +141,9 @@ fn stripped_filtered_line<'a>(s: &'a str) -> Option<&'a str> {
 }
 
 local_data_key!(used_header_map: RefCell>)
+local_data_key!(test_idx: Cell)
+// None == render an example, but there's no crate name
+local_data_key!(pub playground_krate: Option)
 
 pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
     extern fn block(ob: *mut hoedown_buffer, text: *hoedown_buffer,
@@ -149,9 +154,9 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
             let opaque = opaque as *mut hoedown_html_renderer_state;
             let my_opaque: &MyOpaque = &*((*opaque).opaque as *MyOpaque);
             slice::raw::buf_as_slice((*text).data, (*text).size as uint, |text| {
-                let text = str::from_utf8(text).unwrap();
+                let origtext = str::from_utf8(text).unwrap();
                 debug!("docblock: ==============\n{}\n=======", text);
-                let mut lines = text.lines().filter(|l| {
+                let mut lines = origtext.lines().filter(|l| {
                     stripped_filtered_line(*l).is_none()
                 });
                 let text = lines.collect::>().connect("\n");
@@ -180,9 +185,26 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
                 };
 
                 if !rendered {
-                    let output = highlight::highlight(text.as_slice(),
-                                                      None).as_slice()
-                                                           .to_c_str();
+                    let mut s = String::new();
+                    let id = playground_krate.get().map(|krate| {
+                        let idx = test_idx.get().unwrap();
+                        let i = idx.get();
+                        idx.set(i + 1);
+
+                        let test = origtext.lines().map(|l| {
+                            stripped_filtered_line(l).unwrap_or(l)
+                        }).collect::>().connect("\n");
+                        let krate = krate.as_ref().map(|s| s.as_slice());
+                        let test = test::maketest(test.as_slice(), krate, false);
+                        s.push_str(format!("{}",
+                                           i, Escape(test.as_slice())).as_slice());
+                        format!("rust-example-rendered-{}", i)
+                    });
+                    let id = id.as_ref().map(|a| a.as_slice());
+                    s.push_str(highlight::highlight(text.as_slice(), None, id)
+                                         .as_slice());
+                    let output = s.to_c_str();
                     output.with_ref(|r| {
                         hoedown_buffer_puts(ob, r)
                     })
@@ -377,6 +399,7 @@ fn parse_lang_string(string: &str) -> (bool,bool,bool,bool) {
 /// previous state (if any).
 pub fn reset_headers() {
     used_header_map.replace(Some(RefCell::new(HashMap::new())));
+    test_idx.replace(Some(Cell::new(0)));
 }
 
 impl<'a> fmt::Show for Markdown<'a> {
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 4ef3297912f9e..5526c50911f1c 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -230,6 +230,7 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
             logo: "".to_string(),
             favicon: "".to_string(),
             krate: krate.name.clone(),
+            playground_url: "".to_string(),
         },
         include_sources: true,
         render_redirect_pages: false,
@@ -250,6 +251,14 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
                             if "html_logo_url" == x.as_slice() => {
                         cx.layout.logo = s.to_string();
                     }
+                    clean::NameValue(ref x, ref s)
+                            if "html_playground_url" == x.as_slice() => {
+                        cx.layout.playground_url = s.to_string();
+                        let name = krate.name.clone();
+                        if markdown::playground_krate.get().is_none() {
+                            markdown::playground_krate.replace(Some(Some(name)));
+                        }
+                    }
                     clean::Word(ref x)
                             if "html_no_source" == x.as_slice() => {
                         cx.include_sources = false;
@@ -450,6 +459,7 @@ fn write_shared(cx: &Context,
     try!(write(cx.dst.join("jquery.js"),
                include_bin!("static/jquery-2.1.0.min.js")));
     try!(write(cx.dst.join("main.js"), include_bin!("static/main.js")));
+    try!(write(cx.dst.join("playpen.js"), include_bin!("static/playpen.js")));
     try!(write(cx.dst.join("main.css"), include_bin!("static/main.css")));
     try!(write(cx.dst.join("normalize.css"),
                include_bin!("static/normalize.css")));
@@ -2054,14 +2064,15 @@ impl<'a> fmt::Show for Source<'a> {
             try!(write!(fmt, "{0:1$u}\n", i, cols));
         }
         try!(write!(fmt, "
")); - try!(write!(fmt, "{}", highlight::highlight(s.as_slice(), None))); + try!(write!(fmt, "{}", highlight::highlight(s.as_slice(), None, None))); Ok(()) } } fn item_macro(w: &mut fmt::Formatter, it: &clean::Item, t: &clean::Macro) -> fmt::Result { - try!(w.write(highlight::highlight(t.source.as_slice(), Some("macro")).as_bytes())); + try!(w.write(highlight::highlight(t.source.as_slice(), Some("macro"), + None).as_bytes())); document(w, it) } diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index 7831f10ab9195..07dd1a6c173cc 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -156,7 +156,7 @@ nav.sub { padding: 0 10px; margin-bottom: 10px; } -.block h2 { +.block h2 { margin-top: 0; text-align: center; } @@ -396,6 +396,17 @@ pre.rust .doccomment { color: #4D4D4C; } pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; } pre.rust .lifetime { color: #B76514; } +.rusttest { display: none; } +pre.rust { position: relative; } +pre.rust a { transform: scaleX(-1); } +.test-arrow { + display: inline-block; + position: absolute; + top: 0; + right: 10px; + font-size: 150%; +} + .methods .section-header { /* Override parent class attributes. */ border-bottom: none !important; diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 440b829c80c4d..195028c85bfa9 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -678,7 +678,7 @@ window.register_implementors(window.pending_implementors); } - // See documentaiton in html/render.rs for what this is doing. + // See documentation in html/render.rs for what this is doing. var query = getQueryStringParams(); if (query['gotosrc']) { window.location = $('#src-' + query['gotosrc']).attr('href'); diff --git a/src/librustdoc/html/static/playpen.js b/src/librustdoc/html/static/playpen.js new file mode 100644 index 0000000000000..5d2fe9c216602 --- /dev/null +++ b/src/librustdoc/html/static/playpen.js @@ -0,0 +1,29 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*jslint browser: true, es5: true */ +/*globals $: true, rootPath: true */ + +(function() { + if (window.playgroundUrl) { + $('pre.rust').hover(function() { + var id = '#' + $(this).attr('id').replace('rendered', 'raw'); + var a = $('').text('⇱').attr('class', 'test-arrow'); + var code = $(id).text(); + a.attr('href', window.playgroundUrl + '?code=' + + encodeURIComponent(code)); + a.attr('target', '_blank'); + $(this).append(a); + }, function() { + $(this).find('a').remove(); + }); + } +}()); + diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index b3a0ade0624f3..9c0207ebe358d 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -126,7 +126,9 @@ pub fn opts() -> Vec { optmulti("", "markdown-after-content", "files to include inline between the content and of a rendered \ Markdown file", - "FILES") + "FILES"), + optopt("", "markdown-playground-url", + "URL to send code snippets to", "URL") ) } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 961c92940be81..3b6203ef668f7 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -16,6 +16,7 @@ use getopts; use testing; use html::escape::Escape; +use html::markdown; use html::markdown::{MarkdownWithToc, find_testable_code, reset_headers}; use test::Collector; @@ -84,6 +85,11 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches) -> int } let input_str = load_or_return!(input, 1, 2); + let playground = matches.opt_str("markdown-playground-url"); + if playground.is_some() { + markdown::playground_krate.replace(Some(None)); + } + let playground = playground.unwrap_or("".to_string()); let (in_header, before_content, after_content) = match (load_external_files(matches.opt_strs("markdown-in-header") @@ -148,6 +154,9 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches) -> int {before_content}

{title}

{text} + {after_content} "#, @@ -156,7 +165,9 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches) -> int in_header = in_header, before_content = before_content, text = MarkdownWithToc(text), - after_content = after_content); + after_content = after_content, + playground = playground, + ); match err { Err(e) => { @@ -173,7 +184,7 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches) -> int pub fn test(input: &str, libs: HashSet, mut test_args: Vec) -> int { let input_str = load_or_return!(input, 1, 2); - let mut collector = Collector::new(input.to_string(), libs, true, true); + let mut collector = Collector::new(input.to_string(), libs, true); find_testable_code(input_str.as_slice(), &mut collector); test_args.unshift("rustdoctest".to_string()); testing::test_main(test_args.as_slice(), collector.tests); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index ed53b2ac314a8..bc1da5b629e13 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -91,7 +91,6 @@ pub fn run(input: &str, let mut collector = Collector::new(krate.name.to_string(), libs, - false, false); collector.fold_crate(krate); @@ -103,8 +102,8 @@ pub fn run(input: &str, } fn runtest(test: &str, cratename: &str, libs: HashSet, should_fail: bool, - no_run: bool, loose_feature_gating: bool) { - let test = maketest(test, cratename, loose_feature_gating); + no_run: bool) { + let test = maketest(test, Some(cratename), true); let input = driver::StrInput(test.to_string()); let sessopts = config::Options { @@ -201,29 +200,31 @@ fn runtest(test: &str, cratename: &str, libs: HashSet, should_fail: bool, } } -fn maketest(s: &str, cratename: &str, loose_feature_gating: bool) -> String { - let mut prog = String::from_str(r" +pub fn maketest(s: &str, cratename: Option<&str>, lints: bool) -> String { + let mut prog = String::new(); + if lints { + prog.push_str(r" #![deny(warnings)] #![allow(unused_variable, dead_assignment, unused_mut, attribute_usage, dead_code)] "); - - if loose_feature_gating { - // FIXME #12773: avoid inserting these when the tutorial & manual - // etc. have been updated to not use them so prolifically. - prog.push_str("#![feature(macro_rules, globs, struct_variant, managed_boxes) ]\n"); } if !s.contains("extern crate") { - if s.contains(cratename) { - prog.push_str(format!("extern crate {};\n", - cratename).as_slice()); + match cratename { + Some(cratename) => { + if s.contains(cratename) { + prog.push_str(format!("extern crate {};\n", + cratename).as_slice()); + } + } + None => {} } } if s.contains("fn main") { prog.push_str(s); } else { - prog.push_str("fn main() {\n"); - prog.push_str(s); + prog.push_str("fn main() {\n "); + prog.push_str(s.replace("\n", "\n ").as_slice()); prog.push_str("\n}"); } @@ -238,13 +239,11 @@ pub struct Collector { use_headers: bool, current_header: Option, cratename: String, - - loose_feature_gating: bool } impl Collector { pub fn new(cratename: String, libs: HashSet, - use_headers: bool, loose_feature_gating: bool) -> Collector { + use_headers: bool) -> Collector { Collector { tests: Vec::new(), names: Vec::new(), @@ -253,8 +252,6 @@ impl Collector { use_headers: use_headers, current_header: None, cratename: cratename, - - loose_feature_gating: loose_feature_gating } } @@ -268,7 +265,6 @@ impl Collector { self.cnt += 1; let libs = self.libs.clone(); let cratename = self.cratename.to_string(); - let loose_feature_gating = self.loose_feature_gating; debug!("Creating test {}: {}", name, test); self.tests.push(testing::TestDescAndFn { desc: testing::TestDesc { @@ -281,8 +277,7 @@ impl Collector { cratename.as_slice(), libs, should_fail, - no_run, - loose_feature_gating); + no_run); }), }); } diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 904c7da4da2e9..08348c9633382 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -20,7 +20,8 @@ Core encoding and decoding interfaces. #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(macro_rules, managed_boxes, default_type_params, phase)] // test harness access diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 90d6677d61228..109832b7c4795 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -101,7 +101,8 @@ #![crate_type = "dylib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(macro_rules, globs, asm, managed_boxes, thread_local, link_args, linkage, default_type_params, phase, concat_idents, quad_precision_float)] diff --git a/src/libsync/lib.rs b/src/libsync/lib.rs index e0cc57a4967fe..fc4d5fec5f52a 100644 --- a/src/libsync/lib.rs +++ b/src/libsync/lib.rs @@ -18,7 +18,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(phase)] #![deny(deprecated_owned_vector)] diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index f2ae0c15860ab..cc813262576ad 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -45,7 +45,8 @@ #![crate_type = "dylib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(macro_rules, phase)] diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs index a478aa931d444..593af440c197c 100644 --- a/src/libtime/lib.rs +++ b/src/libtime/lib.rs @@ -17,7 +17,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(phase)] #![deny(deprecated_owned_vector)] diff --git a/src/liburl/lib.rs b/src/liburl/lib.rs index 3511b554aea89..0c4db3aa766b6 100644 --- a/src/liburl/lib.rs +++ b/src/liburl/lib.rs @@ -16,7 +16,8 @@ #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(default_type_params)] use std::collections::HashMap; diff --git a/src/libuuid/lib.rs b/src/libuuid/lib.rs index 68c545802adb7..2459a7fc273a9 100644 --- a/src/libuuid/lib.rs +++ b/src/libuuid/lib.rs @@ -60,7 +60,8 @@ Examples of string representations: #![license = "MIT/ASL2"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/")] + html_root_url = "http://doc.rust-lang.org/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(default_type_params)]