Hello
My name is Yifei Yin.
I am a full-time Full Stack Developer 💻 at Verto Health.
tech/ programming, technology-related stuff
- tech/articles/ - opinions
- tech/guides/ - guides & references
- tech/tips/ programming tips, snippets, notes
I am a full-time Full Stack Developer 💻 at Verto Health.
tech/ programming, technology-related stuff
{
"allPosts": {
"/_templates/": [
{
"url": "/_templates/quick-notes",
"excerpt": "",
"frontmatter": {},
"html": "",
"moreAvailable": false
}
],
"/": [
{
"url": "/index",
"excerpt": "",
"frontmatter": {
"noFileTree": true
},
"html": "<h1 id=\"hello\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#hello\">Hello</a></h1>\n<h2 id=\"my-name-is-yifei-yin\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#my-name-is-yifei-yin\">My name is Yifei Yin.</a></h2>\n<p>I am a full-time Full Stack Developer 💻 at <a href=\"https://verto.health\" target=\"_blank\" rel=\"noreferrer\">Verto Health</a>.</p>\n<p><a href=\"https://linkedin.com/in/yif\" target=\"_blank\" rel=\"noreferrer\">LinkedIn</a> | <a href=\"https://github.com/yifeiyin\" target=\"_blank\" rel=\"noreferrer\">GitHub</a></p>\n<ul>\n<li>\n<p><a href=\"./tech/\">tech/</a> programming, technology-related stuff</p>\n<ul>\n<li><a href=\"./tech/articles/\">tech/articles/</a> - opinions</li>\n<li><a href=\"./tech/guides/\">tech/guides/</a> - guides & references</li>\n<li><a href=\"./tech/tips/\">tech/tips/</a> programming tips, snippets, notes</li>\n</ul>\n</li>\n<li>\n<p><a href=\"./shorts/2023-05-01 pgp and ssh keys.html\">My ssh and gpg keys</a></p>\n</li>\n</ul>\n<!--\n\ngit --work-tree=content/ checkout origin/content -- . \n\n-->",
"moreAvailable": true
}
],
"/photography/": [
{
"url": "/photography/2023-03 Lynde Shores Conservation Area",
"excerpt": "<table>\n<thead>\n<tr>\n<th style=\"text-align:center\">White-Tailed Deer</th>\n<th style=\"text-align:center\">Downy Woodpecker</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:center\"><img src=\"./../_assets/yyindev-3125481.jpg\" alt=\"\"></td>\n<td style=\"text-align:center\"><img src=\"./../_assets/yyindev-3125679.jpg\" alt=\"\"></td>\n</tr>\n</tbody>\n</table>\n<p>Others:</p>\n<ul>\n<li>Mourning Dove</li>\n<li>Northern Cardinal</li>\n<li>Squirrel</li>\n<li>Mallard</li>\n</ul>\n",
"frontmatter": {},
"html": "<table>\n<thead>\n<tr>\n<th style=\"text-align:center\">White-Tailed Deer</th>\n<th style=\"text-align:center\">Downy Woodpecker</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:center\"><img src=\"./../_assets/yyindev-3125481.jpg\" alt=\"\"></td>\n<td style=\"text-align:center\"><img src=\"./../_assets/yyindev-3125679.jpg\" alt=\"\"></td>\n</tr>\n</tbody>\n</table>\n<p>Others:</p>\n<ul>\n<li>Mourning Dove</li>\n<li>Northern Cardinal</li>\n<li>Squirrel</li>\n<li>Mallard</li>\n</ul>\n<hr>\n<h2 id=\"white-tailed-deer-female-🦌\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#white-tailed-deer-female-🦌\">White-Tailed Deer, female 🦌</a></h2>\n<p>Should be female because of the lack of antler.</p>\n<p>Male, called Buck, average lifespan 2.9 years; female, called Doe, average lifespan 6.5 years.\nCommunicates with other deers using voice, scent, body language and markings.\nStudy shows that 40-60% of white-tailed deer tested positive for COVID antibodies.</p>\n<p><img src=\"./../_assets/yyindev-3125481.jpg\" alt=\"\">\n<img src=\"./../_assets/yyindev-3126283.jpg\" alt=\"\"></p>\n<h2 id=\"downy-woodpecker-female\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#downy-woodpecker-female\">Downy Woodpecker, female</a></h2>\n<p>Is female because of the lack of red patch on the head.\nLength 14-18 cm, windspan 25-31 cm, weigh 20-33 g, lifespan 1-2 years.\nDowny woodpecker looks almost the same as the hairy woodpecker, but the latter has no black spots on its tail.\n<img src=\"./../_assets/yyindev-3125679.jpg\" alt=\"\"></p>\n<h2 id=\"mourning-dove\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#mourning-dove\">Mourning Dove</a></h2>\n<p>They usually mate for life and lay almost always 2 eggs per clutch. They can produce 2-3 clutches per year (up to 6 clutches), making them the longest breeding bird in North America. Both parents incubate the eggs and take care of the chicks for a period of time. During the day, the male watches the nest while the female watches it at night. The young are almost always under the care of their parents.</p>\n<p>The mourning dove in Canada has the farthest migration distance and can often fly to Mexico in winter.\n<img src=\"./../_assets/yyindev-3125714.jpg\" alt=\"\"></p>\n<h2 id=\"northern-cardinal-female\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#northern-cardinal-female\">Northern Cardinal, female</a></h2>\n<p>Male ones have all red body.</p>\n<p>Their main diet consists of seeds and fruits, while insects are used as supplementary food and to feed their babies. They do not migrate, so they can still be seen in winter. Their lifespan is generally 3-5 years.</p>\n<p>Nesting: The males are responsible for finding materials, while the females bend and complete the nest. The nest often consists of four layers of materials: thin twigs, leaves, bark, grass or pine needles, etc. It usually takes 3-6 days to build a nest. They generally do not reuse their nests.\n<img src=\"./../_assets/yyindev-3125836.jpg\" alt=\"\"></p>\n<h2 id=\"squirrel-🐿️\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#squirrel-🐿️\">Squirrel 🐿️</a></h2>\n<p>There are 22 species of squirrel in Canada.\nThe average lifespan of this species is 8-18 years. They nest in trees and store nuts, seeds, berries, bones, and insects before winter. They do not hibernate.\n<img src=\"./../_assets/yyindev-3125970.jpg\" alt=\"\"></p>\n<h2 id=\"mallard-🦆\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#mallard-🦆\">Mallard 🦆</a></h2>\n<p>Male is the green ones (raeb-raeb-raeb). Female is the gray ones (quack-quack-quack)\nAverage lifespan 5-10 years. Nest near water. 8-10 eggs per clutch. Omnivorous, eats grass, insects, and other foods. In North America, they have at least 15 natural predators, including eagles 🦅, foxes 🦊, and owls 🦉.</p>\n<p><img src=\"./../_assets/yyindev-3126150.jpg\" alt=\"\">\n<img src=\"./../_assets/yyindev-3126152.jpg\" alt=\"\">\n<img src=\"./../_assets/yyindev-3126161.jpg\" alt=\"\"></p>\n<!--\n\n(1)(2)\nWhite-tailed Deer, female 雌性白尾鹿\n(没有鹿角所以应该是雌性)\n雄性鹿叫做 Buck 平均寿命 2.9 年,雌性鹿叫做 Doe 平均寿命 6.5 年。\n会用声音、气味、身体语言、记号与其他鹿交流。\n研究显示美国 40-60% 的白尾鹿被测出了 COVID 抗体。\n\n(3)\nDowny Woodpecker, female 雌性绒啄木鸟\n(头顶没有红斑所以应该是雌性)图中的叼了一颗花生。\n长度 14-18 cm,翼展 25-31 cm,体重 20-33 g,寿命 1-2 年。\n与长嘴啄木鸟(hairy woodpecker)长得几乎一样但后者尾巴没有黑点。\n\n(4)\nMourning Dove 哀鸽\n又称泣鸽、哀鸠 jiū\n一般是一夫一妻制,一窝几乎都是产 2 枚蛋,每年常会产2-3窝蛋(最多 6 窝),是北美洲繁殖期最长的鸟类,雏鸟的双亲都会孵蛋并照顾雏鸟一段时间,白天一般由雄鸟看窝,晚上和清晨由雌鸟看窝,幼仔几乎一直会有家长看管。\n\n加拿大的哀鸽是迁徙距离最远的,在冬季往往能飞到墨西哥。\n\n(5)\nNorthern Cardinal, female 雌性北美红雀\n又称红衣凤头鸟。\n全身通红的是雄性,各种封面图经常是雄性北美红雀因为其鲜艳的颜色。\n主食种子和水果,昆虫则是自己的辅食和并用来喂宝宝。\n因为不会迁徙,所以冬天仍然可以看见。寿命一般 3-5 年。\n筑巢:雄性负责找材料,雌性负责弯折材料并完成筑巢。巢往往有 4 层材料构成:细树枝、叶子、藤皮、草或松树针等。筑巢一般会用 3-6 天。一般不会重复利用巢。\n\n(6)\nSquirrel 松鼠 🐿️\n脊索动物门哺乳纲科啮齿目\n松鼠是一个科,这一只具体是哪个属和种就有点难找了。加拿大有 22 种松鼠。\n平均寿命 8-18 年,在树中筑巢,会在冬天前存坚果种子浆果骨头昆虫等。不会冬眠。\n\n(7)(8)(9)\nMallard 绿头鸭 🦆\n绿头为雄性(叫声 raeb),灰色为雌性(叫声 quack-quack-quack)。\n平均寿命 5-10 年。在水边筑窝,一窝 8-10 颗蛋。是杂食动物,吃草虫子等。在北美有至少 15 种天敌:鹰🦅、狐狸🦊、猫头鹰🦉等等。\n\n📍 图片拍摄于 Lynde Shores Conservation Area\n\n-->",
"moreAvailable": true
},
{
"url": "/photography/2023-04 Pinery Provincial Park",
"excerpt": "<table>\n<thead>\n<tr>\n<th style=\"text-align:center\">Black-Capped Chickadee</th>\n<th style=\"text-align:center\">Red-Breasted Nuthatch</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:center\"><img src=\"./../_assets/yyindev-4079701.jpg\" alt=\"\"></td>\n<td style=\"text-align:center\"><img src=\"./../_assets/yyindev-4089980.jpg\" alt=\"\"></td>\n</tr>\n</tbody>\n</table>\n<p>Others: Common Garter Snake, Great Blue Heron</p>\n",
"frontmatter": {},
"html": "<table>\n<thead>\n<tr>\n<th style=\"text-align:center\">Black-Capped Chickadee</th>\n<th style=\"text-align:center\">Red-Breasted Nuthatch</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:center\"><img src=\"./../_assets/yyindev-4079701.jpg\" alt=\"\"></td>\n<td style=\"text-align:center\"><img src=\"./../_assets/yyindev-4089980.jpg\" alt=\"\"></td>\n</tr>\n</tbody>\n</table>\n<p>Others: Common Garter Snake, Great Blue Heron</p>\n<hr>\n<h2 id=\"black-capped-chickadee\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#black-capped-chickadee\">Black-Capped Chickadee</a></h2>\n<p>State bird of Maine, Massachusetts and New Brunswick\n<img src=\"./../_assets/yyindev-4079701.jpg\" alt=\"\">\n<img src=\"./../_assets/yyindev-4079708.jpg\" alt=\"\"></p>\n<h2 id=\"common-garter-snake\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#common-garter-snake\">Common Garter Snake</a></h2>\n<p>Small to medium sized diurnal (active during day time) snake.\nFor humans, a bite is not dangerous, though it may cause slight itching, burning, and/or swelling.\n<img src=\"./../_assets/yyindev-4089978.jpg\" alt=\"\"></p>\n<h2 id=\"red-breasted-nuthatch\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#red-breasted-nuthatch\">Red-Breasted Nuthatch</a></h2>\n<p>Nuthatch:\nOnly types of bird that can climb downwards on a tree.</p>\n<p>The only significant migrant is the red-breasted nuthatch, which winters widely across North America, deserting the northernmost parts of its breeding range in Canada; it has been recorded as a vagrant in Bermuda, Iceland and England.</p>\n<p>Many birds recognise the simple alarm calls produced by other species, but the red-breasted nuthatch is able to interpret the chickadees' detailed variations and to respond appropriately.</p>\n<p><img src=\"./../_assets/yyindev-4089980.jpg\" alt=\"\"></p>\n<h2 id=\"great-blue-heron\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#great-blue-heron\">Great Blue Heron</a></h2>\n<p>Length 1-1.4 m, wingspan 1.7-2 m, weight only 2-2.5 kg。Nest on trees; eat fish。Excellent night vision. Prey on day and night time.\n<img src=\"./../_assets/yyindev-202304141.jpg\" alt=\"\">\n<img src=\"./../_assets/yyindev-202304142.jpg\" alt=\"\"></p>\n<!--\n(1)(2)(3)\nBlack-capped Chickadee 黑顶山雀\n是美国 Maine、Massachusetts 州鸟和加拿大 New Brunswick 的省鸟\n\n(4)\nCommon Garter Snake 普通束带蛇\n又称袜带蛇、园丁蛇\n是十几种小型至中型北美无毒蛇的统称\n\n(5)\nRed-breasted Nuthatch 白胸䴓 shī\nNuthatch,䴓,又称五子雀,常在树干、树枝、岩石上等地方觅食,喜欢在洞里筑巢,会储存食物以便过冬天。是唯一一种能头向下尾朝上往下爬树的鸟类\n\n(6)(7)\nGreat Blue Heron 大蓝鹭\n长度 1-1.4 m,翼展 1.7-2 m,体重只有 2-2.5 kg。于树上筑巢,吃鱼。有很好的夜市能力,白天晚上都会捕食。\n\n\n📍 图片拍摄于 Pinery Provincial Park\n\n-->\n",
"moreAvailable": true
},
{
"url": "/photography/2023-05 Earl Bales Park",
"excerpt": "<table>\n<thead>\n<tr>\n<th style=\"text-align:center\">American Yellow Warbler</th>\n<th style=\"text-align:center\">Red-Winged Blackbird</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:center\"><img src=\"./../_assets/yyindev-5135477.jpg\" alt=\"\"></td>\n<td style=\"text-align:center\"><img src=\"./../_assets/yyindev-5135493.jpg\" alt=\"\"></td>\n</tr>\n</tbody>\n</table>\n",
"frontmatter": {},
"html": "<table>\n<thead>\n<tr>\n<th style=\"text-align:center\">American Yellow Warbler</th>\n<th style=\"text-align:center\">Red-Winged Blackbird</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:center\"><img src=\"./../_assets/yyindev-5135477.jpg\" alt=\"\"></td>\n<td style=\"text-align:center\"><img src=\"./../_assets/yyindev-5135493.jpg\" alt=\"\"></td>\n</tr>\n</tbody>\n</table>\n<hr>\n<h1 id=\"earl-bales-park\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#earl-bales-park\">Earl Bales Park</a></h1>\n<p><img src=\"./../_assets/yyindev-1995.jpg\" alt=\"\">\n<img src=\"./../_assets/yyindev-1997.jpg\" alt=\"\">\n<img src=\"./../_assets/yyindev-5135455.jpg\" alt=\"\">\n<img src=\"./../_assets/yyindev-5135481.jpg\" alt=\"\"></p>\n<h2 id=\"american-yellow-warbler\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#american-yellow-warbler\">American Yellow Warbler</a></h2>\n<p><img src=\"./../_assets/yyindev-5135477.jpg\" alt=\"\">\n<img src=\"./../_assets/yyindev-5135474.jpg\" alt=\"\"></p>\n<h2 id=\"red-winged-blackbird\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#red-winged-blackbird\">Red-Winged Blackbird</a></h2>\n<p><img src=\"./../_assets/yyindev-5135493.jpg\" alt=\"\">\n<img src=\"./../_assets/yyindev-5135498.jpg\" alt=\"\"></p>\n",
"moreAvailable": true
},
{
"url": "/photography/index",
"excerpt": "",
"frontmatter": {},
"html": "<h1 id=\"photography\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#photography\">Photography</a></h1>\n<!--\nCurrently there's only nature photography. \n\nIn the future there might be:\n- airplanes\n- astrophotography\n- comparisons\n- portraits?\n- city/landscape/etc\n-->\n",
"moreAvailable": true
}
],
"/shorts/": [
{
"url": "/shorts/2023-05-01 pgp and ssh keys",
"excerpt": "",
"frontmatter": {
"excerpt": "none"
},
"html": "<h1 id=\"my-keys\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#my-keys\">My Keys</a></h1>\n<h2 id=\"ssh-public-key\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#ssh-public-key\">SSH Public Key</a></h2>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDfcqn92nnYVAYqc7zgleRZa7/N5xRN327fBBiC5GWG0rVuyIRtr2xMPCyKkctE3daVCku7yy65U3L3mCx6UbYoQBs2gJ7oBD4Uv7dqrjfdkYv7mysIOR/tbUozEwYKlMDSfdE5XvHV+LnKnw4yGSDo4ysMkThPYYek+ONf+pDgfgMV4ez0cMchc1Pgher4Upg3SI5lPGAJloD76k3OQ01ejrRmC7bW6p34BPfyv/CdFOjKD0OzOUOGw35iyRr3LVSTVDuNVPG7hOpTQgQdZImNflirdrN/mEjJtpHWjadOx2X3qpCSodOmwjTQGG0EeKX9pbt8+JyhFt+mcxPBlNEwu1xNqG3N+RcgD/wYe2NV5UypwFS6C/gf5roWkZIpUgw1tYQIWMl3q/5I0OyFVAzycalJA4maoBrklrYyvlFwwqaIAxhyW6NRpoOyMGqqZ/4WRLFna1118r8yrEykMyYkKQemjmeWEi7RDpry2bdzRlL/z/uSlyR/2O7EJNYAuhU= yyin:openpgp:0x85104159</span></span></code></pre>\n</div><p>Public key fingerprint:</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">SHA256:DLo0z1AWo9OLticpFuT+a22Xv/9ZzwbCS/wbhhq1Q00</span></span></code></pre>\n</div><h2 id=\"pgp-gpg-key\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#pgp-gpg-key\">PGP/GPG Key</a></h2>\n<p>You can download it through openpgp.org: <a href=\"https://keys.openpgp.org/vks/v1/by-fingerprint/F57F0B21984C0B1235D5D087CE4E6606FE434FE3\" target=\"_blank\" rel=\"noreferrer\"><code>F57F 0B21 984C 0B12 35D5 D087 CE4E 6606 FE43 4FE3</code></a></p>\n<p>There're 3 subkeys in this block:</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">gpg --list-keys --with-keygrip</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">pub rsa3072 2020-10-02 [SC] [expires: 2024-07-04]</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> F57F0B21984C0B1235D5D087CE4E6606FE434FE3</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> Keygrip = 51683BD3B90B1B62B6FD6943F475656357432751</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">uid [ultimate] Yifei Yin <yifeiyin@foxmail.com></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">uid [ultimate] Yifei Yin <contact@yyin.me></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">sub rsa3072 2020-10-02 [E] [expires: 2024-07-04]</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> Keygrip = A9B9E590B8E31BF2C0EAEB94BBBDBA12C93235A9</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">sub rsa3072 2020-11-10 [A] [expires: 2024-07-04]</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> Keygrip = D597ECDF7C80DDA31156BEF1154C90D15805BEF1</span></span></code></pre>\n</div>",
"moreAvailable": true
},
{
"url": "/shorts/index",
"excerpt": "",
"frontmatter": {},
"html": "<h1 id=\"shorts-home-page\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#shorts-home-page\">Shorts home page</a></h1>\n",
"moreAvailable": true
},
{
"url": "/shorts/look into iperf",
"excerpt": "",
"frontmatter": {},
"html": "",
"moreAvailable": false
},
{
"url": "/shorts/must watch youtube videos",
"excerpt": "",
"frontmatter": {},
"html": "<ul>\n<li>cgp gray highway</li>\n<li>Linguistic English sound</li>\n<li>ccc unit system</li>\n</ul>\n",
"moreAvailable": true
},
{
"url": "/shorts/quickly serve local files through web",
"excerpt": "<p>Option 1:</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">python3 -m http.server</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">python3 -m http.server --help</span></span></code></pre>\n</div><p>Option 2:</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">npm i http-server</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">http-server --help</span></span></code></pre>\n</div><p>Option 3:</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">npx serve</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">npx serve --help</span></span></code></pre>\n</div>",
"frontmatter": {
"excerpt": "all"
},
"html": "<p>Option 1:</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">python3 -m http.server</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">python3 -m http.server --help</span></span></code></pre>\n</div><p>Option 2:</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">npm i http-server</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">http-server --help</span></span></code></pre>\n</div><p>Option 3:</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">npx serve</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">npx serve --help</span></span></code></pre>\n</div>",
"moreAvailable": false
},
{
"url": "/shorts/radio frequency allocation",
"excerpt": "<p><img src=\"./../_assets/20230521-radio-freq-allocation.png\" alt=\"Radio frequency allocation - screenshot\"></p>\n",
"frontmatter": {},
"html": "<p><img src=\"./../_assets/20230521-radio-freq-allocation.png\" alt=\"Radio frequency allocation - screenshot\"></p>\n<hr>\n<p><a href=\"https://ised-isde.canada.ca/site/spectrum-management-telecommunications/en/learn-more/key-documents/canadian-frequency-allocations-table-and-chart/canadian-table-frequency-allocations\" target=\"_blank\" rel=\"noreferrer\">https://ised-isde.canada.ca/site/spectrum-management-telecommunications/en/learn-more/key-documents/canadian-frequency-allocations-table-and-chart/canadian-table-frequency-allocations</a></p>\n",
"moreAvailable": true
},
{
"url": "/shorts/shell extras",
"excerpt": "",
"frontmatter": {},
"html": "<ul>\n<li><a href=\"https://yyin.dev/quick-notes/224-4aafda\" target=\"_blank\" rel=\"noreferrer\">https://yyin.dev/quick-notes/224-4aafda</a></li>\n<li><a href=\"https://yyin.dev/quick-notes/133-0836e9\" target=\"_blank\" rel=\"noreferrer\">https://yyin.dev/quick-notes/133-0836e9</a></li>\n<li><a href=\"https://yyin.dev/quick-notes/070-e755c3\" target=\"_blank\" rel=\"noreferrer\">https://yyin.dev/quick-notes/070-e755c3</a></li>\n<li><a href=\"https://yyin.dev/quick-notes/053-80cd37\" target=\"_blank\" rel=\"noreferrer\">https://yyin.dev/quick-notes/053-80cd37</a></li>\n<li><a href=\"https://yyin.dev/quick-notes/006-cbe0da\" target=\"_blank\" rel=\"noreferrer\">https://yyin.dev/quick-notes/006-cbe0da</a></li>\n<li><a href=\"https://yyin.dev/quick-notes/005-cdcc4b\" target=\"_blank\" rel=\"noreferrer\">https://yyin.dev/quick-notes/005-cdcc4b</a></li>\n</ul>\n",
"moreAvailable": true
}
],
"/tech/articles/": [
{
"url": "/tech/articles/how to debug anything",
"excerpt": "<p>General principles for troubleshooting anything</p>\n",
"frontmatter": {},
"html": "<p>General principles for troubleshooting anything</p>\n<hr>\n<p>General Rules:</p>\n<ol>\n<li>Try easiest solutions first</li>\n<li>Narrow down the problem</li>\n<li>Test your assumptions</li>\n</ol>\n<blockquote>\n<p>Many steps are only applicable to a certain set of problems. Use the ones that apply.</p>\n</blockquote>\n<h2 id=\"step-0-try-again\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#step-0-try-again\">Step 0: Try again</a></h2>\n<ul>\n<li>Pay closer attention this time</li>\n<li>It might be a one-off problem</li>\n<li>Note down the steps to reproduce if it's complex</li>\n<li>If you got multiple errors, always start from the first one</li>\n</ul>\n<h2 id=\"step-1-be-at-the-right-place\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#step-1-be-at-the-right-place\">Step 1: Be at the right place</a></h2>\n<ul>\n<li>Are you editing the right code?</li>\n<li>Are you looking at the correct app? prod vs staging vs local</li>\n<li>Is the app connected to the correct database?</li>\n<li>Are you at the right place but the content are cached?\n<ul>\n<li>Cache by network layers, by build tools, or by external providers?</li>\n<li>Validate by add console.log, breakpoints, change content or css</li>\n</ul>\n</li>\n<li>You can also validate all of the above by crashing the app somewhere else</li>\n</ul>\n<h2 id=\"step-2-what-changed\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#step-2-what-changed\">Step 2: What changed</a></h2>\n<p>At this stage, you should be able to reproduce the bug locally at your will</p>\n<p>How did this problem come to existence?</p>\n<ul>\n<li>Was the feature broken when implementing?</li>\n<li>Or, more likely, some erroneous changes were made</li>\n<li>Did you install new packages? Pulled new commits?</li>\n<li>Can you rollback and compare the difference? (git bisect)</li>\n</ul>\n<h2 id=\"step-3-assume-nothing\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#step-3-assume-nothing\">Step 3: Assume nothing</a></h2>\n<p>It might not be your fault – it could be a bug in the library, or inconsistent behaviour with the documentation.</p>\n<p>Speaking of documentation, are you looking at the right version?</p>\n<p>If you suspect it's the library's problem, do a quick search in github issue, should only take a minute (remember, take easiest route first)</p>\n<p>Also, did you try restarting the app, or your computer? That helps, sometimes.</p>\n<h2 id=\"step-4-reproduce-fast\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#step-4-reproduce-fast\">Step 4: Reproduce fast</a></h2>\n<p>Narrow down the problem and get to a minimum reproducible example.</p>\n<p>You need this anyways, since you need to know when the problem is fixed.</p>\n<p>Evaluate the situation for yourself, and optimize for the validation when necessary. This could mean</p>\n<ul>\n<li>remove authentication, disable certain form validation, or hard code some field values</li>\n<li>write a script that automatically executes the entire test case, or some portions of it</li>\n</ul>\n<p>The test case should require as little as interaction as possible.</p>\n<p>It is sometimes possible to "brute-force" solutions when the possible solutions are limited.</p>\n<ul>\n<li>Simply try each of the options, and execute your test script</li>\n<li>This way you don't have to look into the documentation, since maybe none of them fixes the actual issue</li>\n</ul>\n<h2 id=\"step-5-try-later\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#step-5-try-later\">Step 5: Try later</a></h2>\n<p>Talk to a rubber ducky</p>\n<p>Take a break</p>\n",
"moreAvailable": true
},
{
"url": "/tech/articles/index",
"excerpt": "",
"frontmatter": {},
"html": "",
"moreAvailable": false
},
{
"url": "/tech/articles/interesting domains",
"excerpt": "<p>did you know you can use <a href=\"https://doc.new\" target=\"_blank\" rel=\"noreferrer\">doc.new</a> to create a new google doc and use <a href=\"https://meet.new\" target=\"_blank\" rel=\"noreferrer\">meet.new</a> to start a instant meeting?</p>\n",
"frontmatter": {},
"html": "<p>did you know you can use <a href=\"https://doc.new\" target=\"_blank\" rel=\"noreferrer\">doc.new</a> to create a new google doc and use <a href=\"https://meet.new\" target=\"_blank\" rel=\"noreferrer\">meet.new</a> to start a instant meeting?</p>\n<hr>\n<ul>\n<li>example.com - the example domain</li>\n<li>js.org - github pages</li>\n<li>go.com - Disney (acquired search engine Infoseek)</li>\n<li>ui.com - Ubiquiti</li>\n<li>Owned by cloudflare:\n<ul>\n<li>one.one.one.one</li>\n<li>pages.dev</li>\n</ul>\n</li>\n<li>Owned by google:\n<ul>\n<li>domains.google</li>\n<li>web.dev - chrome</li>\n<li>web.app - firebase</li>\n<li>abc.xyz - alphabet</li>\n</ul>\n</li>\n<li><a href=\"https://whats.new\" target=\"_blank\" rel=\"noreferrer\">https://whats.new</a>\n<ul>\n<li>word.new, docx.new, ppt.new, powerpoint.new, pptx.new, excel.new - New office365 document</li>\n<li>doc.new, sheet.new, presentation.new - New google doc</li>\n<li>meet.new - instantly start google meet</li>\n<li>repo.new, gist.new - github</li>\n</ul>\n</li>\n</ul>\n",
"moreAvailable": true
},
{
"url": "/tech/articles/judging python design decisions",
"excerpt": "<p>with hindsight.</p>\n",
"frontmatter": {
"draft": true
},
"html": "<p>with hindsight.</p>\n<hr>\n<p>Topics:\nThe good ones</p>\n<ul>\n<li>for...else...</li>\n<li>try...except...else...</li>\n<li>std library\n<ul>\n<li><code>functools.cache</code> <code>contextlib.suppress</code></li>\n</ul>\n</li>\n<li>lambda notation (but no easy way to define a function)</li>\n</ul>\n<p>The bad ones</p>\n<ul>\n<li>indent</li>\n<li>list & dict comprehension (map is difficult to use, order is unintuitive)</li>\n<li>named parameters, <code>*args and **args</code></li>\n<li>magic variable</li>\n<li>unreliable pip install</li>\n<li>dict access syntax</li>\n<li>package and <code>__init__.py</code></li>\n<li>keywords can’t be overridden</li>\n</ul>\n",
"moreAvailable": true
},
{
"url": "/tech/articles/the only acceptable date format",
"excerpt": "<p><code>YYYY-MM-DD</code>, reasoning, extensions and more</p>\n",
"frontmatter": {},
"html": "<p><code>YYYY-MM-DD</code>, reasoning, extensions and more</p>\n<hr>\n<h2 id=\"date-formats-standards\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#date-formats-standards\">Date formats Standards</a></h2>\n<ul>\n<li><a href=\"https://en.wikipedia.org/wiki/ISO_8601\" target=\"_blank\" rel=\"noreferrer\">ISO 8601</a></li>\n<li><a href=\"https://ijmacd.github.io/rfc3339-iso8601/\" target=\"_blank\" rel=\"noreferrer\">RFC 3339 vs ISO 8601</a></li>\n<li>The "email or http header date format"\n<ul>\n<li><a href=\"http://tools.ietf.org/html/rfc4021#section-2.1.1\" target=\"_blank\" rel=\"noreferrer\">RFC 4021: Mail Header Fields</a> refers to <a href=\"http://tools.ietf.org/html/rfc822#section-5.1\" target=\"_blank\" rel=\"noreferrer\">RFC 822 section 5.1</a>. and later clarified in <a href=\"http://tools.ietf.org/html/rfc2822#section-3.3\" target=\"_blank\" rel=\"noreferrer\">RFC 2822 section 3.3</a></li>\n<li>For HTTP: <a href=\"https://www.rfc-editor.org/rfc/rfc9110#field.date\" target=\"_blank\" rel=\"noreferrer\">RFC 9110</a></li>\n</ul>\n</li>\n</ul>\n<h2 id=\"reasons\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#reasons\">Reasons</a></h2>\n<ul>\n<li>Human readable</li>\n<li>Machine readable</li>\n<li><a href=\"https://en.wikipedia.org/wiki/ASCII#Character_order\" target=\"_blank\" rel=\"noreferrer\">ASCIIbetical order</a> implies chronological order\n<ul>\n<li>which is almost always used by operating systems when viewing files</li>\n<li>This also means that anything that does not start with a date go to the very end</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"extensions\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#extensions\">Extensions</a></h2>\n<h3 id=\"date-range\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#date-range\">Date Range</a></h3>\n<p>Format: <code>YYYY-MM-DD--YYYY-MM-DD</code></p>\n<p>This ensures compatible order when used mixed with date without range.</p>\n<h3 id=\"use-with-comments\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#use-with-comments\">Use with comments</a></h3>\n<p>Format: <code>YYYY-MM-DD Comments</code>\nFormat: <code>YYYY-MM-DD--YYYY-MM-DD Comments</code></p>\n<h2 id=\"how-to-use\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#how-to-use\">How to use</a></h2>\n<ul>\n<li>Shell: <code>date -I</code> <code>date -Iseconds</code></li>\n<li>Python: <code>from datetime import datetime; datetime.now().isoformat()</code></li>\n<li>JavaScript: <code>new Date().toISOString()</code></li>\n</ul>\n",
"moreAvailable": true
}
],
"/tech/guides/": [
{
"url": "/tech/guides/API design examples",
"excerpt": "<p>POST or GET /search? Page or offset or after for pagination? Let's just look at how big companies are doing it.</p>\n",
"frontmatter": {
"created_at": "2020-10-18T00:00:00.000Z"
},
"html": "<p>POST or GET /search? Page or offset or after for pagination? Let's just look at how big companies are doing it.</p>\n<hr>\n<ul>\n<li><a href=\"https://docs.gitlab.com/ee/api/search.html\" target=\"_blank\" rel=\"noreferrer\">Which one is more <em>RESTful</em>:</a> <a href=\"https://docs.github.com/en/free-pro-team@latest/rest/overview/endpoints-available-for-github-apps#search\" target=\"_blank\" rel=\"noreferrer\">POST</a> <a href=\"https://www.reddit.com/dev/api/#GET_search\" target=\"_blank\" rel=\"noreferrer\">or GET</a> <a href=\"https://stackoverflow.com/questions/20550514/post-or-get-in-a-search-form\" target=\"_blank\" rel=\"noreferrer\"><code>/search</code>?</a></li>\n<li><a href=\"https://stackoverflow.com/questions/13872273/api-pagination-best-practices\" target=\"_blank\" rel=\"noreferrer\">Which is the best way to paginate:</a> <a href=\"https://docs.github.com/en/free-pro-team@latest/rest/reference/issues#list-issues-assigned-to-the-authenticated-user--parameters\" target=\"_blank\" rel=\"noreferrer\">offset, page number</a>, <a href=\"https://docs.gitlab.com/ee/api/commits.html#list-repository-commits\" target=\"_blank\" rel=\"noreferrer\">keyset</a> <a href=\"https://www.reddit.com/dev/api/#GET_about_%7Bwhere%7D\" target=\"_blank\" rel=\"noreferrer\">or seek?</a></li>\n</ul>\n<p>Rather than looking at "best practices", StackOverflow posts, random people's blog posts, or even HTTP RFCs, why not just look at how big companies are doing it.</p>\n<ul>\n<li>\n<p>GitHub: <a href=\"https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps\" target=\"_blank\" rel=\"noreferrer\">https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps</a></p>\n</li>\n<li>\n<p>GitLab: <a href=\"https://docs.gitlab.com/ee/api/api_resources.html\" target=\"_blank\" rel=\"noreferrer\">https://docs.gitlab.com/ee/api/api_resources.html</a></p>\n</li>\n<li>\n<p>Zeplin: <a href=\"https://docs.zeplin.dev/reference#introduction\" target=\"_blank\" rel=\"noreferrer\">https://docs.zeplin.dev/reference#introduction</a></p>\n</li>\n<li>\n<p>Spotify: <a href=\"https://developer.spotify.com/documentation/web-api/reference/\" target=\"_blank\" rel=\"noreferrer\">https://developer.spotify.com/documentation/web-api/reference/</a></p>\n</li>\n<li>\n<p>Facebook: <a href=\"https://developers.facebook.com/docs\" target=\"_blank\" rel=\"noreferrer\">https://developers.facebook.com/docs</a></p>\n</li>\n<li>\n<p>WordPress: <a href=\"https://developer.wordpress.com/docs/api/\" target=\"_blank\" rel=\"noreferrer\">https://developer.wordpress.com/docs/api/</a></p>\n</li>\n<li>\n<p>Riot Games: <a href=\"https://developer.riotgames.com/apis\" target=\"_blank\" rel=\"noreferrer\">https://developer.riotgames.com/apis</a></p>\n</li>\n<li>\n<p>Reddit: <a href=\"https://www.reddit.com/dev/api/\" target=\"_blank\" rel=\"noreferrer\">https://www.reddit.com/dev/api/</a></p>\n</li>\n<li>\n<p>Stripe: <a href=\"https://stripe.com/docs/api\" target=\"_blank\" rel=\"noreferrer\">https://stripe.com/docs/api</a></p>\n</li>\n<li>\n<p>Privacy: <a href=\"https://privacy.com/developer/docs#endpoints\" target=\"_blank\" rel=\"noreferrer\">https://privacy.com/developer/docs#endpoints</a></p>\n</li>\n</ul>\n",
"moreAvailable": true
},
{
"url": "/tech/guides/disk formats",
"excerpt": "<p>explained: <code>FAT, NTFS, FAT32, exFAT, HFS, HFS+, APFS</code></p>\n",
"frontmatter": {},
"html": "<p>explained: <code>FAT, NTFS, FAT32, exFAT, HFS, HFS+, APFS</code></p>\n<hr>\n<p><a href=\"https://en.wikipedia.org/wiki/Disk_formatting\" target=\"_blank\" rel=\"noreferrer\">Wikipedia: Disk formatting</a></p>\n<h2 id=\"by-microsoft\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#by-microsoft\">By Microsoft</a></h2>\n<table>\n<thead>\n<tr>\n<th>name</th>\n<th>alias</th>\n<th>release year</th>\n<th>other info</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>FAT</td>\n<td>File Allocation Table</td>\n<td>1977, floppy disks</td>\n<td><a href=\"https://en.wikipedia.org/wiki/File_Allocation_Table\" target=\"_blank\" rel=\"noreferrer\">wiki</a></td>\n</tr>\n<tr>\n<td>NTFS</td>\n<td>NT File System</td>\n<td>1993</td>\n<td>proprietary (1) (2) <a href=\"https://en.wikipedia.org/wiki/NTFS\" target=\"_blank\" rel=\"noreferrer\">wiki</a></td>\n</tr>\n<tr>\n<td>FAT32</td>\n<td></td>\n<td>1996, MS-DOS 7.1</td>\n<td>4GB max file size. 32 as in 32-bit field for the sector count <a href=\"https://en.wikipedia.org/wiki/File_Allocation_Table#FAT32\" target=\"_blank\" rel=\"noreferrer\">wiki</a></td>\n</tr>\n<tr>\n<td>exFAT</td>\n<td>Extensible FAT</td>\n<td>2006</td>\n<td>optimized for flash memory; <br> no longer proprietary since 2019 <a href=\"https://en.wikipedia.org/wiki/ExFAT\" target=\"_blank\" rel=\"noreferrer\">wiki</a></td>\n</tr>\n</tbody>\n</table>\n<p>(1) NT as in "Windows NT", meant "New Technology", see <a href=\"https://en.wikipedia.org/wiki/Windows_NT#Naming\" target=\"_blank\" rel=\"noreferrer\">this</a>\n(2) Linux and BSD have open-source drivers (read & write), macOS comes with read-only driver</p>\n<h2 id=\"by-apple\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#by-apple\">By Apple</a></h2>\n<table>\n<thead>\n<tr>\n<th>name</th>\n<th>alias</th>\n<th>release year</th>\n<th>other info</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>HFS</td>\n<td>Hierarchical File System</td>\n<td>1985</td>\n<td>proprietary <a href=\"https://en.wikipedia.org/wiki/Hierarchical_File_System\" target=\"_blank\" rel=\"noreferrer\">wiki</a></td>\n</tr>\n<tr>\n<td>Mac OS Extended</td>\n<td>aka HFS Plus, HFS+</td>\n<td>1998, macOS 8.1</td>\n<td>proprietary <a href=\"https://en.wikipedia.org/wiki/HFS_Plus\" target=\"_blank\" rel=\"noreferrer\">wiki</a></td>\n</tr>\n<tr>\n<td>APFS</td>\n<td>Apple File System</td>\n<td>2017, macOS High Sierra</td>\n<td>proprietary <a href=\"https://en.wikipedia.org/wiki/Apple_File_System\" target=\"_blank\" rel=\"noreferrer\">wiki</a></td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"system-defaults\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#system-defaults\">System Defaults</a></h2>\n<table>\n<thead>\n<tr>\n<th>Format</th>\n<th>Products</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>APFS</td>\n<td>Apple products</td>\n</tr>\n<tr>\n<td>NTFS</td>\n<td>Windows products</td>\n</tr>\n<tr>\n<td>exFAT</td>\n<td>SD cards</td>\n</tr>\n</tbody>\n</table>\n",
"moreAvailable": true
},
{
"url": "/tech/guides/DNS records",
"excerpt": "<p>explained: <code>A, AAAA, CAA, MX, NS, CNAME</code></p>\n",
"frontmatter": {},
"html": "<p>explained: <code>A, AAAA, CAA, MX, NS, CNAME</code></p>\n<hr>\n<ul>\n<li><a href=\"https://support.google.com/domains/answer/3251147?hl=en-CA\" target=\"_blank\" rel=\"noreferrer\">Google Support: About resource records</a></li>\n<li><a href=\"https://en.wikipedia.org/wiki/List_of_DNS_record_types\" target=\"_blank\" rel=\"noreferrer\">Wikipedia: List of DNS record types</a></li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>type</th>\n<th>full name</th>\n<th>example</th>\n<th>description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>A</td>\n<td>Address record</td>\n<td><code>@ A 1h 123.123.123.123</code></td>\n<td>domain name to IPv4 address mapping</td>\n</tr>\n<tr>\n<td>AAAA</td>\n<td>IPv6 Address record</td>\n<td><code>www AAAA 1h 2002:db80:1:2:3:4:567:89ab</code></td>\n<td>domain name to IPv6 address mapping</td>\n</tr>\n<tr>\n<td>CAA</td>\n<td>Certification Authority Authorization</td>\n<td><code>example.com. IN CAA 0 issue "letsencrypt.org"</code></td>\n<td>let certain CA to issue certificates for the domain</td>\n</tr>\n<tr>\n<td>MX</td>\n<td>Mail exchange</td>\n<td><code>@ MX 1h 10 mailhost2.example.com.</code></td>\n<td>domain name to mail server mapping; can specify priority</td>\n</tr>\n<tr>\n<td>NS</td>\n<td>Name server</td>\n<td><code>ns1 NS 1h ns-cloud1.googledomains.com.</code></td>\n<td>domain/subdomain to name server mapping; name server holds the resource records and returns corresponding ip address</td>\n</tr>\n<tr>\n<td>CNAME</td>\n<td>Canonical name</td>\n<td><code>www CNAME 1h example.com.</code></td>\n<td>maps a domain to another domain</td>\n</tr>\n</tbody>\n</table>\n<p>To be updated with more record types.</p>\n",
"moreAvailable": true
},
{
"url": "/tech/guides/git tutorial (draft)",
"excerpt": "",
"frontmatter": {},
"html": "<h1 id=\"advanced-tutorial-to-git\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#advanced-tutorial-to-git\">advanced tutorial to git</a></h1>\n<h2 id=\"prerequisites\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#prerequisites\">Prerequisites</a></h2>\n<ol>\n<li>Upgrade your git client\n<ol>\n<li>there are new command/config/helper messages available</li>\n<li>Ex. Git restore/switch, push.autoSetupRemote</li>\n<li>Doesn’t hurt to upgrade anyways</li>\n</ol>\n</li>\n<li>Set up must have configurations\n<ol>\n<li>name, email, etc\n<ol>\n<li>know how to change them, for author info to properly show up on GitHub\n<ol>\n<li>I have seen many people (coop/students) with broken author info</li>\n</ol>\n</li>\n</ol>\n</li>\n<li>Slightly advanced configs (that should have been the defaults):</li>\n<li><a href=\"https://github.com/yifeiyin/CONFIGS/edit/master/git/readme.sh\" target=\"_blank\" rel=\"noreferrer\">https://github.com/yifeiyin/CONFIGS/edit/master/git/readme.sh</a></li>\n</ol>\n</li>\n<li>Know basic operations (commit, push, pull, etc)</li>\n<li>Where to get help\n<ol>\n<li><code>--help</code> anything. The "EXAMPLES" section in git is also often helpful, can just copy it for the slides.</li>\n</ol>\n</li>\n</ol>\n<h2 id=\"slightly-more-advanced-stuff\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#slightly-more-advanced-stuff\">Slightly more advanced stuff</a></h2>\n<h3 id=\"the-de-facto-git-tutorial\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#the-de-facto-git-tutorial\">The de facto git tutorial</a></h3>\n<p><a href=\"https://learngitbranching.js.org/\" target=\"_blank\" rel=\"noreferrer\">https://learngitbranching.js.org/</a></p>\n<ol>\n<li>This is interactive</li>\n<li>The commands are simplified to get the points across\n<ol>\n<li>people will need to (re)learn the proper git commands</li>\n</ol>\n</li>\n<li>There is a way to show exactly that graph in git!!! see below</li>\n</ol>\n<h3 id=\"key-to-understand-the-advanced-git-operations\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#key-to-understand-the-advanced-git-operations\">Key to understand the advanced git operations</a></h3>\n<p>Git commits form a tree. You are almost always at a leaf node.\nA git repo, at its core, is just a tree of commits.</p>\n<p>What is a commit? (Not including merge commit, id really k exactly how they work lol)\nEach commit is comprised of: a reference to parent commit, a list of changes to files, and metadata (author, date)</p>\n<p>Thus, each commit represents 3 things: the changes, the history (by tracing through the parents), which determines every single file content.</p>\n<p>What is a branch? A branch is simply a label, attached to a commit. That’s it.\nBranch is convenient because we can give them a human friendly name.\nAnd content of a branch are expected to change. (Delete or rephrase)</p>\n<p>Understand “HEAD”. This is where you are at. Its also just a label, attached to something.\nHEAD, most of the time, will be attached to a branch. HEAD determines the</p>\n<p><strong>Operations in git can always mapped to a combination of “modification to the commit tree” and some sort of “label movement”.</strong> For example:</p>\n<p>Commit: add new commit as the leaf of where head is. If head is at a branch, advance that branch label to the newly created commit. (Should rephrase this)</p>\n<p>Merge: create a new leaf with two parents. If head is at a branch, advance that branch label to the newly created commit.\nThe idea of “fast forward” and “<code>—-no-ff</code>”: …</p>\n<p><code>git reset</code> (when used with a ref in arguments): move current branch label to ref. This is how you can directly move the branch label. This is operationally equivalent to <code>git checkout -b -f or simply -B</code> (but one moves the current branch label to a ref, one move a branch label to here)</p>\n<p><code>git checkout -b</code>: create new branch label pointing current commit. And move head to point to newly created branch label.</p>\n<p>(Need to introduce the idea of “applying a commit” here)</p>\n<p><code>git cherry-pick</code>: equals to git commit but it doesn’t look at your local files, it takes the changes of that commit instead. Advances branch label the same way.</p>\n<p><code>git rebase</code>: figure out the common ancestor. cherry pick commits that are missing to the top of target. Moves the branch label to the new set of commits. The old commits are lost (“dangling commits”)</p>\n<p><code>git checkout</code>\n<code>git status</code></p>\n<p>These are my takeaways from the tutorials.</p>\n<p><strong>Finally, the graph command as promised</strong>: simply use <code>git log --oneline --graph</code> (there’s a bunch of implied options already assumed by git, decorated, color, etc)</p>\n<p>If you know how to move the branch label, and how to apply a commit. You can do anything.\nSimply copy the graph and save the commit hashes.\nIf you remember the hash, the commit is not lost. (Unless they are garbage collected, Idk all the details)\nYou can manually selectively apply commits (interactive rebase). You can reset the branch label if you messed up your rebase. You can undo a commit, etc, etc</p>\n<p>Push force, pull force, a lot of things you can “force“. What does force even mean?</p>\n<h2 id=\"some-more-advanced-stuff\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#some-more-advanced-stuff\">Some more advanced stuff</a></h2>\n<p>Remotes are also just labels. (?)</p>\n<p>Tag is a alias to a commit hash. It does not move. If your HEAD is at a tag and make a commit, tag does not move. Annotated tag … too advanced</p>\n<p>The common pattern of <code>git log/diff/checkout REF —- FILE1 FILE2</code> the “disambiguation” sign</p>\n<p>Different ways to express a “ref”. Commit hash, branch name, tag, HEAD, relative operators (<code>~^</code>), date operator (<code>main@{3 days ago}</code>)\nDifferent ways to express a range of refs: <code>A..B</code> vs <code>A...B</code></p>\n<p>Stash. is just a temporarily commit with a special label</p>\n<p>In git log, the order of the commits are determined by the dependencies and not by timestamps.</p>\n<p>Git commit dash dash amend\nInteractive rebase</p>\n<p>.gitignore, .gitkeep\ngit config, global, local, etc. git alias</p>\n<p><!— reflog, bisect, 3 way merge, —></p>\n",
"moreAvailable": true
},
{
"url": "/tech/guides/gpg",
"excerpt": "<p>Basic gpg usage, including installing gpg, setting up keys, managing keys and using gpg to sign git commits. You can also use it as your password manager: <a href=\"https://www.passwordstore.org\" target=\"_blank\" rel=\"noreferrer\">pass: the standard unix password manager</a></p>\n",
"frontmatter": {},
"html": "<p>Basic gpg usage, including installing gpg, setting up keys, managing keys and using gpg to sign git commits. You can also use it as your password manager: <a href=\"https://www.passwordstore.org\" target=\"_blank\" rel=\"noreferrer\">pass: the standard unix password manager</a></p>\n<hr>\n<h1 id=\"gpg\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#gpg\">GPG</a></h1>\n<h2 id=\"initial-one-time-setup-create-new-key-pair\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#initial-one-time-setup-create-new-key-pair\">Initial one-time setup - create new key pair</a></h2>\n<p><code>gpg --full-generate-key</code></p>\n<ul>\n<li>Select default option: <code>RSA and RSA</code></li>\n<li>Select default key size: 3072</li>\n<li>Input how long the key is valid for</li>\n<li>Then user id (name, email, comment)</li>\n</ul>\n<p>Use <code>gpg --list-key</code>, same as <code>gpg --list-keys</code> to verify</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">pub rsa3072 2022-01-17 [SC] [expires: 2024-01-17]</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> EBD233E9B7085662F2B0153D66D9B31867619AA3</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">uid Testing <testing@yyin.me></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">sub rsa3072 2022-01-17 [E] [expires: 2024-01-17]</span></span></code></pre>\n</div><h2 id=\"basic-usage\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#basic-usage\">Basic Usage</a></h2>\n<h3 id=\"use-your-public-key\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#use-your-public-key\">Use your public key</a></h3>\n<p>To send someone your public key:\n<code>gpg --export --armor <uid></code></p>\n<p>To upload your public key to openpgp server:\n<code>gpg --export <uid> | curl -T - https://keys.openpgp.org</code></p>\n<h3 id=\"import-other-s-public-key\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#import-other-s-public-key\">Import other's public key</a></h3>\n<p>Import from a file: <code>gpg --import key.asc</code>\nOr by searching on openpgp server: <code>gpg --keyserver hkps://keys.openpgp.org --search-keys <email></code></p>\n<p>(Optional) Verify the fingerprint of the imported key: <code>gpg --fingerprint <id></code>\n(Optional) Sign the new imported key to indicate that you trust this key (and with proper configuration, you trust keys they have signed as well). <code>gpg --sign-key <id></code></p>\n<h3 id=\"using-it-for-messaging\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#using-it-for-messaging\">Using it for messaging</a></h3>\n<p>Encrypt & sign: <code>gpg --encrypt --sign --armor --recipient <recipient-email> < msg.txt > msg.asc</code>\nClear sign: <code>gpg --clear-sign < msg.txt > msg.asc</code>\nDecrypt / verify: <code>gpg < msg.asc</code></p>\n<h3 id=\"in-case-of-emergency\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#in-case-of-emergency\">In case of emergency</a></h3>\n<p>The private key is leaked; or, more likely, you lost your private key and you want to tell everyone to stop using that key. You need to generate a revoke certificate. Keep it secret – it should be kept at the same confidentiality level as the private key itself.</p>\n<p>Revoke certificate are probably already generated. Check files in <code>~/.gnupg/openpgp-revocs.d/</code>.</p>\n<p>Generate revoke certificate: <code>gpg --gen-revoke <id></code>\nUse revoke certificate: <code># Import the certificate as if it was a key</code></p>\n<h2 id=\"signed-git-commits\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#signed-git-commits\">Signed git commits</a></h2>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">$ git help commit</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">...</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">-S[<keyid>], --gpg-sign[=<keyid>], --no-gpg-sign</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> GPG-sign commits. The keyid argument is optional and defaults to the committer</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> identity; if specified, it must be stuck to the option without a space.</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> --no-gpg-sign is useful to countermand both commit.gpgSign configuration</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> variable, and earlier --gpg-sign.</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">...</span></span></code></pre>\n</div><p>Turning on gpg signing for all commits:</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">git config --global commit.gpgSign true</span></span></code></pre>\n</div><p>Set key to use for signing (if you have multiple keys):</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">git config --global user.signingkey <key-id></span></span></code></pre>\n</div><p>View signatures in git log:</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">git log --show-signature</span></span></code></pre>\n</div><p>The most well-known thing for "signed commits" is the green badges on GitHub. To configure, upload your gpg public key to GitHub: <a href=\"https://github.com/settings/gpg/new\" target=\"_blank\" rel=\"noreferrer\">GitHub > Settings > SSH and GPG keys > New GPG key</a></p>\n<hr>\n<p>Other topics not covered:</p>\n<ul>\n<li>Migration: export secret key, export key ring</li>\n<li>Update a key: add email, change expiry date</li>\n<li>Git sign commits</li>\n<li>SSH key\n<ul>\n<li>Enable on gpg</li>\n<li>Enable on ssh agent</li>\n<li>Export public key <code>gpg --export-ssh-key <key id></code></li>\n</ul>\n</li>\n<li>macOS remember passphrase\n<ul>\n<li>macOS keychain</li>\n<li>Pinentry</li>\n<li>macOS pinentry over ssh</li>\n</ul>\n</li>\n</ul>\n<p>My previous notes:</p>\n<ul>\n<li><a href=\"https://yyin.dev/quick-notes/095-4330a5\" target=\"_blank\" rel=\"noreferrer\">Error: gpg is older than us | yyin.dev</a></li>\n<li><a href=\"https://yyin.dev/quick-notes/071-f8c592\" target=\"_blank\" rel=\"noreferrer\">gpg pinentry over ssh | yyin.dev</a></li>\n<li><a href=\"https://yyin.dev/quick-notes/068-76bb1b\" target=\"_blank\" rel=\"noreferrer\">Export PGP keys to printable QR codes | yyin.dev</a></li>\n<li><a href=\"https://yyin.dev/quick-notes/066-df96e7\" target=\"_blank\" rel=\"noreferrer\">gpg forgets passphrase | yyin.dev</a></li>\n<li><a href=\"https://yyin.dev/quick-notes/065-55033d\" target=\"_blank\" rel=\"noreferrer\">GPG extensions | yyin.dev</a></li>\n<li><a href=\"https://yyin.dev/quick-notes/064-d4edd5\" target=\"_blank\" rel=\"noreferrer\">Troubleshooting GPG secret key prompt | yyin.dev</a></li>\n<li><a href=\"https://yyin.dev/gpg-signing\" target=\"_blank\" rel=\"noreferrer\">https://yyin.dev/gpg-signing</a></li>\n</ul>\n",
"moreAvailable": true
},
{
"url": "/tech/guides/index",
"excerpt": "",
"frontmatter": {},
"html": "<h1 id=\"guides\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#guides\">Guides</a></h1>\n",
"moreAvailable": true
}
],
"/tech/": [
{
"url": "/tech/index",
"excerpt": "",
"frontmatter": {},
"html": "<p>Anything programming, technology, computer-related.</p>\n",
"moreAvailable": true
}
],
"/tech/tips/docker/": [
{
"url": "/tech/tips/docker/01 docker start vs run vs create etc",
"excerpt": "<p>docker commands equivalence</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">docker run</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> = create + start + attach</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> = create + ( start -a )</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> = ( run --detach ) + attach</span></span></code></pre>\n</div>",
"frontmatter": {
"excerpt": "all"
},
"html": "<p>docker commands equivalence</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">docker run</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> = create + start + attach</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> = create + ( start -a )</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> = ( run --detach ) + attach</span></span></code></pre>\n</div>",
"moreAvailable": false
},
{
"url": "/tech/tips/docker/02 compose start vs up vs create etc",
"excerpt": "<p>docker compose commands equivalence</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">up =</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> up --no-start (== deprecated command "create")</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> + start</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">down =</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> stop</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> + rm</span></span></code></pre>\n</div>",
"frontmatter": {
"excerpt": "all"
},
"html": "<p>docker compose commands equivalence</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">up =</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> up --no-start (== deprecated command "create")</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> + start</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">down =</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> stop</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> + rm</span></span></code></pre>\n</div>",
"moreAvailable": false
},
{
"url": "/tech/tips/docker/03 ENTRYPOINT vs CMD",
"excerpt": "<p>entrypoint is the "entry" base command. It is the "app" that the image represents. If it does not represent an app, it should be empty.</p>\n<p>cmd is the default argument(s) to the entrypoint. If entrypoint does not exist, cmd gets executed. cmd can be overridden.</p>\n<p><a href=\"https://stackoverflow.com/a/34245657\" target=\"_blank\" rel=\"noreferrer\">https://stackoverflow.com/a/34245657</a></p>\n",
"frontmatter": {
"excerpt": "all"
},
"html": "<p>entrypoint is the "entry" base command. It is the "app" that the image represents. If it does not represent an app, it should be empty.</p>\n<p>cmd is the default argument(s) to the entrypoint. If entrypoint does not exist, cmd gets executed. cmd can be overridden.</p>\n<p><a href=\"https://stackoverflow.com/a/34245657\" target=\"_blank\" rel=\"noreferrer\">https://stackoverflow.com/a/34245657</a></p>\n",
"moreAvailable": false
},
{
"url": "/tech/tips/docker/04 docker without sudo",
"excerpt": "<p>Invoke <code>docker</code> without adding <code>sudo</code> every time.</p>\n<p>You still need root permission to configure this.</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">sudo usermod -aG docker $(whoami)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"># Re-login</span></span></code></pre>\n</div><p><a href=\"https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user\" target=\"_blank\" rel=\"noreferrer\">https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user</a></p>\n",
"frontmatter": {
"excerpt": "all"
},
"html": "<p>Invoke <code>docker</code> without adding <code>sudo</code> every time.</p>\n<p>You still need root permission to configure this.</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">sudo usermod -aG docker $(whoami)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"># Re-login</span></span></code></pre>\n</div><p><a href=\"https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user\" target=\"_blank\" rel=\"noreferrer\">https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user</a></p>\n",
"moreAvailable": false
},
{
"url": "/tech/tips/docker/05 docker compose restart",
"excerpt": "<p>Restart docker-compose with updated images.</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">docker-compose pull</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">docker-compose up -d</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">docker-compose logs -f</span></span></code></pre>\n</div><blockquote>\n<p>If there are existing containers for a service, and the service’s configuration or image was changed after the container’s creation, <code>docker compose up</code> picks up the changes by stopping and recreating the containers (preserving mounted volumes). To prevent Compose from picking up changes, use the <code>--no-recreate</code> flag.</p>\n<p><a href=\"https://docs.docker.com/engine/reference/commandline/compose_up/#description\" target=\"_blank\" rel=\"noreferrer\">https://docs.docker.com/engine/reference/commandline/compose_up/#description</a></p>\n</blockquote>\n",
"frontmatter": {
"excerpt": "all"
},
"html": "<p>Restart docker-compose with updated images.</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">docker-compose pull</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">docker-compose up -d</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">docker-compose logs -f</span></span></code></pre>\n</div><blockquote>\n<p>If there are existing containers for a service, and the service’s configuration or image was changed after the container’s creation, <code>docker compose up</code> picks up the changes by stopping and recreating the containers (preserving mounted volumes). To prevent Compose from picking up changes, use the <code>--no-recreate</code> flag.</p>\n<p><a href=\"https://docs.docker.com/engine/reference/commandline/compose_up/#description\" target=\"_blank\" rel=\"noreferrer\">https://docs.docker.com/engine/reference/commandline/compose_up/#description</a></p>\n</blockquote>\n",
"moreAvailable": false
},
{
"url": "/tech/tips/docker/index",
"excerpt": "",
"frontmatter": {},
"html": "<h1 id=\"docker\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#docker\">Docker</a></h1>\n<!--\nMaybe:\nBuild arguments vs runtime arguments etc\n-->",
"moreAvailable": true
}
],
"/tech/tips/git/": [
{
"url": "/tech/tips/git/index",
"excerpt": "",
"frontmatter": {},
"html": "",
"moreAvailable": false
},
{
"url": "/tech/tips/git/set default branch",
"excerpt": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">git config --global init.defaultBranch main</span></span></code></pre>\n</div>",
"frontmatter": {
"excerpt": "all"
},
"html": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">git config --global init.defaultBranch main</span></span></code></pre>\n</div>",
"moreAvailable": false
},
{
"url": "/tech/tips/git/use orphan branch",
"excerpt": "<p>Use this when you want to setup a new branch that contains a totally different set of files.</p>\n<p>You <em>could</em> simply branch off and delete all files, but I think this is the proper way to do it since they never shared the set of files.</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">git checkout --orphan empty-branch</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">git rm -rf . # or git reset -fd</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">git commit --allow-empty -m "root commit"</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">git push -u origin empty-branch</span></span></code></pre>\n</div><p><a href=\"https://stackoverflow.com/questions/34100048\" target=\"_blank\" rel=\"noreferrer\">https://stackoverflow.com/questions/34100048</a></p>\n",
"frontmatter": {
"excerpt": "all"
},
"html": "<p>Use this when you want to setup a new branch that contains a totally different set of files.</p>\n<p>You <em>could</em> simply branch off and delete all files, but I think this is the proper way to do it since they never shared the set of files.</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">git checkout --orphan empty-branch</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">git rm -rf . # or git reset -fd</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">git commit --allow-empty -m "root commit"</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">git push -u origin empty-branch</span></span></code></pre>\n</div><p><a href=\"https://stackoverflow.com/questions/34100048\" target=\"_blank\" rel=\"noreferrer\">https://stackoverflow.com/questions/34100048</a></p>\n",
"moreAvailable": false
},
{
"url": "/tech/tips/git/worktree",
"excerpt": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">alias gwt='git worktree'</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">cd repo/</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">gwt add -b branch ../repo@branch</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">cd ../repo@branch/</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"># do work...until done</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">cd ../repo/</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">gwt remove ../repo@branch</span></span></code></pre>\n</div><p>For more, read</p>\n<ul>\n<li><a href=\"https://git-scm.com/docs/git-worktree\" target=\"_blank\" rel=\"noreferrer\">https://git-scm.com/docs/git-worktree</a></li>\n<li>Particularly <a href=\"https://git-scm.com/docs/git-worktree#_examples\" target=\"_blank\" rel=\"noreferrer\">https://git-scm.com/docs/git-worktree#_examples</a></li>\n</ul>\n",
"frontmatter": {
"excerpt": "all"
},
"html": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">alias gwt='git worktree'</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">cd repo/</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">gwt add -b branch ../repo@branch</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">cd ../repo@branch/</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"># do work...until done</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">cd ../repo/</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">gwt remove ../repo@branch</span></span></code></pre>\n</div><p>For more, read</p>\n<ul>\n<li><a href=\"https://git-scm.com/docs/git-worktree\" target=\"_blank\" rel=\"noreferrer\">https://git-scm.com/docs/git-worktree</a></li>\n<li>Particularly <a href=\"https://git-scm.com/docs/git-worktree#_examples\" target=\"_blank\" rel=\"noreferrer\">https://git-scm.com/docs/git-worktree#_examples</a></li>\n</ul>\n",
"moreAvailable": false
}
],
"/tech/tips/": [
{
"url": "/tech/tips/index",
"excerpt": "",
"frontmatter": {},
"html": "<h1 id=\"tips-tricks\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#tips-tricks\">Tips & tricks</a></h1>\n<p>Tips, tricks, guides, snippets, best practices – organized by language and tools.</p>\n",
"moreAvailable": true
}
],
"/tech/tips/python/": [
{
"url": "/tech/tips/python/index",
"excerpt": "",
"frontmatter": {},
"html": "",
"moreAvailable": false
},
{
"url": "/tech/tips/python/snippet logging setup",
"excerpt": "<p>Use <code>logger.fatal/error/warn/info/debug</code> to write to file and/or <span style=\"color: red\">c</span><span style=\"color: purple\">o</span><span style=\"color: blue\">l</span><span style=\"color: cyan\">o</span><span style=\"color: green\">r</span><span style=\"color: yellow\">e</span><span style=\"color: orange\">d</span> output to console</p>\n",
"frontmatter": {},
"html": "<p>Use <code>logger.fatal/error/warn/info/debug</code> to write to file and/or <span style=\"color: red\">c</span><span style=\"color: purple\">o</span><span style=\"color: blue\">l</span><span style=\"color: cyan\">o</span><span style=\"color: green\">r</span><span style=\"color: yellow\">e</span><span style=\"color: orange\">d</span> output to console</p>\n<hr>\n<p>Example 1: <a href=\"https://yyin.dev/quick-notes/361-47404d\" target=\"_blank\" rel=\"noreferrer\">https://yyin.dev/quick-notes/361-47404d</a></p>\n<p>Example 2:</p>\n<ul>\n<li><a href=\"https://github.com/yifeiyin/CSC358-A2/blob/main/host.py#LL13-L19C31\" target=\"_blank\" rel=\"noreferrer\">https://github.com/yifeiyin/CSC358-A2/blob/main/host.py#LL13-L19C31</a></li>\n<li>Along with: <a href=\"https://github.com/yifeiyin/CSC358-A2/blob/main/log_helper.py\" target=\"_blank\" rel=\"noreferrer\">https://github.com/yifeiyin/CSC358-A2/blob/main/log_helper.py</a></li>\n<li>Note that this setup doesn't write the logs to a file</li>\n</ul>\n<p>Resource:</p>\n<ul>\n<li>Colored logging: <a href=\"https://stackoverflow.com/a/70796089/7318257\" target=\"_blank\" rel=\"noreferrer\">https://stackoverflow.com/a/70796089/7318257</a></li>\n</ul>\n",
"moreAvailable": true
},
{
"url": "/tech/tips/python/solve circular type dependency",
"excerpt": "<p>Simply add this to the start of the file</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">from __future__ import annotations</span></span></code></pre>\n</div>",
"frontmatter": {},
"html": "<p>Simply add this to the start of the file</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">from __future__ import annotations</span></span></code></pre>\n</div><hr>\n<p><a href=\"https://stackoverflow.com/questions/33837918/type-hints-solve-circular-dependency\" target=\"_blank\" rel=\"noreferrer\">python - Type hints: solve circular dependency - Stack Overflow</a></p>\n",
"moreAvailable": true
},
{
"url": "/tech/tips/python/the only way to create venv",
"excerpt": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">python -m venv venv</span></span></code></pre>\n</div><p><code>virtualenv</code>/<code>venv</code>/<code>pyenv</code>/<code>virtualenvwrapper</code>/etc all refer to different things... see <a href=\"https://stackoverflow.com/questions/41573587/what-is-the-difference-between-venv-pyvenv-pyenv-virtualenv-virtualenvwrappe\" target=\"_blank\" rel=\"noreferrer\">this stackoverflow</a> for an excellent explanation.</p>\n<p>You should call the environment <code>env</code> or <code>venv</code>, assuming it's created inside the project. Reasons:</p>\n<ul>\n<li>standardized gitignore</li>\n<li>potential script automation</li>\n<li>there's no point to give it a specific name – it's in project already</li>\n</ul>\n",
"frontmatter": {
"excerpt": "all"
},
"html": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">python -m venv venv</span></span></code></pre>\n</div><p><code>virtualenv</code>/<code>venv</code>/<code>pyenv</code>/<code>virtualenvwrapper</code>/etc all refer to different things... see <a href=\"https://stackoverflow.com/questions/41573587/what-is-the-difference-between-venv-pyvenv-pyenv-virtualenv-virtualenvwrappe\" target=\"_blank\" rel=\"noreferrer\">this stackoverflow</a> for an excellent explanation.</p>\n<p>You should call the environment <code>env</code> or <code>venv</code>, assuming it's created inside the project. Reasons:</p>\n<ul>\n<li>standardized gitignore</li>\n<li>potential script automation</li>\n<li>there's no point to give it a specific name – it's in project already</li>\n</ul>\n",
"moreAvailable": false
}
],
"/tech/tips/ruby-rails/": [
{
"url": "/tech/tips/ruby-rails/array hash methods",
"excerpt": "<ul>\n<li>\n<p><code>Array#filter === Array#select</code></p>\n</li>\n<li>\n<p><code>Array#map === Array#collect</code></p>\n</li>\n<li>\n<p><code>Array#member? === Array.include?</code></p>\n</li>\n<li>\n<p><code>Array#to</code> return the beginning of the array up to position (inclusive)</p>\n</li>\n<li>\n<p><code>Array#from</code> return the tail of the array from position (inclusive)</p>\n</li>\n<li>\n<p><code>Hash#slice</code> select keys from a hash</p>\n</li>\n<li>\n<p><code>Array#each</code> <code>Hash#each</code></p>\n</li>\n<li>\n<p><code>.map.with_index</code></p>\n</li>\n</ul>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">'abcd'.map.with_index {|x, i| x * i} #=> ["", "b", "cc", "ddd"]</span></span></code></pre>\n</div>",
"frontmatter": {
"excerpt": "all"
},
"html": "<ul>\n<li>\n<p><code>Array#filter === Array#select</code></p>\n</li>\n<li>\n<p><code>Array#map === Array#collect</code></p>\n</li>\n<li>\n<p><code>Array#member? === Array.include?</code></p>\n</li>\n<li>\n<p><code>Array#to</code> return the beginning of the array up to position (inclusive)</p>\n</li>\n<li>\n<p><code>Array#from</code> return the tail of the array from position (inclusive)</p>\n</li>\n<li>\n<p><code>Hash#slice</code> select keys from a hash</p>\n</li>\n<li>\n<p><code>Array#each</code> <code>Hash#each</code></p>\n</li>\n<li>\n<p><code>.map.with_index</code></p>\n</li>\n</ul>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">'abcd'.map.with_index {|x, i| x * i} #=> ["", "b", "cc", "ddd"]</span></span></code></pre>\n</div>",
"moreAvailable": false
},
{
"url": "/tech/tips/ruby-rails/attr_accessor",
"excerpt": "<p><code>attr_accessor/reader/writer</code></p>\n<ul>\n<li><code>attr_accessor</code> can read and write</li>\n<li><code>attr_reader</code> only read value</li>\n<li><code>attr_writer</code> only assign value</li>\n</ul>\n",
"frontmatter": {},
"html": "<p><code>attr_accessor/reader/writer</code></p>\n<ul>\n<li><code>attr_accessor</code> can read and write</li>\n<li><code>attr_reader</code> only read value</li>\n<li><code>attr_writer</code> only assign value</li>\n</ul>\n<hr>\n<p><a href=\"https://www.rubyguides.com/2018/11/attr_accessor/\" target=\"_blank\" rel=\"noreferrer\">https://www.rubyguides.com/2018/11/attr_accessor/</a></p>\n<p>We want expose internal value to outside world</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">class Food</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> def initialize(protein)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> @protein = protein</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> end</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">end</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">bacon = Food.new(21)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">-------</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">Define the following methods:</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> def protein</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> @protein</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> end</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> def protein=(value)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> @protein = value</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> end</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">------</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">OR simply have:</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">class Food</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\tattr_accessor :protein</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> ...</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">end</span></span></code></pre>\n</div>",
"moreAvailable": true
},
{
"url": "/tech/tips/ruby-rails/empty nil etc",
"excerpt": "<ul>\n<li><code>#empty?</code>\n<ul>\n<li>Ruby method; exists on Array, Set, Hash, String</li>\n<li>does not exist on all Enumerable</li>\n<li>on string: true iff it's empty string</li>\n</ul>\n</li>\n<li><code>#nil?</code>\n<ul>\n<li>Ruby method; exists on Object class</li>\n<li>true iff it's nil</li>\n</ul>\n</li>\n<li><code>#blank?</code>\n<ul>\n<li>Rails ActiveSupport method</li>\n<li>on string: true iff the string is whitespace only</li>\n<li>on array/set/hash: same as <code>#empty?</code></li>\n<li><code>true</code> is not blank, <code>nil & false</code> are blank</li>\n</ul>\n</li>\n<li><code>#present?</code>\n<ul>\n<li>opposite of <code>#blank?</code></li>\n</ul>\n</li>\n<li><code>#presence</code>\n<ul>\n<li>return self if present, else nil</li>\n</ul>\n</li>\n</ul>\n",
"frontmatter": {},
"html": "<ul>\n<li><code>#empty?</code>\n<ul>\n<li>Ruby method; exists on Array, Set, Hash, String</li>\n<li>does not exist on all Enumerable</li>\n<li>on string: true iff it's empty string</li>\n</ul>\n</li>\n<li><code>#nil?</code>\n<ul>\n<li>Ruby method; exists on Object class</li>\n<li>true iff it's nil</li>\n</ul>\n</li>\n<li><code>#blank?</code>\n<ul>\n<li>Rails ActiveSupport method</li>\n<li>on string: true iff the string is whitespace only</li>\n<li>on array/set/hash: same as <code>#empty?</code></li>\n<li><code>true</code> is not blank, <code>nil & false</code> are blank</li>\n</ul>\n</li>\n<li><code>#present?</code>\n<ul>\n<li>opposite of <code>#blank?</code></li>\n</ul>\n</li>\n<li><code>#presence</code>\n<ul>\n<li>return self if present, else nil</li>\n</ul>\n</li>\n</ul>\n<hr>\n<ul>\n<li><a href=\"https://stackoverflow.com/questions/57378498/is-there-a-benefit-to-rails-present-method\" target=\"_blank\" rel=\"noreferrer\"><code>if obj.present?</code> vs <code>if obj</code></a></li>\n<li><a href=\"https://blog.appsignal.com/2018/09/11/differences-between-nil-empty-blank-and-present.html\" target=\"_blank\" rel=\"noreferrer\">ref</a></li>\n<li><a href=\"https://github.com/rails/rails/blob/main/activesupport/lib/active_support/core_ext/object/blank.rb\" target=\"_blank\" rel=\"noreferrer\">source code</a></li>\n</ul>\n",
"moreAvailable": true
},
{
"url": "/tech/tips/ruby-rails/index",
"excerpt": "",
"frontmatter": {},
"html": "",
"moreAvailable": false
},
{
"url": "/tech/tips/ruby-rails/meta programming",
"excerpt": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">a = {}</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">a.methods</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">a.method(:to_json)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">a.method(:to_json).arity # get expected # of args</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> a.send(:slice, :key1, :key2)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">== a.method(:slice).call(:key1, :key2)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"># list all methods that ends with '?'</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">'abc'.methods.filter { |a| a.to_s.ends_with?('?') }</span></span></code></pre>\n</div>",
"frontmatter": {
"excerpt": "all"
},
"html": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">a = {}</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">a.methods</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">a.method(:to_json)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">a.method(:to_json).arity # get expected # of args</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> a.send(:slice, :key1, :key2)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">== a.method(:slice).call(:key1, :key2)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"># list all methods that ends with '?'</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">'abc'.methods.filter { |a| a.to_s.ends_with?('?') }</span></span></code></pre>\n</div>",
"moreAvailable": false
},
{
"url": "/tech/tips/ruby-rails/new object literal syntax (3.1+)",
"excerpt": "<p>ruby shorthand hash syntax (punning in js) (ruby 3.1+)</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">a = 1</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">b = 2</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">{ a:, b: }</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"># => { a: 1, b: 2 }</span></span></code></pre>\n</div>",
"frontmatter": {
"excerpt": "all"
},
"html": "<p>ruby shorthand hash syntax (punning in js) (ruby 3.1+)</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">a = 1</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">b = 2</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">{ a:, b: }</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"># => { a: 1, b: 2 }</span></span></code></pre>\n</div>",
"moreAvailable": false
},
{
"url": "/tech/tips/ruby-rails/print methods",
"excerpt": "<ul>\n<li><code>p</code> for each object, directly writes obj.inspect followed by a newline</li>\n<li><code>print</code> low level, does not add new line or seperator by default</li>\n<li><code>puts</code> like regular print</li>\n</ul>\n",
"frontmatter": {
"excerpt": "all"
},
"html": "<ul>\n<li><code>p</code> for each object, directly writes obj.inspect followed by a newline</li>\n<li><code>print</code> low level, does not add new line or seperator by default</li>\n<li><code>puts</code> like regular print</li>\n</ul>\n",
"moreAvailable": false
},
{
"url": "/tech/tips/ruby-rails/syntax class static method",
"excerpt": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">class A</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\tclass << self</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\t\tdef method</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\t \t...</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\t\tend</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\tend</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">end</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">is equivalent to</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">class A</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\tdef self.method</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\t\t...</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\tend</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">end</span></span></code></pre>\n</div>",
"frontmatter": {
"excerpt": "all"
},
"html": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">class A</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\tclass << self</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\t\tdef method</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\t \t...</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\t\tend</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\tend</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">end</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">is equivalent to</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">class A</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\tdef self.method</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\t\t...</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">\tend</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">end</span></span></code></pre>\n</div>",
"moreAvailable": false
},
{
"url": "/tech/tips/ruby-rails/syntax hash keys",
"excerpt": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">{ abc: 1 } === { :abc => 1 } === { "abc": 1 } !== { "abc" => 1 }</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">{ :abc=>"key is a symbol", "abc"=>"key is a string" }</span></span></code></pre>\n</div>",
"frontmatter": {
"excerpt": "all"
},
"html": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">{ abc: 1 } === { :abc => 1 } === { "abc": 1 } !== { "abc" => 1 }</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">{ :abc=>"key is a symbol", "abc"=>"key is a string" }</span></span></code></pre>\n</div>",
"moreAvailable": false
},
{
"url": "/tech/tips/ruby-rails/syntax method keyword args",
"excerpt": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">def initialize(consumable:, account:, amount:, reason:)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> @consumable = consumable</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> @account = account</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> @amount = amount</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> @reason = reason</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">end</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">initialize(consumable: 1, account: 2, amount: 3, reason: 4)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">**must use the keywords when calling the function**</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">def function(arg: 'default')</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> p arg</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">end</span></span></code></pre>\n</div>",
"frontmatter": {
"excerpt": "all"
},
"html": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">def initialize(consumable:, account:, amount:, reason:)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> @consumable = consumable</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> @account = account</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> @amount = amount</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> @reason = reason</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">end</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">initialize(consumable: 1, account: 2, amount: 3, reason: 4)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">**must use the keywords when calling the function**</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">def function(arg: 'default')</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> p arg</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">end</span></span></code></pre>\n</div>",
"moreAvailable": false
},
{
"url": "/tech/tips/ruby-rails/syntax variables starting with @",
"excerpt": "<p>Class variable scoping</p>\n<ul>\n<li><code>@@xxx</code> class variable</li>\n<li><code>@xxx</code> instance variable</li>\n</ul>\n",
"frontmatter": {
"excerpt": "all"
},
"html": "<p>Class variable scoping</p>\n<ul>\n<li><code>@@xxx</code> class variable</li>\n<li><code>@xxx</code> instance variable</li>\n</ul>\n",
"moreAvailable": false
},
{
"url": "/tech/tips/ruby-rails/ways to update",
"excerpt": "<p><img src=\"./../../../_assets/rails6-ways-to_update.png\" alt=\"\">\n<a href=\"https://scottbartell.com/2020/01/30/set-attributes-in-active-record-rails-6/\" target=\"_blank\" rel=\"noreferrer\">Image Source</a></p>\n",
"frontmatter": {
"excerpt": "all"
},
"html": "<p><img src=\"./../../../_assets/rails6-ways-to_update.png\" alt=\"\">\n<a href=\"https://scottbartell.com/2020/01/30/set-attributes-in-active-record-rails-6/\" target=\"_blank\" rel=\"noreferrer\">Image Source</a></p>\n",
"moreAvailable": false
}
],
"/tech/tips/shell/": [
{
"url": "/tech/tips/shell/different ways to write to file",
"excerpt": "<p>Any particular reason to use 2 or 3? probably none</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">... > out.txt</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">... | tee out.txt > /dev/null</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">... | cat > out.txt</span></span></code></pre>\n</div>",
"frontmatter": {
"excerpt": "all"
},
"html": "<p>Any particular reason to use 2 or 3? probably none</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">... > out.txt</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">... | tee out.txt > /dev/null</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">... | cat > out.txt</span></span></code></pre>\n</div>",
"moreAvailable": false
},
{
"url": "/tech/tips/shell/explain all kinds of arrows",
"excerpt": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">> Redirect stdout to a file, write</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">>> Redirect stdout to a file, append</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">2> Redirect stderr to a file</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">&> Redirect all to a file</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">>&2 Copies file descriptor to #2 to #1</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">2>&1 Copies file descriptor to #1 to #2</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">< Use file as stdin</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"><< here-document</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"><<< here-string</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"><(xxx) process substitution</span></span></code></pre>\n</div><p><a href=\"https://wiki.bash-hackers.org/howto/redirection_tutorial\" target=\"_blank\" rel=\"noreferrer\">Illustrated Redirection Tutorial [Bash Hackers Wiki]</a></p>\n<p><a href=\"https://askubuntu.com/questions/678915/whats-the-difference-between-and-in-bash\" target=\"_blank\" rel=\"noreferrer\">command line - What's the difference between <<, <<< and < < in bash? - Ask Ubuntu</a></p>\n",
"frontmatter": {
"excerpt": "all"
},
"html": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">> Redirect stdout to a file, write</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">>> Redirect stdout to a file, append</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">2> Redirect stderr to a file</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">&> Redirect all to a file</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">>&2 Copies file descriptor to #2 to #1</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">2>&1 Copies file descriptor to #1 to #2</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">< Use file as stdin</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"><< here-document</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"><<< here-string</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"><(xxx) process substitution</span></span></code></pre>\n</div><p><a href=\"https://wiki.bash-hackers.org/howto/redirection_tutorial\" target=\"_blank\" rel=\"noreferrer\">Illustrated Redirection Tutorial [Bash Hackers Wiki]</a></p>\n<p><a href=\"https://askubuntu.com/questions/678915/whats-the-difference-between-and-in-bash\" target=\"_blank\" rel=\"noreferrer\">command line - What's the difference between <<, <<< and < < in bash? - Ask Ubuntu</a></p>\n",
"moreAvailable": false
},
{
"url": "/tech/tips/shell/index",
"excerpt": "",
"frontmatter": {},
"html": "",
"moreAvailable": false
},
{
"url": "/tech/tips/shell/record shell session with scriptreplay",
"excerpt": "<p>record and replay everything happening in your terminal, with this linux utility tool.</p>\n",
"frontmatter": {},
"html": "<p>record and replay everything happening in your terminal, with this linux utility tool.</p>\n<hr>\n<h1 id=\"script-and-scriptreplay\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#script-and-scriptreplay\"><code>script</code> and <code>scriptreplay</code></a></h1>\n<p>record and replay everything happening in your terminal, with this linux utility tool.</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">$ man script</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> The script utility makes a typescript of everything printed on your terminal. It is useful</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> for students who need a hardcopy record of an interactive session as proof of an assignment,</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> as the typescript file can be printed out later with lpr(1).</span></span></code></pre>\n</div><p>macOS might require: <code>brew install util-linux</code></p>\n<p>To use:</p>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">script -a "$(date -Is)".log -t"$(date -Is)".time</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">scriptreplay -t=xxx.time xxx.log</span></span></code></pre>\n</div>",
"moreAvailable": true
},
{
"url": "/tech/tips/shell/shell flags",
"excerpt": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">set -x print each line before execute</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">set +x disble it</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">set -e exit when any command fails</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">set +e disable it</span></span></code></pre>\n</div>",
"frontmatter": {
"excerpt": "all"
},
"html": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">set -x print each line before execute</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">set +x disble it</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">set -e exit when any command fails</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">set +e disable it</span></span></code></pre>\n</div>",
"moreAvailable": false
},
{
"url": "/tech/tips/shell/snippet confirm to continue",
"excerpt": "<div class=\"language-shell\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\">shell</span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #676E95; font-style: italic\"># https://stackoverflow.com/a/3232082/7318257</span></span>\n<span class=\"line\"><span style=\"color: #82AAFF\">confirm</span><span style=\"color: #89DDFF\">()</span><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF\">{</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #676E95; font-style: italic\"># call with a prompt string or use a default</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #82AAFF\">read</span><span style=\"color: #A6ACCD\"> </span><span style=\"color: #C3E88D\">-r</span><span style=\"color: #A6ACCD\"> </span><span style=\"color: #C3E88D\">-p</span><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF\">"</span><span style=\"color: #A6ACCD; font-style: italic\">${1</span><span style=\"color: #89DDFF\">:-</span><span style=\"color: #A6ACCD\">Are</span><span style=\"color: #C3E88D\"> </span><span style=\"color: #A6ACCD\">you</span><span style=\"color: #C3E88D\"> </span><span style=\"color: #A6ACCD\">sure</span><span style=\"color: #C3E88D\">? </span><span style=\"color: #89DDFF\">[</span><span style=\"color: #C3E88D\">y/N</span><span style=\"color: #89DDFF\">]</span><span style=\"color: #A6ACCD; font-style: italic\">}</span><span style=\"color: #C3E88D\"> </span><span style=\"color: #89DDFF\">"</span><span style=\"color: #A6ACCD\"> </span><span style=\"color: #C3E88D\">response</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF; font-style: italic\">case</span><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF\">"</span><span style=\"color: #A6ACCD\">$response</span><span style=\"color: #89DDFF\">"</span><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF; font-style: italic\">in</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> [yY][eE][sS]</span><span style=\"color: #89DDFF\">|</span><span style=\"color: #A6ACCD\">[yY]</span><span style=\"color: #89DDFF\">)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #82AAFF\">true</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF\">;;</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF\">*)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #82AAFF\">false</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF\">;;</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF; font-style: italic\">esac</span></span>\n<span class=\"line\"><span style=\"color: #89DDFF\">}</span></span></code></pre>\n</div>",
"frontmatter": {
"excerpt": "all"
},
"html": "<div class=\"language-shell\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\">shell</span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #676E95; font-style: italic\"># https://stackoverflow.com/a/3232082/7318257</span></span>\n<span class=\"line\"><span style=\"color: #82AAFF\">confirm</span><span style=\"color: #89DDFF\">()</span><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF\">{</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #676E95; font-style: italic\"># call with a prompt string or use a default</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #82AAFF\">read</span><span style=\"color: #A6ACCD\"> </span><span style=\"color: #C3E88D\">-r</span><span style=\"color: #A6ACCD\"> </span><span style=\"color: #C3E88D\">-p</span><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF\">"</span><span style=\"color: #A6ACCD; font-style: italic\">${1</span><span style=\"color: #89DDFF\">:-</span><span style=\"color: #A6ACCD\">Are</span><span style=\"color: #C3E88D\"> </span><span style=\"color: #A6ACCD\">you</span><span style=\"color: #C3E88D\"> </span><span style=\"color: #A6ACCD\">sure</span><span style=\"color: #C3E88D\">? </span><span style=\"color: #89DDFF\">[</span><span style=\"color: #C3E88D\">y/N</span><span style=\"color: #89DDFF\">]</span><span style=\"color: #A6ACCD; font-style: italic\">}</span><span style=\"color: #C3E88D\"> </span><span style=\"color: #89DDFF\">"</span><span style=\"color: #A6ACCD\"> </span><span style=\"color: #C3E88D\">response</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF; font-style: italic\">case</span><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF\">"</span><span style=\"color: #A6ACCD\">$response</span><span style=\"color: #89DDFF\">"</span><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF; font-style: italic\">in</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> [yY][eE][sS]</span><span style=\"color: #89DDFF\">|</span><span style=\"color: #A6ACCD\">[yY]</span><span style=\"color: #89DDFF\">)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #82AAFF\">true</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF\">;;</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF\">*)</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #82AAFF\">false</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF\">;;</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> </span><span style=\"color: #89DDFF; font-style: italic\">esac</span></span>\n<span class=\"line\"><span style=\"color: #89DDFF\">}</span></span></code></pre>\n</div>",
"moreAvailable": false
},
{
"url": "/tech/tips/shell/snippet generate random chars",
"excerpt": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\"># All base 64 characters</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">cat /dev/urandom | base64 | head -c 10</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"># Alphanumerics only</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">cat /dev/urandom | base64 | tr -cd "[:upper:][:lower:][:digit:]" | head -c 16</span></span></code></pre>\n</div>",
"frontmatter": {
"excerpt": "all"
},
"html": "<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\"># All base 64 characters</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">cat /dev/urandom | base64 | head -c 10</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"># Alphanumerics only</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">cat /dev/urandom | base64 | tr -cd "[:upper:][:lower:][:digit:]" | head -c 16</span></span></code></pre>\n</div>",
"moreAvailable": false
},
{
"url": "/tech/tips/shell/what do the numbers in man page mean",
"excerpt": "<p><a href=\"https://unix.stackexchange.com/questions/3586/what-do-the-numbers-in-a-man-page-mean\" target=\"_blank\" rel=\"noreferrer\">What do the numbers in a man page mean? - Unix & Linux Stack Exchange</a></p>\n<p>Run <code>man man</code> to find out.</p>\n",
"frontmatter": {},
"html": "<p><a href=\"https://unix.stackexchange.com/questions/3586/what-do-the-numbers-in-a-man-page-mean\" target=\"_blank\" rel=\"noreferrer\">What do the numbers in a man page mean? - Unix & Linux Stack Exchange</a></p>\n<p>Run <code>man man</code> to find out.</p>\n<hr>\n<div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">$ man man</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">MANUAL SECTIONS</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> The standard sections of the manual include:</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> 1 User Commands</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> 2 System Calls</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> 3 C Library Functions</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> 4 Devices and Special Files</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> 5 File Formats and Conventions</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> 6 Games et. al.</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> 7 Miscellanea</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> 8 System Administration tools and Daemons</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"></span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> Distributions customize the manual section to their specifics,</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\"> which often include additional sections.</span></span></code></pre>\n</div><div class=\"language-\"><button title=\"Copy Code\" class=\"copy\"></button><span class=\"lang\"></span><pre v-pre class=\"shiki material-theme-palenight\" ><code><span class=\"line\"><span style=\"color: #A6ACCD\">$ man 1 printf</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">$ man 3 printf</span></span>\n<span class=\"line\"><span style=\"color: #A6ACCD\">$ man -a printf</span></span></code></pre>\n</div>",
"moreAvailable": true
}
],
"/tech/tips/ssh/": [
{
"url": "/tech/tips/ssh/agent forwarding",
"excerpt": "",
"frontmatter": {},
"html": "<p>Use case:</p>\n<ul>\n<li>Given that you can access GitHub locally</li>\n<li>You want to do GitHub things (clone, push, pull) on your remote server</li>\n<li>You don't want to generate a new key pair, or copy your private key to the server (because of security concerns or just the hurdle in general)</li>\n</ul>\n<p>Or,</p>\n<ul>\n<li>You have access to two separate servers</li>\n<li>You want to quickly transfer files between them</li>\n</ul>\n",
"moreAvailable": true
},
{
"url": "/tech/tips/ssh/index",
"excerpt": "",
"frontmatter": {
"noFileTree": true
},
"html": "<h1 id=\"all-the-power-that-comes-with-ssh\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#all-the-power-that-comes-with-ssh\">All the power that comes with SSH</a></h1>\n<p><strong>Every page here is empty. // TODO</strong></p>\n<ol>\n<li><a href=\"./know your setup.html\">know your setup</a> – how to use ssh efficiently</li>\n<li><a href=\"./scp.html\">scp</a> – <code>cp</code> but it's between ssh servers</li>\n<li><a href=\"./sftp and sshfs.html\">sftp and sshfs</a> – mount server's file system to your machine</li>\n<li><a href=\"./port forwarding.html\">port forwarding</a> – may the server localhost be your localhost</li>\n<li><a href=\"./agent forwarding.html\">agent forwarding</a> – ssh over ssh</li>\n<li><a href=\"./web proxy.html\">web proxy</a> – tunnel your web traffic over a quick VPN setup</li>\n<li><a href=\"./VSCode.html\">VSCode</a> – work remotely, GUI for sshfs + port forwarding</li>\n<li><a href=\"./speed test.html\">speed test</a> your ssh connection (pretty janky though)</li>\n</ol>\n",
"moreAvailable": true
},
{
"url": "/tech/tips/ssh/know your setup",
"excerpt": "",
"frontmatter": {},
"html": "<ul>\n<li>.ssh/ folder</li>\n<li>.ssh/config</li>\n<li>.ssh/known_host</li>\n<li>keys, keys provider</li>\n<li>troubleshoot using <code>-v</code></li>\n</ul>\n",
"moreAvailable": true
},
{
"url": "/tech/tips/ssh/port forwarding",
"excerpt": "",
"frontmatter": {},
"html": "",
"moreAvailable": false
},
{
"url": "/tech/tips/ssh/scp",
"excerpt": "",
"frontmatter": {},
"html": "",
"moreAvailable": false
},
{
"url": "/tech/tips/ssh/sftp and sshfs",
"excerpt": "",
"frontmatter": {},
"html": "",
"moreAvailable": false
},
{
"url": "/tech/tips/ssh/speed test",
"excerpt": "",
"frontmatter": {},
"html": "",
"moreAvailable": false
},
{
"url": "/tech/tips/ssh/VSCode",
"excerpt": "",
"frontmatter": {},
"html": "",
"moreAvailable": false
},
{
"url": "/tech/tips/ssh/web proxy",
"excerpt": "",
"frontmatter": {},
"html": "<p>aka VPN\nUsing <code>sshuttle</code></p>\n",
"moreAvailable": true
}
]
}
}