@@ -1087,7 +1087,8 @@ impl<'a> SourceCollector<'a> {
10871087 href. push_str ( component) ;
10881088 href. push ( '/' ) ;
10891089 } ) ;
1090- let mut fname = p. file_name ( ) . expect ( "source has no filename" )
1090+ let mut fname = p. file_name ( )
1091+ . expect ( "source has no filename" )
10911092 . to_os_string ( ) ;
10921093 fname. push ( ".html" ) ;
10931094 cur. push ( & fname) ;
@@ -1373,6 +1374,135 @@ impl<'a> Cache {
13731374 }
13741375}
13751376
1377+ #[ derive( Debug , Eq , PartialEq , Hash ) ]
1378+ struct ItemEntry {
1379+ url : String ,
1380+ name : String ,
1381+ }
1382+
1383+ impl ItemEntry {
1384+ fn new ( mut url : String , name : String ) -> ItemEntry {
1385+ while url. starts_with ( '/' ) {
1386+ url. remove ( 0 ) ;
1387+ }
1388+ ItemEntry {
1389+ url,
1390+ name,
1391+ }
1392+ }
1393+ }
1394+
1395+ impl fmt:: Display for ItemEntry {
1396+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1397+ write ! ( f, "<a href='{}'>{}</a>" , self . url, Escape ( & self . name) )
1398+ }
1399+ }
1400+
1401+ impl PartialOrd for ItemEntry {
1402+ fn partial_cmp ( & self , other : & ItemEntry ) -> Option < :: std:: cmp:: Ordering > {
1403+ Some ( self . cmp ( other) )
1404+ }
1405+ }
1406+
1407+ impl Ord for ItemEntry {
1408+ fn cmp ( & self , other : & ItemEntry ) -> :: std:: cmp:: Ordering {
1409+ self . name . cmp ( & other. name )
1410+ }
1411+ }
1412+
1413+ #[ derive( Debug ) ]
1414+ struct AllTypes {
1415+ structs : HashSet < ItemEntry > ,
1416+ enums : HashSet < ItemEntry > ,
1417+ unions : HashSet < ItemEntry > ,
1418+ primitives : HashSet < ItemEntry > ,
1419+ traits : HashSet < ItemEntry > ,
1420+ macros : HashSet < ItemEntry > ,
1421+ functions : HashSet < ItemEntry > ,
1422+ typedefs : HashSet < ItemEntry > ,
1423+ statics : HashSet < ItemEntry > ,
1424+ constants : HashSet < ItemEntry > ,
1425+ }
1426+
1427+ impl AllTypes {
1428+ fn new ( ) -> AllTypes {
1429+ AllTypes {
1430+ structs : HashSet :: with_capacity ( 100 ) ,
1431+ enums : HashSet :: with_capacity ( 100 ) ,
1432+ unions : HashSet :: with_capacity ( 100 ) ,
1433+ primitives : HashSet :: with_capacity ( 26 ) ,
1434+ traits : HashSet :: with_capacity ( 100 ) ,
1435+ macros : HashSet :: with_capacity ( 100 ) ,
1436+ functions : HashSet :: with_capacity ( 100 ) ,
1437+ typedefs : HashSet :: with_capacity ( 100 ) ,
1438+ statics : HashSet :: with_capacity ( 100 ) ,
1439+ constants : HashSet :: with_capacity ( 100 ) ,
1440+ }
1441+ }
1442+
1443+ fn append ( & mut self , item_name : String , item_type : & ItemType ) {
1444+ let mut url: Vec < _ > = item_name. split ( "::" ) . skip ( 1 ) . collect ( ) ;
1445+ if let Some ( name) = url. pop ( ) {
1446+ let new_url = format ! ( "{}/{}.{}.html" , url. join( "/" ) , item_type, name) ;
1447+ url. push ( name) ;
1448+ let name = url. join ( "::" ) ;
1449+ match * item_type {
1450+ ItemType :: Struct => self . structs . insert ( ItemEntry :: new ( new_url, name) ) ,
1451+ ItemType :: Enum => self . enums . insert ( ItemEntry :: new ( new_url, name) ) ,
1452+ ItemType :: Union => self . unions . insert ( ItemEntry :: new ( new_url, name) ) ,
1453+ ItemType :: Primitive => self . primitives . insert ( ItemEntry :: new ( new_url, name) ) ,
1454+ ItemType :: Trait => self . traits . insert ( ItemEntry :: new ( new_url, name) ) ,
1455+ ItemType :: Macro => self . macros . insert ( ItemEntry :: new ( new_url, name) ) ,
1456+ ItemType :: Function => self . functions . insert ( ItemEntry :: new ( new_url, name) ) ,
1457+ ItemType :: Typedef => self . typedefs . insert ( ItemEntry :: new ( new_url, name) ) ,
1458+ ItemType :: Static => self . statics . insert ( ItemEntry :: new ( new_url, name) ) ,
1459+ ItemType :: Constant => self . constants . insert ( ItemEntry :: new ( new_url, name) ) ,
1460+ _ => true ,
1461+ } ;
1462+ }
1463+ }
1464+ }
1465+
1466+ fn print_entries ( f : & mut fmt:: Formatter , e : & HashSet < ItemEntry > , title : & str ,
1467+ class : & str ) -> fmt:: Result {
1468+ if !e. is_empty ( ) {
1469+ let mut e: Vec < & ItemEntry > = e. iter ( ) . collect ( ) ;
1470+ e. sort ( ) ;
1471+ write ! ( f, "<h3 id='{}'>{}</h3><ul class='{} docblock'>{}</ul>" ,
1472+ title,
1473+ Escape ( title) ,
1474+ class,
1475+ e. iter( ) . map( |s| format!( "<li>{}</li>" , s) ) . collect:: <String >( ) ) ?;
1476+ }
1477+ Ok ( ( ) )
1478+ }
1479+
1480+ impl fmt:: Display for AllTypes {
1481+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1482+ write ! ( f,
1483+ "<h1 class='fqn'>\
1484+ <span class='in-band'>List of all items</span>\
1485+ <span class='out-of-band'>\
1486+ <span id='render-detail'>\
1487+ <a id=\" toggle-all-docs\" href=\" javascript:void(0)\" title=\" collapse all docs\" >\
1488+ [<span class='inner'>−</span>]\
1489+ </a>\
1490+ </span>
1491+ </span>
1492+ </h1>" ) ?;
1493+ print_entries ( f, & self . structs , "Structs" , "structs" ) ?;
1494+ print_entries ( f, & self . enums , "Enums" , "enums" ) ?;
1495+ print_entries ( f, & self . unions , "Unions" , "unions" ) ?;
1496+ print_entries ( f, & self . primitives , "Primitives" , "primitives" ) ?;
1497+ print_entries ( f, & self . traits , "Traits" , "traits" ) ?;
1498+ print_entries ( f, & self . macros , "Macros" , "macros" ) ?;
1499+ print_entries ( f, & self . functions , "Functions" , "functions" ) ?;
1500+ print_entries ( f, & self . typedefs , "Typedefs" , "typedefs" ) ?;
1501+ print_entries ( f, & self . statics , "Statics" , "statics" ) ?;
1502+ print_entries ( f, & self . constants , "Constants" , "constants" )
1503+ }
1504+ }
1505+
13761506impl Context {
13771507 /// String representation of how to get back to the root path of the 'doc/'
13781508 /// folder in terms of a relative URL.
@@ -1414,16 +1544,52 @@ impl Context {
14141544 Some ( i) => i,
14151545 None => return Ok ( ( ) ) ,
14161546 } ;
1547+ let final_file = self . dst . join ( & krate. name )
1548+ . join ( "all.html" ) ;
1549+ let crate_name = krate. name . clone ( ) ;
14171550 item. name = Some ( krate. name ) ;
14181551
1419- // Render the crate documentation
1420- let mut work = vec ! [ ( self , item) ] ;
1552+ let mut all = AllTypes :: new ( ) ;
14211553
1422- while let Some ( ( mut cx, item) ) = work. pop ( ) {
1423- cx. item ( item, |cx, item| {
1424- work. push ( ( cx. clone ( ) , item) )
1425- } ) ?
1554+ {
1555+ // Render the crate documentation
1556+ let mut work = vec ! [ ( self . clone( ) , item) ] ;
1557+
1558+ while let Some ( ( mut cx, item) ) = work. pop ( ) {
1559+ cx. item ( item, & mut all, |cx, item| {
1560+ work. push ( ( cx. clone ( ) , item) )
1561+ } ) ?
1562+ }
14261563 }
1564+
1565+ let mut w = BufWriter :: new ( try_err ! ( File :: create( & final_file) , & final_file) ) ;
1566+ let mut root_path = self . dst . to_str ( ) . expect ( "invalid path" ) . to_owned ( ) ;
1567+ if !root_path. ends_with ( '/' ) {
1568+ root_path. push ( '/' ) ;
1569+ }
1570+ let page = layout:: Page {
1571+ title : "List of all items in this crate" ,
1572+ css_class : "mod" ,
1573+ root_path : "../" ,
1574+ description : "List of all items in this crate" ,
1575+ keywords : BASIC_KEYWORDS ,
1576+ resource_suffix : & self . shared . resource_suffix ,
1577+ } ;
1578+ let sidebar = if let Some ( ref version) = cache ( ) . crate_version {
1579+ format ! ( "<p class='location'>Crate {}</p>\
1580+ <div class='block version'>\
1581+ <p>Version {}</p>\
1582+ </div>\
1583+ <a id='all-types' href='index.html'><p>Back to index</p></a>",
1584+ crate_name, version)
1585+ } else {
1586+ String :: new ( )
1587+ } ;
1588+ try_err ! ( layout:: render( & mut w, & self . shared. layout,
1589+ & page, & sidebar, & all,
1590+ self . shared. css_file_extension. is_some( ) ,
1591+ & self . shared. themes) ,
1592+ & final_file) ;
14271593 Ok ( ( ) )
14281594 }
14291595
@@ -1496,8 +1662,8 @@ impl Context {
14961662 /// all sub-items which need to be rendered.
14971663 ///
14981664 /// The rendering driver uses this closure to queue up more work.
1499- fn item < F > ( & mut self , item : clean:: Item , mut f : F ) -> Result < ( ) , Error > where
1500- F : FnMut ( & mut Context , clean:: Item ) ,
1665+ fn item < F > ( & mut self , item : clean:: Item , all : & mut AllTypes , mut f : F ) -> Result < ( ) , Error >
1666+ where F : FnMut ( & mut Context , clean:: Item ) ,
15011667 {
15021668 // Stripped modules survive the rustdoc passes (i.e. `strip-private`)
15031669 // if they contain impls for public types. These modules can also
@@ -1544,7 +1710,7 @@ impl Context {
15441710 }
15451711
15461712 for item in m. items {
1547- f ( this, item) ;
1713+ f ( this, item) ;
15481714 }
15491715
15501716 Ok ( ( ) )
@@ -1562,13 +1728,14 @@ impl Context {
15621728 let mut dst = try_err ! ( File :: create( & joint_dst) , & joint_dst) ;
15631729 try_err ! ( dst. write_all( & buf) , & joint_dst) ;
15641730
1731+ all. append ( full_path ( self , & item) , & item_type) ;
15651732 // Redirect from a sane URL using the namespace to Rustdoc's
15661733 // URL for the page.
15671734 let redir_name = format ! ( "{}.{}.html" , name, item_type. name_space( ) ) ;
15681735 let redir_dst = self . dst . join ( redir_name) ;
15691736 if let Ok ( redirect_out) = OpenOptions :: new ( ) . create_new ( true )
1570- . write ( true )
1571- . open ( & redir_dst) {
1737+ . write ( true )
1738+ . open ( & redir_dst) {
15721739 let mut redirect_out = BufWriter :: new ( redirect_out) ;
15731740 try_err ! ( layout:: redirect( & mut redirect_out, file_name) , & redir_dst) ;
15741741 }
@@ -1730,11 +1897,12 @@ impl<'a> fmt::Display for Item<'a> {
17301897 version) ?;
17311898 }
17321899 write ! ( fmt,
1733- r##"<span id='render-detail'>
1734- <a id="toggle-all-docs" href="javascript:void(0)" title="collapse all docs">
1735- [<span class='inner'>−</span>]
1736- </a>
1737- </span>"## ) ?;
1900+ "<span id='render-detail'>\
1901+ <a id=\" toggle-all-docs\" href=\" javascript:void(0)\" \
1902+ title=\" collapse all docs\" >\
1903+ [<span class='inner'>−</span>]\
1904+ </a>\
1905+ </span>") ?;
17381906
17391907 // Write `src` tag
17401908 //
@@ -3567,33 +3735,34 @@ impl<'a> fmt::Display for Sidebar<'a> {
35673735
35683736 if it. is_struct ( ) || it. is_trait ( ) || it. is_primitive ( ) || it. is_union ( )
35693737 || it. is_enum ( ) || it. is_mod ( ) || it. is_typedef ( ) {
3570- write ! ( fmt, "<p class='location'>" ) ?;
3571- match it. inner {
3572- clean:: StructItem ( ..) => write ! ( fmt, "Struct " ) ?,
3573- clean:: TraitItem ( ..) => write ! ( fmt, "Trait " ) ?,
3574- clean:: PrimitiveItem ( ..) => write ! ( fmt, "Primitive Type " ) ?,
3575- clean:: UnionItem ( ..) => write ! ( fmt, "Union " ) ?,
3576- clean:: EnumItem ( ..) => write ! ( fmt, "Enum " ) ?,
3577- clean:: TypedefItem ( ..) => write ! ( fmt, "Type Definition " ) ?,
3578- clean:: ForeignTypeItem => write ! ( fmt, "Foreign Type " ) ?,
3579- clean:: ModuleItem ( ..) => if it. is_crate ( ) {
3580- write ! ( fmt, "Crate " ) ?;
3581- } else {
3582- write ! ( fmt, "Module " ) ?;
3738+ write ! ( fmt, "<p class='location'>{}{}</p>" ,
3739+ match it. inner {
3740+ clean:: StructItem ( ..) => "Struct " ,
3741+ clean:: TraitItem ( ..) => "Trait " ,
3742+ clean:: PrimitiveItem ( ..) => "Primitive Type " ,
3743+ clean:: UnionItem ( ..) => "Union " ,
3744+ clean:: EnumItem ( ..) => "Enum " ,
3745+ clean:: TypedefItem ( ..) => "Type Definition " ,
3746+ clean:: ForeignTypeItem => "Foreign Type " ,
3747+ clean:: ModuleItem ( ..) => if it. is_crate( ) {
3748+ "Crate "
3749+ } else {
3750+ "Module "
3751+ } ,
3752+ _ => "" ,
35833753 } ,
3584- _ => ( ) ,
3585- }
3586- write ! ( fmt, "{}" , it. name. as_ref( ) . unwrap( ) ) ?;
3587- write ! ( fmt, "</p>" ) ?;
3754+ it. name. as_ref( ) . unwrap( ) ) ?;
35883755 }
35893756
35903757 if it. is_crate ( ) {
35913758 if let Some ( ref version) = cache ( ) . crate_version {
35923759 write ! ( fmt,
35933760 "<div class='block version'>\
35943761 <p>Version {}</p>\
3595- </div>",
3596- version) ?;
3762+ </div>
3763+ <a id='all-types' href='all.html'><p>See all {}'s items</p></a>" ,
3764+ version,
3765+ it. name. as_ref( ) . unwrap( ) ) ?;
35973766 }
35983767 }
35993768
0 commit comments