summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbdus <gh@abdus.net>2020-10-28 12:36:19 +0530
committerAbdus <gh@abdus.net>2020-10-28 12:36:19 +0530
commit79b75c140fba454b4421f8929cf1beef3cdbfa1f (patch)
treec3d287db98f3ed8ae8cd7706e4dec42030ca20cd
downloadabdus.net-79b75c140fba454b4421f8929cf1beef3cdbfa1f.tar.bz2
abdus.net-79b75c140fba454b4421f8929cf1beef3cdbfa1f.zip
initial commit
-rw-r--r--.github/workflows/gh-pages.yml30
-rw-r--r--.gitignore2
-rw-r--r--archetypes/default.md6
-rw-r--r--config.toml67
-rw-r--r--content/_index.md12
-rw-r--r--content/misc/neovim-logs.md17
-rw-r--r--content/notes/complete-ethical-hacking.md89
-rw-r--r--content/notes/dsa/analysis-of-algorithms.md18
-rw-r--r--content/notes/javascript-object-prototype.md140
-rw-r--r--content/notes/regexp.md71
-rw-r--r--content/notes/rust/ch-1-intro.md43
-rw-r--r--content/notes/rust/ch-10-slice-type.md53
-rw-r--r--content/notes/rust/ch-11-structures.md137
-rw-r--r--content/notes/rust/ch-12-structures-method-syntax.md116
-rw-r--r--content/notes/rust/ch-13-enums.md119
-rw-r--r--content/notes/rust/ch-14-match-operator.md35
-rw-r--r--content/notes/rust/ch-15-if-let.md45
-rw-r--r--content/notes/rust/ch-16-packages.md241
-rw-r--r--content/notes/rust/ch-17-vector-in-rust.md146
-rw-r--r--content/notes/rust/ch-18-string-in-rust.md98
-rw-r--r--content/notes/rust/ch-19-hash-maps-in-rust.md25
-rw-r--r--content/notes/rust/ch-2-cargo.md66
-rw-r--r--content/notes/rust/ch-20-handling-errors.md29
-rw-r--r--content/notes/rust/ch-3-guessing-game.md153
-rw-r--r--content/notes/rust/ch-4-variables-and-mutablity.md121
-rw-r--r--content/notes/rust/ch-5-data-types.md75
-rw-r--r--content/notes/rust/ch-6-functions.md91
-rw-r--r--content/notes/rust/ch-7-control-flow.md116
-rw-r--r--content/notes/rust/ch-8-ownership.md133
-rw-r--r--content/notes/rust/ch-9-references-and-borrowing.md101
-rw-r--r--content/notes/today-i-learned-general.md18
-rw-r--r--content/notes/today-i-learned-tech.md34
-rw-r--r--content/notes/tools/gnu-make.md177
-rw-r--r--content/notes/tools/registers-in-vim.md106
-rw-r--r--content/pages/hire.md19
-rw-r--r--content/pages/keys.md71
-rw-r--r--content/pages/self.md28
-rw-r--r--content/posts/_index.md3
-rw-r--r--content/posts/abortcontroller.md171
-rw-r--r--content/posts/finding-duplicate-files-in-linux.md184
-rw-r--r--content/posts/fixing-pip-issue-in-arch-linux.md54
-rw-r--r--content/posts/get-set-bash.md247
-rw-r--r--content/posts/github-profile-readme-as-twitter-like-feed.md91
-rw-r--r--content/posts/heroku-alternative-caprover-paas.md169
-rw-r--r--content/posts/intro-to-javascript.md75
-rw-r--r--content/posts/neomutt-the-command-line-email-client.md252
-rw-r--r--content/posts/recording-shell-output-the-right-way.md83
-rw-r--r--content/posts/session-management-in-vim.md187
-rw-r--r--content/posts/slice-type-in-rust.md132
-rw-r--r--data/personal.yaml39
-rw-r--r--themes/bronn/LICENSE20
-rw-r--r--themes/bronn/archetypes/default.md2
-rw-r--r--themes/bronn/archetypes/notes.md26
-rw-r--r--themes/bronn/archetypes/posts.md13
-rw-r--r--themes/bronn/layouts/404.html0
-rw-r--r--themes/bronn/layouts/_default/_markup/render-image.html12
-rw-r--r--themes/bronn/layouts/_default/baseof.html10
-rw-r--r--themes/bronn/layouts/_default/list.html36
-rw-r--r--themes/bronn/layouts/_default/single.html111
-rw-r--r--themes/bronn/layouts/index.html147
-rw-r--r--themes/bronn/layouts/partials/footer.html7
-rw-r--r--themes/bronn/layouts/partials/head.html16
-rw-r--r--themes/bronn/layouts/partials/nav.html30
-rw-r--r--themes/bronn/layouts/shortcodes/asciinema5
-rw-r--r--themes/bronn/layouts/shortcodes/caniuse.html13
-rw-r--r--themes/bronn/layouts/taxonomy/list.html15
-rw-r--r--themes/bronn/layouts/taxonomy/term.html36
-rw-r--r--themes/bronn/static/css/layout.css501
-rw-r--r--themes/bronn/static/css/syntax-dark.css82
-rw-r--r--themes/bronn/theme.toml21
70 files changed, 5638 insertions, 0 deletions
diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml
new file mode 100644
index 0000000..b53245c
--- /dev/null
+++ b/.github/workflows/gh-pages.yml
@@ -0,0 +1,30 @@
+name: github pages
+
+on:
+ push:
+ branches:
+ - master
+
+jobs:
+ deploy:
+ runs-on: ubuntu-18.04
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ submodules: true # Fetch Hugo themes (true OR recursive)
+ fetch-depth: 1 # Fetch all history for .GitInfo and .Lastmod
+
+ - name: Setup Hugo
+ uses: peaceiris/actions-hugo@v2
+ with:
+ hugo-version: 'v0.76.5'
+ extended: true
+
+ - name: Build
+ run: hugo --minify
+
+ - name: Deploy
+ uses: peaceiris/actions-gh-pages@v3
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: ./public
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3eec6c0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+resources
+public
diff --git a/archetypes/default.md b/archetypes/default.md
new file mode 100644
index 0000000..00e77bd
--- /dev/null
+++ b/archetypes/default.md
@@ -0,0 +1,6 @@
+---
+title: "{{ replace .Name "-" " " | title }}"
+date: {{ .Date }}
+draft: true
+---
+
diff --git a/config.toml b/config.toml
new file mode 100644
index 0000000..4ecae07
--- /dev/null
+++ b/config.toml
@@ -0,0 +1,67 @@
+baseURL = "https://abdus.net"
+languageCode = "en-us"
+title = "Abdus"
+
+theme = "bronn" # theme name
+disableKinds = [] # disable stuffs
+enableGitInfo = true # valuable git information
+enableEmoji = true # enables emoji support in content files
+
+[params]
+ title = "Abdus"
+ mainSections = ["posts"]
+
+[menu]
+
+ [[menu.main]]
+ identifier = "home"
+ name = "Home"
+ url = "/"
+ weight = 1
+
+ [[menu.main]]
+ identifier = "about"
+ name = "About"
+ url = "/self/"
+ weight = 10
+
+
+ [[menu.main]]
+ identifier = "hire-me"
+ name = "hire me"
+ url = "/hire/"
+ weight = 10
+
+ [[menu.main]]
+ identifier = "blog"
+ name = "blog"
+ url = "/posts/"
+ weight = 10
+
+ [[menu.main]]
+ identifier = "notes"
+ name = "notes"
+ url = "/notes/"
+ weight = 10
+
+[markup]
+[markup.tableOfContents]
+endLevel = 6
+ordered = false
+startLevel = 1
+
+[markup.highlight]
+codeFences = true
+guessSyntax = false
+hl_Lines = ''
+lineNoStart = 1
+lineNos = false
+lineNumbersInTable = false
+noClasses = false
+tabWidth = 2
+
+
+[permalinks]
+pages = "/:filename"
+posts = "/blog/:year/:title/"
+notes = "/notes/:filename"
diff --git a/content/_index.md b/content/_index.md
new file mode 100644
index 0000000..06b9d0a
--- /dev/null
+++ b/content/_index.md
@@ -0,0 +1,12 @@
+---
+title: "Abdus"
+description: Web &nbsp;&nbsp;&middot&nbsp&nbsp; Linux &nbsp;&nbsp;&middot&nbsp&nbsp; Open-Source
+meta:
+ description: |
+ Young Rustacean ·
+ JavaScript Developer ·
+ Open-Source Enthusiast ·
+ Linux Fanboy ·
+ (Neo)Vim for Life! ♥
+---
+
diff --git a/content/misc/neovim-logs.md b/content/misc/neovim-logs.md
new file mode 100644
index 0000000..2a56a22
--- /dev/null
+++ b/content/misc/neovim-logs.md
@@ -0,0 +1,17 @@
+---
+title: 'Neovim Logs'
+date: 2020-08-15T00:56:09+05:30
+draft: true
+meta:
+ image: # url to image. Important for blog listing and seo
+ description: # overrides .Summary
+tags: [logs]
+categories: [misc]
+---
+
+> This file would contain what changes I make to my vim config on a daily basis.
+
+### why
+
+I am keeping record because most of the time I forget what kind of software I am
+installing which are specific to (neo)vim.
diff --git a/content/notes/complete-ethical-hacking.md b/content/notes/complete-ethical-hacking.md
new file mode 100644
index 0000000..68f919c
--- /dev/null
+++ b/content/notes/complete-ethical-hacking.md
@@ -0,0 +1,89 @@
+---
+title: "Complete Ethical Hacking"
+date: 2020-10-20T23:40:32+05:30
+draft: true
+tags: []
+categories: []
+sources: []
+---
+
+<!--
+
+::Annotation Guide::
+~~~~~~~~~~~~~~~~~~~~
+
+* `em` is the modifier
+
+1. em (_text_) - blue underline
+2. strong (**text**) - yelow highlight
+3. del (~~text~~) - red strike-through
+
+4. em > em (_*text*_) - blue circle
+5. em > strong (_**text**_) - lawngreen box
+6. em > del (_~~text~~_) - red cross-off
+-->
+
+## Why Linux?
+
+- it's open-source
+- free of cost
+- environment for pen-testing
+- good for development
+- very light
+- varities of distributions
+
+## Network Commands in Linux
+
+`ifconfig` - shows interfaces and IP addresses corosponding to those interfaces
+
+- MAC Addr - Unique addresses for every device in the world. used to communicate
+ within local network
+- IP Addr - used to communicate over internet. may change.
+
+### Loopback Interface
+
+any traffic that computer sends to the loopback network is addressed to the same
+computer. loopback interface have IP address 127.0.0.0/8 The most common IP
+address for the loopback interface is 127.0.0.1 . Loopback interface is
+represented with `lo` in `iwconfig`/`ipconfig` output.
+
+although any interface can be used to identify the device, loopback interface
+is generally used.
+
+## Information Gathering
+
+- first step in pen-testing
+- act of gathering data for our target
+- any type of data which might help us achieve our shits
+
+### Types of Information Gathering
+
+**Active Info Gathering** from target(website etc)
+
+directly get the data from target. examples: direct packets exchange, talking
+with employes etc etc
+
+**Passive Info Gathering** from target
+
+collecting info from a middle source. example: google about target and gather
+data from a third party website etc
+
+### Goals
+
+- IP Address(s)
+- Employee Emails
+- Employee Phone Numbers
+- Technologies
+
+ - Operating System
+ - Networks
+ - Software
+
+### Tools for Gathering Information
+
+- _WhatWeb_ - Gather information about a website. for more info `man whatweb`
+- _theHarvester_ - Gather info about Email, Hostname and Username
+- _hunter.io_ - Gather info about Email
+- _redhawk_
+
+> Tools often fail. Find related tools in GitHub.
diff --git a/content/notes/dsa/analysis-of-algorithms.md b/content/notes/dsa/analysis-of-algorithms.md
new file mode 100644
index 0000000..e2f5bae
--- /dev/null
+++ b/content/notes/dsa/analysis-of-algorithms.md
@@ -0,0 +1,18 @@
+---
+title: "Analysis of Algorithms"
+date: 2020-07-31T21:42:44+05:30
+draft: false
+tags: ["competitive programming", "ds & algo", "algorithms"]
+categories:
+ - dsa
+sources:
+ - https://www.geeksforgeeks.org/analysis-of-algorithms-set-1-asymptotic-analysis/
+---
+
+why **performance analysis**? because it is important for a software to
+_scale_
+
+
+### Asymptotic Analysis
+
+1. [Geeks For Geeks](https://www.geeksforgeeks.org/analysis-of-algorithms-set-1-asymptotic-analysis/)
diff --git a/content/notes/javascript-object-prototype.md b/content/notes/javascript-object-prototype.md
new file mode 100644
index 0000000..7a49657
--- /dev/null
+++ b/content/notes/javascript-object-prototype.md
@@ -0,0 +1,140 @@
+---
+title: "Javascript Object Prototype"
+date: 2020-09-24T13:24:30+05:30
+draft: true
+tags: []
+categories: []
+sources: []
+---
+
+<!--
+
+::Annotation Guide::
+~~~~~~~~~~~~~~~~~~~~
+
+* `em` is the modifier
+
+1. em (_text_) - blue underline
+2. strong (**text**) - yelow highlight
+3. del (~~text~~) - red strike-through
+
+4. em > em (_*text*_) - blue circle
+5. em > strong (_**text**_) - lawngreen box
+6. em > del (_~~text~~_) - red cross-off
+-->
+
+# Object
+
+Object is `Class`. Almost **everything** in JavaScript is Object.
+
+> All JavaScript values, except premitives, are object.
+
+## Object Properties
+
+Named value in JavaScript objects are called _properties_.
+example:
+
+ const person = {
+ name: 'Jon',
+ age: 23
+ }
+
+ person.name // property
+ person.age // property
+
+### Accessing Object Properties
+
+Object properties can be accessed in multiple ways.
+
+1. `person.name`
+2. `person["name"]`
+3. `const x = "name"; person[x]`
+
+## Object Methods
+
+An Object property is an Object method containing function definition.
+example:
+
+ const person = {
+ name: 'Jon',
+ age: 23,
+ sayHi() {
+ console.log("Hi, " + this.name);
+ }
+ }
+
+ person.sayHi // method
+
+### Accessing Methods
+
+Similar to accessing object properties, methods can be accessed in multiple
+ways.
+
+1. `person.sayHi()`
+2. `person["sayHi"]()`
+3. `const x = "sayHi"; person[x]()`
+
+## Object Creation
+
+Objects can be created in multiple ways. Following are the ways explained in
+detail.
+
+### Object Literal
+
+Most simplest list
+of `key: value` pair inside curly braces {}
+
+ const person = {
+ name: 'Jon'
+ }
+
+### Using `new` Keyword
+
+If `Object()` is invoked with a `new` keyword, it will return an object.
+
+ const person = new Object();
+ person.name = 'jon';
+ person.sayHi = function sayHi() {
+ console.log("Hi, " + this.name);
+ }
+
+### Using Constructor
+
+To create
+constructor is nothing but a function invoked with new keyword.
+
+ function Person (name) {
+ this.name = name;
+ }
+
+ Person.prototype.sayHi = function sayHi() {
+ console.log("Hi, " + this.name);
+ }
+
+ const person = new Person('Jon');
+ person.name // prop
+ person.sayHi // method
+
+<div class="org-center">
+<p>
+The first two ways of defining objects does exactly the same thing. It&rsquo;s better
+to use object literals to create objects in terms of <b>performence</b>, <b>readablity</b>
+and <b>execution speed</b>.
+</p>
+</div>
+
+## Object Mutablity
+
+JavaScript objects are mutable by default. Meaning, they can be easily modified
+after they are defined.
+
+When new variable, the new variable would point to the
+location of old object instead of copying it.
+example:
+
+ const person = { name: 'Jon', age: 23 };
+ const person2 = person; // person === person2
+
+## Looping in Object
+
+TBD
diff --git a/content/notes/regexp.md b/content/notes/regexp.md
new file mode 100644
index 0000000..d2a952e
--- /dev/null
+++ b/content/notes/regexp.md
@@ -0,0 +1,71 @@
+---
+title: "Regular Expression"
+date: 2020-08-28T00:53:22+05:30
+draft: false
+tags: []
+categories: [misc]
+sources:
+ - https://github.com/ziishaned/learn-regex
+---
+
+<!--
+
+::Annotation Guide::
+~~~~~~~~~~~~~~~~~~~~
+
+* `em` is the modifier
+
+1. em (_text_) - blue underline
+2. strong (**text**) - yelow highlight
+3. del (~~text~~) - red strike-through
+
+4. em > em (_*text*_) - blue circle
+5. em > strong (_**text**_) - lawngreen box
+6. em > del (_~~text~~_) - red cross-off
+-->
+
+A regular expression is a **group of characters or symbols** which is used
+to find a **specific pattern in a text**.
+
+![regex](https://raw.githubusercontent.com/ziishaned/learn-regex/master/img/regexp-en.png)
+
+- a string literal is the simplest possible regular expression. `"str"` would
+ match _**str(`s` followed by `t`, followed by `r`)**_.
+- regular expression are generally **case sensitive**
+
+## Meta Characters
+
+- special characters. does not mean anything on their own.
+- some meta character have different meaning when written inside square bracket
+
+| meta char | desc |
+| :---------------------- | :----------------------------------------------------------------------------- |
+| `.` | match any single character except for linebreak |
+| `[]` | char class. matches any char contained between the brackets |
+| `[^ ]` | negated char class. matches any character _NOT_ contained between the brackets |
+| `*` | matches 0 or more repetitions of the preceeding symbol |
+| `+` | match one or more repetitions of preceeding symbol |
+| `?` | makes the preceeding symbol optional |
+| `{n,m}` | match at least `n` but not more than `m` repetitions of preceeding symbol |
+| `(abc)` | char group |
+| `|` | alteration. matches either the chars before or the chars after the symbol |
+| `\` | escapes character |
+| `^` | beginning of the input |
+| `$` | end of the input |
+
+### Things to Remember
+
+set **character range** by using **hyphen** inside character class.
+Example: `/[a-z0-9]/`.
+
+a **period inside a char set** means a literal period
+
+**the `*` (star) with a `.` (dot)** can be used to **match any string of
+characters**. Example: `.*`
+
+braces(also called **quantifiers**) are used to specify the **number of times**
+a character or a group of character **can be repeated**.
+Examples:
+- `[0-9]{3}` - matches _**exactly 3 digits**_.
+- `[a-z]{2,}` - matches _**between 2 and unlimited**_ times
+- `[A-Z]{2, 5}` - matches between _**3 and 5 times**_
diff --git a/content/notes/rust/ch-1-intro.md b/content/notes/rust/ch-1-intro.md
new file mode 100644
index 0000000..cb3ffbe
--- /dev/null
+++ b/content/notes/rust/ch-1-intro.md
@@ -0,0 +1,43 @@
+---
+title: Intro to Rust
+date: 2020-04-19T13:56:28+05:30
+categories: [rust]
+---
+
+> Rust is a statically typed language backed by Mozilla. Rust have no built-in garbage-collection mechanism, yet it gives the maximum possible security to memory leaks.
+
+## 1. The `fn` Keyword
+
+`fn` is a reserved keyword in Rust. It's used for declaring a function.
+
+## 2. The `main()` function
+
+```rs
+fn main() {
+
+}
+```
+
+`main()` function is the entry point of any Rust program. Execution of codes start from here. `main()` function nerither accepts parameter, nor returns anything.
+
+## 3. The `println!` macro
+
+```rs
+fn main() {
+ println!("string");
+}
+```
+
+`println!()` macro is used to print a line to the console. Note the exclamation mark(!) at the end. This is what separates macros from regular functions.
+
+## _Ahead of Time_ Compilation
+
+Rust is an _ahead-of-time_ compiled language. This means, any user having a binary of Rust source-code, could run it even without having the Rust envirnment installed.
+
+## `rustfmt`
+
+`rustfmt` is a standardized Rust formatter. This formatter uses a predefined sets of rules to format source in order to maintain code consistency.
+
+## Example Codes
+
+1. `sources/hello-world.rs`
diff --git a/content/notes/rust/ch-10-slice-type.md b/content/notes/rust/ch-10-slice-type.md
new file mode 100644
index 0000000..9911077
--- /dev/null
+++ b/content/notes/rust/ch-10-slice-type.md
@@ -0,0 +1,53 @@
+---
+date: 2020-05-20T08:47:30+05:30
+title: Slice Type
+tags: ['slice']
+categories:
+ - rust
+---
+
+> Another data type that **does not have ownership** is the slice. Slices let you reference a contiguous sequence of elements in a collection rather than the whole collection.
+
+## Slicing an `String`
+
+```rs
+let s = String::from("Hello, world");
+
+let hello = &s[0..5];
+```
+
+1. If the initial range index is 0(i.e. first index), it could be omitted.
+
+2. If the last range index is 0(i.e. last index), it could be omitted as well.
+
+For example: `&s[..]` would reference the whole string(`"Hello, world"`), instead of referencing a part of it.
+
+> In Rust, `..` is called as range syntax.
+
+#### A program to return first word from given string:
+
+```rs
+fn main() {
+ let s = String::from("Hello, world");
+
+ let word = get_first_word(&s);
+
+ s.clear(); // this line would throw error as it
+ // was borrowed as immutable before
+}
+
+
+fn get_first_word(s: &str) -> &str {
+ let str_bytes = s.as_bytes();
+
+ for (i, &item) in str_bytes.iter().enumerate() {
+ if item == b' ' {
+ return &s[0..i];
+ }
+ }
+
+ return &s[..];
+}
+```
+
+Note: When a parameter is declared as type `slice`, it would be able to accept type `String` as well as type `Slice`. But type `String` can't accept type `Slice`.
diff --git a/content/notes/rust/ch-11-structures.md b/content/notes/rust/ch-11-structures.md
new file mode 100644
index 0000000..4f1e757
--- /dev/null
+++ b/content/notes/rust/ch-11-structures.md
@@ -0,0 +1,137 @@
+---
+date: 2020-05-20T09:30:00+05:30
+title: Structures
+tags: ['structures', 'struct']
+categories:
+ - rust
+---
+
+Structures(`struct`) are compound(and user-defined) data types. Structures are much similar to tuples, except that data can named. Structures can be set as a return type in a function.
+
+## Defining a Struct
+
+Structures are defined using the keyword `struct`. Example:
+
+```rs
+struct Person {
+ name: String,
+ age: u64,
+ sex: karwa_do,
+}
+```
+
+## Instantiating Structs
+
+In order to create a new instance of an Structure, one has to call that structure with concrete values. Example:
+
+```rs
+fn main() {
+ let person1 = Person {
+ name: "Jon",
+ age: 632,
+ sex: "male",
+ }
+}
+```
+
+## Accessing and Mutating values
+
+Dot notation could be used to access a specific value. A structure must be declared as mutable if it needs to be mutated on a later stage. Individual values can't be mutated. Example:
+
+```rs
+
+Person {
+ name: String,
+ age: u64,
+ sex: String,
+}
+
+fn main() {
+ let mut person1 = Person {
+ name: "Jon",
+ age: 632,
+ sex: "male",
+ };
+
+ person1.name = String::from("Jon Snow");
+ println!("Name is {}", person1.name);
+}
+```
+
+## Other Useful Things
+
+1. If function parameter and `struct`'s property name is same, the value part could be omitted. For example, `let p1 = Person{ name }`(assuming that `name` is a function parameter).
+
+2. **Struct update syntax** can be used to copy property from another instance of the same `struct`. For example:
+
+```rs
+fn main() {
+ let p1 = Person {
+ name: "Jon",
+ age: 32,
+ sex: "male",
+ };
+
+ let p2 = Person {
+ name: "Tormund",
+ age: 40,
+ ..p1 // this would copy the value of
+ // p1.age to this instance
+ }
+}
+```
+
+## Tuple Struct
+
+Tuple struct looks similar to tuples. Unlike tuple, tuple struct does have a name.
+
+```rs
+struct Color(i32, i32, i32);
+
+let black = Color(0, 0, 0);
+```
+
+## Example Code Snippet using Struct
+
+```rs
+#[derive(Debug)]
+struct Rectangle {
+ width: i32,
+ height: i32,
+}
+
+fn main() {
+ let r1 = Rectangle {
+ height: 30,
+ width: 20,
+ };
+
+ println!("Rectangle is {:#?}", r1);
+ println!("Area is {}", area(&r1));
+}
+
+fn area(dimension: &Rectangle) -> i32 {
+ dimension.height * dimension.width
+}
+```
+
+**Note:**
+
+1. By default, `println!` mecro can not print structures. A formatter `:?`(`:#?` for pretty print) should be added. Example: `println!("Rectangle is {:#?}", struct_instance);`
+
+2. `#[derive(Debug)]` - Implements `std::fmt::Debug` in `struct Rectangle`. Without this method, above formatter won't work.
+
+3. `&Rectangle` is used so that the `main` function can keep the ownership of `r1` instance.
+
+> Structures could be anonymous as well as named. For example:
+
+```rs
+enum Rect {
+ Dimension {
+ height: u32,
+ width: u32,
+ }
+}
+```
+
+`Rect::Dimension` is an anonymous struct
diff --git a/content/notes/rust/ch-12-structures-method-syntax.md b/content/notes/rust/ch-12-structures-method-syntax.md
new file mode 100644
index 0000000..72f6b2f
--- /dev/null
+++ b/content/notes/rust/ch-12-structures-method-syntax.md
@@ -0,0 +1,116 @@
+---
+date: 2020-05-24T10:34:27+05:30
+title: 'Structures: Method Syntax'
+tags: ['structures', 'struct', 'method']
+categories:
+ - rust
+---
+
+Methods are smiilar to function. Unlike functions, methods are defined within the context of a structure(or an enum or a trait object).
+
+A method(s) is defined using `impl` keyword.
+
+> Method's first parameter is always `self`, which represents the instance of the struct the method is being called on.
+
+## Using Method Syntax
+
+```rs
+struct Rect {
+ height: i32,
+ width: i32,
+}
+
+impl Rect {
+ fn area(&self) -> i32 {
+ self.width * self.height
+ }
+}
+
+fn main() {
+ let r1 = Rect {
+ height: 4,
+ width: 5,
+ };
+
+ println!("Area: {}", r1.area()); // 20
+}
+```
+
+In above example, `area()` is a method of `struct Rect`. `&self` is refers to the `struct` where it is defined. `&self` is passed by reference because we don't need its ownership.
+
+A method can **accept multiple parameters**. Following is an example:
+
+```rs
+struct Rect {
+ height: i32,
+ width: i32,
+}
+
+impl Rect {
+ fn area(&self) -> i32 {
+ self.width * self.height
+ }
+
+ fn can_hold(&self, r: &Rect) -> bool {
+ self.width > r.width && self.height > r.height
+ }
+}
+
+fn main() {
+ let r1 = Rect {
+ height: 4,
+ width: 5,
+ };
+
+ let r2 = Rect {
+ height: 2,
+ width: 3,
+ };
+
+ println!("Area: {}", r1.area()); // 20
+ println!("Can Hold r2: {}", r1.can_hold(&r2)); // true
+}
+```
+
+**Multiple `impl` block** to a same struct can exist. Example:
+
+```rs
+struct Rect {
+ height: i32,
+ width: i32,
+}
+
+impl Rect {
+ fn area(&self) -> i32 {
+ self.width * self.height
+ }
+}
+
+imple Rect {
+ fn can_hold(&self, r: &Rect) -> bool {
+ self.width > r.width && self.height > r.height
+ }
+}
+```
+
+## Associated Functions
+
+Associated functions are similar to methods, except that they won't have access to any instance of the `struct` they were defined in. This is because they don't accept a `self` parameter. `String::from()` is a associated function. Associated functions are called **directly on the `struct`**, unlike methods which are called upon instances.
+
+They generally return a new instance of the `struct` they were defined in. For example:
+
+```rs
+struct Rect {
+ height: i32,
+ width: i32,
+}
+
+impl Rect {
+ fn square(size: i32) -> Rect {
+ Rect {
+ height: size,
+ width: size,
+ }
+ }
+}
+```
diff --git a/content/notes/rust/ch-13-enums.md b/content/notes/rust/ch-13-enums.md
new file mode 100644
index 0000000..f65956d
--- /dev/null
+++ b/content/notes/rust/ch-13-enums.md
@@ -0,0 +1,119 @@
+---
+date: 2020-06-02T01:50:27+05:30
+title: 'Enum'
+tags: ['enum']
+categories: [rust]
+---
+
+> `enum` is a type that can be any one of several variants.
+
+## Enum Example
+
+```rust
+enum IPAddrKind {
+ V4,
+ V6,
+}
+```
+
+## Enum Values
+
+Enum values can be accessed using `::` which is useful. Reason is, each value inside that given enum is of same type. For example:
+
+```rs
+enum IPAddrKind {
+ V4,
+ V6,
+}
+
+fn main() {
+ let version_four = IPAddrKind::V4;
+ let version_six = IPAddrKind::V6;
+
+ // following are valid
+ route(IPAddrKind::V4);
+ route(IPAddrKind::V6);
+}
+
+// `ip_kind` would accept both `V4` and `v6`
+fn route(ip_kind: IPAddrKind) -> bool {
+ true
+}
+```
+
+## Attaching data
+
+```rs
+enum IPAddrKind {
+ V4(String),
+ V6(String),
+}
+
+fn main() {
+ let home = IPAddrKind::V4(String::from("127.0.0.1"));
+ let loopback = IPAddrKind::V6(String::from("::1"));
+}
+```
+
+An enum could hold any kind of data; be it a `struct`, integers, string, or even another enum etc etc. For example:
+
+```rs
+struct IPv4Addr {
+ addr: String,
+}
+
+struct IPv6Addr {
+ addr: String,
+}
+
+enum IPAddr {
+ V4(IPv4Addr),
+ V6(IPv6Addr),
+}
+```
+
+> The advantage of defining `enum` over `struct` is that all data that it would be holding, will be under a same namespace. This would make passing them as function argument easier.
+
+## The `Option` enum
+
+Rust does not have `null`, because they believe that it would probably bring some unintentional errors to the code.
+
+Rust handles the concept of whether a value is present or absent in a diiferent way. `Option` enum is a predefined enum which have two variants: `Some` and `None`. `Some` can hold any kind of data. And `None` would hold nothing, obviously.
+
+```rs
+enum Option<T> {
+ Some(T),
+ None,
+}
+```
+
+The `<T>` syntax is a generic type parameter. This means the `Some` variant of `Option` can hold one piece of data of any type.
+
+enum `Option` is included in prelude. One does not have to explicitly bring it in scope. Even the variants of `Option` are directly available for use.
+
+Example:
+
+```rs
+let some_number = Some(5);
+let some_str = Some("Hello");
+
+let absent_number: Option<i32> = None;
+```
+
+It is important to mention data type when using `None`. Compiler can't extract the type from `None` variant to assign it to `Some`.
+
+Note that the `Option<T>` and `T`(where `T` holds a value of any type) are not same. That's because, let's say, we stored a `i32` value in `T` and assigned it to a variable. Now what compiler unserstands is `i32` is a premitive data type, whereas `Option<i32>` is of type `Option`. Doing any operation between `i32` and `Option<i32>` would result in an error.
+
+This prevents programmer from making errors by assuming a value is not null when it actually is. In order to perform any ops with `Option<i32>`, one must convert it to type `i32`. There are utility methods like `is_some`, `is_none`, `clone` are available under `Option` enum which could be used to carry out conversions.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/content/notes/rust/ch-14-match-operator.md b/content/notes/rust/ch-14-match-operator.md
new file mode 100644
index 0000000..7cd06d1
--- /dev/null
+++ b/content/notes/rust/ch-14-match-operator.md
@@ -0,0 +1,35 @@
+---
+date: 2020-06-03T12:48:31+05:30
+title: "Match Control flow"
+categories: [rust]
+tags: ["control-flow", "match"]
+---
+
+`match` is a control flow operator. It works similar to a coin sorting machine,
+i.e. it would start matching patterns(a.k.a arms) from top to bottom until
+it finds a matching pattern. Example:
+
+```rs
+enum Coin {
+ Penny,
+ Nickel,
+ Dime,
+ Quarter
+}
+
+fn match_coin(coin: Coin) -> u8 {
+ match coin {
+ Coin::Penny => 1,
+ Coin::Nickel => 5,
+ Coin::Dime => 10,
+ Coin::Quarter => 25,
+ }
+}
+
+fn main() {
+ let c = match_coin(Coin::Penny);
+ println!("{}", c);
+}
+```
+
+[Skipped this chapter. Gotta finish it later on]
diff --git a/content/notes/rust/ch-15-if-let.md b/content/notes/rust/ch-15-if-let.md
new file mode 100644
index 0000000..b0fbd38
--- /dev/null
+++ b/content/notes/rust/ch-15-if-let.md
@@ -0,0 +1,45 @@
+---
+date: 2020-06-03T12:48:31+05:30
+title: "Concise Control Flow with if-let"
+tags: ["control-flow", "match"]
+categories: [rust]
+---
+
+`if let` syntax allows to write `if` and `let` togather in a less verbose way
+to handle values that match one pattern while ignoring the rest.
+
+Example:
+
+```rust
+let some_var = Some(0u8);
+match some_var {
+ Some(3) => println!("three"),
+ _ => (),
+}
+```
+
+can be written as:
+
+```rust
+if let Some(3) = some_var {
+ println!("three");
+}
+```
+
+> `if let` is a syntax sugar for `match` that runs code when the value matches
+one pattern and then ignores all other values.
+
+An `else` block could as well be attached into `if let`. This `else` block
+would work like a wildcard, i.e.`_` in `match` can be replaced by `else` in
+`if let`.
+
+Example:
+
+```rust
+let mut count = 0;
+if let Coin::Quarter(state) = coin {
+ println!("State quarter from {:?}!", state);
+} else {
+ count += 1;
+}
+```
diff --git a/content/notes/rust/ch-16-packages.md b/content/notes/rust/ch-16-packages.md
new file mode 100644
index 0000000..c449131
--- /dev/null
+++ b/content/notes/rust/ch-16-packages.md
@@ -0,0 +1,241 @@
+---
+date: 2020-06-09T19:45:17+05:30
+title: "Package Management"
+categories: [rust]
+tags: ["package"]
+---
+
+Package management comes into play when a project gets bigger and bigger.
+Dividing codes into multiple files and grouping them make a project more
+maintainable.
+
+A package can contain multiple binary crate and optionally one library crate.
+
+Additionally, a package can help encapsulate codes that are not meant for
+others to see. It can also enable scoping.
+
+Rust's Module System:
+
+- Packages: Cargo feature that let user build, test and share crates
+- Crates: A tree of modules that produces a library or executable
+- Modules and `use`: Let user contron the organization, scope and encapsulation.
+- Paths: A way of naming an item, such as `struct`, function or module
+
+## Understanding `cargo new project-name`
+
+When user runs `cargo new project-name`, Cargo generates a couple of files
+inside `project-name` directory. They are: config.toml and `src/main.rs`.
+
+`config.toml` is the configuration file. This file contains dependancies and
+other project related informations.
+
+`src/main.rs` is the entry point for the Rust compiler. One does not have to
+mention entry point in config file, as Rust treats `main.rs` as entry point
+by convention. Similarly, `src/lib.rs` means the project contains a library
+crate with the same name as package. There can be any number of binaries
+inside `bin/` directory.
+
+## The `mod`
+
+`mod` token stands for module. It can be used to declare a module. A module
+can host multiple modules nested inside it. Other than modules, it can
+hold `struct`, functions etc.
+
+An example:
+
+```rust
+mod front_of_the_house {
+ mod hosting {
+ fn add_to_wishlist() {};
+ }
+}
+```
+
+## Paths
+
+Rust find the codes we want to use by path. A path can be relative or absolute.
+Absolute path starts with crate name or literal `crate`.
+
+A relative path, on the other hand, starts from the current module and uses
+`self`, `super` or an indetifier in current module.
+
+Both absolute and relative paths are followed by one or more indetifier
+separated by `::`.
+
+Example:
+
+```rust
+pub fn call_them() {
+ // absolute path
+ crate::front_of_the_house::hosting::add_to_wishlist();
+
+ // relative path
+ front_of_the_house::hosting::add_to_wishlist();
+}
+```
+
+## Exposing Paths using `pub`
+
+By default, a path is always private. In order to make it public, `pub` keyword
+must be prepend.
+
+Example:
+
+```rust
+mod front_of_the_house {
+ mod hosting {
+ fn add_to_wishlist() {};
+ }
+}
+```
+
+## Relative path using `super`
+
+`super` keyword is similar to UNIX `..` operator. It refers to parent module.
+
+## Making `enum` and `struct` public
+
+Prepeding `pub` keyword to a `struct` or `enum` would make it public.
+However, an extra step would require for making `struct` field public.
+One need to prepend `pub` keyword to any field that are supposed to be public.
+
+Example:
+
+```rust
+mod back_of_house {
+ pub struct Breakfast {
+ pub toast: String,
+ seasonal_fruit: String,
+ }
+
+ impl Breakfast {
+ pub fn summer(toast: &str) -> Breakfast {
+ Breakfast {
+ toast: String::from(toast),
+ seasonal_fruit: String::from("peaches"),
+ }
+ }
+ }
+}
+
+pub fn eat_at_restaurant() {
+ let mut meal = back_of_house::Breakfast::summer("Rye");
+
+ meal.toast = String::from("Wheat");
+ println!("I'd like {} toast please", meal.toast);
+}
+```
+
+## The `use` Keyword
+
+`use` keyword brings function, `struct` etc into the scope where it is being
+called from. Example:
+
+```rust
+mod front_of_house {
+ pub mod hosting {
+ pub fn add_to_waitlist() {}
+ }
+}
+
+use front_of_the_house::hosting;
+
+hosting::add_to_waitlist(); // this will refer to module `front_of_the_house`
+```
+
+It is wise to call parent(or a location) which clearly explains where the said
+variable is defined, instead of just the associated function.
+
+```rust
+use front_of_the_house::hosting::add_to_waitlist; // not good
+use front_of_the_house::hosting; // good. now we know where it is defined
+```
+
+Apart from that, bringing same two or more types with same name into scope
+requires to call their parent modules.
+
+```rust
+use std::fmt;
+use std::io;
+
+fn function1() -> fmt::Result {}
+
+fn function2() -> io::IoResult<()> {}
+```
+
+## The `as` keyword
+
+`as` keyword can rename a module so that things does not conflict with each
+other.
+
+```rust
+use std::fmt::Result;
+use std::io::Result as IoResult;
+
+fn function1() -> Result {}
+
+fn function2() -> IoResult<()> {}
+```
+
+## Re-exporting an imported name
+
+When bringing in a name into scope using `use`, the name is private to current
+scope. This name could be re-exported for external codes to call it.
+
+```rust
+pub use crate::front_of_the_house::hosting;
+```
+
+In above example, anything that is attached to `hosting` that is public,
+would become available for external codes to call.
+
+## Using external packages
+
+In order to use an external crate from crates.io, one needs to define it in
+`Cargo.toml` file. When building the project, `cargo` automatically downloads
+all mentioned crates from `Cargo.toml` and adds them to project.
+
+```toml
+// Cargo.toml
+[dependencies]
+rand = "0.5.5"
+```
+
+Calling `rand` in code:
+
+```rust
+use rand::Rng;
+
+fn main() {
+ let number = rand::thread_rng().gen_range(1, 101);
+}
+```
+
+## Using nested paths
+
+Different varient of `use` keyword can be used to reduce `use` list.
+
+```rust
+// SAME PREFIX
+
+// this ...
+use std::cmp::Ordering;
+use std::io;
+
+// can be written as ...
+use std::{cmp::Ordering, io};
+
+
+
+// ELIMINATE COMMON PART
+
+use std::io;
+use std::io::Write;
+// to
+use std::io::{self, Write};
+```
+
+## Glob Operator (`*`)
+
+Glob operator bring every public names into scope.
+Example: `use std::collections::*;`
diff --git a/content/notes/rust/ch-17-vector-in-rust.md b/content/notes/rust/ch-17-vector-in-rust.md
new file mode 100644
index 0000000..b3a341f
--- /dev/null
+++ b/content/notes/rust/ch-17-vector-in-rust.md
@@ -0,0 +1,146 @@
+---
+title: "Vector in Rust"
+date: 2020-08-12T08:36:16+05:30
+draft: false
+tags: [vector, collection]
+categories: [rust]
+sources:
+ - https://doc.rust-lang.org/book/ch08-01-vectors.html
+---
+
+<!--
+
+::Annotation Guide::
+~~~~~~~~~~~~~~~~~~~~
+
+* `em` is the modifier
+
+1. em (_text_) - blue underline
+2. strong (**text**) - yelow highlight
+3. del (~~text~~) - red strike-through
+
+4. em > em (_*text*_) - blue circle
+5. em > strong (_**text**_) - lawngreen box
+6. em > del (_~~text~~_) - red cross-off
+-->
+
+Vector:
+
+- stores value of **same type**
+- stores values **next to each other in heap**
+- can store values **dynamically**
+
+### creating a Vector
+
+when using _associate function_ `::new()`, one must use **type annotation**
+so that compiler have info about what kind of values to be stored in there
+
+```rust
+// empty vector
+let v1: Vec<i32> = Vec::new();
+
+// vecor with some initial values
+let v2: vec![1, 2, 3];
+```
+
+### updating a vector
+
+Vector provide methods for running operations on any of its instances.
+
+```rust
+let mut v = Vec::new();
+
+// add new values
+v.push(5);
+v.push(10);
+```
+
+> when a vector is dropped, all its content would vanish as well
+
+### accessing values
+
+vectors are **indexed by number, starting at 0**
+
+there are two ways to access a vactor element. first way is similar to
+accessing array elements. second option is, using vector-specific methods
+
+1. accessing using `&` and `[]`
+
+ ```rust {hl_lines=[2]}
+ let v = vec![1, 2, 3];
+ println!("first element: {}", &v[0]);
+
+ println!("{}", &v[1000]); // panics
+ ```
+
+ This methods is quite straightforward. but it would _*create panic*_ when
+ the index is out of bound.
+
+2. using `.get()`
+
+ ```rust {hl_lines=[3]}
+ let v = vec![1, 2, 4];
+
+ match v.get(2) {
+ Some(third) => println!("third element is: {}", third),
+ None => println("no third element present"),
+ }
+ ```
+
+ `.get()` returns enum `Option<T>` which have two variants: `Some<T>` and
+ `None`.
+
+while **holding a reference** to an item, new items **cannot be added**.
+check out the following code for example:
+
+```rust
+// won't compile
+let mut v = vec![1, 2, 3, 4, 5];
+
+let first = &v[0];
+
+v.push(6);
+
+println!("The first element is: {}", first);
+```
+
+this is because of Rust's borrowing rules. When holding a reference to an
+element, pointer would **point to an specific memory location**. if new item gets
+added, the length of Vector would expand making it **not able to fit** in current
+memory sequence at times. if that happens, the whole vector would be **relocated**
+to an **available continous memory location**. This, in turn, would make the
+**reference to previously allocated memory invalid**. Hence Rust does not allow it.
+
+### iterating & mutating a vector
+
+one could iterate over a vector using `for` loop.
+
+```rust
+let v = vec![1, 2, 4, 5];
+for i in &mut v {
+ // prints the value of `i`
+ println!("{}", i);
+
+ // modify `i`
+ *i += 10;
+}
+```
+
+`*` is known as **dereference operator**. `&` returns reference to the element.
+so, in order to edit that element, we must get its true value.
+
+### using enum to store multiple types
+
+```rust
+enum SpreadsheetCell {
+ Int(i32),
+ Float(f64),
+ Text(String),
+}
+
+let row = vec![
+ SpreadsheetCell::Int(3),
+ SpreadsheetCell::Text(String::from("blue")),
+ SpreadsheetCell::Float(10.12),
+];
+```
diff --git a/content/notes/rust/ch-18-string-in-rust.md b/content/notes/rust/ch-18-string-in-rust.md
new file mode 100644
index 0000000..25376e6
--- /dev/null
+++ b/content/notes/rust/ch-18-string-in-rust.md
@@ -0,0 +1,98 @@
+---
+title: 'String in Rust'
+date: 2020-08-12T10:09:17+05:30
+draft: false
+tags: [string, string, collection]
+categories: [rust]
+sources:
+ - https://doc.rust-lang.org/book/ch08-02-strings.html
+---
+
+<!--
+
+::Annotation Guide::
+~~~~~~~~~~~~~~~~~~~~
+
+* `em` is the modifier
+
+1. em (_text_) - blue underline
+2. strong (**text**) - yelow highlight
+3. del (~~text~~) - red strike-through
+
+4. em > em (_*text*_) - blue circle
+5. em > strong (_**text**_) - lawngreen box
+6. em > del (_~~text~~_) - red cross-off
+-->
+
+in the core language, Rust provides _only one type of string_: `str`, which is
+often seen in its borrowed form `&str`.
+
+Rust's standard library provdes another type: `String`. this type is **growable**,
+**owned** and **mutable**.
+
+### creating new String
+
+```rust
+let s1 = "some string".to_string(); // create string from literals
+let mut s = String::new(); // creates an empty string
+let s2 = String::from("initial content"); // initialize with a value
+
+// strings are utf-8 encoded. it can include any
+// properly encoded data
+let hello = String::from("नमस्ते");
+```
+
+### updating string
+
+```rust
+// using .push_str() method
+let mut s = String::from("foo");
+s.push_str("bar");
+
+
+// push a char using .push() method
+s.push('l');
+
+
+// concate with + and format!() macro
+let s1 = String::from("Hello, ");
+let s2 = String::from("world!");
+let s3 = s1 + &s2;
+// note s1 has been moved and can no longer be used
+
+format!("{}{}", s1, s2);
+```
+
+- `push_str()` method **does not take** ownership.
+- characters are enclosed in **single quotes** (`'`)
+- indexing of string would not work as expected. when indexing, Rust **returns
+ bytes** instead of character.
+
+### Bytes, Scalar values and Grapheme Clusters
+
+example string: "नमस्ते"
+
+- bytes: `[224, 164, 168, 224, 164, 174, 224, 164, 184, 224, 165, 141, 224, 164, 164, 224, 165, 135]` (vector of `u8` values)
+- scalar values: `['न', 'म', 'स', '्', 'त', 'े']` (six `char`)
+- grapheme clusters: `["न", "म", "स्", "ते"]` (four "letters")
+
+### accessing elements in a string
+
+String values can be accessed with a `for` loop.
+
+```rust
+// print elements as char
+for c in "नमस्ते".chars() {
+ print!("{} ", c);
+}
+// prints: न म स ् त े
+
+// print elements as bytes
+for b in "नमस्ते".bytes() {
+ print!("{} ", b);
+}
+// prints: 224 164 ...... 165 135
+```
+
+Rust's standard library *__does not implement__* functionality for getting
+grapheme clusters. external libraries does.
diff --git a/content/notes/rust/ch-19-hash-maps-in-rust.md b/content/notes/rust/ch-19-hash-maps-in-rust.md
new file mode 100644
index 0000000..224cd23
--- /dev/null
+++ b/content/notes/rust/ch-19-hash-maps-in-rust.md
@@ -0,0 +1,25 @@
+---
+title: 'Ch 19 Hash Maps in Rust'
+date: 2020-08-12T12:02:59+05:30
+draft: true
+tags: []
+categories: []
+sources: []
+---
+
+<!--
+
+::Annotation Guide::
+~~~~~~~~~~~~~~~~~~~~
+
+* `em` is the modifier
+
+1. em (_text_) - blue underline
+2. strong (**text**) - yelow highlight
+3. del (~~text~~) - red strike-through
+
+4. em > em (_*text*_) - blue circle
+5. em > strong (_**text**_) - lawngreen box
+6. em > del (_~~text~~_) - red cross-off
+-->
+
diff --git a/content/notes/rust/ch-2-cargo.md b/content/notes/rust/ch-2-cargo.md
new file mode 100644
index 0000000..f69956c
--- /dev/null
+++ b/content/notes/rust/ch-2-cargo.md
@@ -0,0 +1,66 @@
+---
+title: Cargo
+date: 2020-04-19T14:32:19+05:30
+categories: [rust]
+---
+
+Cargo is the Rust package manager and build tool. It's used to initialize, build and manage dependencies of a project.
+
+## 1. `cargo new PROJECT_NAME`
+
+```sh
+$ cargo new cargo-example
+Created binary (application) `cargo-example` package
+```
+
+To initialize a project, one needs to run `cargo new` followed by the `project_name`. Cargo will create a directory `project_name`, add `.gitignore`, `src/main.rs` and `Cargo.toml`.
+
+The `src/main.rs` is the entry-point to the project. Rust expects project related codes to live inside `src` directory, leaving top-level directory for config files, readme etc. This makes project more organized.
+
+`Cargo.toml` is the package file. This file stores everything needed for the project to build. The `[package]` section of the file stores the general package informaton. And `[dependencies]` section stores information dependency information.
+
+## 2. `cargo build`
+
+```sh
+$ cargo new cargo-example
+Compiling cargo-example v0.1.0 (/home/crow/Dev/rust/sources/cargo-example)
+Finished dev [unoptimized + debuginfo] target(s) in 0.41s
+```
+
+`cargo build` generates an unoptimized build(along with debug info) out of the source code. Generated binary should be inside the `target` directory inside `example-project` To run the binary, one needs to call it like this: `./target/debug/cargo-example`, inside a terminal in project root.
+
+## 3. `cargo run`
+
+```sh
+$ curgo run
+ Finished dev [unoptimized + debuginfo] target(s) in 0.01s
+ Running `target/debug/cargo-example`
+Hello, world!
+```
+
+`run` subcommand of `cargo` runs a compiled binary. Or if the binary is not available, it compiles source to binary and then run the resultant binary.
+
+## 3. `cargo check`
+
+```sh
+$ cargo check
+ Checking cargo-example v0.1.0 (/home/crow/Dev/rust/sources/cargo-example)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.13s
+```
+
+`check` checks the source if it's compilable. This command does not compile the source into a binary.
+
+## 4. `cargo build --release`
+
+```sh
+$ cargo build --release
+Compiling cargo-example v0.1.0 (/home/crow/Dev/rust/sources/cargo-example)
+Finished release [optimized] target(s) in 0.29s
+```
+
+The `--release` flag compiles to an optimized binary suitable to use in production.
+
+## `Cargo.lock`
+
+This is a lockfile created and managed by Cargo to track exact version of dependencies. This file should not be edited manually.
+
diff --git a/content/notes/rust/ch-20-handling-errors.md b/content/notes/rust/ch-20-handling-errors.md
new file mode 100644
index 0000000..c85c29b
--- /dev/null
+++ b/content/notes/rust/ch-20-handling-errors.md
@@ -0,0 +1,29 @@
+---
+title: "Handling Errors"
+date: 2020-08-12T12:03:43+05:30
+draft: true
+tags: [error, error handling]
+categories: [rust]
+sources: []
+---
+
+<!--
+
+::Annotation Guide::
+~~~~~~~~~~~~~~~~~~~~
+
+* `em` is the modifier
+
+1. em (_text_) - blue underline
+2. strong (**text**) - yelow highlight
+3. del (~~text~~) - red strike-through
+
+4. em > em (_*text*_) - blue circle
+5. em > strong (_**text**_) - lawngreen box
+6. em > del (_~~text~~_) - red cross-off
+-->
+
+two kind of errors in Rust:
+
+- **recoverable**, which are of type `Result<T, E>`
+- **unrecoverable**, with `panic!()` macro
diff --git a/content/notes/rust/ch-3-guessing-game.md b/content/notes/rust/ch-3-guessing-game.md
new file mode 100644
index 0000000..ca7cc9b
--- /dev/null
+++ b/content/notes/rust/ch-3-guessing-game.md
@@ -0,0 +1,153 @@
+---
+title: Guessing Game
+date: 2020-04-20T10:51:15+05:30
+tags: [game]
+categories: [rust]
+---
+
+```rust
+use rand::Rng;
+use std::cmp::Ordering;
+use std::io;
+
+fn main() {
+ println!("Guess the Number!!");
+
+ loop {
+ println!("Please input your guess");
+
+ let mut guess = String::new();
+ let secret_number = rand::thread_rng().gen_range(1, 200);
+
+ io::stdin()
+ .read_line(&mut guess)
+ .expect("Faild to Read Line");
+
+ let guess: u32 = match guess.trim().parse() {
+ Ok(num) => num,
+ Err(_) => {
+ println!("Invalid Input.");
+ continue;
+ }
+ };
+
+ match guess.cmp(&secret_number) {
+ Ordering::Less => println!("Too Small!"),
+ Ordering::Greater => println!("Too Big!"),
+ Ordering::Equal => {
+ println!("You win!");
+ break;
+ }
+ }
+ }
+}
+```
+
+## Explanation
+
+### The `use` statement
+
+```rust
+use rand::Rng;
+use std::cmp::Ordering;
+use std::io;
+```
+
+Rust only brings a few types into global scope, by default. The rest of the types a program needs, should be brought to scope by using the `use` keyword.
+
+Here, `rand` is an external package, `Ordering` is an `enum` for comparing two variables of same type. `Ordering` provides `Ordering:Less`, `Ordering:Greater` and `Ordering:Equal`. `io` provides methods required for input and output.
+
+### Loop
+
+```rust
+loop {
+
+}
+```
+
+`loop` is keyword for creating infinite loops. In the above program, it allows user to keep-on guessing until they make the correct choice.
+
+### `let`, `mut` and `String::new()`
+
+```rust
+let mut guess = String::new();
+```
+
+`let` is a keyword for **defining variables** and assign a value to it. By default, Rust variables are immutable. They can't be changed once declared. The `mut` keyword is used for **mutating a variable** so that it could be modified in a later stage.
+
+The `String::new()` creates an empty value of type `string`. The **`new()` after `::` is known as an associated function** of the type `String`.
+
+> An associated function is implemented on a type, rather than on a particular instance of a Type. Some languages call this a static method.
+
+### Getting a Random Number
+
+```rust
+let secret_number = rand::thread_rng().gen_range(1, 200);
+```
+
+Here, a random number is generated using an external package called `rand`. It is first imported using `use rand::Rng;`. `rand::thread_rng` is the perticular generator used in this example. This generator is local to the current thread and seeded by the Operating System.
+
+Method `gen_range()` generates a random number between two given parameter.
+
+### Adding an external package
+
+In order to add an external package, one needs add the package name and version number in `Cargo.toml` file. Cargo follows the specifications set by `SemVer`.
+match guess.cmp(&secret_number) {
+Ordering::Less => println!("Too Small!"),
+Ordering::Greater => println!("Too Big!"),
+Ordering::Equal => {
+println!("You win!");
+break;
+}
+}
+
+### Getting input from `stdin`
+
+```rust
+io::stdin()
+ .read_line(&mut guess)
+ .expect("Faild to Read Line");
+```
+
+`read_line()` method gets a string from `stdin`. The `expect()` method is used to handle possible errors.
+
+### Mutating Parameters
+
+By default, parameters in Rust does not mutate. If the mutation is needed, it has to be done using `mut` keyword. For rxample, `someFn(&mut someVar)`. Here, `someVar` is passed by reference.
+
+### Variable Shadowing and Error Handling
+
+```rust
+let guess: u32 = match guess.trim().parse() {
+ Ok(num) => num,
+ Err(_) => {
+ println!("Invalid Input.");
+ continue;
+ }
+};
+```
+
+Variable Shadowing is **the process of redeclaring a already defined variable with a new type**. This is a unique thing allowed in Rust! Shadowing helps a programmer to save-up memory space by reusing a variable.
+
+**`u32`** (unsigned 32 bit Integer) is the data type the string is to be converted to.
+
+`trim()` method (of type String) on `guess` variable removes extra characters like newline, trailing space etc from a String.
+
+`parse()` method tries to parse a number from given string. It could result in either of two values: `Ok` and `Err`.
+
+`match` is a keyword which is used to compare the value of `parse()` method with a given `enum`. So, if the `parse()` method returns `Ok`, `Ok(num) => num,` block would be executed. Otherwise, `Err(_) => { println!("Invalid Input."); continue; }` block would be executed.
+
+### `Less`, `Greater`, `Equal`
+
+```rust
+match guess.cmp(&secret_number) {
+ Ordering::Less => println!("Too Small!"),
+ Ordering::Greater => println!("Too Big!"),
+ Ordering::Equal => {
+ println!("You win!");
+ break;
+ }
+}
+```
+
+`Ordering` is provided by `std::cmp::Ordering`. It is used to compare the results of two number. This is used along with `.cmp()` method which returns an `enum`.
diff --git a/content/notes/rust/ch-4-variables-and-mutablity.md b/content/notes/rust/ch-4-variables-and-mutablity.md
new file mode 100644
index 0000000..6d9bac2
--- /dev/null
+++ b/content/notes/rust/ch-4-variables-and-mutablity.md
@@ -0,0 +1,121 @@
+---
+date: 2020-04-20T20:27:47+05:30
+title: Variables and Mutablity
+categories: [rust]
+---
+
+> In Rust, Variables **are Immutable** by default.
+
+## Demo Program
+
+### Immutable
+
+```rs
+// This program won't compile because
+// the value of `x` has been changed after
+// the first declaration(without using `mut`)
+
+fn main() {
+ let x = 5;
+ println!("Value of X is {}", x);
+
+ x = 15;
+ println!("Value of X is {}", x);
+}
+```
+
+### Output of `cargo run`:
+
+```sh
+$ cargo run
+Compiling variables v0.1.0 (/home/crow/Dev/rust/sources/variables)
+error[E0384]: cannot assign twice to immutable variable `x`
+ --> src/main.rs:4:5
+ |
+2 | let x = 5;
+ | -
+ | |
+ | first assignment to `x`
+ | help: make this binding mutable: `mut x`
+3 | println!("Value of X is {}", x);
+4 | x = 15;
+ | ^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
+error: could not compile `variables`.
+
+To learn more, run the command again with --verbose.
+```
+
+### Mutable
+
+```rs
+fn main() {
+ let mut x = 5;
+ println!("The value of x is: {}", x);
+ x = 6;
+ println!("The value of x is: {}", x);
+}
+```
+
+### Output of `cargo run`
+
+```sh
+$ cargo run
+Compiling variables v0.1.0 (/home/crow/Dev/rust/sources/variables)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.38s
+ Running `target/debug/variables`
+Value of X is 5
+Value of X is 6
+```
+
+## Mutating a Value
+
+In order to change the value of a variable after it's been declared, one needs to use `mut` keyword along with `let`. For example: `let mut foo = 'bar'`.
+
+## Constants
+
+```rs
+const MAX_POINTS: u32 = 100_000;
+```
+
+In Rust, immutable variables may look like a constant, but in real, they are not. There is a little difference between variables and constants. They are:
+
+1. Declared using `const` keywords, instead of `let`.
+2. Data Type must be annotated while declaring
+3. Constants are **always immutable**.
+4. Unlike variables, constants can be declared in any scope.
+5. Constants may only be set to a constant expression, not the result of a function call or any other value that could only be computed at runtime.
+
+## Variable Shadowing
+
+Shadowing is the process of redeclearing a already decleared variable. Shadowing does not assign a new value to the previous variable, but creates a new variable of the same name and assigns a value to it. So, **shadowed variable can have different data types**.
+
+```rs
+// Shadowing example
+fn main() {
+ let x = 5;
+ let x = x + 1;
+ let x = x * 2;
+
+ println!("The value of x is: {}", x);
+}
+```
+
+Shadoing is **different** from making a variable `mut`, as a mutated variable can be reassigned a new variable of same data-type. But shadowed variables can be assigned a new value of different data-type than original variable.
+
+Following block is allowed in Rust, because the `spaces` variable is being shadowed. So, the first instance of `spaces` is dropped from memory as soon as the second instance is decleared.
+
+```rs
+let spaces = " "; // type: string
+let spaces = spaces.len(); // type: unsigned 32bit integer
+```
+
+But this block is not allowed, as the variable is being mutated. Hence, the data-type of reassigned value must match the data-type of previous value.
+
+```rs
+let mut spaces = " "; // mutated
+spaces = spaces.len(); // error[E0308]: mismatched types
+```
diff --git a/content/notes/rust/ch-5-data-types.md b/content/notes/rust/ch-5-data-types.md
new file mode 100644
index 0000000..03e440f
--- /dev/null
+++ b/content/notes/rust/ch-5-data-types.md
@@ -0,0 +1,75 @@
+---
+date: 2020-04-21T11:30:38+05:30
+title: Data Types
+tags: ['data-types']
+categories: [rust]
+---
+
+> Every value in Rust is of a certain data type, which tells Rust what kind of data is being specified so it knows how to work with that data.
+
+## Data Types in Rust:
+
+1. **Scalar**
+ - **Integers**
+ - (**`i8 | u8`**) - 8-bit Integer
+ - (**`i16 | u16`**) - 16-bit Integer
+ - (**`i32 | u32`**) - 32-bit Integer
+ - (**`i64 | u64`**) - 64-bit Integer
+ - (**`i128 | u128`**) - 128-bit Integer
+ - (**`isize | usize`**) - Integer size depends upon the system architecture.
+ - **Floating Point** Numbers
+ - **`f32`** - Single-precision 32-bit floating point numbers
+ - **`f64`**(default) - Single-precision 64-bit floating point numbers
+ - **Booleans**
+ - `true`
+ - `false`
+ - **Characters**
+ - **`char`** - 4-bytes in size. Capable of holding an Unicode Scalar Value(including Chinese, Japanese, and Korean characters; emoji; and zero-width spaces etc)
+2. **Compound**
+ - **Tuple**
+ - **Array**
+
+### Tuple
+
+General way of grouping togather a number of values with variety of types.
+
+```rs
+fn main() {
+ let tup: (i32, f64, u8) = (500, 5.2, 1);
+
+ // accessing values
+ // destructuring method
+ let (x, y, z) = tup; // x = 500, y = 5.2, z = 1
+
+ // `access by index` method
+ let five_hun = tup.0;
+ let float5_2 = tup.1;
+ let one = tup.2;
+}
+```
+
+### Array
+
+Array stores collections of multiple values, but of same type.
+
+```rs
+fn main() {
+ // declaring an array
+ let a = [1, 3, 4, 6, 5];
+ let b: [i32, 3] = [1, 4, 2]; // array of size 3 of type `i32`
+ let c = [4, 10]; // array of size `10` containing same value, i.e. `4`
+
+ // accessing an array
+ const firstValue = a[0];
+ const secondValue = a[1];
+
+ // main panic
+ const valueDoesNotExists = a[400];
+}
+```
+
+> Accessing an element of an array which is past the end of the array, would result an `index out of bounds` error, which in result would `panic` the `main` thread. This gives a more safe memory access, as the program won't be able to access invalid memory location.
+
+## Notes
+
+1. Always check if index of an array which is supposed to be accessed, is less than the length of the array. Otherwise, `main` thread would panic.
diff --git a/content/notes/rust/ch-6-functions.md b/content/notes/rust/ch-6-functions.md
new file mode 100644
index 0000000..b2a6d23
--- /dev/null
+++ b/content/notes/rust/ch-6-functions.md
@@ -0,0 +1,91 @@
+---
+date: 2020-04-22T16:51:40+05:30
+title: Functions
+tags: ['functions']
+categories: [rust]
+---
+
+Functions are block of codes which are instructed to accomplish specific task(s).
+
+To write a function, the `fn` keyword is used, followed by function name.
+
+> By convention, `snake_case` is used while naming a function.
+
+## Parameters
+
+Functions can accepts parameters, which are special variables that are part of a function’s signature. Parameter names are followed by a type name.
+
+```rs
+fn main() {
+ another_function(32);
+}
+
+fn another_function(x: i32) {
+ println!("{}", x);
+}
+```
+
+## Function Body
+
+Whatever resides inside the curly braces after function name, called as function body. Function body is consists of expression and statement.
+
+**Statement**: Statements are instructions that perform some action and do not return a value.
+
+**Expression**: Expressions evaluate to a resulting value. Expressions **should not** end with a semicolon. Example:
+
+```rs
+fn main() {
+ let x = 5;
+
+ let y = {
+ let x = 3; // Ends with a semicolon
+ x + 1 // no semicolon
+ }
+
+ // `y` evaluates to `4`, which is a return value
+}
+```
+
+## Function Return
+
+> In Rust, the return value of the function is synonymous with the value of the final expression in the block of the body of a function.
+
+In order to return a value from a function, user need to write a type after an arrow (`->`).
+
+User could return early from a program using the `return` keyword.
+
+```rs
+fn five() -> i32 {
+ 5
+ // `5` would be returned as it's the final expression
+ // putting a semicolon after `5` would throw an error:
+ // error[E0308]: mismatched types
+ // because semicolon made it a statement; and statement returns nothing
+ // so the return type of function mismatched with what was actually returned,
+ // which is basically nothing
+}
+
+fn main() {
+ let x = five();
+
+ println!("Value of x is {}", x);
+}
+```
+
+## Returning multiple values with tuple
+
+In Rust, tuples could be used to return multiple values.
+
+```rust
+fn main() {
+ let string_a = String::from("Hello, world");
+ let (string_b, len) = claculate_len(string_a);
+
+ println!("{} {}", string_b, len);
+}
+
+fn claculate_len(s: String) -> (String, usize) {
+ let length = s.len();
+ (s, length)
+}
+```
diff --git a/content/notes/rust/ch-7-control-flow.md b/content/notes/rust/ch-7-control-flow.md
new file mode 100644
index 0000000..5eb35a8
--- /dev/null
+++ b/content/notes/rust/ch-7-control-flow.md
@@ -0,0 +1,116 @@
+---
+date: 2020-04-22T17:13:47+05:30
+title: Control Flow
+tags: ['control-flow', 'if', 'if-else']
+categories: [rust]
+---
+
+## if, if else, else if
+
+An `if` expression allows you to branch your code depending on conditions.
+
+```rs
+fn main() {
+ let num: i8 = 2;
+
+ if num < 5 {
+ println!("Number is Samll");
+ } else if num % 2 === 0 {
+ println!("Divisible by 2");
+ } else {
+ println!("Number is Big");
+ }
+}
+```
+
+> In Rust, condition must resolve to a value of type `bool`, i.e. either `true` or `false`. Otherwise the program won't compile.
+
+## let in if Statement
+
+```rs
+fn main() {
+ let isTrue = true;
+ let aNumber = if isTrue {
+ 5 // no semicolon
+ } else {
+ 10 // no semicolon
+ }
+}
+// also, data type should be same for each if-else
+// block
+```
+
+Since `if` is an expression, it can be assigned to variable. But it is also worth mentioning that the data type of all the `if`, `else` blocks. Otherwise the following error would occur:
+
+```sh
+error[E0308]: if and else have incompatible types
+```
+
+## Loops
+
+### loop
+
+```rs
+fn main() {
+ let mut counter = 0;
+ let value = loop {
+ counter += 1;
+
+ if counter == 10 {
+ break counter * 2; // here, semicolon needed
+ }
+ }
+
+ println!("Value is {}", value);
+}
+```
+
+`loop` is a keyword used for running an infinite loop. This `loop` could be ended using `break` keyword.
+
+> `loop` is capable of returning value. Any expression/value placed after `break` keyword would be returned.
+
+### while
+
+`while` is a conditional loop built-in to Rust.
+
+```rs
+fn main() {
+ let mut number = 3;
+
+ while number != 0 {
+ println!("{}!", number);
+
+ number -= 1;
+ }
+}
+```
+
+Using `while` loop as a replacement of `for` loop would result in slow execution of code, as compiler would add runtime code for checking `checking index out of bound` error.
+
+### for
+
+```rs
+fn main() {
+ let a = [1, 2, 4, 5, 6];
+
+ for element in a.iter() {
+ println!("{}", element);
+ }
+}
+```
+
+Given an array of items, a `for` loop would iterate over each of them and pass the value to defind variable. In above case, `element`.
+
+```rs
+fn main() {
+ for number in (1..4).rev() {
+ println!("{}!", number);
+ }
+
+ println!("LIFTOFF!!!");
+}
+```
+
+## Related Code
+
+1. `sources/temp-conversion.rs`
diff --git a/content/notes/rust/ch-8-ownership.md b/content/notes/rust/ch-8-ownership.md
new file mode 100644
index 0000000..e948917
--- /dev/null
+++ b/content/notes/rust/ch-8-ownership.md
@@ -0,0 +1,133 @@
+---
+date: 2020-04-26T21:03:58+05:30
+title: Ownership
+tags: ['ownership']
+categories: [rust]
+excerpt: Each value in Rust has a variable that is called its **Owner**. There can only be one owner at a time. When the owner goes out of scope, the value will be dropped.
+---
+
+## Ownership Rules
+
+- Each value in Rust has a variable that is called its **Owner**.
+- There can only be one owner at a time.
+- When the owner goes out of scope, the value will be dropped.
+
+Type `String` can be mutated, but string literals can not. Reason behind: literals are stored in stack during compile-time, which makes it impossible to grow an string during runtime. Type `String` can be mutated because, it's stored in heap.
+
+> Rust has no Garbage Collector. It takes a different approach to release unused memory. Whenever a variable goes out of scope, the memory which was occupied by variable, would be returned.
+
+```rs
+{
+ let s = String::from("hello"); // s is valid from this point forward
+
+ // do stuff with s
+}
+// this scope is now over, and s is no
+// longer valid
+```
+
+There is a special function called `drop` which Rust calls internally to release unused memory space.
+
+## Variables and their Values
+
+```rs
+let a = 10; // initial declaration
+let b = a; // value of `a` was copied to `b` as a
+ // new variable
+```
+
+> In Rust, primitive values are always stored in Stack. Heap is for Compound variables.
+
+```rs
+let s1 = String::from("hello");
+let s2 = s1; // pointer to `s1`'s object. `s1` destroyed
+```
+
+An object is made up of three parts: 1. **Pointer** to the memory location where object is stored 2. **Length** 3. **Capacity**
+
+**s1(stored in Stack)** and **hello(stored in heap)**
+
+![](https://doc.rust-lang.org/book/img/trpl04-01.svg)
+
+On assigning `s1` to a new variable, it will point to the same heap location. Because, when a `s1` is assigned to `s2`, all three parts(ptr, len, capacity) were copied.
+
+**s2(stored in Stack):**
+
+![](https://doc.rust-lang.org/book/img/trpl04-02.svg)
+
+Now, when `s1` and `s2` would go out of the scope, compiler would try to free the same memory twice, which is known as **Double Free Error**. This would lead to **memory corruption**, and ultimately security vulnerabilities.
+
+Here, **Rust's memory safety** rules comes into play. Compiler makes previous variable(`s1`, in this case) invalid, copying everything to `s2`. Accessing `s1` after declaring `s2` would result into error.
+
+```sh
+error[E0382]: use of moved value: `s1`
+```
+
+## Move
+
+The process of creating a new variable and invalidating previous one is known as **Move**. (Somewhat similar to a _Shallow Copy_ in other languages). This method copies stack-data to a new location.
+
+## Copy
+
+Deep Copy means copying a variable to a new location, completely. This copying incudes Stack data(ptr, length, capacity) along with heap data(Type `String` and similar)
+
+In order to deep copy an object, one could use `clone()` method.
+
+```rs
+let s1 = String::from("Hello");
+let s2 = s1.clone();
+```
+
+## Ownership and Functions
+
+Ownership in function works in a similar way as variables. Passing a value to function would eiter move or copy.
+
+```rust
+fn main() {
+ let s = String::from("Hello, World"); // `s` came into scope
+
+ make_move(s); // `s` out of scope as it's moved to `make_move` function
+
+ println!("value of x is {}", x); // error[E0382]: borrow of moved value: `s`
+
+ let x: u32 = 123; // `x` came into scope
+
+ make_copy(x); // `x` moves to `make_copy`. but since `x` is of type u32, it can still be used
+
+ println!("value of x is {}", x);
+}
+
+// changes ownership of parameter
+fn make_move(some_str: String) {
+ println!("value of some_str is {}", some_str);
+}
+
+// does not changes ownership of parameter
+fn make_copy(some_int: u32) {
+ println!("value of some_int is {}", some_int);
+}
+```
+
+> Returning value from a function would also transfar the value. (Example Below)
+
+```rust
+fn main() {
+ let s1 = give_ownership(); // came into scope
+ let s2 = String::from("Hello World"); // came into scope
+ let s3 = take_and_give_back(s2); // came into scope. `s2` moved into `take_and_give_back` which in turn ruturned it to `s3`
+}
+// all variables goes out of scope.
+// `s1` dropped
+// nothing happens to `s2` as it was moved previously
+// `s3` dropped
+
+fn give_ownership() -> String {
+ String::from("Hello, world")
+}
+
+fn take_and_give_back(str: String) -> String {
+ str
+}
+```
+
+> The ownership of a variable follows the same pattern every time: assigning a value to another variable moves it. When a variable that includes data on the heap goes out of scope, the value will be cleaned up by drop unless the data has been moved to be owned by another variable.
diff --git a/content/notes/rust/ch-9-references-and-borrowing.md b/content/notes/rust/ch-9-references-and-borrowing.md
new file mode 100644
index 0000000..ae3779c
--- /dev/null
+++ b/content/notes/rust/ch-9-references-and-borrowing.md
@@ -0,0 +1,101 @@
+---
+date: 2020-05-07T15:41:28+05:30
+title: References and Borrowing
+tags: ['references', 'ownership', 'borrowing']
+categories: [rust]
+---
+
+When a variable is passed by reference to a function parameter, the function does not take ownership of that variable. Instead, it stores a pointer which would _refer_ to that specific memory location. Passing a variable by reference to a function is known as **Borrowing**.
+
+```rs
+fn main() {
+ let s1 = String::from("Rust is awesome");
+ let length_s1 = calc_len(&s1);
+
+ println!("The length of '{}' is {}.", s1, len);
+}
+
+fn calc_len(str: &String) -> usize {
+ str.len()
+} // `str` goes out of scope. but since it never owned `s1`, nothing would happen.
+```
+
+Since the `calc_len` function does not own variable `s1`, `s1` never goes out of scope once the function is done executing.
+
+> `&` is used to create a reference to a variable
+
+## Mutating `passed by reference` variable
+
+By default, mutations in borrowed variables are not allowed(just like in owned variables). One need to mutate it using the `mut` keyword. Example:
+
+```rs
+fn main() {
+ let mut s1 = String::from("Hello, "); // declare as mutable
+ change_str(&mut s1); // pass to func as mutable
+
+ println!("{}", s1);
+}
+
+fn change_str(str: &mut String) { // accept a mutable reference
+ str.push_str("world");
+}
+```
+
+### Mutable Variable Restrictions
+
+1. A variable **can be mutated only once** at a given scope. This may look weird but it actually prevents unwanted data modifications(data race).
+
+> A data race is similar to a race condition and happens when these three behaviors occur: 1. Two or more pointers access the same data at the same time. 2. At least one of the pointers is being used to write to the data. 3. There’s no mechanism being used to synchronize access to the data.
+
+2. A variable can only be borrowed as mutable if its immutable reference is not used after borrowing it as mutable. Look at the following code snippet to understand better.
+
+**Compiler Error**
+
+```rs
+let mut s = String::from("hello");
+
+let r1 = &s; // no problem
+let r2 = &s; // no problem
+let r3 = &mut s; // BIG PROBLEM
+
+println!("{}, {}, and {}", r1, r2, r3);
+// immutable reference used
+// after a mutable reference `r3`.
+
+// error[E0502]: cannot borrow `s` as mutable
+// because it is also borrowed as immutable
+```
+
+**No Compiler Errors**
+
+```rs
+let mut s = String::from("hello");
+
+let r1 = &s; // no problem
+let r2 = &s; // no problem
+println!("{} and {}", r1, r2);
+// r1 and r2 are no longer used after this point
+
+let r3 = &mut s; // no problem
+println!("{}", r3);
+```
+
+> Reference’s scope starts from where it is introduced and continues through the last time that reference is used
+
+## Dangling References
+
+Leaving a reference to a memory location which was returned/freed.
+
+```rs
+fn main() {
+ let reference_to_nothing = dangle();
+}
+
+fn dangle() -> &String {
+ let s = String::from("hello");
+
+ &s
+} // s went out of scope. So, the memory location was returned. `&s` points to a free memory location. This would result a compile-time error
+
+// error[E0106]: missing lifetime specifier
+```
diff --git a/content/notes/today-i-learned-general.md b/content/notes/today-i-learned-general.md
new file mode 100644
index 0000000..decea0c
--- /dev/null
+++ b/content/notes/today-i-learned-general.md
@@ -0,0 +1,18 @@
+---
+title: Today I Learned (General)
+---
+
+### 16 June, 2020
+
+#### Seppuku
+
+A Japanese ritual performed by high command when they loose a battle
+where there were most likely to win. The person who is supposed to perform this
+ritual, would kill himself with a dagger by cutting a part of abdomen
+horizentally so that some of the organ comes out of his belly. This is also
+known as __Harakiri__(belly cutting).
+
+Initially this was reserved for Samurai, but adopted by other people when time
+passed on.
+
+The reason behind doing this ritual is, to __restore honor__.
diff --git a/content/notes/today-i-learned-tech.md b/content/notes/today-i-learned-tech.md
new file mode 100644
index 0000000..13dfb09
--- /dev/null
+++ b/content/notes/today-i-learned-tech.md
@@ -0,0 +1,34 @@
+---
+title: Today I Learned (Tech)
+---
+
+### 17 June, 2020
+
+#### ES6: Private method using `Symbol()`
+
+Symbol in JavaScript(ES6) is a data type. The speciality about Symbols are
+that the value is unique. Using this feature, one could abstract methods of
+ES6 `class`. Here's an example:
+
+```javascript {hl_lines=[2, 5, "8-10"]}
+(() => {
+ const FORMAT_MSG = Symbol();
+ class SayHello {
+ constructor(name) {
+ this[FORMAT_MSG](name);
+ }
+
+ [FORMAT_MSG](name) {
+ this.message = `Hello, ${name}`
+ }
+
+ done() {
+ alert(this.message);
+ }
+ }
+
+ window.SayHello = SayHello; // make it available to global scope
+})()
+```
+
+credit: [Rajesh Pillai](https://teachyourselfcoding.com/articles/javascript-es6-private-methods-in-class-without-closure-using-symbol/)
diff --git a/content/notes/tools/gnu-make.md b/content/notes/tools/gnu-make.md
new file mode 100644
index 0000000..9155f6d
--- /dev/null
+++ b/content/notes/tools/gnu-make.md
@@ -0,0 +1,177 @@
+---
+title: "Make and Makefile"
+date: 2020-08-10T19:54:34+05:30
+draft: false
+tags: [build-tools, devtools]
+categories: [tools]
+sources:
+ - https://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
+ - https://www.gnu.org/software/make/manual/make.html
+ - https://www.gnu.org/software/make/
+---
+
+<!--
+
+::Annotation Guide::
+~~~~~~~~~~~~~~~~~~~~
+
+* `em` is the modifier
+
+1. em (_text_) - blue circle
+2. strong (**text**) - yelow highlight
+3. del (~~text~~) - red strike-through
+
+4. em > em (_*text*_) - blue underline
+5. em > strong (_**text**_) - lawngreen box
+6. em > del (_~~text~~_) - red cross-off
+-->
+
+`make` is a tool responsible for **generating binary and other non-source
+files** of a program from the program's source.
+
+`make` can be used to compile source code of **any language**.
+
+### Features
+
+- _enables user to build and install_ software without knowing the details of
+ that specific software
+- _compiles source files as needed_. can relate to _**hot-reloading**_.
+- `make` is also capable of _installing and uninstalling_ packages.
+
+A _Makefile_ contains **instructions** for `make` to run. A series of
+instructions are known as **a rule**. A Makefile also describes relationship
+among files.Example of a simple _rule_:
+
+```makefile
+target … : prerequisites …
+ recipe
+ …
+ …
+```
+
+- **target** is usually the **name of the file** that is generated by a program.
+ This file generally is an executable or object file.
+ A target can also be the **name of an action** to carry out, sucj as `clean`.
+- **prerequisite** is a file that is used as input to create _target_.
+- **recipe** is an action `make` caries out.
+
+> `make` uses tab for _**indentation**_. Failing to use it would throw an _*error*_
+
+### Makefile Processing
+
+- by default, starts with _**first target**_. also known as default _goal_
+- `make` must process rules the target depends on
+- recompilation is done only when **target is older than source** files; or
+ when _target_ does not exists
+
+### Variables
+
+- allows **storing data in variable**
+- variable declaration example: _**`objects = main.o kbd.o`**_.
+
+```makefile
+objects = main.o kbd.o
+
+edit : $(objects)
+ cc -o edit $(objects)
+main.o : main.c defs.h
+ cc -c main.c
+kbd.o : kbd.c defs.h command.h
+ cc -c kbd.c
+clean :
+ rm edit $(objects)
+```
+
+### Implicit Rules
+
+`make` has an _**implicit rule for updating `.o` file**_ from a correspondingly
+named `.c` file using `cc -c` command.
+
+when a `.c` file is used through implicit rule, it is also added to the
+list of prerequisites. Hence, _**`.c` files can be omitted from
+prerequisites' list**_.
+
+Example:
+
+```makefile
+objects = main.o kbd.o command.o display.o
+
+edit : $(objects)
+ cc -o edit $(objects)
+
+main.o : defs.h
+kbd.o : defs.h command.h
+command.o : defs.h command.h
+display.o : defs.h buffer.h
+
+.PHONY : clean
+clean :
+ rm edit $(objects)
+```
+
+when using implicit rules, an alternate way of writing Makefile can be used.
+in this type of Makefile, entries are _**grouped by their prerequisites**_
+instead of by their targets
+
+Example:
+
+```makefile
+objects = main.o kbd.o command.o display.o
+
+edit : $(objects)
+ cc -o edit $(objects)
+
+$(objects) : defs.h
+kbd.o command.o files.o : command.h
+display.o : buffer.h
+```
+
+### Cleaning Directory
+
+`make` can clean a given directory. for that Makefile should have an
+explicit _*.PHONY*_ target.
+
+> .PHONY prevents `make` to confuse it with an actual file target
+> and _causes it to continue_ in spite of errors from `rm`.
+
+taget `clean` can be executed by **passing it as an arg** to `make`
+
+`clean` _**should not be placed**_ at top of the Makefile. Otherwise it would
+become global target and will be executed by default.
+
+```makefile
+.PHONY : clean
+clean :
+ -rm edit $(objects)
+```
+
+### what a Makefile may contain
+
+1. **variable definitions**
+2. **directives** (instruction for make to do something special while
+ reading the makefile)
+ - Reading another makefile
+ - deciding whether to ignore a part of Makefile
+3. **comments** (starts with `#`). for multiline comment, a _backslash_ should
+ be used at breakpoints
+
+- _**Long lines can be splitted into multiple lines using backslash**_
+
+### Including other Makefile
+
+- `make` can read multiple Makefiles which are added using `include` directive.
+filenames can contain shell file name patterns.
+- if included file is empty, `make` _does nothing_.
+ ```makefile
+ include foo *.make $(bar)
+ ```
+- when path of file is not absolute, and the file is not found in current dir,
+`make` looks for it in some other places(in following order).
+ 1. dirs **mentioned with -I** flag (`--include-dir`)
+ 2. `prefix/include`
+ 3. `/usr/gnu/include`
+ 4. `/usr/local/include`
+ 5. `/usr/include`
+- _NOT_FOUND warnings/errors_ can be _**supressed with `-include` directive**_
+- env variable `MAKEFILES` can be used to **preload other makefiles**
+(spearated by whitespace)
diff --git a/content/notes/tools/registers-in-vim.md b/content/notes/tools/registers-in-vim.md
new file mode 100644
index 0000000..36ed33f
--- /dev/null
+++ b/content/notes/tools/registers-in-vim.md
@@ -0,0 +1,106 @@
+---
+title: "Registers in Vim"
+date: 2020-07-26T08:55:22+05:30
+draft: false
+tags: [vim, neovim, editor]
+categories: [tools]
+sources:
+ - https://www.tutorialspoint.com/vim/vim_registers.htm
+ - https://www.brianstorti.com/vim-registers/
+---
+
+- Registers in Vim are simply **different locations** where Vim could store texts.
+- a register can be accessed by using `"` as prefix. For example: key `"r` can
+access register `r`.
+
+What content a register is currently holding, can be revealed by using command
+`:reg <name of register>`. Without the name, `reg` command would list all
+registers filled with certain data.
+
+
+### Register Operations
+
+- **yank** to register `x`: `"xyw`
+- **delete** to register `d`: `"ddw`
+- **put** from register `a`: `"ap`
+
+### Types of Registers
+
+There are ten types of register vim comes with. Here are some of the most
+important ones.
+
+- **unnamed register**
+- **named register**
+- **numbered registers**
+- **blackhole register** (`"_`)
+- **read-only registers**
+- **expression register**(`"=`)
+- **search register**
+
+#### Unnamed Regist
+
+vim have a default registers, which is used if the commands are not prefixed
+with a register name. This register is known by the name **unnamed register**.
+This register can be accessed with `""`. This register would always contain the
+latest yanked/deleted texts.
+
+#### Named Registers
+
+There are **26** named registers. By default, they are not being used by Vim.
+To use, say `a` register, one should **prepend command with `"a`**. For example:
+`"adw` (delete a word and store in `a` register).
+
+There are two ways to use named register. If one uses small caps alphabet, the
+content which was **previously stored in it, would be overriden**. In case of
+**capital letter**, the **content would be appended**.
+
+#### Numbered Register
+
+Denoted by numbers _0_ to _9_. These registers stores previously yanked and
+deleted content. Register **0 would store the latest yank**. And register **1 to 9
+would store the last 9 deleted texts**(even after shutdown and reboot). 1 being
+the latest and 9 the oldest delete.
+
+> One does not loose yanked/deleted texts in vim. They just don't know where to
+look for it!
+
+#### Blackhole Register
+
+Black Hole Register is a register which does not stores anything. Whatever
+is directed to this register, would get vanished. This register is denoted by
+**`_`**(`"_d` would completely delete a word. obviously, can be brought back
+using `u`).
+
+#### Read-only Registers
+
+As the name suggests, they can't be used by user for the purpose of storing
+arbitary texts. There are 4 read-only registers:
+
+- `".`: Stores the last inserted texts.
+- `"%`: Stores the current(relative) file path
+- `":`: Stores most recently executed command. Goes quite handy with _@_(command
+runner. example, _@:_)
+- `"#`: stores the (relative) location of [alternate file](#TODO) for current
+window.
+
+#### Expression Register
+
+This register stores the value of an expression. When **`<C-r>=` is pressed in
+insert mode**, a `=` sign would show up in command line. **Any expression run in
+command line would be stored in expression register** (`"=`).
+
+Example: `<C-r>=system('ls')` would write down the result of `ls` under
+cursor-line, and store the command in `=` register.
+
+#### Search Register
+
+Stores the latest search term searched with `/`, `?`, `*` or `#`. Useful when one
+needs to re-type a complex term or RegEx. Can be accessed using `<C-r>X`(where *X*
+is `/`, `?`, `*` or `#`).
+
+
+---
+
+Source:
+1. [Vim registers: The basics and beyond](https://www.brianstorti.com/vim-registers/)
+2. [Vim - Registers](https://www.tutorialspoint.com/vim/vim_registers.htm)
diff --git a/content/pages/hire.md b/content/pages/hire.md
new file mode 100644
index 0000000..0fc48b0
--- /dev/null
+++ b/content/pages/hire.md
@@ -0,0 +1,19 @@
+---
+title: "Hire Me"
+---
+
+I am available for work Feel free to send me a mail at
+[contact@abdus.net](mailto:contact@abdus.net). You can find an online copy of my
+resume at [resume.abdus.net](resume.abdus.net).
+
+Relevant Information:
+
+- **Work Experience:** 2 Months(as an Intern). Fresher.
+- **Overall Coding Experience:** I have been writing code since 2017. I used to code
+ even before 2017, but that was not really full-time.
+- **Projects:** Everything on [GitHub](https://github.com/abdus)
+- **LinkedIn:** [here](https://linkedin.com/in/thisisabdus)
+
+If you need anything else, just ask me :)
+
+![Unsplash Image](https://images.unsplash.com/photo-1496545672447-f699b503d270?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&w=600 "Source: <a href='https://unsplash.com/photos/qelGaL2OLyE'>Unsplash</a>")
diff --git a/content/pages/keys.md b/content/pages/keys.md
new file mode 100644
index 0000000..b197f27
--- /dev/null
+++ b/content/pages/keys.md
@@ -0,0 +1,71 @@
+---
+title: Keys
+---
+
+This page holds information about my keys. You can send me encrypted messages
+using my public key. For a detailed guide on how to encrypt and sign data,
+follow [this guide](#).
+
+### GPG Public Key
+
+```plaintext
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQINBF7ps8gBEADCgXjLyu8rvtC6TRr+D8TzQUFjff4QB3qVABss5fq7kySU/ouF
+PGg5fO3m6TJx/9RN3eRLzMRDKvaMA3pCEC6+jLCXejsIHFnVv+zi4QyH+LifAL15
+WhyERqTF50K27WHINT6Rqc2dgIaIsN3ZiuFdI2NaWcGhZVazDhq24qIfsBaF7rZS
+DC4MzaX7y/zyGUMIAp0Uh+ymhWHgqCQy8HDJMy5rfFwKAVkPl0yfsrZ66tYhb8TD
+7uGGTmXL7S+J5E9ogA77OEyseS6Ud+YLvDwNK8YxjhjaebMJHF1JmXBDTab9nc98
+t3wX75L4pJd7Fkqm7BiPrXvOAzvZAwNZmgWGpn88nZIAL4nQkmQ2h0T5izOHYk9m
+UANAUpUWMGfBc6FCYVuNSF+h1758izVW3cHPFEezsX17vjvnuvHLnhL1n94L5XK7
+lQOhYBUkkTNppst6GaO7DvazTz7Mi+LP7AGFEPrZp+amSNUnbgs8fS3D+kMQdzhq
+5V++5IPCfV5POq+3G6mHmQmgVY/dwxUb+Q7Yww9VC/qzBVUW7YXbdg4VEISAiDtt
+U7BQca6lPwxV77lajtFBG8M6DJU4xZDwwgMcUu9fTWuCipJzdCNVw/95GkFdR5ig
+7Nc2xBd7oRPgpVurQgTA3jlRu6RgwzrbAIBR0MoIL1y6QqsjGFhXd3B/AwARAQAB
+tB5BYmR1cyBTLiBBemFkIDxtYWlsQGFiZHVzLnh5ej6JAk4EEwEIADgWIQQMmk6S
+Z8U4X8uZyP/rOWbje6Pf2AUCXumzyAIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIX
+gAAKCRDrOWbje6Pf2J2DD/92bTOROeBhmprKvW0c+1XkMSab72d+5fLOO5lALuqo
+zm040unWKp5FOij04d5+Cs0aV+ACMnNhApntfkZwHEDntqenRm3dvBbntFO6Jecd
+duDwO03+Z0x4RFFidhajnyfhdfaYIMb+2yFDvd+zLux2Qof/XXXbkjgdHRs+taXn
+H49M5NgEyTlfqOyIoNtPI038HDGsAQJR18kR40+JMlegACk8YJnHMt6TLZEvTW8o
+NWDrEGYP669d+20weJbriruGxf4qK5EFMBnO9SgEARNIw56uLgDSjazcUfapPpfl
+oNLLQ2RIi6+IBbM8XhB39PEjrPN9H7h1ftzBkZz+sPpWuc2LKsMfklv1xPudE4pH
+AGMVBOYEVc4cHkO0Jjq4ZFzUs81RHPWWRDj3/kkpIfEvbgfMTftE2BLNFurKVz8q
+aFifs6gflV3Y+MaXcD0yUGiondzp3Jn9/DNtFrLcKme3sblpAJj5qhN6dksERWC+
+EX07qZ3NQJVfgsejVvatUaToNFqVg/WyWqg2ki2l0jCLw5HqkqswfhU8HC7+mOBO
+Pugoijo3tBBnsnM4k1im8NUkGquNPU5NZI4uxOHbieXtyMhS9FOkAcE4pDLaVQjo
+wWN2go7YYNZbSx2kPDQLY4zbr985WqJg0RMXijl5IuGrUgwUE3kBoTRLWz73xENL
+y7kCDQRe6bPIARAA1gvg5Hf7vNLdrsjAs4ujlJnTerem0jrIBLY6ZazobZ/xCM1E
+va0iKWVQbo244AKnaFDETX6AaeA6hO3BBoYUWKwpiOtlz2D8vKAHTD4XRw7hQDN8
+63gV1kmDyqPoFJdmR25QLOt6qU2ZGfp+5Hocsxj8pDL3TcwF0BhiDftbXnX8S6du
+4Tx+ZPqkYQK3bgyuO9YUhNjTlrLrAyvm6+I8z9Gs7oVwWtQGl9acISfpvsKGX+ZD
+goo07PJlH/K07nunIgGIrFV7T5cbTqgRDvQ81fXRLP2qhnQMhtChwnRMpvDM4JML
+CMMznsXxqniBWUtx/lY//0TrvOXGHprIGCsGYGbcb5TRBfILGmUPJTKOOc/wHhlN
+mY50sBSfvQgAwLmMABu1V3M3arMWRJY3YfHZhnOZ34m43+T6OOPOjs1NTshEot+y
+X1GhtBrvWpMOojQE5DhvUoSxuiryGdx19llWWplkEg8Ju9ff7Hh9sAmSilPcmoI4
+0R9ByrfpzqFJDHjvBqTeLyCUMfi7rNmMOtjgsOpdPa/lDI9cSvR6UpZQB8nQoI65
+i2d6DcJswg2b4Mhr3JTu7mXxfbjZTQrb5zAgsLysLrMSB19i+vSYQGpg6AgM4vDy
+XDyoiCZ/+BvJU7xbKzNnG0XU4QyrvsIgvDL8Rg34+cyXAcX6y2ykI4oBDi8AEQEA
+AYkCNgQYAQgAIBYhBAyaTpJnxThfy5nI/+s5ZuN7o9/YBQJe6bPIAhsMAAoJEOs5
+ZuN7o9/Ywj4QALblriz6Lu+VNEAp2/2j1306NDmEqlJ/WYA1erB9amj8cdeoTjM9
+ZXcOmSGPN4v/KdQX84CTDxe056iCrgeIisjlaGDM1mfDMX/d+FaTzCy/8NBpqidU
+rUETHFktyjt1qouDQNLhP+U53SN+ZsU0fJht1Yl3PGuAXsIz/EcYgrFp2KiS2BMf
+dH6iOqZ/HdVzB30jLAiurMKCUSg3i7M10TR60aKWwz+GsTlYEVPHI69smyBOoAZ9
+1v2ogNafz4m4+KYsogq4IRebCI4KfRr/Kl2n7aEksPfjTfEixpbKuJI/p5rV9Ty+
+sM/8mVjXVWDE4CZQvbWVHkoObebnRwtDW5f0sE3+uaG18q0nDkIFEJoxHaedgjYP
+pMlo7ndhXYeVyaZarfPMrFzBv7SYfOFFzZV882ZhAiE8bYVkuU4OrrqKD/3vKBRK
+914eRYFuTwDblvWfjjcXxrZFMb7VN5OysGwYtKOyKnHbXgVBeyjl5zoTrdIynuuT
+0Lh71M5NNSc8M9RsNT6yw9BBxLhjrY+9LJ+mG1zxi0klA8lwleNJjLbGhWTnIDaK
+Y+PXVZDjoFscYjQSt+fmqbaMQYBPd6I7oEMBcHOToBvk1hRVt8/AKmz1UAOIZNzx
+dbPxtJkWBo/meGLNJlgav97mc+ULhytmbgQjsPSWzw7EBl/mUirOA00P
+=ET/J
+-----END PGP PUBLIC KEY BLOCK-----
+```
+
+### SSH Public Key
+
+If you want me to access your computer for any reason, please add this `ssh` key.
+
+```plaintext
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCaPseTrZqARbvFxp/qChI35N6Ivqz+1gVVXn699/4tavjgf/2dOIhHhfLbZ6IPhmXIutBC50w8Qju1YJbwT6XpoZqs31DIVCVctJUT5TY3OGzw28ZtGWvnilr1u09ozba7V/ctfyz4rGBS48NK8je10MzDLwbInSHPCN0ojboAc2vnQCmEIbMp6pXVS/wA8dfNYu27Nub/bnuHjb+pBF3s/UvTjk2jxRCr8fEMyVDJMNbuhk0yBIE3OIrjO2w4qC9TqPhdFToGHusIOmZvjPUSkAH21qKOm91+JPNTtY8T28oGzNZ75mWWIsli8nl8SwC4Ym0/rbo0pMUm9fFWNviL3ALa5jiAcjagIqw5WDPRO0jo2pYdEmtFEF8Z5VJQv/Rdk+bzp178WMuwf81wwjYR8vBcvw++JHiVCw1Q2zUdsVlQsq/YPnKp2R35i22WQ0czbTDKt8Y5WBV3UrKzwuP19wsmCP11gOWLRBKs1EW8lm12Ah8FKTr3nV9A351Ai5LWY8v98LnRm3+BwkXgkjJBx/YWyAPApOZ7CuklwV8bb8RRnUqzjYb7L8NxtsRasFJU1S30Ka4hylDFr9m8jcBXL7p5V5nuVBCRdiWN7/9RZtpGBTvmuxRcVPam5aDgOihiuX39d0cXGJuDgAeI2ZCJOqrW2jakL5AB0Sz7N+bZKw== mail@abdus.xyz
+```
diff --git a/content/pages/self.md b/content/pages/self.md
new file mode 100644
index 0000000..39de575
--- /dev/null
+++ b/content/pages/self.md
@@ -0,0 +1,28 @@
+---
+title: "About Me"
+---
+
+Hey there, I am Abdus. I am a full-stack developer.
+
+Don't really know what to write about myself. I will try to write something
+anyways.
+
+I learnt most of the things I know on my own. I don't have a degree in Computer
+Science, but I do have one in Computer Applications.
+
+Desperately trying to fill this page up with random things :/
+
+I am a Linux geek. I have been using [Arch Linux](https://archlinux.org) since
+almost 2 years++. Here, I have my [dotfiles](https://github.com/abdus/dotfiles)
+
+If you are a recruiter, have a look at my [resume](https://resume.abdus.net).
+And if you are a developer, here's my [GitHub
+Profile](https://github.com/abdus).
+
+Contact Info You may Need:
+
+- contact@abdus.net
+- [LinkedIn Profile](https://linkedin.com/in/thisisabdus)
+
+
+Oh...BTW I love playing GTA V.
diff --git a/content/posts/_index.md b/content/posts/_index.md
new file mode 100644
index 0000000..433692f
--- /dev/null
+++ b/content/posts/_index.md
@@ -0,0 +1,3 @@
+---
+title: Archive
+---
diff --git a/content/posts/abortcontroller.md b/content/posts/abortcontroller.md
new file mode 100644
index 0000000..b69e2b0
--- /dev/null
+++ b/content/posts/abortcontroller.md
@@ -0,0 +1,171 @@
+---
+draft: false
+meta:
+ image: /images/262edf0c536be421bf4750d50673f523.jpg
+ description: null
+featured: false
+title: "Terminating DOM Operations at will: 'AbortController' in JavaScript"
+date: 2020-07-26T21:51:49+05:30
+tags:
+ - js
+ - javascript
+ - dom
+categories:
+ - javascript
+tableofcontents: true
+---
+
+## Intro
+
+**AbortController** is an interface which provides a way for terminating one or
+more web request as and when desired.
+
+This generally means that a request can be terminated by a user whenever needed,
+irrespective of whether the operation is finished or not.
+`AbortSignal` can be implemented in any web platform API which uses
+[`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
+
+## The API
+
+AbortController provides a few things for users to implement it effectively in
+code. At the time of writing this, the constructor would return an instance which
+contains a method `AbortController.abort()` and a property
+`AbortController.signal`(read-only).
+
+- `AbortController.signal` - Returns a `AbortSignal` instance
+- `AbortController.abort()` - Aborts a DOM Request
+
+### AbortSignal
+
+`AbortController.signal` returns an instance of type `AbortSignal` which
+represents the current state of the AbortController instance.
+It has a read-only property `AbortSignal.aborted`. Type of property `aborted`
+is `Boolean`.
+
+`AbortSignal` is also responsible for communicating with DOM as an Event Listener
+can be attached to it.
+
+## Using AbortController
+
+To use AbortController in a `Promise`, one must adhere to a few rules.
+[Source](https://dom.spec.whatwg.org/#abortcontroller-api-integration)
+
+- Function should accept `AbortSignal` through a `signal` property. For example:
+ ```javascript
+ function abortThis(arg1, { signal }) {
+ return new Promise((resolve, reject) => {
+ // function body
+ })
+ }
+ ```
+- When method `aborted()` is called, **reject the Promise** with a
+`DOMException` `AbortError`
+ ``` javascript
+ throw new DOMException('aborted by user', 'ABORT_ERR');
+ ```
+- Abort immediately if the `aborted` flag on `AbortSignal` is set to `true`.
+
+
+## Browser Support
+
+Despite being a relatively new API, browser support for AbortController is
+quite awesome! All major browser _fully_ supports it. Following is a chart
+from _Can I Use_.
+
+<!--Embed for the feature from Can I Use-->
+{{< caniuse feature="abortcontroller" periods="future_1,current,past_1,past_2" >}}
+
+## Examples
+
+Following are a few examples of `AbortController` API. First one is using `fetch`
+API. On the second example, I will try to implement it in a `Promise`.
+
+### Using Fetch API
+
+```javascript
+const controller = new AbortController();
+const signal = controller.signal;
+
+// fetch a URL
+fetch('https://jsonplaceholder.typicode.com/todos/1', { signal })
+ .then(raw => raw.ok && raw.json())
+ .then(console.log)
+ .catch(e => console.log(e.message));
+
+// driver code
+setTimeout(() => {
+ // abort network request if it takes
+ // more than a second
+ controller.abort();
+}, 500);
+```
+
+The above code allows a network request to run for `500ms`. If data has been
+fetched within that period, it would return JSON representation of the response.
+Otherwise, it would abort the request.
+
+### Implementing using Promise
+
+In this section, I will try to implement `AbortController` for a function which
+returns Promise. Should be quite easy and straightforward. [Here is a Gist](https://gist.github.com/abdus/90ec5cab55f55e44b18835276bdc66b2) for the same.
+
+```javascript
+/* this function would return a Promise
+ * which would resolve with value `hello`
+ * after 4s
+ */
+function abortTask({ signal }) {
+ return new Promise((resolve, reject) => {
+ // 1. check if it's already aborted
+ if (signal && signal.aborted) {
+ return reject(new DOMException('`signal` is in `aborted` state', 'ABORT_ERR'));
+ }
+
+ // wait for 4s
+ setTimeout(() => resolve("hello"), 4000);
+
+ // 2. add a listener to `signal` to check its state
+ signal && signal.addEventListener('abort', () => {
+ // reject promise when signal.aborted changes to `true`
+ return reject(new DOMException('aborted by user', 'ABORT_ERR'));
+ })
+ })
+}
+
+
+
+/* DRIVER CODE */
+let signal; // just so that I could re-use it
+
+
+// when `signal.aborted` is `false`
+const abortController_1 = new AbortController();
+signal = abortController_1.signal;
+
+abortTask({ signal })
+ .then(t => console.log(t)) // hello
+ .catch(e => console.error(e.message))
+
+
+// when `signal.aborted` is `true`
+const abortController_2 = new AbortController();
+signal = abortController_2.signal;
+
+abortController_2.abort();
+
+abortTask({ signal })
+ .then(t => console.log(t))
+ .catch(e => console.error(e.message)) // err
+
+
+// when user calls AbortController.abort()
+const abortController_3 = new AbortController();
+signal = abortController_3.signal;
+
+// abort task in 2s
+setTimeout(() => abortController_3.abort(), 2000);
+
+abortTask({ signal })
+ .then(t => console.log(t))
+ .catch(e => console.error(e.message)) // err
+```
diff --git a/content/posts/finding-duplicate-files-in-linux.md b/content/posts/finding-duplicate-files-in-linux.md
new file mode 100644
index 0000000..8c83020
--- /dev/null
+++ b/content/posts/finding-duplicate-files-in-linux.md
@@ -0,0 +1,184 @@
+---
+draft: false
+meta:
+ image: /images/a41f9d00c5c8b8890d2d5788cf19a801.jpg
+ description: Creating a simple duplicate file finder with an algorithmic
+ approach using GNU Bash. This post is focused on how coding something by
+ keeping algorithmic thinking in mind would make it better
+featured: false
+title: Finding Duplicate Files in Linux - The Hard Way
+date: 2020-07-11T21:53:45+05:30
+tags:
+ - algorithms
+ - bash
+categories:
+ - linux
+tableofcontents: true
+---
+
+Duplicate files, in Layman's term, are the files which are exactly a copy of
+one another. For example, if we have two files _biz_ A and B; A would be a
+duplicate of B if it has the same content as file B.
+
+Duplicates are generally unavoidable. No matter what you do, you would always
+end up getting a few of them. Going through the whole file system and finding
+them one by one is a tedious job. And no sane person would ever think of doing
+that manually when the file count is literally in thousands.
+
+Filtering them out and removing is quite easy though. All you need to do is
+install some tools like [`rdfind`](https://rdfind.pauldreik.se/), [`fslint`](https://www.pixelbeat.org/fslint/) etc. Run a few commands, and
+duplicates would vanish. [Here is a guide](https://www.tecmint.com/find-and-delete-duplicate-files-in-linux/) to help you out.
+
+If that's what you are here for, you won't have to read any further. Download
+any one of those tools and get your job done. This post emphasizes on how to
+**build one such tool** for your use :)
+
+## 1. Comparing File Content
+
+The first way is to compare the contents of one file with all available files in
+that directory. So, if you have like 10 files: choose a random file and read its
+content. Store its content in a variable. Loop through rest of the files and
+compare their contents with the one you have stored in a variable. If matches,
+delete that file. If not, move on.
+
+A simple code example would help better in understanding (for simplicity, I am
+ignoring directories):
+
+```bash
+#!/bin/bash
+
+# program to find a duplicate
+# public key file
+
+for f in `ls -p | grep -v /` # filter files
+do
+ f_CONTENT=`cat "$f"`;
+ for g in `ls -p | grep -v /`
+ do
+ g_CONTENT=`cat "$g"`
+ if [[ $f_CONTENT == $g_CONTENT && $f != $g ]]; then
+ # duplicate
+ echo "DUPLICATE: $f === $g";
+ fi
+ done
+done
+```
+
+As you might have already understood how resource hungry this program would be.
+I mean, it is not. But compared to other possible ways, it's a resource-hungry
+process.
+
+This program would have a time **complexity of O(n^2)**. Not ideal.
+
+### Limitations
+
+So, here's a summary of why I think this approach is bad:
+
+- Takes up more resources than it should
+- Have a complexity of O(n^2)
+
+## 2. Using Hashing Technique
+
+My second option is to use file-hash. This method would be quite similar to
+the previous one, except that instead of storing file content, I would be
+storing the hash value of that content :)
+
+If you are wondering what a hash is; well, it is a unique string of alphanumeric
+characters generated from a given object.
+
+For a given object(like ASCII characters, binary files etc), the generated hash
+would always be the same. Change a character(even space), and it would differ.
+
+Generation of hash is done by using algorithms. You feed an algorithm
+with data, and it calculates the hash value of that data. There are
+so many hashing algorithms that are available out there. A few among them are
+SHA, BlowFish, MD5 etc which are quite popular.
+
+One more unique thing about hash is, it is irreversible. You can't extract the
+content from which the hash was generated.
+
+> Note that, this method won't give much better result over the previous method as hashing is a slow process and it _does_ consume a lot of resources.
+
+In Linux, there are tools for generating a hash of any given files. In most of the
+distributions, they are pre-installed.
+
+Following is a Bash Script which would implement whatever I said so far.
+
+```bash
+#!/bin/bash
+
+# find duplicate using hashing technique
+for f in `ls -p | grep -v /`
+do
+ f_sha=`sha1sum "$f" | awk '{ print $1 }'`;
+ for g in `ls -p | grep -v /`
+ do
+ g_sha=`sha1sum "$g" | awk '{ print $1 }'`
+
+ if [[ $f_sha == $g_sha && $f != $g ]]; then
+ # duplicate
+ echo "SAME: $f === $g";
+ fi
+ done
+done
+```
+
+As you can see, it does not make any huge difference. Worse, it adds an extra
+step of calculating SHA1SUM of each file.
+
+## 3. Maps (or HashMaps)
+
+Or Dictionary, Object, Associative array, HashTable ... whatever you call them.
+Hashmaps are a collection of pairs of key-value stored inside a variable. One
+prominent benefit of the hashtable is that **complexity of searching an element is O(1)**. Read more about hash-table on [Wikipedia](https://en.wikipedia.org/wiki/Hash_table).
+
+What does this mean? I could **reduce the time complexity of my code to O(n)**.
+
+## Combining Everything ...
+
+Since I can combine the hashing technique(mentioned in the previous method) with
+HashTable, the program would be more efficient and simple. I won't have to use
+two `for` loops. This would also reduce time complexity.
+
+I am not using file content as key in hashtable. I could have stored either
+a file name or file content as a key. But neither of then would work.
+
+- Two files would never have the same name under a single context.
+- File content could be of any type, ranging from ASCII to Multimedia etc.
+ This does not make it ideal for using as Key.
+- Just imagine, what if the file size is huge.. HUGE? like 2 or 3 GB! Or more!
+ it would increase the space needed by the program to run, ultimately increasing
+ the resource consumption.
+
+So, I will be using SHA1SUM(generated using `sha1sum` tool) as key. For value,
+I would just set it to `true` since it does not matter what value it
+holds.
+
+Since v4.0, Bash provides a native way of creating HashTables. I won't have to
+look for another language to write this small program.
+
+Enough explaining, here is the code:
+
+```bash
+#!/bin/bash
+
+declare -A checksums # `checksums` is a hash-table
+
+for f in `ls -pS | grep -v /`
+do
+ file_hash=`sha1sum "$f" | awk '{ print $1 }'`
+ if [[ "${checksums[$file_hash]}" == true ]]; then
+ echo "DUP: $f"
+ else
+ checksums[$file_hash]=true;
+ fi
+done
+```
+
+## Conclusion
+
+There is no point in reinventing the wheel. There are so many popular tools for
+finding and removing duplicates from the file system. Use any one of them.
+
+I am learning algorithms. So, I thought of explaining some stuff which would help
+me understand it better. Hence, this article.
diff --git a/content/posts/fixing-pip-issue-in-arch-linux.md b/content/posts/fixing-pip-issue-in-arch-linux.md
new file mode 100644
index 0000000..46cff07
--- /dev/null
+++ b/content/posts/fixing-pip-issue-in-arch-linux.md
@@ -0,0 +1,54 @@
+---
+title: "Fixing PIP Issue in Arch Linux"
+date: 2020-04-01T22:43:30+05:30
+draft: false
+categories: ['linux',]
+tags: ['pip', 'arch-linux', 'pacman', 'python']
+---
+
+
+Recently, I was upgrading Arch Linux on my laptop. And I encountered something
+unusual with `pip` and its libraries. Everything related to pip(and pip itself)
+can not be upgraded in anyways!
+
+The problem wasn't new to me. I knew what I am doing wrong. I was using pip to
+install package on system-level. So, obviously, pacman was not owning it.
+So, the easiest solution for me was to delete files that are not owned by
+pacman and blocking the upgrade process. And I did! I was quite sure about this,
+because a while ago, I faced a similar issue for installing npm packages
+on system level using sudo.
+
+Phew! Successfully installed upgrades!!
+
+But, the issue was not completely gone! The other day, I needed python for
+running some scripts(with external dependency libraries).
+So, I needed to use pip to install package.
+
+Now, because I deleted some files(or probably all of them) from
+`/usr/lib/python3.8/site-packages` directory during the upgrade process,
+I was getting an error saying that, package `six` not found.
+
+I tried reinstalling pip, did not work. Removed pip and installed again,
+did not work either. I was little bit worried by now .. lol.
+Because, I don't really know much about python world. Neither searching google
+was quite helpful. I mean, I literally knew what was wrong,
+and yet I couldn't do anything.
+
+## Reinstalling Everything Worked!
+
+Yeah! It. Just. Worked!! Now, finally I can use `pip` instead of `pip2` .. haha
+
+To do a full system reinstall, one do it like this on Arch Linux:
+`pacman -Qnq | sudo pacman -S -`. It is safe! No worries about that.
+
+## Points to Remember
+
+1. Don't use `sudo` to install packages with anything other than pacman.
+2. Store pip packages in user's directory instead of any system-level
+locations(like `/usr/lib` etc)
+3. Always use `pip` with the `--user` flag.
+Example: `pip install <package_name> --user`
+4. `lostfiles` in AUR is an useful application for filtering packages not owned
+by pacman.
+
+Good Day!!
diff --git a/content/posts/get-set-bash.md b/content/posts/get-set-bash.md
new file mode 100644
index 0000000..50de197
--- /dev/null
+++ b/content/posts/get-set-bash.md
@@ -0,0 +1,247 @@
+---
+title: 'Get, Set ... Bash'
+date: 2020-07-17T22:58:50+05:30
+draft: true
+meta:
+ image: # url to image. Important for blog listing and seo
+ description: # overrides .Summary
+featured: false # feature a post in homepage
+tableofcontents: true # whether to generate ToC
+tags: ["bash", "cli"]
+categories: ["linux"]
+---
+
+**Bruno Again Shell**, _aka_ BASH, is an interpreter developed by GNU Foundation.
+This interpreter/shell is capable of running Linux system commands. It also
+has features like loops, conditions etc which makes it quite capable of doing
+scripting.
+
+> This article is some sort of **Note to Self**. This will be an in-depth reference. I reference things from here when I am writing a BASH script.
+
+## Running a Script
+
+There are couple of ways to run a bash script(or any other scripts, in general).
+The most popular way is, `./` followed by script path. For example, if I have a
+script file inside `~/Desktop`. Assume that non-existant file name is
+`set-time.sh`. Now to run that file, one may type something like
+`./Desktop/set-time.sh`(again, assuming that they are inside home directory).
+In response to this command, shell would execute codes available inside
+`set-time.sh`.
+
+Another way is: to actually write the script interpreter, followed by script path.
+For example: `bash ~/Desktop/set-time.sh`.
+
+## Hashbang (Shebang)
+
+In [Running a Script](#running-a-script) section, did you think about how the
+shell would know which interpreter to use? Well, that is done by a special line
+of code. This line of code is known as Shebang(or Hashbang). An example of
+hashbang is: `#!/bin/bash`. This is simply telling shell that: when running the
+code, use `bash` program. `/bin/bash` is the path to bash interpreter.
+
+A shebang must always be at the top of the script.
+
+> Bash is a Shell. There are many other shells similar to Bash. A few of them are: C-Shell, Z-Shel, Fish Shell etc. Each shell have their own specifications for interpreter. They sometime may vary in features. This post is focused on Bash.
+
+## Comments
+
+In Bash, line with a preceeding '#' would be considered as comment(except for
+shebang). Comments are for documenting a script internally, just like any
+other languages.
+
+## Variables
+
+Variables in Bash are pretty much similar to any other languages, except for one
+major difference. That is: there should be no space between variable name, `=`
+and it value. An example would demonstrate it better.
+
+```bash
+#!/bin/bash
+
+HELLO="world" # notice that there's
+ # no whitespace
+
+WORLD = "hello" # this would throw an
+ # error
+```
+
+A variablen name **does not have to be in uppercase**. It's just a convention.
+
+### Storing Command outputs
+
+Output of another command could as well be stored in a variable. To do so, one
+has to spawn up a child-process using either `$()` or **``**. Following is an
+example to illustrate the same.
+
+```bash
+#!/bin/bash
+
+NOW=`date`
+NOW_MD5=$(date | md5sum)
+```
+
+## Printing Variables/String Literals
+
+There are two ways one could print someting to `stdout`. One is `printf` and the
+other is `echo`. Both have their own features (as they co-exists).
+
+### Echo
+
+The familiar one. `echo` takes an input as argument and send it to `stdout`(which
+is generally a terminal window). However, before sending it to `stdout`, it does
+removes all newline characters from given content.
+
+### Printf
+
+`printf` works quite similar to `echo` except that it does not removes any newline
+character.
+
+So, in summary:
+
+- Echo (`echo`)
+ - removes newline (`\n`) character
+- Printf (`printf`)
+ - does not remove any newline characters
+
+## Redirect and Pipe
+
+### Redirect
+
+Redirects is a way to send the **output of a command to any arbitary locations**.
+For example: if I want to run date command, but don't want to print it's output
+in `stdout`. I could "redirect" it to `/dev/null` using `>` operator.
+Demonstration:
+
+```bash
+#!/bin/bash
+
+date > /dev/null
+```
+
+Apart from `stdout`, `stdin` and `stderr`, redirect could send output to files
+as well. Hint: It will create the file if it does not exists.
+
+> `/dev/null`, _a.k.a._ "the blackhole", is a special device in GNU/Linux. Whatever you redirect to this location, would get vanished ... just like anything that goes inside a blackhole.
+
+### Pipe
+
+Pipe is used to send **output of one command to be used as input of another**.
+`|` is knwon as the Pipe operator.
+
+**Example**: I have a csv file containing names of all my classmates along with their
+address. And I need to print address of a given name to `stdout`. But before that,
+I need to replace `,` with `=`. How do I do that? Let's see.
+
+```bash
+#!/bin/bash
+
+FILE=path/to/file.csv
+REPLACE_CHAR=","
+NAME_TO_FIND="Rickard"
+
+cat $FILE \
+| tr $REPLACE_CHAR "|" \
+| grep --color="always" -i $NAME_TO_FIND
+```
+
+Nothing much is going on in this script. First, I read the content of file `$FILE`
+using `cat` utility command, then I **pipe** the output to `tr`, which ***essientially***
+replaces all comma characters with equal sign.
+
+## Logical Operators
+
+`&&`, `||`, `!` etc are known as **logical operators**. How these operators
+work, could be demonstrated by using circuit gates and truth-table.
+
+`&&`(_a.k.a_ AND) **executes the right hand side expression only when the left
+hand side expression evalutes to true**. Similarly, `||` (_a.k.a_ OR) would
+execute left hand side. **If LHS evalutes to `false`, it would execute the
+right hand side expression**. `!` (_a.k.a_ NOT) would simply **invert a
+given boolean value**.
+
+## Control Flows
+
+BASH provides conditionals out-of-the-box. Following are some example of `if`,
+`if..elif` etc. There's nothing much to discuss about. If I find out any
+interesting edge cases, I will update them later on. For now, look at following
+codeblock to know about control-flows:
+
+> Bash treats empty strings as falsy value, much like any other sane language.
+
+### `if`, `if..else` and `if..elif`
+
+```bash
+#!/bin/bash
+
+NAME="abdus"
+
+# if statement
+if [[ $NAME == "abdus" ]];
+then
+ echo "Hello, $NAME";
+fi
+
+# if..else
+if [[ $NAME == "azad" ]];
+then
+ echo "Won't be printed"
+else
+ echo "Hello, $NAME"
+fi
+
+# if..elif
+if [[ $NAME == "hey" ]];
+then
+ echo "Not a Name"
+elif [[ $NAME == "azad" ]];
+then
+ echo "That's Last Name"
+else
+ echo "Hello, $NAME"
+fi
+
+# Note that one does not have to put
+# double square bracket around the
+# condition all the time. TODO: write
+# how both are different
+```
+
+
+## Loops
+
+Loops are a language feature which enables programmer to do a task repeatedly.
+Bash have four kind of loops, namely `for`, `while`, `until` and `select`.
+
+### TODO: Write about `break`, `continue` etc
+
+### `for` Loop
+
+For a given list, a for loop would go through each item and execute the enclosed
+code in loop's body. Example:
+
+```bash
+#!/bin/bash
+
+# VARIATION: 1
+# this script would list
+# output of ls command
+# separated by newline
+for item in `ls`;
+do
+ echo "NAME :: $item"
+done
+
+# VARIATION: 2
+# this would output given
+# array-like input
+for item in shell scripting is cool
+do
+ echo "$item"
+done
+```
+
+### `while` Loop
+
+### `until` Loop
+
+### `select` Loop
diff --git a/content/posts/github-profile-readme-as-twitter-like-feed.md b/content/posts/github-profile-readme-as-twitter-like-feed.md
new file mode 100644
index 0000000..4175fb1
--- /dev/null
+++ b/content/posts/github-profile-readme-as-twitter-like-feed.md
@@ -0,0 +1,91 @@
+---
+title: "Using Github Profile Readme as 'Twitter-like' Feed"
+date: 2020-08-20T06:46:55+05:30
+draft: false
+meta:
+ image: https://dev-to-uploads.s3.amazonaws.com/i/lk63wznpuwhi5mzcgtkh.png # url to image. Important for blog listing and seo
+ description: # overrides .Summary
+featured: false # feature a post in homepage
+tableofcontents: true # whether to generate ToC
+tags: [github, mastodon]
+categories: [misc]
+---
+
+![github profile readme](https://dev-to-uploads.s3.amazonaws.com/i/lk63wznpuwhi5mzcgtkh.png)
+
+I had this weird idea of using GitHub profile README as Twitter-like(well,
+Mastodon TBH) feed! There was no specific reason for doing so. I roughly
+thought it would boost my Mastodon profile(which is quite new at the moment)
+reach.
+
+Another reason was to see how far I could go with limited tools (as Github
+ReadMe does not support JavaScript yet).
+
+## Generating those Cards
+
+There was only one thing to figure out. How to create beautiful status cards
+with limited CSS! I knew I could use SVG and make whatever I want. But not
+all browser supports every feature of SVG yet. So, generating and
+storing SVG codes as images may not always work.
+
+Since GitHub has introduced workflows(better be late than never), I chose to
+render SVG on a webpage and convert them to PNG, all in Server-side.
+
+This way, I am assured that SVG would be rendered in the latest browser and
+converted PNG. But how do I do it?
+
+There is a package called [Puppeteer](https://github.com/puppeteer/puppeteer) in the NPM registry. This library gives
+the user a way to control Chromium/Firefox browser programmatically. This,
+by default, runs browser in headless mode. So, the user would be able to run it
+without a Desktop Environment.
+
+## Getting 'Toots' from Mastodon
+
+If you don't know about Mastodon, you can think of it as Open-Source Twitter!
+[Read more about Mastodon](https://joinmastodon.org/).
+
+Mastodon have an API to fetch public toots of any profile without using an
+API key. The response is in JSON, so parsing it was quite simple.
+
+> Biggest surprise: If I add a Middot (·) somewhere inside SVG, loading image
+> won't work! It throws an encoding error.
+
+## Installing Font
+
+After pushing the initial version to GitHub, I noticed that the font I was
+using locally was not available in Github Workflows environment. So, I had to
+install them manually. Although I could simply add a font CDN using `style`
+tag within SVG, why not do it the Linux' way? :P
+
+Installing font through command-line as just three simple steps.
+
+- download font as a zip archive
+- extract font files to `~/.fonts` using `unzip`
+- run `fc-cache -f -v` to manually update the font cache
+
+## Writing Workflow Steps
+
+I set-up the workflow to run in two events. First is, when I push something to
+the repository. And second is, on every hour (using a Cronjob). This way, I won't
+have to worry about updating ReadMe manually when I post a new toot.
+
+- Setting up Node and NPM was done by an action called [`setup-node`](https://github.com/actions/setup-node).
+- Installing required font was done by a custom bash [script I wrote](https://github.com/abdus/abdus/blob/57372e8c9321a3c0d1141098483a0c2a648315a6/.github/workflows/publish.yml#L21-L26).
+- Finally, the [image creation script](https://github.com/abdus/abdus/blob/master/index.mjs) was run using Node, commit the changes, and push them back to GitHub.
+
+And the work is done here!
+
+## Conslusion
+
+Sure, this thing was just for fun. But I learnt quite a few new things.
+
+- I can't use Middot(or similar characters) within an SVG tag. Now I know
+ what to look for when there's an encoding issue.
+- I understand how `action/checkout` works. This will help me write better
+ workflows in future.
+- I learnt about some SVG tags. For example, `switch` and `foreignObject`.
+
+If you liked this, I would be happy if you **star 🌟 [this repository](https://github.com/abdus/abdus)**.
+You can follow me on Mastodon. My handle is **@abdus@linuxrocks.online**.
+
+_Also published in [dev.to](https://dev.to/abdus/using-github-profile-readme-as-twitter-like-feed-25k4)_
diff --git a/content/posts/heroku-alternative-caprover-paas.md b/content/posts/heroku-alternative-caprover-paas.md
new file mode 100644
index 0000000..187d564
--- /dev/null
+++ b/content/posts/heroku-alternative-caprover-paas.md
@@ -0,0 +1,169 @@
+---
+title: "Get Your Own Heroku - a Guide on How to Run a Custom 'PaaS' for deploying Apps"
+date: 2020-04-26T11:05:04+05:30
+draft: false
+tags: ['paas', 'heroku', 'node.js', 'vps', 'custom platform']
+categories: ['cloud']
+---
+
+Heroku is a fantastic platform for Node.js developers. It made deployment
+of Node.js apps super easier. But obviously. it have so many limitations on
+free-tier, which makes it less ideal for deploying certain kind of projects,
+like a telegram bot etc.
+
+## The Idea
+
+I was having a pretty similar issue. I needed to host a bot. Initially, it was
+in Heroku, but due to the fact that every apps on Heroku free tier goes for
+sleep after inactivity of around 30 minutes. This, generally, is not a problem
+for websites, but bots won't work. There is always a delay on bot response.
+
+First, I thought I would build my own Heroku-like platform. But it's not really
+easy. So, I went off with an open-source 'Platform as a Service' software.
+
+Likely, there are many such open-sourced products available. One of them is
+**[CapRover](https://github.com/caprover/caprover)**.
+
+### Features
+
+1. Docker-based deployment. Each of the deployed app would have their own
+isolated space.
+2. Support for `Dockerfile`. A `Dockerfile` would maximize the possibilities of
+what you could do with the deployments.
+
+## Prerequisites
+
+Nothing much required, really! All you need is:
+
+- A VPS to host CapRover. Preferably DigitalOcean
+ It should also have a Linux OS installed. Ubuntu is preferred.
+- Basic Linux Shell Skills for installing required applications.
+- A Domain Name
+
+### Initial Server Setup
+
+If you are using Digital Ocean, first you need to create a droplet. Digital
+Ocean have a nice guide on [how-to setup a droplet](https://www.digitalocean.com/docs/droplets/how-to/create/).
+
+Once you are done creating a Droplet, it's time to update the system.
+To do that, you need to access your droplet using SSH.
+[This tutorial](https://www.digitalocean.com/docs/droplets/how-to/connect-with-ssh/)
+would help you do that.
+
+After connecting to droplet via SSH, update and upgrade the system using
+`sudo apt update && sudo apt upgrade`. Note that, these commands are for Ubuntu.
+
+We also need a couple of other software in order to get our CapRover
+server up and running. We will be installing them one by one.
+
+#### Docker
+
+CapRover is built on top of Docker. So, it's an essential essential software.
+To install docker, checkout the official [Docker documentation for Ubuntu](https://docs.docker.com/engine/install/ubuntu/).
+
+> You may need to add the current user to `docker` group. To do so,
+run `sudo usermod -aG docker <user_name>`. Otherwise, you will get a docker error.
+
+#### Node.js and NPM
+
+Yeah, these Node thing is everywhere these days :/ But anyways, it should be
+relatively easier to install. Note that, by default Ubuntu repository have
+`node v8.x.x`. We need at least `v10.x.x`. So to install
+`node v13.x.x` via NodeSource:
+
+```sh
+curl -sL https://deb.nodesource.com/setup_13.x | sudo -E bash -
+```
+
+Then run `apt-get install` command.
+
+```sh
+sudo apt-get install -y nodejs
+```
+
+To confirm that you have Node installed, run `node -v` from terminal.
+
+#### NPM
+
+It's possible that NPM was installed along with Node.js. You can verify that
+using `npm -v`. In case it is not installed, install it from Ubuntu repository
+using `sudo apt install npm`.
+
+By default, NPM needs `sudo` to install global packages, which is not
+recommended. To change this behavior, change `prefix` in NPM config.
+Run `npm config set prefix dir_name`(replace `dir_name`
+with a directory name where you want to have npm packages).
+You also, need to add `dir_name/bin` to your PATH variable.
+
+### Domain Setup
+
+By now, you should have a static IP address assigned to your Digital Ocean
+droplet. If you have a domain name purchased, you need to point it to your
+server IP address using A record. For example: you want
+`captain.yourdomain.com` as your app host. You need to setup two
+different a records.
+
+```txt
+cap A 3.23.76.12
+*.captain A 3.23.76.12
+```
+
+At this point, your server is ready to host CapRover. You may additionally need
+to allow some ports in order to make CapRover work.
+You can allow them using `ufw` command in Ubuntu.
+
+```sh
+ufw allow 80,443,3000,996,7946,4789,2377/tcp; ufw allow 7946,4789,2377/udp;
+```
+
+Note that, this command must run in root shell.
+
+## Install CapRover and CapRover CLI
+
+Thanks to the devloper of CapRover, it's super easy to install.
+All we need is to run one command, sit back and watch it installing.
+
+```sh
+docker run -p 80:80 -p 443:443 -p 3000:3000 -v /var/run/docker.sock:/var/run/docker.sock -v /captain:/captain caprover/caprover
+```
+
+Once the CapRover installation is done, visit `cap.domainname.com:3000` to
+verify if CapRover is working. We also need to install CapRover CLI in order
+to manage deployment, sertup server etc. To install CapRover from NPM,
+run `npm i -g caprover`. Once installed, run `caprover serversetup`,
+and follow the interactive command prompt.
+
+At this point, you have a CapRover instance running successfully. Check this
+guide for various
+[deployment methods](https://caprover.com/docs/deployment-methods.html).
+
+> Before deploying a project, make sure to create an `app` using the Web GUI.
+Otherwise, you won't be able to deploy.
+
+For more information about CapRover and it's configurations,
+check out its **[official docs](https://caprover.com/docs)**.
+
+## Conclusions
+
+Having a self-managed PaaS could be very handy.
+Following are a few reasons I choose to go with a self-managed PaaS
+for hosting apps.
+
+1. I would be saving money.
+ Generally, if I go for Heroku non-free tier, I would be paying a lot
+ of money compared to what I pay now.
+2. Shared Resources.
+ Server resources won't get wasted because each and every app would be
+ able to access resources from the same resource pool. So, let's say,
+ I have 2 GB of RAM. And I need only 1 GB to host XYZ webapp.
+ Now, I can use the remaining amount of RAM to spin-up a
+ new instance ABC webapp.
+3. Support for [insert techstack name]
+ Since, CapRover uses docker to deploy a new instance, I can basically
+ run apps built using any back-end technologies.
+ And write how to deploy it using a Dockerfile. I have so much
+ flexibility now.
+
+The only downside I could think of is, I have to look after the server.
+This is won't be a big deal, thanks to AWS ❤️
+
diff --git a/content/posts/intro-to-javascript.md b/content/posts/intro-to-javascript.md
new file mode 100644
index 0000000..70dc29a
--- /dev/null
+++ b/content/posts/intro-to-javascript.md
@@ -0,0 +1,75 @@
+---
+title: "Resources to Learn JavaScript"
+date: 2020-07-26T19:01:58+05:30
+draft: true
+meta:
+ image: # url to image. Important for blog listing and seo
+ description: # overrides .Summary
+featured: false # feature a post in homepage
+tableofcontents: true # whether to generate ToC
+tags: [js, javascript, web, web-tech]
+categories: [javaScript]
+---
+
+Before you go through the resources, you should have a basic understanding about
+what JavaScript is, what it does .. etc.
+
+JavaScript is one of the core languages used for building anything on web,
+originally designed by Branden Eich at Netscape. JavaScript(known as LiveScript,
+back then) was first shipped with Netscape Navigator, making Netscape Navigator
+the first browser to support dynamic web pages. This all happened at 1995.
+
+Fast-forward to 2009, ECMA International standardized the language specs and
+released ECMAScript 5(_a.k.a_ ES5), which was widely adopted by everyone.
+
+> Ecma International is an industry association founded in 1961 and dedicated
+> to the standardization of Information and Communication Technology (ICT) and
+> Consumer Electronics (CE).
+
+## Resources
+
+Following are the links to a few resources I have collected to help you learn
+JavaScript.
+
+### Websites/Blogs
+
+- [JavaScript Info](https://javascript.info)
+- [W3Schools](https://w3schools.com)
+- [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
+- [Free Code Camp](https://freecodecamp.com)
+- [Dev Docs](https://devdocs.io/javascript)
+- [Can I Use](https://caniuse.com) - A website for checking whether a feature is supported in targeted browsers.
+- [Overreacted](https://overreacted.io)
+
+### YouTube Channels
+
+- [LevelUpTuts](https://www.youtube.com/user/LevelUpTuts)
+- [Traversy Media](https://www.youtube.com/user/TechGuyWeb)
+- [Programming With Most](https://www.youtube.com/user/programmingwithmosh)
+- [Academind](https://www.youtube.com/channel/UCSJbGtTlrDami-tDGPUV9-w)
+
+### YouTube Playlists
+
+- [Vanilla JavaScript: Traversy Media](https://www.youtube.com/playlist?list=PLillGF-RfqbbnEGy3ROiLWk7JMCuSyQtX)
+- [Learn JavaScript: Programming with Mosh](https://www.youtube.com/playlist?list=PLTjRvDozrdlxEIuOBZkMAK5uiqp8rHUax)
+- [JavaScript ES6: Traversy Media](https://www.youtube.com/playlist?list=PLillGF-RfqbZ7s3t6ZInY3NjEOOX7hsBv)
+- [HTML, CSS & JS Basics: Academind](https://www.youtube.com/playlist?list=PL55RiY5tL51oJMqB1syVpXmQySoJsduFl)
+
+### Learn by Doing
+
+- [Node School](https://nodeschool.io/)
+- [Frontend Mentor](https://www.frontendmentor.io/)
+- [JavaScript 30 by Wes Bos](https://javascript30.com/)
+
+### Books
+
+- [You Don't Know JS](https://github.com/getify/You-Dont-Know-JS)
+- [Eloquent JavaScript](https://eloquentjavascript.net/)
+- [JavaScript: the Good Parts](https://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742/)
+
+### Courses
+
+- [The Complete Web Developer in 2020: Zero to Mastery](https://www.udemy.com/course/the-complete-web-developer-zero-to-mastery/)
+- [The Modern Javascript Bootcamp Course (2020)](https://www.udemy.com/course/javascript-beginners-complete-tutorial/)
+- [Academind](https://academind.com/)
+- [Frontend Masters](https://frontendmasters.com/)
diff --git a/content/posts/neomutt-the-command-line-email-client.md b/content/posts/neomutt-the-command-line-email-client.md
new file mode 100644
index 0000000..f397f48
--- /dev/null
+++ b/content/posts/neomutt-the-command-line-email-client.md
@@ -0,0 +1,252 @@
+---
+title: "NeoMutt: the Command Line Email Client"
+date: 2020-10-20T14:07:39+05:30
+draft: false
+meta:
+ image: https://i.ibb.co/rFj4XY0/pipes.png # url to image. Important for blog listing and seo
+ description: # overrides .Summary
+featured: false # feature a post in homepage
+tags: [mutt, email]
+categories: [tools]
+---
+
+Mutt is a command-line email client which can connect to IMAP/POP3 and SMTP
+protocols as well as read emails from local directories.
+
+![https://i.ibb.co/rFj4XY0/pipes.png](https://i.ibb.co/rFj4XY0/pipes.png)
+
+So, how do I stumbled upon it? I am trying to optimize my workflow. Having to
+click around a GUI-based email client isn't my thing. So, I look for
+alternatives.
+
+Why Mutt? because Mutt features a keybinding which is similar to Vim. This
+means, a single set of shortcuts would work pretty much everywhere.
+Although I am using NeoMutt, things are pretty much the same in both.
+
+> All mail clients suck. This one just sucks less.
+
+Here I am going to document how I set-up Mutt from Scratch!
+
+## Install
+
+Mutt and NeoMutt are available in official repositories of most of the Linux
+distribution. I am using Arch Linux, so I just needed to run
+`sudo pacman -Syu neomutt`. You don't need to install additional packages to
+get Mutt working.
+
+One more thing, I am using NeoMutt to get access to some extra features Mutt
+does not provide by default. There are not many differences in UI and
+functionalities.
+
+## Config files
+
+Neomutt stores system-wide config inside `XDG_CONFIG_DIR`(which is essentially
+`/etc/xdg/neomutt`). For per-user configs, Neomutt uses one of the following
+locations:
+
+- `~/.muttrc`
+- `~/.mutt/muttrc`
+- `~/.config/mutt/muttrc`
+- `~/.neomuttrc`
+- `~/.neomutt/neomuttrc`
+- `~/.config/neomutt/muttrc`
+
+A Mutt config file generally includes a couple of sections. Let's start with
+the essential ones.
+
+### The 'user' configs
+
+```bash
+set realname = 'YOUR NAME'
+set from = 'YOUR EMAIL'
+set use_from = yes
+set signature = "~/.mutt/signature"
+```
+
+First three fields are pretty much self-explanatory. The `signature` is a text
+file which contains my email signature and will be appended to emails I compose.
+
+This `signature` field can store commands as well. For example: setting it to
+`set signature = "fortune |"` would print a random\* message as my signature.
+Notice that pipe character(`|`) at the end. This tells Mutt that the value is
+a command, and not a file path.
+
+---
+
+\* for this to work, a package called `fortune-mod` is needed to be installed
+
+---
+
+### IMAP config
+
+IMAP/POP3 protocol is used to read remote mailboxes. The primary difference
+between IMAP and POP3 is: POP3 stores emails locally and delete them from
+server. IMAP is just the opposite. Following is how to configure IMAP:
+
+```bash
+set imap_user = 'EMAIL ADDRESS'
+set imap_authenticators="oauthbearer"
+set imap_keepalive = 300
+set mail_check = 120
+unset imap_passive # open a new IMAP connection automatically
+set imap_oauth_refresh_command="OAUTH_HANDLER_COMMAND"
+```
+
+Again, there are not many things to explain in this section (except for that
+`imap_oauth_refresh_command`). Since Gmail(GSuite) discourages creating **an app
+passwords** and allowing **less secure apps**, I am using a method called
+**OAuth2** to authenticate my address. More information on how to connect to
+Gmail with OAuth2 is [available here](https://github.com/google/gmail-oauth2-tools/wiki/OAuth2DotPyRunThrough)
+
+If you are using password-based authentication, you can mention a field called
+`imap_password` and put your password as its value. Otherwise, leave it blank.
+Mutt would as you for a password every time you try to log in.
+
+FYI, IMAP stands for Internet Message Access Protocol and POP3 stands for
+Post Office Protocol.
+
+### SMTP config
+
+Simple Mail Transfer Protocol, a.k.a SMTP, is the protocol used for sending
+emails. (yes, we have two different protocols for sending and accessing email).
+
+```bash
+set smtp_url = "smtp://SMTP_URL:587"
+set ssl_starttls = yes
+set ssl_force_tls = yes
+set smtp_authenticators="oauthbearer"
+set smtp_oauth_refresh_command="OAUTH_HANDLER_COMMAND"
+```
+
+Here, `ssl_force_tls` and `ssl_force_tls` are responsible for enforceing a TLS
+connection as it's more secure.
+
+### Sidebar
+
+I have a sidebar for accessing all my GMail folders easily. You don't have to
+enable one if you don't want to. Just skip the following config block.
+
+```bash
+set sidebar_visible
+set sidebar_format = "%B%?F? [%F]?%* %?N?%N/?%S"
+set mail_check_stats
+bind index,pager B sidebar-toggle-visible
+```
+
+Setting `sidebar_visible` would render the sidebar window(or whatever you call
+it).
+
+`mail_check_stats` basically fetches email stats (example: read/unread etc).
+
+### Remote Folders
+
+Note that `mail_check_stats`. This is extremely important if you are enabling
+sidebar or want to access remote folders within Mutt. I wasted a couple of hours
+to find out why Mutt was unable to find my remote folders :/
+Remote mailboxes can be controlled using `mailboxes` as well.
+
+And the last line is a keybinding responsible for toggling view of the sidebar.
+
+## Signature
+
+With Mutt, you can define a custom signature which would be appended to all new
+emails. To add a new signature, open config and add a new line:
+`set signature = "~/.mutt/signature"`. Here, `.mutt/signature` is the file I am
+using to store my plaintext signature which looks something like this:
+
+```txt
+Regards,
+Abdus
+
+public key: https://abdus.xyz/keys
+fingerprint: C8FF EB39 66E3 7BA3 DFD8
+```
+
+Of course, it could be any arbitrary text file(as long as the file is readable by
+current user)
+
+## Colors
+
+Mutt comes with a dull colorscheme. That's not even a colorscheme, just white
+text on a black background. Luckily, the user can modify it to their liking.
+
+I would recommend choosing a pre-written colorscheme for your Mutt. Or if you
+choose to write your own, feel free to read up documentations on Mutt website :)
+[See this link](https://github.com/neomutt/neomutt/issues/340).
+
+Sidenote: Colors could be directly added into `muttrc`, but it is a good
+practice to keep colorscheme config in a separate file and then import them into
+`muttrc`.
+
+If you ask me for colorscheme suggestions, I would gladly suggest Dracula and
+Gruvbox. They are two best colorscheme for Mutt(or for anything, in general) out
+there.
+
+- [Gruvbox](https://www.sthu.org/code/codesnippets/mutt-gruvbox.html)
+- [Dracula](https://github.com/dracula/mutt)
+
+## Keybindings
+
+I think keybinding is what makes a command-line application great! Mutt, out of
+the box, features a Vim-like keybinding which already gives us a reason to
+like Mutt. `hjkl` is `<3`!
+
+Apart from default keybindings, the user could add custom bindings as they like.
+It's very simple to add a new key-binding. `bind` is the keyword used to define
+a new binding.
+
+```muttrc
+# keybinding for toggling sidebar. honestly, this is the only
+# custom binding I have right now.
+bind index,pager B sidebar-toggle-visible
+```
+
+It's possible to define keybindings right inside `muttrc`. But you should move
+them to a separate file when they grow bigger.
+
+## Rendering HTML Emails
+
+By default, mutt is not capable of showing HTML emails. It is a plaintext email
+client. So, rendering HTML emails won't make much sense.
+
+However, HTML emails can be rendered using third-party clients, for example:
+`lynx`, `links` or any other software which renders HTML. A browser would also
+work.
+
+To configure mutt to show HTML emails, create a file called `.mailcap` in home
+directory with following lines in it:
+
+```mailcap
+# brave is my default web-browser
+text/html; brave %s; nametemplate=%s.html;
+# links is a command-line web-browser
+text/html; links -dump %s; nametemplate=%s.html; copiousoutput
+```
+
+Then, in `muttrc`, add this line: `auto_view text/html`. Now, Mutt will
+use `.mailcap` file to render HTML attachments using appropriate programs.
+
+## Composing an Email
+
+To compose an email, press `m`. Fill-up `To:` address, `Subject:` line and other
+necessary pieces of information. Once you do it, Mutt will drop you in the
+editor you've chosen to write the email. If you have set a signature before,
+you will see it here.
+
+When done writing the mail, save and exit from the editor. Mut will allow you to
+do final changes/adjustments. In this window, press `y` to send the email.
+
+To change the default editor for composing an email, add/change this line in `muttrc`:
+`set editor=whatever`.
+
+## Encrypting/Signing Messages
+
+Signing emails with a public key comes built into Mutt. There's not much set
+up to be done, except for you need a pair of PGP keys
+(I won't cover how to generate a PGP key-pair. Google it up).
+
+Once you are done composing email, press `P`(essentially stands for PGP). You
+will see available PGP actions at the bottom of the window. Just use whatever you
+need.
+
+That's it!
diff --git a/content/posts/recording-shell-output-the-right-way.md b/content/posts/recording-shell-output-the-right-way.md
new file mode 100644
index 0000000..24c2997
--- /dev/null
+++ b/content/posts/recording-shell-output-the-right-way.md
@@ -0,0 +1,83 @@
+---
+title: 'Recording Shell Output the Right Way'
+date: 2020-07-10T21:27:30+05:30
+draft: false
+meta:
+ image: # url to image. Important for blog listing and seo
+ description: # overrides .Summary
+featured: false # feature a post in homepage
+tableofcontents: true # whether to generate ToC
+tags: ['tools', 'shell-recording', 'asciinema']
+categories: ['linux']
+---
+
+> TL,DR; go and install `asciinema` from [asciinema.org](https://asciinema.org) and start recording your terminal sessions.
+
+We, the terminal geeks often need to record our shell in-order to explain
+something to our geek friends; or even just to showcase a new CLI tool we built
+yesterday night.
+
+## Recording Screen ...
+
+Sucks! Yes, it sucks. Why? couple of good reasons:
+
+- if you have a device with low screen resolution, record output would often get
+pixelated
+- there might be other distractions on screen. for example: notifications
+- no way you would be able to copy-paste command from that screen-recording into
+your shell.
+- no easy way to share recorded output
+
+... and many other things.
+
+## ... the Right Way!
+
+`asciinema` is here to rescue. ASCIINema is a command-line tool to record a shell
+session. It is not just another recorder. It records ASCII characters from `stdin`,
+`stdout` and `stderr` devices. And presents the output in a way that is playable
+right inside the terminal.
+
+### Features
+
+Here, I am listing the most popular and commonly used features from `asciinema`.
+For a detailed list, visit [asciinema official website](https://asciinema.org).
+
+- record quite easily. All you need is download and install `asciinema` binary.
+- easy to distribute. when you are done recording the session, you'll be asked
+if you want to publish your recording to ASCIINema website. If not, save it locally.
+- Embeddable. Following is a asciicast of my NeoVim config :)
+{{< asciinema id="dCji7muVN6wBBcmqIAQtdLN4H" >}}
+- copy and paste texts from an asciicast to terminal. this especially helps when
+you don't want to type a goddamn config file from a video.
+- remote ASCIINema upload server can be self-hosted.
+
+Guess that much of features are enough to convince you :)
+
+### Installation
+
+Loads of ways. Using:
+
+- **Pacman** - `pacman -Syu asciinema`
+- **Debian** - `apt-get install asciinema`
+- **PyPi** - `pip3 install asciinema`
+
+more ways on [installation page](https://asciinema.org/docs/installation).
+
+### How to use
+
+To start recording, type `asciinema rec` and hit enter. This will spwan a new
+shell window(which will obviously be recorded).
+
+On recording finish, asciinema would ask whether you want to upload it to ASCIINema
+website. If not, it will be saved locally.
+
+`asciinema play` is capable of playing a local asciicast as well as a remote
+asciicast from a URL.
+
+`asciinema cat` spits out text available from a cast. output can be copied to
+system clipboard.
+
+## Conclusion
+
+Far better than old-school screen-recording tools when it comes to terminal
+session recording.
diff --git a/content/posts/session-management-in-vim.md b/content/posts/session-management-in-vim.md
new file mode 100644
index 0000000..3911ddf
--- /dev/null
+++ b/content/posts/session-management-in-vim.md
@@ -0,0 +1,187 @@
+---
+title: "Session Management in Vim"
+date: 2020-10-26T16:22:18+05:30
+draft: false
+meta:
+ image: https://i.ibb.co/HYtd6Bf/pipes.png
+ description: # overrides .Summary
+featured: false # feature a post in homepage
+tableofcontents: true # whether to generate ToC
+tags: [vim, neovim, editor]
+categories: [tools]
+---
+
+If you ask me about the most underrated feature in Vim, my answer would be
+'Session Management' straightaway! Just like any other "modern" editors, Vim
+does support sessions.
+
+![pipes](https://i.ibb.co/HYtd6Bf/pipes.png)
+
+## What is a Session
+
+Before I go in-depth, let me explain what exactly is a Session in Vim. Simply
+put(from `:help session`): A Session keeps the Views for all windows, plus the global settings.
+
+An example of session could be: If I have opened a project and worked for an
+hour, and then closed it. My Vim session would be one hour long.
+
+Sessions in Vim are not persistent by default. One has to make it persistent.
+Most people do not know about it because they probably have never felt the
+need for it.
+
+I was one of those people who didn't feel the need for storing sessions, until
+recently. And I am not ashamed of it. It just happens... mostly because, we
+don't need it _yet_.
+
+## Importance of Session
+
+To answer the question 'How a persistent Session is Useful', let's find out what
+we lack without it.
+
+1. **Time**. Yes! Imagine, you are working on a project, and for some reason,
+ you closed Vim. So when you open it again, you gotta recreate those perfectly
+ sized windows, open files of reconfigure options etc.
+2. **Context**. It's not easy to remember which file you were editing, the last
+ time you have worked on a project.
+
+Now, what if I say that you could boot into Vim without losing any of the
+previous windows, tabs etc? not even the cursor location. That would be
+great, is not it?
+
+That's where persistent session comes into action. It enables Vim to load
+the last session, much like what we see in editors like Visual Studio Code.
+
+## Storing Sessions
+
+There are multiple techniques one may use to handle Sessions. I will, however,
+talk about the one I use.
+
+First, I let Vim look for any existing session files. If one exists for the
+current session, Vim would update it automatically when I close Vim. The Reason
+I don't let Vim save Sessions for which no session file exists, because that
+makes me counter-productive. For example, I needed to edit a config file, say,
+`.vimrc` from my `$HOME` directory. Had I enabled auto-create session file, a
+new session file for `$HOME` directory will be created, which I obviously don't
+want. That session does not make any sense.
+
+So, if a session file is not created automatically, how do I create it then?
+Well, it's really simple. I defined a command for creating new Sessions, called
+`SessCreate` using [Vim Language](http://vimdoc.sourceforge.net/htmldoc/usr_41.html).
+Now, I can simply call this command from inside Vim whenever I need it.
+
+Let me show you how I did it.
+
+### Snippet
+
+```vim
+fu! SessionCreate()
+ if !isdirectory(expand("~/.vim/sessions"))
+ execute "call mkdir(expand('~/.vim/sessions', 'p'))"
+ endif
+ execute 'mksession ~/.vim/sessions/' . split(getcwd(), '/')[-1] . '.vim'
+endfunction
+
+command SessCreate call SessionCreate()
+```
+
+### Explanation:
+
+```vim
+if !isdirectory(expand("~/.vim/sessions"))
+ execute "call mkdir(expand('~/.vim/sessions', 'p'))"
+endif
+```
+
+Check if a directory `$HOME/.vim.sessions` exist. If not, create it with
+`execute "call mkdir(expand('~/.vim/sessions', 'p'))"`. This is the directory
+where sessions are stored. An alternate location for storing session is the
+project directory itself. But that is not something I want to use, as not
+everyone uses Vim. So, this would be an added bloat for them.
+
+`call` in Vim Script is uses to call a function. `mkdir()` is used to create a
+new directory. `p` is a flag that can be passed to `mkdir()` so that it creates
+parent directories as and when necessary. Lastly, `expand()` is used to expand
+any Shell expandables. Here, it converts `~` to `/home/username`.
+
+```vim
+execute 'mksession ~/.vim/sessions/' . split(getcwd(), '/')[-1] . '.vim'
+```
+
+`mksession` is a built-in command for creating session from current Vim state.
+It saves the created session in `~/.vim/sessions/DIR_NAME.vim`. Here, the
+`DIR_NAME` is the working directory where Vim is opened. So, session for
+`~/Projects/github/awesome-vim` would be saved into
+`~/.vim/sessions/awesome-vim.vim`.
+
+### Saving a Session in Existing Session File
+
+Now, it's time for some automation. Check out the following code snippet:
+
+```vim
+fu! SessionSave()
+ if filewritable(expand('~/.vim/sessions/' . split(getcwd(), '/')[-1] . '.vim'))
+ execute 'mksession! ~/.vim/sessions/' . split(getcwd(), '/')[-1] . '.vim'
+ endif
+endfunction
+```
+
+This function checks whether the existing session file is writable. And save
+latest session if true. That's it. The exclamation mark(`!`) is for overwriting
+previous session.
+
+### Restoring a Session
+
+Finally, when I open Vim again, I want saved buffer(if any) to be restored.
+Following function is responsible for this:
+
+```vim
+fu! SessionRestore()
+ let l:session_file = '~/.vim/sessions/' . split(getcwd(), '/')[-1] . '.vim'
+ if filereadable(expand(session_file))
+ echo session_file
+ execute 'source ~/.vim/sessions/' . split(getcwd(), '/')[-1] . '.vim'
+
+ if bufexists(1)
+ for l in range(1, bufnr('$'))
+ if bufwinnr(l) == -1
+ exec 'sbuffer ' . l
+ endif
+ endfor
+ endif
+ endif
+endfunction
+```
+
+Let me explain what it does exactly.
+
+```vim
+let l:session_file = '~/.vim/sessions/' . split(getcwd(), '/')[-1] . '.vim'
+if filereadable(expand(session_file))
+ echo session_file
+ execute 'source ~/.vim/sessions/' . split(getcwd(), '/')[-1] . '.vim'
+endif
+```
+
+First, check if the file is readable. There's no point in sourcing it if Vim
+can't access it. Then simply source it to Vim. That's it.
+
+```vim
+if bufexists(1)
+ for l in range(1, bufnr('$'))
+ if bufwinnr(l) == -1
+ exec 'sbuffer ' . l
+ endif
+ endfor
+endif
+```
+
+`bufexists()` function checks if any
+[buffer](https://vim.fandom.com/wiki/Buffers) exists. `bufnr()` returns all
+available buffers. ...and so on. Read more about them using `:help FUNC_NAME`
+in Vim.
+
+So, that's it. Persistent Sessions makes our life dramatically easier when using
+Vim (or NeoVim, GVim whatever flavour you use).
+
+P.S.: I am a new Vim user. I am open to suggesstions. Feel free to suggest
+anything that would make use Vim in a more productive way!!
diff --git a/content/posts/slice-type-in-rust.md b/content/posts/slice-type-in-rust.md
new file mode 100644
index 0000000..61ef48d
--- /dev/null
+++ b/content/posts/slice-type-in-rust.md
@@ -0,0 +1,132 @@
+---
+title: "Slice Type in Rust"
+date: 2020-06-30T12:26:32+05:30
+draft: false
+meta:
+ image: # url to image. Important for blog listing and seo
+ description: "slice is a data-type in Rust. Slice references a contiguous
+ sequence from a given collection. one cool thing about slice is, it
+ can accept both String and Slice types(unlike String, which
+ accepts only itself)..."
+featured: false # feature a post in homepage
+tableofcontents: true # whether to generate ToC
+tags: []
+categories: []
+---
+
+In Rust, there is a concept of borrowing and taking ownership. This is a concept
+not many languages implement.
+
+## Ownership and Borrowing
+
+In a Rust program, any given value is owned by a variable. For instance, if we
+declare `let a = 30;`, value `30` would be owned by variable `a`.
+
+Following is a program to illustrate it:
+
+```rust {hl_lines=["5-6"]}
+// won't compile
+fn main() {
+ let some_string = String::from("hello world");
+
+ println!("Length {}", str_length(some_string));
+ println!("string is '{}'", some_string);
+}
+
+fn str_length(s: String) -> usize {
+ s.len()
+}
+```
+
+### Taking Ownership
+
+Look at the highlighted codeblock. I am passing the variable `some_string` to
+function `str_length()` which accepts parameter as value. When the function gets
+called, the value of `some_string` **moves** to function `str_length`, making the
+variable unusable after the function
+call(here: `println!("string is '{}'", some_string);`).
+This is called **taking ownership**.
+
+### Borrowing
+
+On the other hand: if I pass argument `some_string` to `str_length` by reference,
+the ownership would be retained by `some_string`. A modified version of
+`str_length` signature would look like:
+
+```rust
+fn str_length(s: &String)
+```
+
+This is known as **Borrowing**. It is not quite as simple as it looks like.
+There are certains rules which needs to be followed while borrowing a value. For
+instance: a variable can be mutated only once at a given scope.
+
+## The Slice Type
+
+A `slice` is reference to a **contiguous sequence** of elements in a collection.
+It does not take ownership(since it just _references_ a sequence).
+
+```rust {hl_lines=[4]}
+// slice of a string
+fn main() {
+ let s1 = String::from("hello, Rust");
+ let sliced_str = &s1[0..5]; // hello
+}
+```
+
+A good thing about slice is that it accepts type `String` as well as itself
+(i.e. `str` type), unlike `String`(which does not accept `str`).
+
+> In Rust, `..` is called as range syntax.
+>
+An example would demonstrate it better:
+
+```rust
+fn main() {
+ let str1 = String::from("hello, Rust");
+
+ print_str(&str1[2..4]); // ll
+ print_str(&str1); // hello, Rust
+}
+
+fn print_str(s: &str) {
+ println!("{}", s);
+}
+```
+
+### Slice Varients
+
+Slice comes with quite a few varients, which fits different use cases. Here I am
+listing a few:
+
+**Referencing from the start of a Collection:** when referencing from the very
+first element in a collection(i.e. 0), one could ommit it. Example: `&s[..4]`.
+
+Likewise, when **referencing upto the last element of a collection**, can be
+omitted. `&s[3..]`.
+
+Similarly, when **referencing the whole collection(i.e. from start to end)**,
+one can ommit ranges in range syntax. Example: `&s[..]`
+
+### Real-World Example
+
+```rust {hl_lines=[13]}
+fn main() {
+ let s = String::from("Hello, world");
+ let word = get_first_word(&s);
+
+ println!("First word is '{}'", word);
+}
+
+fn get_first_word(s: &str) -> &str {
+ let str_bytes = s.as_bytes();
+
+ for (i, &item) in str_bytes.iter().enumerate() {
+ if item == b' ' {
+ return &s[0..i];
+ }
+ }
+
+ return &s[..];
+}
+```
diff --git a/data/personal.yaml b/data/personal.yaml
new file mode 100644
index 0000000..ced46ce
--- /dev/null
+++ b/data/personal.yaml
@@ -0,0 +1,39 @@
+testimonials:
+ - name: Devyesh Tandon
+ designation: CTO, MailModo
+ content: |
+ Abdus is a geek and has a keen eye on details. He has shown an amazingly
+ high execution speed on the tasks assigned. It surely will be an enriching
+ experience to work with Abdus.
+
+ - name: Andrei Neagoie
+ designation: Founder, Zero to Mastery
+ content: |
+ I have known Abdus for about 2 years now as he has helped me manage a
+ community of 80,000 programmers and engineers. I can always rely on Abdus
+ to be professional, but more importantly his work ethic and always being
+ available to help out with the community is what sets him apart. If you
+ have an opportunity to work with Abdus, you are among the lucky ones.
+ One of the most reliable people I know.
+
+ - name: Aquibur Rahman
+ designation: CEO, MailModo
+ content: |
+ Abdus is one of the most sincere young software engineer we have worked
+ with. Besides being good at understanding the problem, he goes deep in to
+ looking for the solution himself. I am sure with his hard work and grit,
+ he is going to succeed always in his life.
+
+
+social:
+ - url: https://linuxrocks.online/@abdus
+ name: Mastodon
+ fa: 'fab fa-mastodon'
+
+ - url: https://github.com/abdus
+ name: LinkedIn
+ fa: 'fab fa-github'
+
+ - url: https://linkedin.com/in/thisisabdus
+ name: LinkedIn
+ fa: 'fab fa-linkedin-in'
diff --git a/themes/bronn/LICENSE b/themes/bronn/LICENSE
new file mode 100644
index 0000000..faff36e
--- /dev/null
+++ b/themes/bronn/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2020 YOUR_NAME_HERE
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/themes/bronn/archetypes/default.md b/themes/bronn/archetypes/default.md
new file mode 100644
index 0000000..ac36e06
--- /dev/null
+++ b/themes/bronn/archetypes/default.md
@@ -0,0 +1,2 @@
++++
++++
diff --git a/themes/bronn/archetypes/notes.md b/themes/bronn/archetypes/notes.md
new file mode 100644
index 0000000..746117a
--- /dev/null
+++ b/themes/bronn/archetypes/notes.md
@@ -0,0 +1,26 @@
+---
+title: '{{ replace .Name "-" " " | title }}'
+date: {{ .Date }}
+draft: true
+tags: []
+categories: []
+sources: []
+---
+
+<!--
+
+::Annotation Guide::
+~~~~~~~~~~~~~~~~~~~~
+
+* `em` is the modifier
+
+1. em (_text_) - blue underline
+2. strong (**text**) - yelow highlight
+3. del (~~text~~) - red strike-through
+
+4. em > em (_*text*_) - blue circle
+5. em > strong (_**text**_) - lawngreen box
+6. em > del (_~~text~~_) - red cross-off
+-->
+
+
diff --git a/themes/bronn/archetypes/posts.md b/themes/bronn/archetypes/posts.md
new file mode 100644
index 0000000..eba3dd3
--- /dev/null
+++ b/themes/bronn/archetypes/posts.md
@@ -0,0 +1,13 @@
+---
+title: '{{ replace .Name "-" " " | title }}'
+date: {{ .Date }}
+draft: true
+meta:
+ image: # url to image. Important for blog listing and seo
+ description: # overrides .Summary
+tags: []
+categories: []
+---
+
+<!-- Start Typing... -->
+
diff --git a/themes/bronn/layouts/404.html b/themes/bronn/layouts/404.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/themes/bronn/layouts/404.html
diff --git a/themes/bronn/layouts/_default/_markup/render-image.html b/themes/bronn/layouts/_default/_markup/render-image.html
new file mode 100644
index 0000000..d563dda
--- /dev/null
+++ b/themes/bronn/layouts/_default/_markup/render-image.html
@@ -0,0 +1,12 @@
+{{ if .Title }}
+<figure>
+ <img
+ src="{{ .Destination | safeURL }}"
+ alt="{{ .Text }}"
+ title="{{ .Title }}"
+ />
+ <figcaption>{{ .Title | safeHTML }}</figcaption>
+</figure>
+{{ else }}
+<img src="{{ .Destination | safeURL }}" alt="{{ .Text }}" />
+{{ end }}
diff --git a/themes/bronn/layouts/_default/baseof.html b/themes/bronn/layouts/_default/baseof.html
new file mode 100644
index 0000000..cbe4d44
--- /dev/null
+++ b/themes/bronn/layouts/_default/baseof.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ {{- partial "head.html" . -}}
+ <body>
+ <div id="content">
+ {{- partial "nav.html" . -}} {{- block "main" . }}{{- end }}
+ </div>
+ {{- partial "footer.html" . -}}
+ </body>
+</html>
diff --git a/themes/bronn/layouts/_default/list.html b/themes/bronn/layouts/_default/list.html
new file mode 100644
index 0000000..6868a0c
--- /dev/null
+++ b/themes/bronn/layouts/_default/list.html
@@ -0,0 +1,36 @@
+{{ define "main" }}
+<!-- -->
+<main class="list-layout max-width-60rem margin-auto">
+ <h1 class="accent-color font-eczar text-center color-accent">{{ .Title }}</h1>
+ <section class="max-width-45rem margin-auto">
+ {{ range .Pages }}
+ <a href="{{ .Permalink | absURL }}" class="card">
+ <h3 class="font-eczar color-accent margin-0">{{ .Title }}</h3>
+ <div class="content" style="color: #183446">
+ {{ if .Params.meta.description }}
+ <!--.-->
+ {{ .Params.meta.description | truncate 150 }}
+ <!--.-->
+ {{ else }}
+ <!--.-->
+ {{ .Summary | truncate 150 }}
+ <!--.-->
+ {{ end }}
+ </div>
+
+ <p style="margin-bottom: 0">
+ <span class="btn btn-extra-small"> {{ .ReadingTime }} Mins</span>
+ {{ if .Params.tags }} {{ range .Params.tags }}
+ <span class="btn btn-extra-small">#{{ . }}</span>
+ {{ end }} {{ end }}
+ <!--.-->
+ {{ with .Date }}
+ <span class="btn btn-extra-small"> {{ .Format "2 Jan, 2006" }}</span>
+ {{ end }}
+ </p>
+ </a>
+ {{ end }}
+ </section>
+</main>
+<!-- -->
+{{ end }}
diff --git a/themes/bronn/layouts/_default/single.html b/themes/bronn/layouts/_default/single.html
new file mode 100644
index 0000000..d0427cf
--- /dev/null
+++ b/themes/bronn/layouts/_default/single.html
@@ -0,0 +1,111 @@
+{{ define "main" }}
+
+<main class="max-width-60rem margin-auto single-layout">
+ <h1 class="font-eczar title color-accent">{{ .Title }}</h1>
+
+ <div class="max-width-45rem margin-auto">
+ <p class="color-accent meta">
+ <strong>
+ {{ with .Date }}
+ <small class="btn btn-extra-small"
+ >{{ .Format "2 January, 2006" }}</small
+ >
+ {{ end }}
+ <!--.-->
+ {{ range .Params.categories }}
+ <a
+ class="btn btn-extra-small"
+ href='{{ printf "/categories/%s" . | absURL }}'
+ >{{ . }}</a
+ >
+ {{ end }}
+ <!--.-->
+ {{ if not (eq .Section "pages") }}
+ <span class="btn btn-extra-small">{{ .ReadingTime }} Mins</span>
+ {{ end }}
+ </strong>
+ </p>
+ <!--.-->
+ <div class="content">{{ .Content }}</div>
+ {{ range .Params.tags }}
+ <a class="btn btn-small" href='{{ printf "/tags/%s" . | absURL }}'
+ >#{{ . }}</a
+ >
+ {{ end }}
+ </div>
+</main>
+
+{{ if eq .Section "notes" }}
+<script type="module">
+ import { annotate } from "https://unpkg.com/rough-notation?module";
+
+ function checkParent(elem) {
+ const parent = elem.parentElement;
+ const strong = document.createElement("strong");
+ const em = document.createElement("em");
+ const del = document.createElement("del");
+ console.log(elem.hasChildNodes(), elem);
+
+ if (
+ parent.constructor === strong.constructor ||
+ parent.constructor === em.constructor ||
+ parent.constructor === del.constructor
+ )
+ return false;
+ if (elem.childElementCount > 0) return false;
+ return true;
+ }
+
+ function annotateElement(selector, type, color) {
+ document.querySelectorAll(selector).forEach((elem) => {
+ const shouldAllowAnnotation = checkParent(elem);
+ if (shouldAllowAnnotation)
+ annotate(elem, { type, color, multiline: true, animate: false }).show();
+ });
+ }
+
+ function annotateNestedElement(selector, type, color) {
+ document.querySelectorAll(selector).forEach((elem) => {
+ annotate(elem, {
+ type,
+ color,
+ multiline: true,
+ animate: false,
+ brackets: ["left", "right", "top", "bottom"],
+ }).show();
+ });
+ }
+
+ try {
+ annotateElement("em", "underline", "#5465ff");
+ annotateElement("strong", "highlight", "#5465ff66");
+ annotateElement("del", "strike-through", "#ff0000");
+ annotateNestedElement("em > del", "crossed-off", "#ff0000");
+ annotateNestedElement("em > strong", "box", "#5465ff");
+ annotateNestedElement("em > em", "circle", "#5465ff66");
+ annotateNestedElement("blockquote", "bracket", "#5465ff");
+ } catch (exception) {
+ console.log(exception.message);
+ }
+</script>
+
+<style>
+ .single-layout em,
+ .single-layout strong,
+ .section-conten del {
+ font-style: normal;
+ font-weight: normal;
+ text-decoration: none;
+ }
+
+ blockquote {
+ background-color: #fff;
+ padding: 0.3rem;
+ margin: 2rem 0;
+ }
+</style>
+
+{{ end }}
+
+<!--.-->
+{{ end }}
diff --git a/themes/bronn/layouts/index.html b/themes/bronn/layouts/index.html
new file mode 100644
index 0000000..2d46673
--- /dev/null
+++ b/themes/bronn/layouts/index.html
@@ -0,0 +1,147 @@
+{{ define "main" }}
+<main class="homepage max-width-60rem margin-auto">
+ <header>
+ <div>
+ <h1 class="font-eczar">{{ .Title }}</h1>
+ <p>{{ .Params.description | safeHTML }}</p>
+ </div>
+ </header>
+
+ <section class="social">
+ {{ with .Site.Data.personal.social }}
+ <!--.-->
+ {{ range . }}
+ <a
+ href="{{ .url }}"
+ target="_blank"
+ rel="noopener noreferer"
+ class="social-icon"
+ >
+ <i class="{{ .fa }}"></i>
+ </a>
+ {{ end }}
+ <!--.-->
+ {{ end }}
+ </section>
+
+ <section class="experience grid grid-2 grid-sm-1">
+ <div class="title-card">
+ <h3 class="font-eczar">EXPERIENCE</h3>
+ <p>
+ Fresh out of the College(which I hardly attended). I am mostly a
+ self-taught Developer, with around 2 months of experience as an Intern
+ in a Start-Up
+ </p>
+ <p>
+ <a href="#" class="btn">LinkedIn</a>
+ </p>
+ </div>
+ <div class="content-card">
+ <h3 class="font-eczar">Front-End Developer</h3>
+ <strong class="color-accent font-weight-700">MaiModo</strong>
+ <small class="color-accent">August 2020 - September 2020</small>
+ </div>
+ </section>
+
+ <section class="projects grid grid-2 grid-sm-1">
+ <div class="title-card">
+ <h3 class="font-eczar">PROJECTS</h3>
+ <p>
+ I have built a few projects which are worth showing to my (future)
+ employer. Here, I am listing a few of them. Rest can be found on my
+ GitHub profile.
+ </p>
+ <p>
+ <a href="#" class="btn">GitHub</a>
+ </p>
+ </div>
+ <div class="content-card card">
+ <h3 class="font-eczar color-accent">Chat App</h3>
+ <p>
+ A real-time chat application built using NodeJS, JavaScript, MongoDB and
+ Express
+ </p>
+ <p>
+ <a class="btn btn-small" href="#">SourceCode</a>
+ <a class="btn btn-small" href="#">LiveDemo</a>
+ </p>
+ </div>
+ <div class="content-card card">
+ <h3 class="font-eczar color-accent">Movie Wiki</h3>
+ <p>
+ A simple web-app built using ReactJS for searching movie's information
+ using API.
+ </p>
+ <p>
+ <a class="btn btn-small" href="#">SourceCode</a>
+ <a class="btn btn-small" href="#">LiveDemo</a>
+ </p>
+ </div>
+ <div class="content-card card">
+ <h3 class="font-eczar color-accent">dotfiles</h3>
+ <p>A collection of all the dotfiles I use on a daily basis.</p>
+ <p>
+ <a class="btn btn-small" href="#">SourceCode</a>
+ </p>
+ </div>
+ </section>
+
+ <section class="writings grid grid-2 grid-sm-1">
+ <div class="title-card">
+ <h3 class="font-eczar">WRITINGS</h3>
+ <p>
+ Like almost every other developer, I do share whatever I learn in my
+ Blog. I also have a section for sharing my daily learnings.
+ </p>
+ <p>
+ <a href="/posts" class="btn">Blog</a>
+ <a href="/notes" class="btn">Notes</a>
+ </p>
+ </div>
+ <div class="content-card">
+ <div>
+ {{ range first 4 (where site.RegularPages "Type" "in" site.Params.mainSections) }}
+ <p>
+ <strong
+ ><a class="color-accent" href="{{ .Permalink | absURL }}"
+ >{{ .Title }}</a
+ ></strong
+ >
+ <br />
+ <small>{{ .Date.Format "2 January, 2006" }}</small>
+ </p>
+ {{ end }}
+ </div>
+ </div>
+ </section>
+
+ <section class="recommendations grid grid-2 grid-sm-1">
+ <div class="title-card">
+ <h3 class="font-eczar">Recommendations</h3>
+ <p>
+ I have worked with these people in the past. Here's what they think
+ about me and my work. All of these testimonials are coming from my
+ LinkedIn profile.
+ </p>
+ <p>
+ <a class="btn" href="https://linkedin.com/in/thisisabdus">LinkedIn</a>
+ </p>
+ </div>
+ {{ with .Site.Data.personal.testimonials }}
+ <!--.-->
+ {{ range . }}
+ <div class="content-card card">
+ <div class="color-accent">{{ .content }}</div>
+ <div class="flex-grow-1"></div>
+ <div class="name-image color-accent">
+ <strong class="font-eczar">{{ .name }}</strong>
+ <br />
+ <small class="btn btn-small">{{ .designation }}</small>
+ </div>
+ </div>
+ {{ end }}
+ <!--.-->
+ {{ end }}
+ </section>
+</main>
+{{ end }}
diff --git a/themes/bronn/layouts/partials/footer.html b/themes/bronn/layouts/partials/footer.html
new file mode 100644
index 0000000..d4a931e
--- /dev/null
+++ b/themes/bronn/layouts/partials/footer.html
@@ -0,0 +1,7 @@
+<footer class="max-width-60rem">
+ <a href="/self/">About Me</a> &middot;
+ <a href="/notes/">My Dev Notes</a> &middot;
+ <a href="/hire-me/">Hire Me</a> &middot;
+ <a href="/keys/">Cryptographic Keys</a> &middot;
+ <a href="mailto:contact@abdus.net">contact@abdus.net</a>
+</footer>
diff --git a/themes/bronn/layouts/partials/head.html b/themes/bronn/layouts/partials/head.html
new file mode 100644
index 0000000..92311ff
--- /dev/null
+++ b/themes/bronn/layouts/partials/head.html
@@ -0,0 +1,16 @@
+<link rel="stylesheet" href={{ "/css/layout.css" | absURL }} media="all" />
+<!--<link rel="stylesheet" href={{ "/css/syntax-dark.css" | absURL }} media="all" />-->
+<link
+ href="https://fonts.googleapis.com/css2?family=Eczar:wght@400;500;600;700;800&family=Lato:wght@400;700;900&display=swap"
+ rel="stylesheet"
+/>
+<link
+ href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&display=swap"
+ rel="stylesheet"
+/>
+<script
+ src="https://kit.fontawesome.com/66c0687ece.js"
+ crossorigin="anonymous"
+></script>
+
+<meta name="viewport" content="width=device-width, initial-scale=1.0" />
diff --git a/themes/bronn/layouts/partials/nav.html b/themes/bronn/layouts/partials/nav.html
new file mode 100644
index 0000000..bd8242a
--- /dev/null
+++ b/themes/bronn/layouts/partials/nav.html
@@ -0,0 +1,30 @@
+<nav class="max-width-60rem margin-auto top-nav">
+ <a href="/">Abdus</a>
+ <div class="icon" id="nav-handler">
+ <i class="fas fa-bars"></i>
+ </div>
+ <div class="nav-items">
+ {{ $page_url := .Permalink | relURL }}
+ <!--i-->
+ {{ range $index, $element := .Site.Menus.main }}
+ <!--i-->
+ {{ if eq $page_url ($element.URL | relURL) }}
+ <a href="{{ $element.URL }}" class="active">
+ <span class="num">{{ printf "%02d" (add $index 1) }}</span>
+ <span class="name">{{ $element.Name }}</span>
+ </a>
+ {{ else }}
+ <a href="{{ $element.URL }}">
+ <span class="num">{{ printf "%02d" (add $index 1) }}</span>
+ <span class="name">{{ $element.Name }}</span>
+ </a>
+ {{ end }} {{ end }}
+ </div>
+</nav>
+
+<script>
+ const handler = document.querySelector("#nav-handler");
+ const nav = document.querySelector(".nav-items");
+
+ handler.onclick = () => nav.classList.toggle("show");
+</script>
diff --git a/themes/bronn/layouts/shortcodes/asciinema b/themes/bronn/layouts/shortcodes/asciinema
new file mode 100644
index 0000000..5686705
--- /dev/null
+++ b/themes/bronn/layouts/shortcodes/asciinema
@@ -0,0 +1,5 @@
+<script
+ id='asciicast-{{ .Get "id" }}'
+ src="https://asciinema.org/a/{{ .Get "id" }}.js"
+ async
+></script>
diff --git a/themes/bronn/layouts/shortcodes/caniuse.html b/themes/bronn/layouts/shortcodes/caniuse.html
new file mode 100644
index 0000000..b345404
--- /dev/null
+++ b/themes/bronn/layouts/shortcodes/caniuse.html
@@ -0,0 +1,13 @@
+<script src="https://cdn.jsdelivr.net/gh/ireade/caniuse-embed/public/caniuse-embed.min.js"></script>
+
+<div
+ class="ciu_embed"
+ data-feature={{ .Get "feature" }}
+ data-periods={{ .Get "periods" }}
+ data-accessible-colours={{ or (.Get "accessible_color" ) false }}
+>
+ <p>
+ Data on support for the {{ .Get "feature" }} feature across the major
+ browsers
+ </p>
+</div>
diff --git a/themes/bronn/layouts/taxonomy/list.html b/themes/bronn/layouts/taxonomy/list.html
new file mode 100644
index 0000000..6aef7e9
--- /dev/null
+++ b/themes/bronn/layouts/taxonomy/list.html
@@ -0,0 +1,15 @@
+{{ define "main" }}
+<!-- -->
+<main class="list-layout max-width-60rem margin-auto">
+ <h1 class="accent-color font-eczar text-center color-accent">{{ .Title }}</h1>
+ <section class="max-width-45rem margin-auto">
+ {{ range .Data.Terms }}
+ <a class="btn btn-small taxonomy-list" href="{{ .Page.Permalink |absURL }}">
+ {{ .Page.Title }}
+ <small>{{ .Count }}</small>
+ </a>
+ {{ end }}
+ </section>
+</main>
+<!-- -->
+{{ end }}
diff --git a/themes/bronn/layouts/taxonomy/term.html b/themes/bronn/layouts/taxonomy/term.html
new file mode 100644
index 0000000..6868a0c
--- /dev/null
+++ b/themes/bronn/layouts/taxonomy/term.html
@@ -0,0 +1,36 @@
+{{ define "main" }}
+<!-- -->
+<main class="list-layout max-width-60rem margin-auto">
+ <h1 class="accent-color font-eczar text-center color-accent">{{ .Title }}</h1>
+ <section class="max-width-45rem margin-auto">
+ {{ range .Pages }}
+ <a href="{{ .Permalink | absURL }}" class="card">
+ <h3 class="font-eczar color-accent margin-0">{{ .Title }}</h3>
+ <div class="content" style="color: #183446">
+ {{ if .Params.meta.description }}
+ <!--.-->
+ {{ .Params.meta.description | truncate 150 }}
+ <!--.-->
+ {{ else }}
+ <!--.-->
+ {{ .Summary | truncate 150 }}
+ <!--.-->
+ {{ end }}
+ </div>
+
+ <p style="margin-bottom: 0">
+ <span class="btn btn-extra-small"> {{ .ReadingTime }} Mins</span>
+ {{ if .Params.tags }} {{ range .Params.tags }}
+ <span class="btn btn-extra-small">#{{ . }}</span>
+ {{ end }} {{ end }}
+ <!--.-->
+ {{ with .Date }}
+ <span class="btn btn-extra-small"> {{ .Format "2 Jan, 2006" }}</span>
+ {{ end }}
+ </p>
+ </a>
+ {{ end }}
+ </section>
+</main>
+<!-- -->
+{{ end }}
diff --git a/themes/bronn/static/css/layout.css b/themes/bronn/static/css/layout.css
new file mode 100644
index 0000000..2776d5e
--- /dev/null
+++ b/themes/bronn/static/css/layout.css
@@ -0,0 +1,501 @@
+* {
+ font-family: inherit;
+ box-sizing: border-box;
+}
+
+body,
+html {
+ margin: 0;
+ font-family: Lato, sans-serif;
+ line-height: 1.6;
+ font-size: 1.1rem;
+ color: #183446;
+}
+
+nav.top-nav {
+ display: flex;
+ justify-content: space-between;
+ padding-top: 3rem;
+ padding-bottom: 2rem;
+ text-transform: uppercase;
+ font-weight: 900;
+ font-size: 0.8em;
+}
+
+blockquote {
+ color: #5465ff;
+ font-weight: bold;
+ font-size: 1.2em;
+ line-height: 1.4;
+ margin: 0;
+ padding-left: 1rem;
+ border-left: 4px solid #5465ff;
+}
+
+blockquote p {
+ margin: 0;
+}
+
+img {
+ width: 100%;
+ max-width: 100%;
+ border-radius: 0.3rem;
+}
+
+figure {
+ margin: 1rem 0;
+}
+
+figcaption {
+ text-align: center;
+ margin: 0;
+ font-weight: 400;
+ font-size: 0.8em;
+ opacity: 0.9;
+}
+
+nav.top-nav a {
+ text-decoration: none;
+ color: #183446;
+}
+
+nav.top-nav a:not(:first-child) {
+ margin-left: 3rem;
+}
+
+nav.top-nav a.active {
+ color: #5465ff;
+}
+
+nav.top-nav a .num {
+ opacity: 0.5;
+ margin-right: 0.3rem;
+}
+
+nav.top-nav a.active .num {
+ color: #5465ff;
+}
+
+nav.top-nav .icon {
+ display: none;
+}
+
+@media (max-width: 700px) {
+ nav.top-nav {
+ flex-wrap: wrap;
+ }
+
+ nav.top-nav .nav-items {
+ display: flex;
+ flex-direction: column;
+ min-width: 99%;
+ display: none;
+ }
+
+ nav.top-nav .nav-items a {
+ margin: 0;
+ padding: 0.6rem 0;
+ }
+
+ nav.top-nav .icon {
+ display: block;
+ }
+
+ nav.top-nav .show {
+ display: flex;
+ }
+}
+
+.btn {
+ /*TODO*/
+ color: #fff;
+ background: #5465ff;
+ display: inline-block;
+ padding: 0.6rem 0.9rem;
+ font-weight: bold;
+ text-decoration: none;
+ margin: 0.2rem 0;
+}
+
+.btn-small {
+ font-size: 0.8em;
+ padding: 0.4rem 0.7rem;
+}
+
+.btn-extra-small {
+ font-size: 0.7em;
+ padding: 0.3rem 0.6rem;
+}
+
+.font-eczar {
+ font-family: "Eczar", serif;
+ line-height: unset;
+}
+
+.font-weight-700 {
+ font-weight: 900;
+}
+
+.text-center {
+ text-align: center;
+}
+
+.max-width-60rem {
+ max-width: 60rem;
+ padding: 0 1rem;
+}
+
+.max-width-45rem {
+ max-width: 45rem;
+}
+
+.margin-auto {
+ margin: auto;
+}
+
+.margin-0 {
+ margin: 0;
+}
+
+code,
+pre {
+ font-family: "Space Mono", monospace;
+ font-size: 0.9em;
+}
+
+code {
+ background-color: #5465ff18;
+ padding: 0 4px;
+ border-radius: 0.3rem;
+}
+
+pre code {
+ border: unset;
+ padding: unset;
+ border-radius: unset;
+ background-color: unset;
+}
+
+pre {
+ padding: 1.5rem;
+ border-radius: 0.4rem;
+ overflow-x: auto;
+ color: #5465ff;
+ box-shadow: 0px 41px 148px rgba(84, 101, 255, 0.05),
+ 0px 18.9555px 68.4249px rgba(84, 101, 255, 0.0370838),
+ 0px 10.8459px 39.1512px rgba(84, 101, 255, 0.031339),
+ 0px 6.5834px 23.7645px rgba(84, 101, 255, 0.0269974),
+ 0px 3.96679px 14.3191px rgba(84, 101, 255, 0.0230026),
+ 0px 2.20896px 7.97382px rgba(84, 101, 255, 0.018661),
+ 0px 0.95006px 3.42949px rgba(84, 101, 255, 0.0129162);
+}
+
+.grid {
+ display: grid;
+ row-gap: 5rem;
+ column-gap: 4rem;
+ margin-bottom: 10rem;
+}
+
+.grid-2 {
+ grid-template-columns: repeat(2, 1fr);
+}
+
+.grid h3 {
+ font-size: 1.4em;
+ margin: 0;
+}
+
+.title-card p {
+ margin: 1.5rem 0;
+}
+
+.title-card h3 {
+ display: inline-block;
+}
+
+.title-card h3::after {
+ content: " ";
+ display: block;
+ width: 100%;
+ height: 20px;
+ margin-top: -1.5rem;
+ /*TODO: move to colors.css*/
+ background: #5465ff60;
+}
+
+.card::after {
+ content: " ";
+ padding: 2rem;
+}
+
+footer {
+ margin: 8rem auto 0 auto;
+ padding: 2rem 0 !important;
+ font-size: 0.8em;
+ border-top: 1px dashed #5465ff;
+ color: #5465ff;
+}
+footer a {
+ color: inherit;
+ opacity: 0.8;
+ text-decoration: none;
+ margin: 0.8rem;
+}
+
+footer a:first-child {
+ margin-left: 0;
+}
+
+@media (max-width: 700px) {
+ .grid-sm-1 {
+ grid-template-columns: 1fr;
+ row-gap: 2rem;
+ }
+}
+/*homepage header*/
+.homepage header {
+ margin-top: 2rem;
+ padding: 6rem 1rem;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+
+ /*TODO: move to colors.css*/
+ color: #fff;
+ background: #5465ff;
+}
+
+.homepage header div {
+ max-width: 22rem;
+}
+
+.homepage header h1 {
+ font-weight: 700;
+ font-size: 2.7em;
+ line-height: 1;
+}
+
+.homepage header h1,
+.homepage header p {
+ margin: 0;
+}
+
+.homepage .social {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin: 6rem auto 6rem auto;
+}
+
+.homepage .social-icon {
+ margin: 0.5rem;
+ padding: 1rem 2rem;
+ font-size: 2.5em;
+ border-radius: 0.4rem;
+ text-decoration: none;
+ /*TODO: move to colors.css*/
+ background: #fff;
+ color: #5465ff;
+ box-shadow: 0px -17px 306px rgba(84, 101, 255, 0.12),
+ 0px -7.10219px 135.309px rgba(84, 101, 255, 0.0862625),
+ 0px -3.79717px 73.4215px rgba(84, 101, 255, 0.0715329),
+ 0px -2.12866px 40.6911px rgba(84, 101, 255, 0.06),
+ 0px -1.13052px 21.059px rgba(84, 101, 255, 0.0484671),
+ 0px -0.470434px 8.46377px rgba(84, 101, 255, 0.0337375);
+}
+
+.homepage .social-icon:hover {
+ color: #5465ff;
+}
+
+.homepage .experience .title-card,
+.homepage .writings .title-card {
+ grid-column: 2 / span 1;
+ text-align: right;
+}
+
+.homepage .experience .content-card small {
+ margin-top: -0.2rem;
+ display: block;
+}
+
+.homepage .experience .content-card:nth-child(2),
+.homepage .writings .content-card:nth-child(2) {
+ grid-row: 1 / span 1;
+}
+
+.homepage .recommendations .name-image {
+ line-height: 1.3;
+ margin-top: 1rem;
+}
+
+.card {
+ position: relative;
+ /*TODO*/
+ background: #fff;
+ border: 1px solid #5465ff;
+ padding: 2rem;
+ border-radius: 0.3rem;
+ display: flex;
+ flex-direction: column;
+}
+
+.card::after {
+ content: " ";
+ display: block;
+ /*TODO*/
+ background: #5465ff;
+ position: absolute;
+ top: 15px;
+ left: 15px;
+ bottom: -15px;
+ right: -15px;
+ z-index: -100;
+ border-radius: 0.3rem;
+}
+
+.card h3 {
+ line-height: 1;
+ font-size: 1.2em;
+}
+
+.card p {
+ margin: 1rem 0;
+ color: #5465ff;
+}
+
+/*TODO*/
+.color-accent {
+ color: #5465ff;
+ text-decoration: none;
+}
+
+.color-white {
+ color: #fff;
+ text-decoration: none;
+}
+
+@media (max-width: 700px) {
+ .homepage header h1 {
+ font-size: 2em;
+ }
+
+ .homepage header {
+ padding: 2rem 1rem;
+ }
+
+ .homepage .social {
+ margin: 3rem auto;
+ }
+
+ .homepage .social-icon {
+ font-size: 1.7em;
+ padding: 0.7rem 1.4rem;
+ }
+
+ .homepage .experience .title-card,
+ .homepage .writings .title-card {
+ grid-column: unset;
+ text-align: left;
+ }
+
+ .homepage .experience .content-card:nth-child(2),
+ .homepage .writings .content-card:nth-child(2) {
+ grid-row: unset;
+ }
+}
+
+/*single layout*/
+.single-layout h1.title,
+.list-layout h1.title {
+ text-align: center;
+ margin: 3rem 0;
+ line-height: 1.1;
+}
+
+.single-layout a,
+.list-layout a {
+ position: relative;
+ text-decoration: none;
+ color: #5465ff;
+ font-weight: bold;
+}
+
+.single-layout a:visited,
+.list-layout a:visited {
+ opacity: 0.4;
+}
+
+.list-layout .btn,
+.single-layout .btn {
+ color: #fff;
+}
+
+.single-layout .content h1,
+.single-layout .content h2,
+.single-layout .content h3,
+.single-layout .content h4,
+.single-layout .content h5,
+.single-layout .content h6,
+.list-layout .content h1,
+.list-layout .content h2,
+.list-layout .content h3,
+.list-layout .content h4,
+.list-layout .content h5,
+.list-layout .content h6 {
+ line-height: 1.2;
+ font-weight: 900;
+ font-size: 1.5em;
+}
+
+/*list layout*/
+
+.flex-grow-1 {
+ flex-grow: 1;
+}
+
+.list-layout .title {
+ display: inline-block;
+ margin-right: 1rem;
+ font-weight: normal;
+}
+
+.list-layout .date {
+ margin-left: 0.5rem;
+}
+
+.list-layout .card {
+ margin: 4rem 0;
+ display: block;
+}
+
+.list-layout .card .content {
+ overflow: hidden;
+ font-weight: 400;
+}
+
+.list-layout .card h3 {
+ line-height: 1.5;
+}
+
+/*taxonomy*/
+.taxonomy-list small {
+ background: #dadada57;
+ padding: 0.1rem 0.5rem;
+ border-radius: 0.2rem;
+ margin-left: 0.2rem;
+ display: inline-block;
+}
+
+@media (max-width: 700px) {
+ .list-layout .card {
+ padding: 1rem;
+ }
+
+ footer {
+ text-align: center;
+ padding: 1rem !important;
+ }
+}
diff --git a/themes/bronn/static/css/syntax-dark.css b/themes/bronn/static/css/syntax-dark.css
new file mode 100644
index 0000000..83a208e
--- /dev/null
+++ b/themes/bronn/static/css/syntax-dark.css
@@ -0,0 +1,82 @@
+/* Background */ .chroma { color: #e7e9db; background-color: #2f1e2e }
+/* Other */ .chroma .x { }
+/* Error */ .chroma .err { color: #ef6155 }
+/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
+/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; width: auto; overflow: auto; display: block; }
+/* LineHighlight */ .chroma .hl { display: block; width: 100%;background-color: #ffffcc }
+/* LineNumbersTable */ .chroma .lnt { margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
+/* LineNumbers */ .chroma .ln { margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
+/* Keyword */ .chroma .k { color: #815ba4 }
+/* KeywordConstant */ .chroma .kc { color: #815ba4 }
+/* KeywordDeclaration */ .chroma .kd { color: #815ba4 }
+/* KeywordNamespace */ .chroma .kn { color: #5bc4bf }
+/* KeywordPseudo */ .chroma .kp { color: #815ba4 }
+/* KeywordReserved */ .chroma .kr { color: #815ba4 }
+/* KeywordType */ .chroma .kt { color: #fec418 }
+/* Name */ .chroma .n { }
+/* NameAttribute */ .chroma .na { color: #06b6ef }
+/* NameBuiltin */ .chroma .nb { }
+/* NameBuiltinPseudo */ .chroma .bp { }
+/* NameClass */ .chroma .nc { color: #fec418 }
+/* NameConstant */ .chroma .no { color: #ef6155 }
+/* NameDecorator */ .chroma .nd { color: #5bc4bf }
+/* NameEntity */ .chroma .ni { }
+/* NameException */ .chroma .ne { color: #ef6155 }
+/* NameFunction */ .chroma .nf { color: #06b6ef }
+/* NameFunctionMagic */ .chroma .fm { }
+/* NameLabel */ .chroma .nl { }
+/* NameNamespace */ .chroma .nn { color: #fec418 }
+/* NameOther */ .chroma .nx { color: #06b6ef }
+/* NameProperty */ .chroma .py { }
+/* NameTag */ .chroma .nt { color: #5bc4bf }
+/* NameVariable */ .chroma .nv { color: #ef6155 }
+/* NameVariableClass */ .chroma .vc { }
+/* NameVariableGlobal */ .chroma .vg { }
+/* NameVariableInstance */ .chroma .vi { }
+/* NameVariableMagic */ .chroma .vm { }
+/* Literal */ .chroma .l { color: #f99b15 }
+/* LiteralDate */ .chroma .ld { color: #48b685 }
+/* LiteralString */ .chroma .s { color: #48b685 }
+/* LiteralStringAffix */ .chroma .sa { color: #48b685 }
+/* LiteralStringBacktick */ .chroma .sb { color: #48b685 }
+/* LiteralStringChar */ .chroma .sc { }
+/* LiteralStringDelimiter */ .chroma .dl { color: #48b685 }
+/* LiteralStringDoc */ .chroma .sd { color: #776e71 }
+/* LiteralStringDouble */ .chroma .s2 { color: #48b685 }
+/* LiteralStringEscape */ .chroma .se { color: #f99b15 }
+/* LiteralStringHeredoc */ .chroma .sh { color: #48b685 }
+/* LiteralStringInterpol */ .chroma .si { color: #f99b15 }
+/* LiteralStringOther */ .chroma .sx { color: #48b685 }
+/* LiteralStringRegex */ .chroma .sr { color: #48b685 }
+/* LiteralStringSingle */ .chroma .s1 { color: #48b685 }
+/* LiteralStringSymbol */ .chroma .ss { color: #48b685 }
+/* LiteralNumber */ .chroma .m { color: #f99b15 }
+/* LiteralNumberBin */ .chroma .mb { color: #f99b15 }
+/* LiteralNumberFloat */ .chroma .mf { color: #f99b15 }
+/* LiteralNumberHex */ .chroma .mh { color: #f99b15 }
+/* LiteralNumberInteger */ .chroma .mi { color: #f99b15 }
+/* LiteralNumberIntegerLong */ .chroma .il { color: #f99b15 }
+/* LiteralNumberOct */ .chroma .mo { color: #f99b15 }
+/* Operator */ .chroma .o { color: #5bc4bf }
+/* OperatorWord */ .chroma .ow { color: #5bc4bf }
+/* Punctuation */ .chroma .p { }
+/* Comment */ .chroma .c { color: #776e71 }
+/* CommentHashbang */ .chroma .ch { color: #776e71 }
+/* CommentMultiline */ .chroma .cm { color: #776e71 }
+/* CommentSingle */ .chroma .c1 { color: #776e71 }
+/* CommentSpecial */ .chroma .cs { color: #776e71 }
+/* CommentPreproc */ .chroma .cp { color: #776e71 }
+/* CommentPreprocFile */ .chroma .cpf { color: #776e71 }
+/* Generic */ .chroma .g { }
+/* GenericDeleted */ .chroma .gd { color: #ef6155 }
+/* GenericEmph */ .chroma .ge { font-style: italic }
+/* GenericError */ .chroma .gr { }
+/* GenericHeading */ .chroma .gh { font-weight: bold }
+/* GenericInserted */ .chroma .gi { color: #48b685 }
+/* GenericOutput */ .chroma .go { }
+/* GenericPrompt */ .chroma .gp { color: #776e71; font-weight: bold }
+/* GenericStrong */ .chroma .gs { font-weight: bold }
+/* GenericSubheading */ .chroma .gu { color: #5bc4bf; font-weight: bold }
+/* GenericTraceback */ .chroma .gt { }
+/* GenericUnderline */ .chroma .gl { }
+/* TextWhitespace */ .chroma .w { }
diff --git a/themes/bronn/theme.toml b/themes/bronn/theme.toml
new file mode 100644
index 0000000..46db5de
--- /dev/null
+++ b/themes/bronn/theme.toml
@@ -0,0 +1,21 @@
+# theme.toml template for a Hugo theme
+# See https://github.com/gohugoio/hugoThemes#themetoml for an example
+
+name = "Bronn"
+license = "MIT"
+licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE"
+description = ""
+homepage = "http://example.com/"
+tags = []
+features = []
+min_version = "0.41.0"
+
+[author]
+ name = ""
+ homepage = ""
+
+# If porting an existing theme
+[original]
+ name = ""
+ homepage = ""
+ repo = ""