#!/usr/bin/env ruby
require 'open3'
require 'fileutils'
-require 'webrick'
require 'redcarpet'
+require 'erb'
# TODO:
+# * Implement search functionality on sitemap
+# * break javascript out to separate files
+# * Add id linking with title and custom text
+# * Add searchable, filterable z-index
+# * Add tagging and tag filtering for search
# * Add page attachment mechanism
# * Add save shortcut
-# * Add a create method
-# * Add a delete method
-# * Add a move/rename method
# * Add git revisioning for pages
SITE_TITLE = "Michael D. Lowis"
(() => {
const keys = {
"e": () => { window.location = window.location + "?edit=true"; },
- "s": () => { window.location = "/sitemap.html"; }
+ "i": () => { window.location = "/sitemap.html"; },
+ "n": () => { window.location = "/new"; }
};
- document.onkeydown = (ev) => (!!keys[ev.key] ? (keys[ev.key])(ev) : true);
+ document.onkeyup = (ev) => (!!keys[ev.key] ? (keys[ev.key])(ev) : true);
})();
</script>
eos
+SEARCH_SCRIPT = <<-eos
+ <script>
+ (()=>{
+ let tags = [];
+
+ const filterPages = (allitems) => {
+ const value = search.value.toLowerCase();
+ for (var i = 0; i < pages.children.length; i++) {
+ const child = pages.children[i];
+ if (child.style.display !== "none" || allitems) {
+ if (!child.text) {
+ child.text = child.innerText.toLowerCase();
+ }
+ if (!child.tagmap) {
+ child.tagmap = {};
+ const tags = (child.children[0].dataset.tags || "").split(" ");
+ tags.forEach((c)=>(child.tagmap[c] = true));
+ }
+ const titleMatch = (child.text.toLowerCase().indexOf( value ) !== -1);
+ const tagsMatch = (tags.every((t)=>(child.tagmap[t])));
+ console.log(tagsMatch);
+ child.style.display = ((titleMatch && tagsMatch) ? "list-item" : "none");
+ }
+ }
+ };
+
+ search.onkeyup = (ev) => {
+ filterPages(ev.key === "Backspace");
+ ev.stopPropagation();
+ }
+
+ const oninput = (ev)=>{
+ if ((filterTags.value !== "") && (ev.inputType === "insertReplacementText" || ev.key === "Enter")) {
+ const tagName = filterTags.value.toLowerCase();
+ tags.push(tagName);
+ const link = document.createElement('a');
+ link.href = "#";
+ link.style.margin = "0 5px 0 5px";
+ link.onclick = ()=>{
+ tags = tags.filter((e)=>(e != tagName));
+ link.remove();
+ filterPages(true);
+ };
+ link.appendChild(document.createTextNode("[X] " + filterTags.value.toLowerCase()));
+ activeTags.appendChild(link);
+ filterTags.value = "";
+ filterPages(false);
+ }
+ }
+
+ filterTags.oninput = oninput;
+ filterTags.onkeyup = oninput;
+ })(); </script>
+eos
def html_path(src)
src.sub(/\.([^.]*)$/, '.html').sub(/^#{PAGES_DIR}/, HTML_DIR)
(PAGES_DIR + path).sub(/^\/html\//,'').sub(/\.html$/, ".md")
end
+def web_path(path)
+ "/" + path.sub(/^(#{PAGES_DIR}|#{HTML_DIR})/, '').sub(/\.md$/,'.html')
+end
+
class Page
def initialize(src)
@markdown = (File.exist?(src) ? File.read(src) : "")
@page_path = src.gsub(%r{/+},'/')
@gendate = Time.now.to_s
@page_title = (@markdown.match(/#\s*(.*)$/) || [])[1]
+ $db[:pages][@page_path] ||= {}
+ $db[:pages][@page_path][:path] = @page_path
+ $db[:pages][@page_path][:title] = @page_title
+ $db[:pages][@page_path][:tags] = []
end
def generate_graph(graph)
"<p>"+data.sub(/<\?[^?]*\?>/,'')+"</p>"
end
- def parse_graphs
+ def parse_extras
graph = nil
text = []
@markdown.split("\n").each do |ln|
graph = nil
elsif graph
graph << ln
+ elsif ln =~ /^@tags(.*)$/ then
+ $db[:pages][@page_path][:tags] += ($1 || "").split
else
+ ln.scan(/[a-zA-Z_][a-zA-Z0-9_]*/).map{|w| w.downcase }.each do |w|
+ $db[:words][w] ||= ($db[:nextw] += 1)
+ $db[:pages][@page_path][:words] ||= {}
+ $db[:pages][@page_path][:words][$db[:words][w]] = 1
+ end
text << ln
end
end
def view()
if not @article
- @markdown = parse_graphs()
+ @markdown = parse_extras()
@article = $markdown.render(@markdown)
end
ERB.new(File.read(VIEW_TEMPLATE)).result(binding)
end
def gensitemap()
- links = []
- Dir.glob("#{PAGES_DIR}/**/*.md").each do |f|
- path = f.sub(/\.([^.]*)$/, '.html').sub(/^#{PAGES_DIR}/, "")
- title = (File.read(f).match(/#\s*(.*)$/) || [])[1] || path
- links << { path: path, title: title }
- end
File.open("#{PAGES_DIR}/sitemap.md", "w") do |f|
f.puts "<!-- WARNING: This page autogenerated. Manual changes will be lost -->"
f.puts "# Sitemap\n\n"
- links.sort_by{|h| h[:title] }.each {|l| f.puts "[#{l[:title]}](#{l[:path]})<br/>" }
+ f.puts "\n\n<p><label>Search:</label><input id=\"search\" type=\"text\"/></p>\n\n"
+ f.puts "<ul id=\"pages\">"
+ $db[:pages].values.sort_by{|h| h[:title] }.each do |p|
+ f.puts "<li><a href=\"#{web_path(p[:path])}\" tags=\"#{p[:tags].join(" ")}\">#{p[:title]}</a></li>"
+ end
+ f.puts "</ul>"
+ f.puts "\n\n<p>#{SEARCH_SCRIPT}</p>"
end
end
end
gensitemap()
html = html.sub("<!--EDIT-->",
- "<a class='navLink shrink' href='#{path}?edit=true'>[edit]</a>")
+ "<a href='new'>[new]</a>" +
+ "<a href='#{path}?edit=true'>[edit]</a>")
html.sub("<!--EDIT_SCRIPT-->", EDIT_SCRIPT)
end
def do_post(req, res, path)
page_path = page_path(path)
FileUtils.mkdir_p(File.dirname(page_path))
- markup = req.query["markup"].gsub("\r\n","\n").gsub(/</,"<").gsub(/>/,">")
+ markup = req.query["markup"].gsub(/<br\/?>/,"\n").gsub("\r\n","\n").gsub(/</,"<").gsub(/>/,">")
File.open(page_path, "wb") {|f| f.write(markup) }
res.status = 302
res["Location"] = req.path
end
def do_get(req, res, path)
- if path.end_with?(".html")
+ if path == "/new"
+ res.status = 302
+ res["Location"] = "/#{Time.now.strftime("%Y%m%d%k%M%S")}.html" if path == "/new"
+ elsif path.end_with?(".html")
page_path = page_path(path)
+ puts path
if (req.query["edit"] == "true") || (not File.exist?(page_path))
do_edit(req, res, path, page_path)
else
#-------------------------------------------------------------------------------
+$db = { pages: {}, words: {}, nextw: 0 }
$plantuml_in, $plantuml_out, _ = Open3.popen2(PLANTUML_CMD)
$markdown = Redcarpet::Markdown.new(
genallpages()
if ARGV.length > 0 then
+ require 'webrick'
$server = WEBrick::HTTPServer.new(
:Port => SERVER_PORT,
:SSLEnable => false,
$server.mount_proc '/' do |req, res|
rqtype = req.request_method
+ puts req.path
path = (req.path.end_with?("/") ? req.path + "index.html" : req.path)
if rqtype == "GET"
do_get(req, res, path)
end
end
- trap 'INT' do
- $server.shutdown
- # genallpages()
- end
+ trap 'INT' do $server.shutdown end
$server.start
end
+
+#pp $db
\ No newline at end of file
}
h1, h2, h3, h4, h5, h6 {
- margin: 1.5em 0em 0rem 0em;
+ margin: 1.5em 0em 0em 0em;
font-weight: 100;
}
h1 { font-size: 2.00em; }
padding: 0.5em 1em 0.5em 1em;
}
- .headerLink, .navLink {
+ header a {
color: #222222;
text-decoration: none;
- }
-
- .headerLink {
font-size: 1.5rem;
margin-left: 1rem;
+ flex-grow: 1;
}
- .navLink {
- font-size: 1rem;
- margin-right: 1rem;
- }
-
- .box {
- width: 100%;
+ nav, header {
display: flex;
flex-wrap: wrap;
}
- .grow { flex-grow: 1; }
- .shrink { flex-shrink: 1; }
+
+ nav a {
+ font-size: 1rem;
+ margin: 0 1rem 0 0;
+ flex-shrink: 1;
+ }
</style>
</head>
<body>
- <div class="header">
- <hr/>
- <div class="box">
- <a class="headerLink grow" href="/index.html">
- <%= @site_title %>
- </a>
- <a class="navLink shrink" href='/index.html'>home</a>
- <a class="navLink shrink" href='/projs/index.html'>projects</a>
- <a class="navLink shrink" href='/notes/index.html'>notes</a>
- <a class="navLink shrink" href='/sitemap.html'>sitemap</a>
+ <hr/>
+ <header>
+ <a href="/index.html"><%= @site_title %></a>
+ <nav>
+ <a href='/index.html'>home</a>
+ <a href='/projs/index.html'>projects</a>
+ <a href='/notes/index.html'>notes</a>
+ <a href='/sitemap.html'>sitemap</a>
<!--EDIT-->
- </div>
- <hr/>
- </div>
+ </nav>
+ </header>
- <article>
+ <hr/>
+ <article id="article">
<%= @article %>
</article>
- <div class="footer">
- <hr style="margin-top: 2em"/>
+ <hr style="margin-top: 2em"/>
+ <footer>
<div style="text-align: center">
<%= @gendate %>
</div>
- </div>
+ </footer>
<!--EDIT_SCRIPT-->
</body>
</html>
--- /dev/null
+@tags todo
+
+# Todo List
+
+## Now
+### Release Plugin
+* Fix links on release report
+* Fix up variant handling approach
+* Add support for reports generated by the assembly build
+
+### Miscellaneous
+* Build for Andrew (FCA TT)
+* Build for Ryan (AR0233)
+* release plugin
+* review feedback
+* broken builds
+
+## Soon
+* Allen's review write-up
+* Get a dongle and DiVa setup for Randy
+
+## Later
+* Asciidoc documentation for CVP
+* Update SerDes confluence page
+
+## Follow-Up
+* Corporate Gen 2 Backlight issue on startup
+* AR0233 Development (Will)
+
--- /dev/null
+@tags data-structures trees tries associative-array
+
+# Trie
+A type of tree structure designed for mapping a set of keys to associated values. Each level of the tree is indexed by a character in the key to determine the next node to look at. The bitwise variant of this structure uses the bits of an integer value to index into the structure and retrieve the corresponding data.
+
+## Further Reading
+* [Trie](https://en.wikipedia.org/wiki/Trie)
+* [Radix Tree](https://en.wikipedia.org/wiki/Radix_tree)
+* [Hash Array Mapped Trie](https://en.wikipedia.org/wiki/Hash_array_mapped_trie)
+* https://www.techiedelight.com/trie-implementation-insert-search-delete/
+* http://www.mathcs.emory.edu/~cheung/Courses/323/Syllabus/Text/trie01.html
+* https://github.com/panosalbanis/bitwise-trie/blob/master/trie.c
+* http://www.cs.yale.edu/homes/aspnes/pinewiki/RadixSearch.html
+@tags c programming style-guide
+
# C Programming Guidelines
This is a suggested set of guidelines to follow when writing C code. It is based on my own experience as well as the influential "The Power of 10: Rules for Developing Safety-Critical Code".
+@tags erlang language programming
+
# Erlang
**Type System:** Dynamically typed<br/>
**Memory Management:** Garbage Collected (Automatic)<br/>
+@tags forth language programming
+
# Forth
**Type System:** None<br/>
**Memory Management:** Manual<br/>
+@tags game-dev programming
+
# Game Programming
* https://github.com/a1studmuffin/SpaceshipGenerator
+* https://github.com/eduard-permyakov/permafrost-engine
+
+@tags note-index
+
# Notes
This section of the site is constructed as an informal wiki (using [awiki](https://git.mdlowis.com/?p=projs/awiki.git;a=summary)). As such, it is a chaotic mess of notes, musings, and useful links. Enter at your own risk...
* [Programming Languages](proglangs.html)
* [C Programming Rules](c_style.html)
* [Game Programming](game_prog.html)
+* [Linux Programming](linux.html)
+* [Web Development](webdev.html)
## Writing
* [Article Ideas](article_ideas.html)
## Miscellaneous
* [Cube Algorithms](misc/cube_alogrithms.html)
-* [Recipes](recipes.html)
+* [Recipes](recipes/)
* [FPGA Development](misc/fpga_dev.html)
* [Open Source Programs](misc/open_source.html)
* [Zettelkasten](misc/zettelkasten.html)
--- /dev/null
+@tags linux programming
+
+# Linux Programming
+* [Writing to the framebuffer](http://seenaburns.com/2018/04/04/writing-to-the-framebuffer/)
+* https://news.ycombinator.com/item?id=23391380
+* https://github.com/oasislinux/oasis
+* https://nixos.org/learn.html
+@tags lua programming language
+
# Lua
## References
https://www.lua.org/doc/jucs05.pdf
+@tags rubix rubix-cube cube-algorithms
+
# Cube Algorithms
## Orient Corners
+@tags fpga
+
# FPGA Development
## Free Books
* [Quick Start Guide to VHDL](https://link.springer.com/book/10.1007/978-3-030-04516-6)
-* [Introduction to Logic Circuits & Logic Design with VHDL](https://link.springer.com/book/10.1007/978-3-030-12489-2)
+* [Introduction to Logic Circuits & Logic Design with VHDL](https://link.springer.com/book/10.1007/978-3-030-12489-2)
+@tags note-index open-source
+
# Open Source Programs
* [Pick](https://github.com/mptre/pick) - Fuzzy picker, inspiration for the fuzzy picker in tide
* [Nushell](https://www.nushell.sh/book/en/table_of_contents.html) - interesting new command shell with piping of data and metadata
* [ES Shell](https://github.com/wryun/es-shell) - An extensible shell with higher order functions
+* [oksh](https://github.com/ibara/oksh) - Portable OpenBSD ksh
+* [choose](https://github.com/theryangeary/choose) - Alternative to cut or awk for picking fields out of a text stream.
+@tags zettelkasten
+
# Zettelkasten
-An interesting approach to note taking that has similarities to a wiki. Should investigate making awiki support some of the ideas here:
+An interesting approach to note taking that has similarities to a wiki. Originally implemented using numbered index cards. Cards can be cross referenced and can link to one another by id. Each card covers one topic in a manner such that the card can be read and is useful standalone (The cards are atomic). Each card has a defined home in the catalog (determined by ID) thus making it easy to perform cross referencing and find cards later.
+
+In digital form, each note is typically given a unique ID based on the date and time it was created. This ID is then used to link notes together and build topical trees. In addition, notes can be "tagged" to indicate related topics or otherwise categorize the note. These tags can then be used to find the notes later.
+
+Should investigate making awiki support some of the ideas here:
* https://zettelkasten.de/tools/
* https://writingcooperative.com/zettelkasten-its-like-gtd-for-writing-and-here-s-why-you-should-consider-it-7dddf02be394
+@tags oberon programming language
+
# Oberon 07
## Declarations and scope rules
+@tags ocaml programming language
+
# OCaml
**Type System:** Strongly statically typed with type inference (Hindley-Milner)<br/>
**Memory Management:** Garbage Collected (Automatic)<br/>
+@tags note-index programming
+
# Programming Languages
## Designs I'm Working On
* [Oberon 07](oberon07.html)
* [Forth](forth.html)
* [Lua](lua.html)
+* [Postfix](https://cs.wellesley.edu/~cs251/s05/postfix.pdf)
## Compiler Design
* https://inf.ethz.ch/personal/wirth/CompilerConstruction/index.html
* https://inf.ethz.ch/personal/wirth/ProjectOberon/index.html
+* https://sr.ht/%7Emcf/cproc/
## Runtime Design
* [ZINC Abstract Machine](zam.html)
+@tags note-index
+
# Random Thoughts
https://untools.co/ - Tools for better thinking
+++ /dev/null
-# Recipes
-
-* [Banana Brown Sugar Pancakes](recipes/banana_pancakes.html)
-* [Plain Old Pancakes](recipes/pancakes.html)
-* [Teriyaki Sauce](recipes/teriyaki_sauce.html)
-* [Zucchini Cookies](recipes/zucchini_cookies.html)
-* [Zucchini Cookies With Oats](recipes/zucchini_cookies_with_oats.html)
+@tags recipe pancakes
+
# Banana Brown Sugar Pancakes
Makes 10 Pancakes
--- /dev/null
+@tags recipes note-index
+
+# Recipes
+* [Banana Brown Sugar Pancakes](banana_pancakes.html)
+* [Plain Old Pancakes](pancakes.html)
+* [Teriyaki Sauce](teriyaki_sauce.html)
+* [Zucchini Cookies](zucchini_cookies.html)
+* [Zucchini Cookies With Oats](zucchini_cookies_with_oats.html)
+@tags recipe pancakes
+
# Plain Old Pancakes
## Ingredients
+@tags recipe sauce
+
# Teriyaki Sauce
## Ingredients
+@tags recipe cookies
+
# Zucchini Cookies
Makes 96 cookies. Takes 45 minutes.
+@tags recipe cookies
+
# Zucchini Cookies With Oats
## Ingredients
## Directions
-1. preheat oven to 350° F. Lightly grease baking sheets.
+1. preheat oven to 350 F. Lightly grease baking sheets.
2. combine flour, cinnamon and baking soda in small bowl.
3. Beat butter and sugar in large mixer bowl until well combined.
4. Add egg and vanilla extract, beat well.
+@tags scheme programming language
+
# Scheme
**Type System:** Dynamically typed<br/>
**Memory Management:** Garbage Collected (Automatic)<br/>
+@tags sclpl programming language language-design
+
# SCLPL Design Notes
Language Requirements:
--- /dev/null
+@tags web-dev programming
+
+# Web Development
+* [Preview of links using an iframe](http://jsfiddle.net/yboss/q29tP/)
+@tags vm language-design runtime
+
# ZINC Abstract Machine
## Registers
+@tags archived
+
# Archived Projects
No longer developed but still contain useful bits of code.
-# Projects
+# Project Organization
I have a large number of side projects and ideas that I am exploring. In order to keep these things organized, I split these projects up into three distinct categories as defined below:
* [Projects](projects/): Matured ideas that have moved past the proof of concept phase and may even be in active use.