462 lines
24 KiB
HTML
462 lines
24 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<html lang="en" class="sidebar-visible no-js light">
|
||
|
|
||
|
<head>
|
||
|
<meta charset="utf-8">
|
||
|
<title>Hitch Hiker Linux</title>
|
||
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||
|
<meta name="description" content="">
|
||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
|
<meta name="theme-color" content="#ffffff" />
|
||
|
|
||
|
<link rel="icon" href="/favicon.svg">
|
||
|
<link rel="shortcut icon" href="/favicon.png">
|
||
|
|
||
|
<link rel="stylesheet" href="/handbook/css/variables.css">
|
||
|
<link rel="stylesheet" href="/handbook/css/general.css">
|
||
|
<link rel="stylesheet" href="/handbook/css/chrome.css">
|
||
|
|
||
|
<link rel="stylesheet" href="/handbook/css/print.css" media="print">
|
||
|
|
||
|
<!-- Fonts -->
|
||
|
<link rel="stylesheet" href="/handbook/FontAwesome/css/font-awesome.css">
|
||
|
|
||
|
<link rel="stylesheet" href="/handbook/fonts/fonts.css">
|
||
|
|
||
|
<!-- Highlight.js Stylesheets -->
|
||
|
<link rel="stylesheet" href="/handbook/highlight.css">
|
||
|
<link rel="stylesheet" href="/handbook/tomorrow-night.css">
|
||
|
<link rel="stylesheet" href="/handbook/ayu-highlight.css">
|
||
|
|
||
|
<!-- Custom Stylesheets -->
|
||
|
<link rel="stylesheet" href="/hhl.css">
|
||
|
|
||
|
</head>
|
||
|
|
||
|
<body>
|
||
|
<!-- Provide site root to javascript -->
|
||
|
<script type="text/javascript">
|
||
|
var path_to_root = "/handbook";
|
||
|
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
|
||
|
</script>
|
||
|
|
||
|
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||
|
<script type="text/javascript">
|
||
|
try {
|
||
|
var theme = localStorage.getItem('mdbook-theme');
|
||
|
var sidebar = localStorage.getItem('mdbook-sidebar');
|
||
|
|
||
|
if (theme.startsWith('"') && theme.endsWith('"')) {
|
||
|
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
||
|
}
|
||
|
|
||
|
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
||
|
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
||
|
}
|
||
|
} catch (e) { }
|
||
|
</script>
|
||
|
|
||
|
<!-- Set the theme before any content is loaded, prevents flash -->
|
||
|
<script type="text/javascript">
|
||
|
var theme;
|
||
|
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||
|
if (theme === null || theme === undefined) { theme = default_theme; }
|
||
|
var html = document.querySelector('html');
|
||
|
html.classList.remove('no-js')
|
||
|
html.classList.remove('light')
|
||
|
html.classList.add(theme);
|
||
|
html.classList.add('js');
|
||
|
</script>
|
||
|
|
||
|
<!-- Hide / unhide sidebar before it is displayed -->
|
||
|
<script type="text/javascript">
|
||
|
var html = document.querySelector('html');
|
||
|
var sidebar = 'hidden';
|
||
|
if (document.body.clientWidth >= 1080) {
|
||
|
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||
|
sidebar = sidebar || 'visible';
|
||
|
}
|
||
|
html.classList.remove('sidebar-visible');
|
||
|
html.classList.add("sidebar-" + sidebar);
|
||
|
</script>
|
||
|
|
||
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||
|
<div class="sidebar-scrollbox">
|
||
|
<ol class="chapter">
|
||
|
<li class="chapter-item affix ">
|
||
|
<a href="/">Home</a>
|
||
|
</li>
|
||
|
<li class="chapter-item affix ">
|
||
|
<a href="/news/">News</a>
|
||
|
</li>
|
||
|
<li class="chapter-item affix ">
|
||
|
<a href="/about/">About</a>
|
||
|
</li>
|
||
|
<li class="chapter-item affix ">
|
||
|
<a href="/pub/">Download</a>
|
||
|
</li>
|
||
|
<li class="chapter-item affix ">
|
||
|
<a href="https://git.hitchhiker-linux.org">Source</a>
|
||
|
</li>
|
||
|
<li class="spacer"></li>
|
||
|
<li class="chapter-item affix ">
|
||
|
<a href="/handbook/">Handbook</a>
|
||
|
</li>
|
||
|
</ol>
|
||
|
</div>
|
||
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||
|
</nav>
|
||
|
<div id="page-wrapper" class="page-wrapper">
|
||
|
<div class="page">
|
||
|
<div id="menu-bar-hover-placeholder"></div>
|
||
|
<div id="menu-bar" class="menu-bar sticky bordered">
|
||
|
<div class="left-buttons">
|
||
|
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||
|
<i class="fa fa-bars"></i>
|
||
|
</button>
|
||
|
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
||
|
<i class="fa fa-paint-brush"></i>
|
||
|
</button>
|
||
|
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
||
|
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
|
||
|
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
||
|
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
||
|
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
||
|
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
<h1 class="menu-title">
|
||
|
Hitch Hiker Linux
|
||
|
</h1>
|
||
|
</div>
|
||
|
|
||
|
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
||
|
<script type="text/javascript">
|
||
|
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
||
|
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
||
|
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
||
|
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
||
|
});
|
||
|
</script>
|
||
|
<div id="content" class="content">
|
||
|
<main>
|
||
|
|
||
|
<h1><a class="header" href="#recent" id="recent">On Libc, rust experiments, and Risc-V</a></h1>
|
||
|
<p class="subtitle"><strong>2020-11-15</strong></p>
|
||
|
<h2 id="libc">LibC</h2>
|
||
|
<p>Recently I have continued the exercise of re-implementing certain base system utilities in C, uncovering more and more differences between BSD and GNU libc implementations. At this point it's really easy to say that I have a strong preference for the BSD extensions to the libc standard as opposed to the GNU extensions. The Berkeley programmers, when they added features, added truly useful features.</p>
|
||
|
<p>Take random number generation as an example. It is fairly common when programming on Linux to open and read from /dev/urandom. BSD, in the meantime, offers a group of functions in libc (arc4random) that combine pseudo-random number generation with cryptography to produce pseudo-random data that is truly difficult to guess, with a low CPU overhead.</p>
|
||
|
<p>Another small place where I found the BSD libc to offer superior functionality was when I was writing my own version of the <em>mktemp</em> utility. The BSD versions of the mkstemp and mkdtemp functions allow one to give a template with a variable-length suffix, to give a choice between quick (with a smaller suffix) or as secure as you want to be. By increasing the suffix length, one can exponentially increase the number of possible filenames, making temp files a more difficult vector of attack.</p>
|
||
|
<p>The GNU (and musl actually) versions of these functions only allow a six character random suffix, period. In fact, my earlier port of mktemp from BSD did not function as expected in this regard, and the GNU coreutils programmers had to roll their own functions to get equivalent functionality to the BSD counterparts. I have elected to not abstract this deficiency away in my code, and the HHL version of the mktemp utility uses the available versions of mkstemp and mkdtemp, with a six character suffix. I would rather maintain the simplicity of the program than to take a risk of introducing bugs by writing my own functions here.</p>
|
||
|
<p>In any event, the work that I have been doing here makes a strong case for a future port of musl, with the additions of some BSD functions ported to work with musl, as our base C library. As attractive as BSD libc is, a direct port is unrealistic as so much of it is tied to kernel interfaces that differ on Linux. I just find it a shame that Linux users are mostly saddled with such a piece of crap (bloated while still being less functional) in such an important position in the software stack.</p>
|
||
|
<h2 id="rust">Rust</h2>
|
||
|
<p>There are a lot of programming languages, and they tend to come and go regularly. As programming languages go, it's a safe bet that C, C++, Java and Python will be sticking around. Of the less pervasive languages Go and Rust seem to be well ahead of the pack as pertaining to mass adoption. Go is interesting, largely because of what it leaves out. Go is simple. Go avoids the feature creep that seems to be inevitable in all modern software. However, Go achieves memory safety by using garbage collection. I want to like Go, but that one anti-feature prevents me from even trying it.</p>
|
||
|
<p>Rust, on the other hand, has feature upon feature to the point where I really am hoping that they ever finish the language someday. That said, I'm intrigued by Rust for a number of reasons. I have been toying with learning the language for a while, doing some simple learning exercises and reading the Rust Book. I recently decided to just dive in and start writing my own programs using Rust, as that seems to be the only way to truly learn a language. My first full Rust program is a clone of a C program that I wrote for generating sine lookup tables, useful in DSP applications. The C version is perfectly fine, but I basically wanted to try porting a known working program and see how well the control flow translated.</p>
|
||
|
<p>The process was not completely smooth, and it took quite a few iterations to get to the point where the program compiled and actually functioned. However, the documentation is excellent and provided solutions to most of my issues. The other thing that really impressed me was the compiler messages. Often, the compiler will tell you literally the exact change needed to make your program compile. Coming from C, this is a breath of fresh air. And when we're talking about Rust, chances are that if it compiles it's also going to function exactly as expected.</p>
|
||
|
<p>Rust is also elegant in a way that C never will be. Consider the following C code:</p>
|
||
|
<pre style="background-color:#2b303b;">
|
||
|
<code class="language-C" data-lang="C"><span style="color:#b48ead;">for </span><span style="color:#c0c5ce;">( i = </span><span style="color:#d08770;">0</span><span style="color:#c0c5ce;">; i < </span><span style="color:#d08770;">10</span><span style="color:#c0c5ce;">, i++) {
|
||
|
</span><span style="color:#65737e;">// some code
|
||
|
</span><span style="color:#c0c5ce;">}
|
||
|
</span></code></pre>
|
||
|
<p>And the equivalent Rust:</p>
|
||
|
<pre style="background-color:#2b303b;">
|
||
|
<code class="language-Rust" data-lang="Rust"><span style="color:#b48ead;">for</span><span style="color:#c0c5ce;"> i in </span><span style="color:#d08770;">1</span><span style="color:#c0c5ce;">..</span><span style="color:#d08770;">10 </span><span style="color:#c0c5ce;">{
|
||
|
</span><span style="color:#65737e;">// some code
|
||
|
</span><span style="color:#c0c5ce;">}
|
||
|
</span></code></pre>
|
||
|
<p>One thing that requires a different mindset when one moves from an old-school language like C, to a modern language like Rust, is that in C et al, the standard library tries to be all inclusive. Programmers (at least the good ones) try to avoid adding dependencies to anything other than the standard library. Rust, however, has Cargo. Cargo is, in effect, a built in package manager. This is not unheard of; Python has pip and has for years. In Rust, however, the standard library is quite small and everyone pretty much freely uses cargo to access functionality that is not included in libstd. In my case I used cargo to pull in the excellent clap crate, which parses command line arguments and also provides built in documentation. Compared to getopt in C, clap both does more and does it with little effort.</p>
|
||
|
<p>At this point int time, however, Rust is not going to be landing in the HitchHiker base system, as the only viable Rust compiler uses llvm as a backend. At some point in the future this may well change anyway, as I have been growing increasingly frustrated with both Glibc and gcc (a brief skim of some earlier blog posts will quickly turn up examples). The obvious replacements are musl and the clang compiler, which, being based on llvm, would make the further inclusion of rustc trivial.</p>
|
||
|
<h2 id="risc-v">Risc-V</h2>
|
||
|
<p>I do a fair amount of electronics experimenting and often employ various microcontrollers in my projects. Some are Atmega based, while I have more recently fallen in love with the ATSAMD51 Arm Cortex M4 processor based boards from Adafruit. Just this week I have acquired something new to me: a Risc-V based MCU from Seeed Studio, the Sipeed Longan Nano. It's a brilliant chip, although quite lacking in documentation and example code. I'll be playing with it a lot.</p>
|
||
|
<p>The Nano, however, is a microcontroller, not a full SOC that is capable of running Linux. Right now there are few options for developers wanting to experiment with Risc-V with a full operating system, and the best ones are all prohibitively expensive for their capability. Due out next year, however, is the PicoRio board from Rios labs that is described as close in form factor and capabilities to most Arm boards based around the RPI format. Provided this board is not vaporware and actually does materialize at a reasonable cost, I intend for HItchHiker Linux to be running on it as soon as feasible. I intend to make HitchHiker one of the very first options independent of distros such as Debian and Fedora, and to make Risc-V a first class citizen. It is my hope that in doing so HitchHiker might help to push along the adoption of truly open hardware on which to run open software.</p>
|
||
|
|
||
|
|
||
|
<hr>
|
||
|
<p class="subtitle"><strong>Tags for this post:</strong></p>
|
||
|
|
||
|
<a class="tags" href="/tags/c-programming/">C programming</a>
|
||
|
|
||
|
<a class="tags" href="/tags/rust/">Rust</a>
|
||
|
|
||
|
<a class="tags" href="/tags/nongnu/">NonGNU</a>
|
||
|
|
||
|
<a class="tags" href="/tags/riscv/">RiscV</a>
|
||
|
|
||
|
<a class="tags" href="/tags/glibc/">Glibc</a>
|
||
|
|
||
|
<a class="tags" href="/tags/utilities/">Utilities</a>
|
||
|
|
||
|
|
||
|
|
||
|
</main>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<script>
|
||
|
(function themes() {
|
||
|
var html = document.querySelector('html');
|
||
|
var themeToggleButton = document.getElementById('theme-toggle');
|
||
|
var themePopup = document.getElementById('theme-list');
|
||
|
var themeColorMetaTag = document.querySelector('meta[name="theme-color"]');
|
||
|
var stylesheets = {
|
||
|
ayuHighlight: document.querySelector("[href$='ayu-highlight.css']"),
|
||
|
tomorrowNight: document.querySelector("[href$='tomorrow-night.css']"),
|
||
|
highlight: document.querySelector("[href$='highlight.css']"),
|
||
|
};
|
||
|
|
||
|
function showThemes() {
|
||
|
themePopup.style.display = 'block';
|
||
|
themeToggleButton.setAttribute('aria-expanded', true);
|
||
|
themePopup.querySelector("button#" + get_theme()).focus();
|
||
|
}
|
||
|
|
||
|
function hideThemes() {
|
||
|
themePopup.style.display = 'none';
|
||
|
themeToggleButton.setAttribute('aria-expanded', false);
|
||
|
themeToggleButton.focus();
|
||
|
}
|
||
|
|
||
|
function get_theme() {
|
||
|
var theme;
|
||
|
try { theme = localStorage.getItem('mdbook-theme'); } catch (e) { }
|
||
|
if (theme === null || theme === undefined) {
|
||
|
return default_theme;
|
||
|
} else {
|
||
|
return theme;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function set_theme(theme, store = true) {
|
||
|
let ace_theme;
|
||
|
|
||
|
if (theme == 'coal' || theme == 'navy') {
|
||
|
stylesheets.ayuHighlight.disabled = true;
|
||
|
stylesheets.tomorrowNight.disabled = false;
|
||
|
stylesheets.highlight.disabled = true;
|
||
|
|
||
|
ace_theme = "ace/theme/tomorrow_night";
|
||
|
} else if (theme == 'ayu') {
|
||
|
stylesheets.ayuHighlight.disabled = false;
|
||
|
stylesheets.tomorrowNight.disabled = true;
|
||
|
stylesheets.highlight.disabled = true;
|
||
|
ace_theme = "ace/theme/tomorrow_night";
|
||
|
} else {
|
||
|
stylesheets.ayuHighlight.disabled = true;
|
||
|
stylesheets.tomorrowNight.disabled = true;
|
||
|
stylesheets.highlight.disabled = false;
|
||
|
ace_theme = "ace/theme/dawn";
|
||
|
}
|
||
|
|
||
|
setTimeout(function () {
|
||
|
themeColorMetaTag.content = getComputedStyle(document.body).backgroundColor;
|
||
|
}, 1);
|
||
|
|
||
|
if (window.ace && window.editors) {
|
||
|
window.editors.forEach(function (editor) {
|
||
|
editor.setTheme(ace_theme);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
var previousTheme = get_theme();
|
||
|
|
||
|
if (store) {
|
||
|
try { localStorage.setItem('mdbook-theme', theme); } catch (e) { }
|
||
|
}
|
||
|
|
||
|
html.classList.remove(previousTheme);
|
||
|
html.classList.add(theme);
|
||
|
}
|
||
|
|
||
|
// Set theme
|
||
|
var theme = get_theme();
|
||
|
|
||
|
set_theme(theme, false);
|
||
|
|
||
|
themeToggleButton.addEventListener('click', function () {
|
||
|
if (themePopup.style.display === 'block') {
|
||
|
hideThemes();
|
||
|
} else {
|
||
|
showThemes();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
themePopup.addEventListener('click', function (e) {
|
||
|
var theme = e.target.id || e.target.parentElement.id;
|
||
|
set_theme(theme);
|
||
|
});
|
||
|
|
||
|
themePopup.addEventListener('focusout', function(e) {
|
||
|
// e.relatedTarget is null in Safari and Firefox on macOS (see workaround below)
|
||
|
if (!!e.relatedTarget && !themeToggleButton.contains(e.relatedTarget) && !themePopup.contains(e.relatedTarget)) {
|
||
|
hideThemes();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// Should not be needed, but it works around an issue on macOS & iOS: https://github.com/rust-lang/mdBook/issues/628
|
||
|
document.addEventListener('click', function(e) {
|
||
|
if (themePopup.style.display === 'block' && !themeToggleButton.contains(e.target) && !themePopup.contains(e.target)) {
|
||
|
hideThemes();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
document.addEventListener('keydown', function (e) {
|
||
|
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; }
|
||
|
if (!themePopup.contains(e.target)) { return; }
|
||
|
|
||
|
switch (e.key) {
|
||
|
case 'Escape':
|
||
|
e.preventDefault();
|
||
|
hideThemes();
|
||
|
break;
|
||
|
case 'ArrowUp':
|
||
|
e.preventDefault();
|
||
|
var li = document.activeElement.parentElement;
|
||
|
if (li && li.previousElementSibling) {
|
||
|
li.previousElementSibling.querySelector('button').focus();
|
||
|
}
|
||
|
break;
|
||
|
case 'ArrowDown':
|
||
|
e.preventDefault();
|
||
|
var li = document.activeElement.parentElement;
|
||
|
if (li && li.nextElementSibling) {
|
||
|
li.nextElementSibling.querySelector('button').focus();
|
||
|
}
|
||
|
break;
|
||
|
case 'Home':
|
||
|
e.preventDefault();
|
||
|
themePopup.querySelector('li:first-child button').focus();
|
||
|
break;
|
||
|
case 'End':
|
||
|
e.preventDefault();
|
||
|
themePopup.querySelector('li:last-child button').focus();
|
||
|
break;
|
||
|
}
|
||
|
});
|
||
|
})();
|
||
|
|
||
|
(function sidebar() {
|
||
|
var html = document.querySelector("html");
|
||
|
var sidebar = document.getElementById("sidebar");
|
||
|
var sidebarLinks = document.querySelectorAll('#sidebar a');
|
||
|
var sidebarToggleButton = document.getElementById("sidebar-toggle");
|
||
|
var sidebarResizeHandle = document.getElementById("sidebar-resize-handle");
|
||
|
var firstContact = null;
|
||
|
|
||
|
function showSidebar() {
|
||
|
html.classList.remove('sidebar-hidden')
|
||
|
html.classList.add('sidebar-visible');
|
||
|
Array.from(sidebarLinks).forEach(function (link) {
|
||
|
link.setAttribute('tabIndex', 0);
|
||
|
});
|
||
|
sidebarToggleButton.setAttribute('aria-expanded', true);
|
||
|
sidebar.setAttribute('aria-hidden', false);
|
||
|
try { localStorage.setItem('mdbook-sidebar', 'visible'); } catch (e) { }
|
||
|
}
|
||
|
|
||
|
|
||
|
var sidebarAnchorToggles = document.querySelectorAll('#sidebar a.toggle');
|
||
|
|
||
|
function toggleSection(ev) {
|
||
|
ev.currentTarget.parentElement.classList.toggle('expanded');
|
||
|
}
|
||
|
|
||
|
Array.from(sidebarAnchorToggles).forEach(function (el) {
|
||
|
el.addEventListener('click', toggleSection);
|
||
|
});
|
||
|
|
||
|
function hideSidebar() {
|
||
|
html.classList.remove('sidebar-visible')
|
||
|
html.classList.add('sidebar-hidden');
|
||
|
Array.from(sidebarLinks).forEach(function (link) {
|
||
|
link.setAttribute('tabIndex', -1);
|
||
|
});
|
||
|
sidebarToggleButton.setAttribute('aria-expanded', false);
|
||
|
sidebar.setAttribute('aria-hidden', true);
|
||
|
try { localStorage.setItem('mdbook-sidebar', 'hidden'); } catch (e) { }
|
||
|
}
|
||
|
|
||
|
// Toggle sidebar
|
||
|
sidebarToggleButton.addEventListener('click', function sidebarToggle() {
|
||
|
if (html.classList.contains("sidebar-hidden")) {
|
||
|
var current_width = parseInt(
|
||
|
document.documentElement.style.getPropertyValue('--sidebar-width'), 10);
|
||
|
if (current_width < 150) {
|
||
|
document.documentElement.style.setProperty('--sidebar-width', '150px');
|
||
|
}
|
||
|
showSidebar();
|
||
|
} else if (html.classList.contains("sidebar-visible")) {
|
||
|
hideSidebar();
|
||
|
} else {
|
||
|
if (getComputedStyle(sidebar)['transform'] === 'none') {
|
||
|
hideSidebar();
|
||
|
} else {
|
||
|
showSidebar();
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
sidebarResizeHandle.addEventListener('mousedown', initResize, false);
|
||
|
|
||
|
function initResize(e) {
|
||
|
window.addEventListener('mousemove', resize, false);
|
||
|
window.addEventListener('mouseup', stopResize, false);
|
||
|
html.classList.add('sidebar-resizing');
|
||
|
}
|
||
|
function resize(e) {
|
||
|
var pos = (e.clientX - sidebar.offsetLeft);
|
||
|
if (pos < 20) {
|
||
|
hideSidebar();
|
||
|
} else {
|
||
|
if (html.classList.contains("sidebar-hidden")) {
|
||
|
showSidebar();
|
||
|
}
|
||
|
pos = Math.min(pos, window.innerWidth - 100);
|
||
|
document.documentElement.style.setProperty('--sidebar-width', pos + 'px');
|
||
|
}
|
||
|
}
|
||
|
//on mouseup remove windows functions mousemove & mouseup
|
||
|
function stopResize(e) {
|
||
|
html.classList.remove('sidebar-resizing');
|
||
|
window.removeEventListener('mousemove', resize, false);
|
||
|
window.removeEventListener('mouseup', stopResize, false);
|
||
|
}
|
||
|
|
||
|
document.addEventListener('touchstart', function (e) {
|
||
|
firstContact = {
|
||
|
x: e.touches[0].clientX,
|
||
|
time: Date.now()
|
||
|
};
|
||
|
}, { passive: true });
|
||
|
|
||
|
document.addEventListener('touchmove', function (e) {
|
||
|
if (!firstContact)
|
||
|
return;
|
||
|
|
||
|
var curX = e.touches[0].clientX;
|
||
|
var xDiff = curX - firstContact.x,
|
||
|
tDiff = Date.now() - firstContact.time;
|
||
|
|
||
|
if (tDiff < 250 && Math.abs(xDiff) >= 150) {
|
||
|
if (xDiff >= 0 && firstContact.x < Math.min(document.body.clientWidth * 0.25, 300))
|
||
|
showSidebar();
|
||
|
else if (xDiff < 0 && curX < 300)
|
||
|
hideSidebar();
|
||
|
|
||
|
firstContact = null;
|
||
|
}
|
||
|
}, { passive: true });
|
||
|
|
||
|
// Scroll sidebar to current active section
|
||
|
var activeSection = document.getElementById("sidebar").querySelector(".active");
|
||
|
if (activeSection) {
|
||
|
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
|
||
|
activeSection.scrollIntoView({ block: 'center' });
|
||
|
}
|
||
|
})();
|
||
|
</script>
|
||
|
|
||
|
</body>
|
||
|
|
||
|
</html>
|