summary refs log tree commit diff stats
path: root/doc
Commit message (Expand)AuthorAgeFilesLines
* doc/colorschemes: ugh, its no logical but bitwise OR!hut2010-03-171-1/+1
* incremented verison number v1.0.4hut2010-03-121-2/+2
* standardized formatting of headings in doc/hut2010-03-122-13/+31
* added doc/uml.txthut2010-03-121-0/+5
* updated pydochut2010-03-1217-161/+33
* updated pydochut2010-03-1270-3946/+816
* added two new colorschemes using 88 colorshut2010-03-121-0/+23
* added documentation on how colorschemes workhut2010-03-121-0/+91
* added symlink: doc/help => ranger/helphut2010-02-281-0/+1
* incremented version number and updated pydoc html files v1.0.3hut2010-02-1675-1972/+1415
* doc/cd-after-exit: updatedhut2010-02-141-21/+15
* doc/pick.sh: corrected commit orderhut2010-02-091-1/+1
* doc: what breaks cd-after-exit support in zshhut2010-02-091-0/+2
* pick.sh: added -m to checkout commadshut2010-02-051-3/+3
* pick.sh: added variables for easier customizationhut2010-02-041-7/+8
* added doc/pick.shhut2010-02-041-0/+24
* updated dochut2010-01-211-4/+20
* 1.0.2! v1.0.2hut2010-01-1430-84/+116
* updated pydoc documentationhut2010-01-1361-846/+795
* todo: added more info on bug #31hut2010-01-091-0/+5
* random cleanups and fixeshut2010-01-071-5/+6
* new minor version v1.0.1hut2010-01-022-4/+4
* updated pydoc documentationhut2010-01-0248-788/+3167
* notify: merged into statusbar, allow to view the log in the pagerhut2010-01-013-35/+2
* cleanupshut2009-12-311-1/+5
* rename filelist(container) to browsercolumn/browserviewhut2009-12-313-38/+76
* updated uml projecthut2009-12-305-73/+215
* shorten comment in ranger.pyhut2009-12-261-0/+4
* moved /uml to /doc/umlhut2009-12-2514-0/+2180
* Explained cd-after-exit featurehut2009-12-251-0/+132
* moved pydoc pages to doc/pydochut2009-12-2565-0/+0
* updated pydoc pageshut2009-12-2565-0/+10505
vector; #define SIZE(X) (assert((X).size() < (1LL<<(sizeof(int)*8-2))), static_cast<int>((X).size())) #include<string> using std::string; #include<iostream> using std::cin; using std::cout; using std::cerr; #include<sstream> using std::istringstream; bool starts_with(const string& s, const string& pat) { string::const_iterator a=s.begin(), b=pat.begin(); for (/*nada*/; a!=s.end() && b!=pat.end(); ++a, ++b) if (*a != *b) return false; return b == pat.end(); } // input void read_body(string name, string definition_line, map<string, vector<string> >& segment) { // last definition wins; this only matters for the 'Entry' label in the code segment segment[name] = vector<string>(); segment[name].push_back(definition_line); while (!cin.eof()) { if (cin.peek() != ' ' && cin.peek() != '$') break; // assumes: no whitespace but spaces; internal labels start with '$' string line; getline(cin, line); segment[name].push_back(line); } } void read_lines(string segment_header, map<string, vector<string> >& segment) { // first segment header wins if (segment.empty()) segment["=="].push_back(segment_header); // '==' is a special key containing the segment header while (!cin.eof()) { if (cin.peek() == '=') break; // assumes: no line can start with '=' except a segment header assert(cin.peek() != ' '); // assumes: no whitespace but spaces string line; getline(cin, line); istringstream lstream(line); string name; getline(lstream, name, ' '); assert(name[SIZE(name)-1] == ':'); name.erase(--name.end()); read_body(name, line, segment); } } void read_lines(map<string, vector<string> >& code, map<string, vector<string> >& data) { while (!cin.eof()) { string line; getline(cin, line); assert(starts_with(line, "== ")); map<string, vector<string> >& curr = (line.substr(3, 4) == "code") ? code : data; // HACK: doesn't support segments except 'code' and 'data' read_lines(line, curr); } } // treeshake bool any_line_matches(string pat, const vector<string>& lines) { for (int i = 0; i < SIZE(lines); ++i) if (lines.at(i).find(pat) != string::npos) // conservative: confused by word boundaries, comments and string literals return true; return false; } bool is_dead(string key, const map<string, vector<string> >& code, const map<string, vector<string> >& data) { if (key == "Entry") return false; if (key == "==") return false; for (map<string, vector<string> >::const_iterator p = code.begin(); p != code.end(); ++p) { if (p->first == key) continue; if (any_line_matches(key, p->second)) return false; } for (map<string, vector<string> >::const_iterator p = data.begin(); p != data.end(); ++p) { if (p->first == key) continue; if (any_line_matches(key, p->second)) return false; } return true; } void treeshake(map<string, vector<string> >& code, map<string, vector<string> >& data) { for (map<string, vector<string> >::iterator p = code.begin(); p != code.end(); ++p) { if (is_dead(p->first, code, data)) { //? cerr << " erasing " << p->first << '\n'; code.erase(p); return; } } for (map<string, vector<string> >::iterator p = data.begin(); p != data.end(); ++p) { if (is_dead(p->first, code, data)) { //? cerr << " erasing " << p->first << '\n'; data.erase(p); return; } } } // output void dump(const map<string, vector<string> > definitions) { // nothing special needed for segment headers, since '=' precedes all alphabet in ASCII for (map<string, vector<string> >::const_iterator p = definitions.begin(); p != definitions.end(); ++p) { const vector<string>& lines = p->second; for (int i = 0; i < SIZE(lines); ++i) cout << lines[i] << '\n'; } } int main() { map<string, vector<string> > code, data; read_lines(code, data); for (int iter = 0; ; ++iter) { //? cerr << "iter: " << iter << '\n'; int old_csize = SIZE(code), old_dsize = SIZE(data); treeshake(code, data); if (SIZE(code) == old_csize && SIZE(data) == old_dsize) break; } dump(code); dump(data); return 0; }