diff options
| Commit | 88a5b49611a0a4d1eb47ba86b9123159443ce4cb (patch) | |
|---|---|---|
| Author | 2025-12-23 22:54:20 +0200 | |
| Committer | 2025-12-23 22:54:20 +0200 | |
| Files | 22ce3c36887f506898cc7636a80abf245ae240e7 /src/blog | |
| syndamia.com-88a5b49611a0a4d1eb47ba86b9123159443ce4cb.tar syndamia.com-88a5b49611a0a4d1eb47ba86b9123159443ce4cb.tar.gz syndamia.com-88a5b49611a0a4d1eb47ba86b9123159443ce4cb.zip | ||
| Parent | 0be8d4b427a0f0944552769edc9a080dbaf79cee (diff) | |
feat!: Update dunbar after inline brace character swap
45 files changed, 668 insertions, 668 deletions
diff --git a/src/blog/2.6-years-of-web-design/index.du b/src/blog/2.6-years-of-web-design/index.du index 10d1237..2678065 100644 --- a/src/blog/2.6-years-of-web-design/index.du +++ b/src/blog/2.6-years-of-web-design/index.du @@ -31,7 +31,7 @@ For code blocks, the background was a dark-blue color with a blue-ish font color [image ./img/v1.0-code\ block.png] -Although I wasn't the one to invent that color scheme, it was *[inspired]* from [url https://github.com/linuxmint/xed xed]'s Oblivion theme. +Although I wasn't the one to invent that color scheme, it was [*inspired*] from [url https://github.com/linuxmint/xed xed]'s Oblivion theme. It wasn't all completely bonkers, there were some not-so-ugly design decisions. Navigation was done with tabs, which look decently nice on a desktop. @@ -51,9 +51,9 @@ Finally, tables, like those used in the "Projects" listing, were the absolute du [image ./img/v1.0-projects.png] As you can see, the design was overwhelmingly ugly, with many boneheaded decisions behind it. -Did I mention every post had to be written entirely by hand in HTML, except for the headers and footers, which were [url https://gitlab.com/Syndamia/syndamiadotcom/-/tree/v1.0/website/js =[generated client-side with JavaScript]=]? +Did I mention every post had to be written entirely by hand in HTML, except for the headers and footers, which were [url https://gitlab.com/Syndamia/syndamiadotcom/-/tree/v1.0/website/js [=generated client-side with JavaScript=]]? -Nonetheless, it served as a good starting point and stepping stone, for my web development *[adventures]*. +Nonetheless, it served as a good starting point and stepping stone, for my web development [*adventures*]. ### v2.0 @@ -171,7 +171,7 @@ That's where everything stayed for a while. ### v3.0 -Of course, there were changes, I wrote more posts, tweaked some of the styling, hell, I even started adding (=[non required]=) JavaScript functionality. +Of course, there were changes, I wrote more posts, tweaked some of the styling, hell, I even started adding ([=non required=]) JavaScript functionality. Still, I was yearning for something better. Scalability was continuing to be an issue, outside of the annoying misalignment, navigation buttons in the header or footer would disappear into the void if it's contents were too long: @@ -239,7 +239,7 @@ Happy holidays everyone! This post has been in the works since 01 August 2020. At the time it was just called [url https://gitlab.com/Syndamia/syndamiadotcom/-/tree/501942b638c34582de2f73dc31423c9322eb81fd/src/blog/syndamiadotcom "syndamiadotcom"] and was listed under the now defunct "Projects" section. -It was actually still available on the website, under `[/blog/syndamiadotcom/]`, but I didn't list it in the blogs page. +It was actually still available on the website, under [`/blog/syndamiadotcom/`], but I didn't list it in the blogs page. That first iteration looked at the layout in a much stiffer and uninteresting way. I was talking about what exact color codes I used for crying out loud. @@ -252,4 +252,4 @@ As you saw, learning the little I know about web design was a slow trial and err The same will happen with making blog posts and other articles. I'm not a writer and I'm not interested enough to learn things properly. -*[P.S.]* Expect this post to be updated in the future, when I make new releases! +[*P.S.*] Expect this post to be updated in the future, when I make new releases! diff --git a/src/blog/bash-is-weird/index.du b/src/blog/bash-is-weird/index.du index 8bb9632..3fbc2cd 100644 --- a/src/blog/bash-is-weird/index.du +++ b/src/blog/bash-is-weird/index.du @@ -6,7 +6,7 @@ [$pagenav] 'footnote parameter-expansion Of course this is just one of the many ways to reference and work with variables. -For very basic stuff, BASH is decently simple and intuitive, for example variables are set with the format `[name=value]` and they're referenced with `[\$name]` [$parameter-expansion]. +For very basic stuff, BASH is decently simple and intuitive, for example variables are set with the format [`name=value`] and they're referenced with [`\$name`] [$parameter-expansion]. However, that changes once you start diving deeper (as I had to do for my [url /talks/linuxgraphy-by-strabo Linuxgraphy by Strabo] presentation). An example which illustrates my point would be: @@ -18,13 +18,13 @@ echo $((myvar += 46)) ${myvar[\${myvar:0:1}]} It has 3 things which really bothered me: :ordered -1. The output of `[\$(echo A B C)]` is replaced "literally", and then the whole expression is evaluated. - Meaning, `[myvar=($(echo A B C))]` turns into `[myvar=(A B C)]`, which creates an array with those three letters. +1. The output of [`\$(echo A B C)`] is replaced "literally", and then the whole expression is evaluated. + Meaning, [`myvar=($(echo A B C))`] turns into [`myvar=(A B C)`], which creates an array with those three letters. .p - I thought the "returned" value of `[\$(echo A B C)]` would be the whole string "A B C", so the array would have one element, that string. - However, `[\$()]` isn't really a function, which takes arguments, "creates" commands and returns their output. - It's [url https://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html Command =[Substitution]=], the text gets executed and it's output =[replaces]= the `[\$(...)]` itself (slightly reminiscent of [url https://lispcookbook.github.io/cl-cookbook/macros.html LISP macros]). + I thought the "returned" value of [`\$(echo A B C)`] would be the whole string "A B C", so the array would have one element, that string. + However, [`\$()`] isn't really a function, which takes arguments, "creates" commands and returns their output. + It's [url https://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html Command [=Substitution=]], the text gets executed and it's output [=replaces=] the [`\$(...)`] itself (slightly reminiscent of [url https://lispcookbook.github.io/cl-cookbook/macros.html LISP macros]). .p Side note: obviously, the original expected behaviour can happen if we use some quotes: @@ -32,21 +32,21 @@ It has 3 things which really bothered me: ```bash myvar=("$(echo A B C)") -2. On the second line, `[myvar]` *[becomes]* an integer and then we do an arithmetic operation on it, nothing wrong here. - `[\${parameter:offset:length}]` returns the substring from `[parameter]` from `[offset]` with size `[length]`, but we're giving it a "number", so it should either throw some sort of error or return something default, like 0. +2. On the second line, [`myvar`] [*becomes*] an integer and then we do an arithmetic operation on it, nothing wrong here. + [`\${parameter:offset:length}`] returns the substring from [`parameter`] from [`offset`] with size [`length`], but we're giving it a "number", so it should either throw some sort of error or return something default, like 0. However it correctly returns the number 1 (and no, that isn't a default, the number is correctly parsed as a string). .p This shows that numbers are actually strings too, and numerical operations are just weird string operations. Contrary to any dynamically-typed language, it's not like the type of a variable is inferred from it's value, [url https://tldp.org/LDP/abs/html/untyped.html there isn't a type at all]! - Which makes everything even more weird, considering you *[can]* [url https://www.gnu.org/software/bash/manual/bash.html#index-declare create variables with a specific type]. + Which makes everything even more weird, considering you [*can*] [url https://www.gnu.org/software/bash/manual/bash.html#index-declare create variables with a specific type]. -3. Finally, the arguably biggest weirdness of it all, is `[\${myvar[1]}]`. - It doesn't matter how it is represented, at first `[myvar]` was the list of values A, B, C and now it's a number, this should return nothing. - Per contra, the value `[B]` is returned instead! +3. Finally, the arguably biggest weirdness of it all, is [`\${myvar[1]}`]. + It doesn't matter how it is represented, at first [`myvar`] was the list of values A, B, C and now it's a number, this should return nothing. + Per contra, the value [`B`] is returned instead! .p - Via trial and error, we find that our number will be returned when the index is 0, and with index 2 we get `[C]`. + Via trial and error, we find that our number will be returned when the index is 0, and with index 2 we get [`C`]. So all variables are arrays, and by default for integer and string operations, the first value is used? .p diff --git a/src/blog/connect-to-mysql-in-dotnet-ef/index.du b/src/blog/connect-to-mysql-in-dotnet-ef/index.du index 5f0e968..e745f16 100644 --- a/src/blog/connect-to-mysql-in-dotnet-ef/index.du +++ b/src/blog/connect-to-mysql-in-dotnet-ef/index.du @@ -15,13 +15,13 @@ 2. [url #dbcontext-child-class DBContext child class] -I have found that connecting a `[.NET]` application to a `[MySql]` database (with Entity Framework) can be tricky. Here is what works for me. +I have found that connecting a [`.NET`] application to a [`MySql`] database (with Entity Framework) can be tricky. Here is what works for me. -Also, [url https://www.nuget.org/packages/MySql.Data.EntityFrameworkCore/ MySql.Data.EntityFrameworkCore] has been =[depricated]= since *[October 2020]*. If you need setup instructions with it, read [url https://gitlab.com/Syndamia/syndamiadotcom/-/blob/0510e29526c6d7681587fff4c98a339e8c69e9b5/src/blog/connect-to-mysql-in-csharp-ef/article.md this]. +Also, [url https://www.nuget.org/packages/MySql.Data.EntityFrameworkCore/ MySql.Data.EntityFrameworkCore] has been [=depricated=] since [*October 2020*]. If you need setup instructions with it, read [url https://gitlab.com/Syndamia/syndamiadotcom/-/blob/0510e29526c6d7681587fff4c98a339e8c69e9b5/src/blog/connect-to-mysql-in-csharp-ef/article.md this]. ## NuGet packages -You'll need to install [url https://www.nuget.org/packages/Pomelo.EntityFrameworkCore.MySql/ Pomelo.EntityFrameworkCore.MySql]. It provides the stuff necessary for connecting and using a `[MySql]` database. +You'll need to install [url https://www.nuget.org/packages/Pomelo.EntityFrameworkCore.MySql/ Pomelo.EntityFrameworkCore.MySql]. It provides the stuff necessary for connecting and using a [`MySql`] database. ## Connection string @@ -30,29 +30,29 @@ There are [url https://www.connectionstrings.com/mysql/ a lot] of ways to setup ``` "server=localhost; port=YOUR-PORT; user id=YOUR-USER-ID; password=YOUR-PASSWORD; database=NAME-OF-DATABASE; SslMode=none" -If you are using `[MySQL Workbench]` and you don't know your port and id, you can look at the server information from the `[MySQL Connections]` page. +If you are using [`MySQL Workbench`] and you don't know your port and id, you can look at the server information from the [`MySQL Connections`] page. [image ./img/connections.png MyServer root 127.0.0.1:3306] In this example, the user id is _root_ and the port is _3306_. ## Connecting -To connect, you'll need to call the `[UseMySql]` method, either in [url #asp.net-startup ASP.NET Startup] or in a [url #dbcontext-child-class DBContext child class]. +To connect, you'll need to call the [`UseMySql`] method, either in [url #asp.net-startup ASP.NET Startup] or in a [url #dbcontext-child-class DBContext child class]. -The method requires at least two arguments: connection string and `[MySql]` server version. The latter you can find, by going to the `[Help/About Workbench]` window inside `[MySQL Workbench]`. +The method requires at least two arguments: connection string and [`MySql`] server version. The latter you can find, by going to the [`Help/About Workbench`] window inside [`MySQL Workbench`]. [image ./img/about-workbench.png] [image ./img/workbench-version.png] -For the server version argument, create a new object of type `[MySqlServerVersion]` and give it's constructor a new object of type `[Version]`, to which you give the version numbers. The result should look something like this: +For the server version argument, create a new object of type [`MySqlServerVersion`] and give it's constructor a new object of type [`Version`], to which you give the version numbers. The result should look something like this: ```c# .UseMySql(CONNECTION_STRING, new MySqlServerVersion(new System.Version(8, 0, 21))) -Where `[CONNECTION_STRING]` is a (constant) variable that contains your connection string, and 8, 0, 21 are the version numbers. +Where [`CONNECTION_STRING`] is a (constant) variable that contains your connection string, and 8, 0, 21 are the version numbers. ### ASP.NET Startup -For `[ASP.NET]` applications, the connection must be put inside the `[ConfigureServices]` method of the `[Startup.cs]` file. If you already have a `[.UseSQL]` method call in there, just replace it with your `[.UseMySql]` method and arguments. +For [`ASP.NET`] applications, the connection must be put inside the [`ConfigureServices`] method of the [`Startup.cs`] file. If you already have a [`.UseSQL`] method call in there, just replace it with your [`.UseMySql`] method and arguments. The result should look something along the lines of: @@ -69,7 +69,7 @@ public void ConfigureServices(IServiceCollection services) ### DBContext child class -Another way to connect is via a `[DBContext]` child class (so, inside your own DB context). Just, override the `[OnConfiguring]` method and call the `[.UseMySql]` method from the `[optionsBuilder]` parameter. +Another way to connect is via a [`DBContext`] child class (so, inside your own DB context). Just, override the [`OnConfiguring`] method and call the [`.UseMySql`] method from the [`optionsBuilder`] parameter. ```c# protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) diff --git a/src/blog/disable-sticky-keys-popup/index.du b/src/blog/disable-sticky-keys-popup/index.du index 4826ea7..a51a7a1 100644 --- a/src/blog/disable-sticky-keys-popup/index.du +++ b/src/blog/disable-sticky-keys-popup/index.du @@ -5,27 +5,27 @@ 'define edited 01 November 2021 [$pagenav] -We've all been there: you're playing a game and after pressing `[Shift]` multiple times, you get a popup about "Sticky Keys", similar to this one: +We've all been there: you're playing a game and after pressing [`Shift`] multiple times, you get a popup about "Sticky Keys", similar to this one: [image ./img/windows-sticky-keys-prompt.png] This is how to stop the popup from showing up ever again: :ordered -1. Press =[Windows key + R]=, type in `[control access.cpl]`, and then press =[OK]= +1. Press [=Windows key + R=], type in [`control access.cpl`], and then press [=OK=] [image ./img/windows-run-control-access.png] -2. Inside the opened up window, press =[Make the keyboard easier to use]= +2. Inside the opened up window, press [=Make the keyboard easier to use=] [image ./img/windows-make-keyboard-highlighted.png] -3. After that, press =[Set up Sticky Keys]= +3. After that, press [=Set up Sticky Keys=] [image ./img/windows-sticky-keys-highlighted.png] -4. Uncheck the =[Turn on Sticky Keys when SHIFT is pressed five times]= +4. Uncheck the [=Turn on Sticky Keys when SHIFT is pressed five times=] [image ./img/windows-sticky-keys-disable.png] -5. Finally, press =[OK]= and close the window +5. Finally, press [=OK=] and close the window diff --git a/src/blog/encrypted-email/index.du b/src/blog/encrypted-email/index.du index 8051eb5..4ed85d7 100644 --- a/src/blog/encrypted-email/index.du +++ b/src/blog/encrypted-email/index.du @@ -29,25 +29,25 @@ When you try and look around for articles, regarding encrypted emails, all you'l That's why, after a fairly lengthy research process, I've decided to do just that. These are the more common ways to encrypt your email with their strengths and weaknesses. I also wrote a (somewhat rough) [url /blog/how-to-encrypt-email tutorial on how to setup] [url #openpgp OpenPGP] or [url #smime S/MIME] in practice. -*[Note:]* What I'm referring to is end-to-end encryption, where you send an encrypted email, and the recipient decrypts it. Encryption between you and a mail server is practically a given and is setup by the mail server administrator. +[*Note:*] What I'm referring to is end-to-end encryption, where you send an encrypted email, and the recipient decrypts it. Encryption between you and a mail server is practically a given and is setup by the mail server administrator. ## Encryption and signature Unless stated otherwise, all of the listed encryption (and signature) schemes work by utilizing [url https://en.wikipedia.org/wiki/Public-key_cryptography public-key cryptography]. -In brief, if you are sending an encrypted email, the =[recipient]= needs to have generated a public and private key pair. Then you need to have acquired =[their public key]=. Finally, if you want to send them an encrypted email: +In brief, if you are sending an encrypted email, the [=recipient=] needs to have generated a public and private key pair. Then you need to have acquired [=their public key=]. Finally, if you want to send them an encrypted email: .numbered -1. You encrypt =[your]= email with =[their public key]= -2. The recipient decrypts =[your]= message with =[their private key]= +1. You encrypt [=your=] email with [=their public key=] +2. The recipient decrypts [=your=] message with [=their private key=] -And if someone wants to send =[you]= an encrypted email, =[you]= need to generate a public and private key pair, share =[your public key]= with them, and when you receive the message, decrypt it with =[your private key]=. +And if someone wants to send [=you=] an encrypted email, [=you=] need to generate a public and private key pair, share [=your public key=] with them, and when you receive the message, decrypt it with [=your private key=]. Every email you send can be [url https://en.wikipedia.org/wiki/Digital_signature digitally signed] (not to be confused with [url https://en.wikipedia.org/wiki/Digital_signature electronic signatures]), meaning the message is (cryptographically) "signed", and with this signature, the recipient can check if the message was changed during transit. Digital signatures also use public-key cryptography, but the other way around: .numbered -1. You sign =[your]= email with =[your private key]= -2. Then the recipient verifies =[your]= message with =[your public key]=. +1. You sign [=your=] email with [=your private key=] +2. Then the recipient verifies [=your=] message with [=your public key=]. This might sound a bit complicated, but all you need to worry about is you and the recipient generating these public-private key pairs, exchanging public keys, and your email client should handle the rest. And if you use a tool like [url https://www.pep.security/en/ pEp], the creation and exchange of keys can be easily automated. @@ -101,7 +101,7 @@ Unlike OpenPGP it doesn't use a web of trust, but a [url https://en.wikipedia.or So, already, it has a huge advantage, you don't need to exchange keys, since the email client will handle it. S/MIME is most often used by corporations/organizations, so support in commercial mail clients like [url https://support.google.com/a/answer/6374496?hl=en#zippy= Google Workspace Enterprise Edition] and [url https://support.microsoft.com/en-us/office/encrypt-messages-by-using-s-mime-in-outlook-on-the-web-878c79fc-7088-4b39-966f-14512658f480 Outlook Enterprise/Business] ([url https://docs.microsoft.com/en-us/exchange/security-and-compliance/smime-exo/configure-smime-exo?view=o365-worldwide Exchange Online has to be configured] by an administrator and can be used only with [url https://docs.microsoft.com/en-us/deployoffice/endofsupport/microsoft-365-services-connectivity paid clients]) is available. -On the other hand, you can browse [url https://support.google.com/a/answer/7448393?hl=en&ref_topic=9061730 Google's] and [url https://docs.microsoft.com/en-us/security/trusted-root/participants-list Microsoft's] trusted (root) CAs all you want, but you'll find that there is only one place where you could register a certificate for free: [url https://www.actalis.com/s-mime-certificates.aspx Actalis]. A good tutorial on the procedure can be found [url https://www.dannyguo.com/blog/how-to-get-a-free-s-mime-certificate/ here], but beware, *[they]* generate the private key. +On the other hand, you can browse [url https://support.google.com/a/answer/7448393?hl=en&ref_topic=9061730 Google's] and [url https://docs.microsoft.com/en-us/security/trusted-root/participants-list Microsoft's] trusted (root) CAs all you want, but you'll find that there is only one place where you could register a certificate for free: [url https://www.actalis.com/s-mime-certificates.aspx Actalis]. A good tutorial on the procedure can be found [url https://www.dannyguo.com/blog/how-to-get-a-free-s-mime-certificate/ here], but beware, [*they*] generate the private key. Otherwise, it's email encryption capabilities are the same as those outlined in [url #pgpmime PGP/MIME]. @@ -129,7 +129,7 @@ projects to create alternatives to email that are more secure yet still email-li And outline zero trust and fingerprinting as the main advantages of these systems. Also most of these systems are [url https://en.wikipedia.org/wiki/Peer-to-peer peer-to-peer]. -Given that these projects aren't really email, I won't dive much deeper into it. But I will mention, almost all listed projects seem to have been abandoned. Those still under active development are [url http://goldbug.sourceforge.net/ goldbug] and [url https://retroshare.cc/ retroshare]. Until 2021, zeronet *[was]* updated, but the [url https://github.com/shortcutme author] seems to have [url https://github.com/HelloZeroNet/ZeroNet/issues/2808#issuecomment-1132820787 disappeared]. +Given that these projects aren't really email, I won't dive much deeper into it. But I will mention, almost all listed projects seem to have been abandoned. Those still under active development are [url http://goldbug.sourceforge.net/ goldbug] and [url https://retroshare.cc/ retroshare]. Until 2021, zeronet [*was*] updated, but the [url https://github.com/shortcutme author] seems to have [url https://github.com/HelloZeroNet/ZeroNet/issues/2808#issuecomment-1132820787 disappeared]. ## Centralized non-email systems @@ -157,13 +157,13 @@ Protonmail, or [url https://proton.me/ proton.me] as they are called now, which Funnily enough, Protonmail doesn't really fit in any of the listed categories, since encrypted emails outside the system will work as any [url #openpgp OpenPGP] encrypted one. -Protonmail's services have a free tier, which should be enough for lighter usage, but restricts =[heavily]= storage, label and folder count, amount of sent messages per day, etc. At the time of writing, their second tier pretty much lifts all restrictions for 5 euro per month (without annual contracts). Check out their pricing [url https://proton.me/pricing here]. +Protonmail's services have a free tier, which should be enough for lighter usage, but restricts [=heavily=] storage, label and folder count, amount of sent messages per day, etc. At the time of writing, their second tier pretty much lifts all restrictions for 5 euro per month (without annual contracts). Check out their pricing [url https://proton.me/pricing here]. ### Tutanota [url https://tutanota.com/ Tutanota] uses it's own special system for security. In brief, all of your emails are (zero-access) stored and end-to-end encrypted with (mostly) [url https://en.wikipedia.org/wiki/Advanced_Encryption_Standard AES 128], and while they generate and hold your public and private keys, your password is needed to decrypt your private key (do check out their [url https://tutanota.com/security/ security page] for more details). -However, it's crucial to note that they are a type *[2. Semi-closed system]*. If you send an encrypted email to a non-tutanota recipient, the recipient will get a URL from which they will be able to reply, through Tutanota's web client. +However, it's crucial to note that they are a type [*2. Semi-closed system*]. If you send an encrypted email to a non-tutanota recipient, the recipient will get a URL from which they will be able to reply, through Tutanota's web client. Finally, pricing. In general, they have a lot less features than [url #protonmail Protonmail], but their free tier is a lot more capable than [url #protonmail Protonmail]'s. Their pricing is extremely flexible, being able to buy specific features by themselves, like storage or mail aliases. Check it out [url https://tutanota.com/pricing/ here]. diff --git a/src/blog/export-skype/index.du b/src/blog/export-skype/index.du index b9046b2..9f88ce7 100644 --- a/src/blog/export-skype/index.du +++ b/src/blog/export-skype/index.du @@ -22,47 +22,47 @@ Continue reading for the required steps on doing it. .unordered - You could be asked to sign in. - After signing in you'll need to *[open the link again]*, since you would be redirected to the wrong place. + After signing in you'll need to [*open the link again*], since you would be redirected to the wrong place. 2. After opening the link you should be greeted by something like this. - Check the two checkboxes next to =[Conversations]= and =[Files]= *[(pointed to by the red arrows)]*. + Check the two checkboxes next to [=Conversations=] and [=Files=] [*(pointed to by the red arrows)*]. [image ./img/initial-screen.png] -3. Press =[Submit request]=. - After being greeted by this screen, press =[Continue]=. +3. Press [=Submit request=]. + After being greeted by this screen, press [=Continue=]. [image ./img/export-prepared.png] .bulleted - - You should now see an =[Available exports]= section near the top of the page. - The status will be =[Pending]=. + - You should now see an [=Available exports=] section near the top of the page. + The status will be [=Pending=]. .p [image ./img/available-exports.png] -5. Reload the page after a bit of time. When your export is ready, you'll find a =[Download]= button next to it, click it. +5. Reload the page after a bit of time. When your export is ready, you'll find a [=Download=] button next to it, click it. [image ./img/download-button.png] -Your export will be downloaded as a `[.tar]` archive file. -You'll need an archiver utility to extract the files, something like [url https://www.rarlab.com/download.htm WinRAR] or [url https://www.7-zip.org/ 7-Zip] *[(I personally recommend 7-Zip, it is completely free (no need to worry about your [url https://youtu.be/fTgZRVVr3_Y infinite trial]) and works faster)]*. +Your export will be downloaded as a [`.tar`] archive file. +You'll need an archiver utility to extract the files, something like [url https://www.rarlab.com/download.htm WinRAR] or [url https://www.7-zip.org/ 7-Zip] [*(I personally recommend 7-Zip, it is completely free (no need to worry about your [url https://youtu.be/fTgZRVVr3_Y infinite trial]) and works faster)*]. ## Viewing your export - Official Tool :ordered 1. Extract your archive -2. Open the [url https://go.skype.com/skype-parser Skype Parser Download], which will prompt you to save `[skype-parser.zip]` +2. Open the [url https://go.skype.com/skype-parser Skype Parser Download], which will prompt you to save [`skype-parser.zip`] -3. Extract `[skype-parser.zip]` +3. Extract [`skype-parser.zip`] -4. Inside the `[skype-parser]` folder, open `[index.html]` (it might be named just `[index]`). You'll be greeted by this page in your browser: +4. Inside the [`skype-parser`] folder, open [`index.html`] (it might be named just [`index`]). You'll be greeted by this page in your browser: [image ./img/default-skype-parser-index.png] -5. Click the `[Choose File]` option and select the `[messages.json]` (it might be named just `[messages]`) file from your export. +5. Click the [`Choose File`] option and select the [`messages.json`] (it might be named just [`messages`]) file from your export. [image ./img/choose-file.png] -6. Press the `[Load]` button right below, and you're done. +6. Press the [`Load`] button right below, and you're done. On the left side you have your conversations, and when opening one, your messages will be displayed to the right (just like in Skype itself) [image ./img/archived-conversations-skype-default.png] @@ -78,11 +78,11 @@ The fix is using an alternative to the official tool. Their source code can be found over at [url https://github.com/ArtemVeremienko/skype-parser github.com/ArtemVeremienko/skype-parser]. :ordered -1. Go to the [url https://github.com/ArtemVeremienko/skype-parser/releases/latest latest release of his skype-parser] and download `[skype-parser.zip]` +1. Go to the [url https://github.com/ArtemVeremienko/skype-parser/releases/latest latest release of his skype-parser] and download [`skype-parser.zip`] [image ./img/github-skype-parser-download.png] 2. Extract all of the files. - They'll be in the same folder as the `[skype-parser.zip]` file, so find the `[index.html]` file and open it. + They'll be in the same folder as the [`skype-parser.zip`] file, so find the [`index.html`] file and open it. 3. Continue from step 5 onward of the [url #viewing-your-export-official-tool Viewing your export - Official Tool] section diff --git a/src/blog/fix-network-brother-printers/index.du b/src/blog/fix-network-brother-printers/index.du index c6ac699..045bb39 100644 --- a/src/blog/fix-network-brother-printers/index.du +++ b/src/blog/fix-network-brother-printers/index.du @@ -10,19 +10,19 @@ Before we start, make sure you have CUPS and avahi installed and running. ## Make sure CUPS recognises it Go to [url https://localhost:631/printers/ localhost:631/printers] and make sure your printer is listed there. -If =[not]=, go to `[Administration/Add Printer]` and select your printer. -If it's =[not]= listed even there, then you have some other network connectivity issue. +If [=not=], go to [`Administration/Add Printer`] and select your printer. +If it's [=not=] listed even there, then you have some other network connectivity issue. Otherwise [url #try-to-print-a-test-page try to print a test page]. -### Check if it =[is]= recognised on the network. +### Check if it [=is=] recognised on the network. Execute in the command line: ```bash avahi-browse --all -t -r -There will be a lot of output, but scroll down until you find something *[like]*: +There will be a lot of output, but scroll down until you find something [*like*]: ``` = enp0s25 IPv4 Brother HL-L2350DW series _pdl-datastream._tcp local @@ -30,7 +30,7 @@ hostname = [BRW9C305B9EC83D.local] address = [192.168.0.110] The exact values aren't important, just make sure the part after IPv4 is the model of your printer. -`[address]` is the local printer address, ping it. +[`address`] is the local printer address, ping it. In this example, the command would be: ```bash @@ -38,11 +38,11 @@ ping 192.168.0.110 .bulleted - If the ping is successful, you might also want to put that IP address in your browser. - With the example, you would open the link `[http://192.168.0.110]`. - Your printer =[may]= or =[may not]= support Web Based Management, which would allow you to edit it's setting from the browser. + With the example, you would open the link [`http://192.168.0.110`]. + Your printer [=may=] or [=may not=] support Web Based Management, which would allow you to edit it's setting from the browser. If the page isn't available, don't worry about it. -If output is =[not]= something like `[64 bytes from ...]` (so, if it is `[Destination Host Unreachable]` or ping just hangs, without output), then it's an issue with your network or printer network configuration. +If output is [=not=] something like [`64 bytes from ...`] (so, if it is [`Destination Host Unreachable`] or ping just hangs, without output), then it's an issue with your network or printer network configuration. Make sure the printer is properly connected to the network.\n Otherwise, this shows that your computer has network access to the printer, and all problems are local. @@ -52,7 +52,7 @@ Otherwise, this shows that your computer has network access to the printer, and Go to [url https://www.openprinting.org/printers www.openprinting.org/printers] and enter your model. If it isn't listed then it doesn't work for sure. Alternatively, if it is and the rating [url https://wiki.linuxfoundation.org/openprinting/database/databaseintro#about_the_data isn't "Perfectly"], then read the whole page, in case networking is listed as nonfunctional. -If it =[is]= supported, then: +If it [=is=] supported, then: ### Check if there are drivers available @@ -61,7 +61,7 @@ Run in the command line: ```bash lpinfo -v -If you only get entries like `[network WORD]`, without anything which looks like a URL (URI), then you may not have a working driver. +If you only get entries like [`network WORD`], without anything which looks like a URL (URI), then you may not have a working driver. Make sure you have installed any or tried all of the drivers listed in the printer's [url https://www.openprinting.org/printers www.openprinting.org] page. ## Try to print a test page @@ -73,7 +73,7 @@ After a little while, the "State" should change from "pending" to "processing" ( ### Unable to locate printer "SOMETHING.local" If you also have the error "Unable to locate printer "SOMETHING.local"." (obviously SOMETHING is the exact value you get), then that means the printer is accessed via the domain name "SOMETHING.local". -`[.local]` domains require a special DNS server to be resolved, so inside `[/etc/nsswitch.conf]`, on the line that starts with `[hosts]`, add to it's end the value `[mdns_minimal]`. +[`.local`] domains require a special DNS server to be resolved, so inside [`/etc/nsswitch.conf`], on the line that starts with [`hosts`], add to it's end the value [`mdns_minimal`]. It should look something like: ``` @@ -82,4 +82,4 @@ hosts: files dns mdns_minimal After saving your changes, your printer should pretty quickly start printing the test page, no need to restart anything. .bulleted -- if your printer supports Web Based Management, then you should be able to go open the page `[http://SOMETHING.local]` in your browser and edit your printer settings from there. +- if your printer supports Web Based Management, then you should be able to go open the page [`http://SOMETHING.local`] in your browser and edit your printer settings from there. diff --git a/src/blog/fix-no-frame-buffer-plan9/index.du b/src/blog/fix-no-frame-buffer-plan9/index.du index 4e9c877..8d63c0b 100644 --- a/src/blog/fix-no-frame-buffer-plan9/index.du +++ b/src/blog/fix-no-frame-buffer-plan9/index.du @@ -14,7 +14,7 @@ init: rc exit status: rio 31: display open [image ./img/boot-prompt-no-frame-buffer-error.png] -For some reason, on certain configurations, the `[xga]` (`[vga]`) monitor type does not work when booting into Plan 9, even though it works fine during install. The fix is to adjust monitor settings to `[vesa]`: +For some reason, on certain configurations, the [`xga`] ([`vga`]) monitor type does not work when booting into Plan 9, even though it works fine during install. The fix is to adjust monitor settings to [`vesa`]: :ordered 1. In the shell prompt enter @@ -62,12 +62,12 @@ sam /n/9fat/plan9.ini b /n/9fat/plan9.ini and click the green-backgrounded box. - Then replace `[xga]` with `[vesa]`: + Then replace [`xga`] with [`vesa`]: ``` , x/xga/ s/xga/vesa - and click the green-backgrounded box again. We're almost done here, enter `[w]`, wait a bit, and finally enter `[q]`. + and click the green-backgrounded box again. We're almost done here, enter [`w`], wait a bit, and finally enter [`q`]. :unordered - If you want to check whether the file was properly saved, feel free to run @@ -79,10 +79,10 @@ cat /n/9fat/plan9.ini [image ./img/rio-plan9ini-cat.png] - - The first command opens the `[plan9.ini]` file for editing, and the second command, finds every line that contains `[xga]` (there should probably be only one) and on each matching line replaces `[xga]` with `[vesa]`. Refer to the [url https://p9f.org/sys/doc/sam/sam.html docs] for more information. + - The first command opens the [`plan9.ini`] file for editing, and the second command, finds every line that contains [`xga`] (there should probably be only one) and on each matching line replaces [`xga`] with [`vesa`]. Refer to the [url https://p9f.org/sys/doc/sam/sam.html docs] for more information. -5. That's it, all we have to do is halt our file system with `[fshalt]` (or type out the command in the [url https://9p.io/wiki/plan9/Installing_Plan_9_on_Qemu/ Qemu installation guide]) and Force Reset the virtual machine. +5. That's it, all we have to do is halt our file system with [`fshalt`] (or type out the command in the [url https://9p.io/wiki/plan9/Installing_Plan_9_on_Qemu/ Qemu installation guide]) and Force Reset the virtual machine. The next time you boot into Plan 9 and into your user, the graphical environment should load fine. Enjoy Plan 9! diff --git a/src/blog/fix-qc-timeout/index.du b/src/blog/fix-qc-timeout/index.du index d882d15..11dfa32 100644 --- a/src/blog/fix-qc-timeout/index.du +++ b/src/blog/fix-qc-timeout/index.du @@ -6,7 +6,7 @@ [$pagenav] Depending on your harddrive, you may get a 15 second delay on boot. -Looking at the kernel logs (with `[dmesg]`), you may find the following errors: +Looking at the kernel logs (with [`dmesg`]), you may find the following errors: ``` kernel: ata1.00: qc timeout after 15000 msecs (cmd 0x47) @@ -23,7 +23,7 @@ Meaning, add the following parameter: ``` libata.force=1.00:nodmalog -where `[1.00]` is the thing between "ata" and ":". +where [`1.00`] is the thing between "ata" and ":". So, if your logs were @@ -68,16 +68,16 @@ With DMA, the CPU could ask the drive for everythng it wants (not a tiny bit), a The benefit is that the CPU can do other work while the transfer is going on, greatly improving efficiency, but the downside is that the harddrive has to support it (have a DMAC chip on it). Normally it would be useful for the DMAC to keep logs in a special place on the drive. -~[This is where the issue comes from: your harddrive supports DMA but does not support logs for it. +[~This is where the issue comes from: your harddrive supports DMA but does not support logs for it. However, the Linux kernel has no good way of knowing that, there is no "property" on the drive which tells us this. -The only way is to try and read from that log: if it succeeds, then there is support, if it fails, then there isn't.]~ +The only way is to try and read from that log: if it succeeds, then there is support, if it fails, then there isn't.~] -~[But what does it mean to fail? +[~But what does it mean to fail? The simplest definition would be for the drive to return an error singal, but in our case, the drive would just not return anything, ignoring our request. In that case, how would we know if the drive just doesn't know how to respond (meaning it doesn't support the logs) or if it's just very slow? -Well, we can't, so we put a time limit, if it doesn't respond in 15 seconds, then it probably doesn't support it.]~ +Well, we can't, so we put a time limit, if it doesn't respond in 15 seconds, then it probably doesn't support it.~] -That's what the error is saying: `[qc]` is short for [url https://docs.kernel.org/driver-api/libata.html#origins-of-commands "queued command"], it's used to represent a (S)ATA command (hence the `[cmd]` at the end, telling us which command it's referring to). +That's what the error is saying: [`qc`] is short for [url https://docs.kernel.org/driver-api/libata.html#origins-of-commands "queued command"], it's used to represent a (S)ATA command (hence the [`cmd`] at the end, telling us which command it's referring to). So, the kernel is telling us "The hard drive (ATA) command to read (DMA) logs timed out after 15 seconds" (it first says a command timed out, then it says which one). By adding that kernel parameter, we're telling Linux that the drive doesn't support DMA logs, therefore the kernel doesn't need to do this "wait 15 seconds for response if support exists" routine. diff --git a/src/blog/fmi-i-vissheto-obrazovanie-v-programistkata-industriq/balove-2021.du b/src/blog/fmi-i-vissheto-obrazovanie-v-programistkata-industriq/balove-2021.du index 9f98e46..0796818 100644 --- a/src/blog/fmi-i-vissheto-obrazovanie-v-programistkata-industriq/balove-2021.du +++ b/src/blog/fmi-i-vissheto-obrazovanie-v-programistkata-industriq/balove-2021.du @@ -5,7 +5,7 @@ 'define edited 14 July 2023 [$pagenav] -*[Тази страница е разширение на [url ./ "ФМИ и висшето образование в програмистката индустрия"].]* +[*Тази страница е разширение на [url ./ "ФМИ и висшето образование в програмистката индустрия"].*] Благодарение на електронната система за кандидатстване, имам минимални балове на трите класирания през 2021 за компютърни науки, софтуерно инженерство и информатика (без информационни системи, защото не исках да влизам там). Понеже такава информация много не се разпространява, тук ще я споделя подробно. @@ -19,9 +19,9 @@ Балът се формираше така: .bulleted -- 3 по оценката от Математика II *[или]* 2.5 по оценката от Математика I (което от двете носи по-голямо число) +- 3 по оценката от Математика II [*или*] 2.5 по оценката от Математика I (което от двете носи по-голямо число) - + -- ако си ходил на държавен зрелостен изпит по математика, оценката от него, *[иначе]* оценката по математика от дипломата +- ако си ходил на държавен зрелостен изпит по математика, оценката от него, [*иначе*] оценката по математика от дипломата За някакво усещане за баловете, ще напиша минималната нужна оценка от изпитите, считайки оценката от ДЗИ или дипломата за 6,00. Ако балът е под 13.5, то тогава със сигурност са приети студенти, които са имали по-малко от 6.00 на ДЗИ/диплома и са компенсирали с резултати на изпитите по математика (не може да кандидатстваш с оценка, по-ниска от 3.000). @@ -67,7 +67,7 @@ |: 3.877 |: Информатика - платено редовно -|: *[11.62]* +|: [*11.62*] |: 3.000 |: 3.000 @@ -91,7 +91,7 @@ |: 4.263 |: Информатика - редовно -|: *[10.64]* +|: [*10.64*] |: 3.000 |: 3.000 @@ -135,7 +135,7 @@ |: 4.406 |: Информатика - редовно -|: *[12.00]* +|: [*12.00*] |: 3.000 |: 3.000 diff --git a/src/blog/fmi-i-vissheto-obrazovanie-v-programistkata-industriq/index.du b/src/blog/fmi-i-vissheto-obrazovanie-v-programistkata-industriq/index.du index 3b13c4c..ec2f9b8 100644 --- a/src/blog/fmi-i-vissheto-obrazovanie-v-programistkata-industriq/index.du +++ b/src/blog/fmi-i-vissheto-obrazovanie-v-programistkata-industriq/index.du @@ -51,7 +51,7 @@ Аз вече съм следвал 2 години в университет, плюс това имам сериозен опит от преди това. Макар и този блогпост да е главно за [url https://www.fmi.uni-sofia.bg/ Факултета по Математика и Информатика] към [url https://www.uni-sofia.bg/index.php Софийски Университет], по-общата ми цел е да споделя всичко , което знам свързано с образованието в индустрията. -Бърза бележка: всичко казано =[важи за моя випуск]=, с времето нещата се изменят и може повечето информация тук да бъде =[остаряла]=. +Бърза бележка: всичко казано [=важи за моя випуск=], с времето нещата се изменят и може повечето информация тук да бъде [=остаряла=]. Допълнително, [url ./balove-2021.html тук] имам изкарани баловете във ФМИ (на СУ) за 2021 година. ## Кой съм аз @@ -126,7 +126,7 @@ Във ФМИ много от предметите са математики и програмиранията се говори, че не са много добре. Онлайн има стотици часове материали и курсове, повечето от които са безплатни, на всяка тема свързана с програмиране. -Допълнително имаш [url https://www.telerikacademy.com/ Telerik Academy] и [url https://softuni.bg/ SoftUni] (само искам да напомня, че =[СофтУни не е университет]=, макар и така да се казват) - две места които предлагат разнообразни програмистки и чисто практически курсове (и също дават сертификати). +Допълнително имаш [url https://www.telerikacademy.com/ Telerik Academy] и [url https://softuni.bg/ SoftUni] (само искам да напомня, че [=СофтУни не е университет=], макар и така да се казват) - две места които предлагат разнообразни програмистки и чисто практически курсове (и също дават сертификати). А и повечето програмисти нямат висше и са самоуки, тоест този път не е изобщо странен, даже е най-често следвания. Финалното ми мнение се намира [url #section-19 най-долу], но един такова решение трябва да се вземе с възможно най-много информация. @@ -138,7 +138,7 @@ От тях, най-желани са компютърни науки и софтуерно инженерство (тези ще наричам "хубавите" специалности). В информатика се влизаше много лесно, там балът беше [url ./balove-2021.html безнадеждно нисък], обаче следването е най-трудно от всички останали дисциплини. -Късането е брутално, особено първи курс: по Алгебра 1 от към 200 човека (това включваше и минали години май) само един човек беше *[допуснат]* до изпит (ама си го мина де). +Късането е брутално, особено първи курс: по Алгебра 1 от към 200 човека (това включваше и минали години май) само един човек беше [*допуснат*] до изпит (ама си го мина де). По дискретни структури бяха повече, цели 10тима човека. Общо от 1ви курс преминаха успешно 20-30 човека във 2ри курс (за да минеш не е нужно всички изпити да си минал, ама детайли [url #section-10 по-късно]). Има няколко причини за това: @@ -174,20 +174,20 @@ Като обобщение, това са дисциплините подредени от най-трудна за минаване към най-лесна: :ordered -1. =[Информатика]=: много трудно, не по много основателни причини, макар че като цяло малцинството което успява да завърши са на високо ниво. +1. [=Информатика=]: много трудно, не по много основателни причини, макар че като цяло малцинството което успява да завърши са на високо ниво. Не препоръчвам, ако не си много издържлив и КН и СИ не са се получили. -2. =[Компютърни науки, 2ри поток]=: трудно, но като цяло е сравнително основателно (пак на моменти е малко нечестно, но не толкова колкото при информатика), нивото просто е високо. +2. [=Компютърни науки, 2ри поток=]: трудно, но като цяло е сравнително основателно (пак на моменти е малко нечестно, но не толкова колкото при информатика), нивото просто е високо. Поне от моя випуск, повечето от най-добрите се намират тук. Ако си представим, че има някакво перфектно ниво на обучение, където не е твърде лесно, но и не е твърде трудно, бих казал че КН2 се намира малко над това ниво. -3. =[Компютърни науки, 1ви поток]=: малко по-лесно от КН2, но с малко понижаване на качеството. +3. [=Компютърни науки, 1ви поток=]: малко по-лесно от КН2, но с малко понижаване на качеството. Има добро количество материал, което в КН2 ти е набито в главата, докато при КН1 си го забравил след лятната ваканция (не че това не важи в обратната посока, но в КН2 ни вкарват повече неща в умовете). В сравнение с перфектното ниво, КН1 е малко под него. Обаче трябва да се има в предвид, че 2ри курс сложиха доста взискателни преподаватели. Ако това се запази, разликата между двата потока може да изчезне. -4. =[Софтуерно инженерство]=: забележимо по-лесно от компютърни науки, повечето хора по повечето дисциплини минават без твърде много проблеми. +4. [=Софтуерно инженерство=]: забележимо по-лесно от компютърни науки, повечето хора по повечето дисциплини минават без твърде много проблеми. Ама нивото също спада забележително, макар и бала да е най-висок. Както споменах, при компютърни науки е по-добре, ама нивото на СИ пак е сравнително ок. -5. =[Информационни системи]=: нисичък бал и сравнително лесно, но не ми изглежда да е супер развиващо за програмисти. +5. [=Информационни системи=]: нисичък бал и сравнително лесно, но не ми изглежда да е супер развиващо за програмисти. Не бих препоръчал, освен ако алтернативата не е информатика. @@ -225,10 +225,10 @@ С новия изпит вече конкуренцията е малко по-висока, все пак са се явили 969[$2022-kandidati] ученици на Математика през 2022 и максимум 979[$2023-kandidati] през 2023. Местата са същия брой, така че излиза към примерно трима човека за едно място и ако примерно имаш 3ка или 4ка може и да не влезеш във ФМИ. -Обаче, =[най-важното: материалът във ФМИ не се е изменил!]= +Обаче, [=най-важното: материалът във ФМИ не се е изменил!=] Макар и изпитът да е значително по-лесен, трудността на материала не се е снижила (или поне толкова, колкото изпита) и в същото време математиката се изучава доста. Тоест, един човек, влязъл с най-ниския бал на Математика ще е далеч по-неподготвен за ФМИ от човек с минимален бал на Математика II. -Затова =[препоръчвам всеки кандидат-студент да може да реши някоя Математика II за към 4-4.50!]= +Затова [=препоръчвам всеки кандидат-студент да може да реши някоя Математика II за към 4-4.50!=] Това са горе-долу 5-6 от 8те задачи. Иначе ако не можеш редовно да учиш математика и не можеш да се справиш с такива задачи (които са по-прости като характер в сравнение с това, което учим в университета), следването ти ще бъде твърде трудно според мен. @@ -253,7 +253,7 @@ Оценката се формира по различни начини при различните предмети, но най-често контролните и домашните през семестъра носят 40-50% и през сесията си изкарваш останалата част от оценката. Също понякога, ако си се справил достатъчно добре на контролните през семестъра, може да бъдеш освободен от изпит-задачи (не е нужно да ходиш и като оценка на него ти се пише средно аритметично от контролните). -Обаче почти винаги =[ако изкараш двойка на някой от изпитите през сесията, цялата ти оценка за предмета става двойка!]= +Обаче почти винаги [=ако изкараш двойка на някой от изпитите през сесията, цялата ти оценка за предмета става двойка!=] 'footnote september Разговорно на поправителната сесия им викаме септември, макар и само един-два дена от нея да са в този месец. Причината е, че просто до преди няколко години наистина е била през септември, но са я изместили назад. Защо са я изместили, не знам. @@ -282,7 +282,7 @@ Количеството подготовка за едно контролно зависи от човек на човек, но ако нищо не си учил, бих казал че е поне една-две интензивни седмици за сериозните предмети са достатъчни. За домашните е по-малко, защото по принцип те са върху неща, изучавани на упражнения, така че ако си си водел записки (или споделящи колеги са водели) ще знаеш как да решиш всички задачи (разбира се, има изключения). -Това обаче е =[само за контролни-задачи по някои предмети]=, все пак имаш теория и имаш задачи за които ти трябва теория, и тя вече не може да се научи толкова бързо. +Това обаче е [=само за контролни-задачи по някои предмети=], все пак имаш теория и имаш задачи за които ти трябва теория, и тя вече не може да се научи толкова бързо. Нещо много хубаво е, че никой не следи за присъствие на занятия и не се пишат отсъствия както в училище. Разбира се, това не означава, че не е нужно да се ходи на всички занятия, напротив, но ако искаш винаги може да пропуснеш нещо. @@ -305,13 +305,13 @@ Обаче, си задължен и да ходиш на избираеми дисциплини: имаш минимален брой избираеми за всеки семестър, минимален общ брой за всичките години и минимален брой ECTS кредити за всичките години. За разлика от училище, имаш доста голям избор и много от тях са интересни и полезни. -Обаче, =[не записвай избираеми през първи курс!]= -Скоро ще обсъдим предметите, обаче =[първи курс е най-труден и изисква цялото ти работно време!]= -Това трябва да навежда на мисълта, че =[не трябва да работиш по време на първи курс]=, освен ако не ти се налага или не си от най-умните хора в специалността. +Обаче, [=не записвай избираеми през първи курс!=] +Скоро ще обсъдим предметите, обаче [=първи курс е най-труден и изисква цялото ти работно време!=] +Това трябва да навежда на мисълта, че [=не трябва да работиш по време на първи курс=], освен ако не ти се налага или не си от най-умните хора в специалността. Материалът е нещо напълно ново, не само като изучавани неща, ами и като концепции и модел на учене. -Ама каквото и да си говорим, =[най-доброто обучение се намира в избираемите дисциплини!]= +Ама каквото и да си говорим, [=най-доброто обучение се намира в избираемите дисциплини!=] Не е задължително да си доцент или професор, за да направиш избираема, и може да я направиш както си искаш. Има много такива, които се водят от бивши студенти на ФМИ, които сега работят в големи компании, и предоставят супер практично и готино обучение. За някои неща даже не можеш да намериш в България курсове, като [url https://intranet.fmi.uni-sofia.bg/index.php/s/uGI4XDReO3WoUok Реализация на езици за програмиране], където се разглежда как се правят компилатори или [url https://intranet.fmi.uni-sofia.bg/index.php/s/v2v4WlP2GdDbWtb Употреба и скриптиране на Vim], където подробно поглежда един от най-добрите текстови редактори някога създавани. @@ -357,7 +357,7 @@ ##### Зимен семестър -=[Алгебра 1]=: пълното име е линейна алгебра. +[=Алгебра 1=]: пълното име е линейна алгебра. Занимава се главно с линейни уравнения (ax + by + ... + mz = k), обаче интересното идва като изследваме операции върху тях и ги навържем в пространства. Много фундаментален предмет, използват се поне части от него в много клони на математиката и инженерството (защото много неща могат да се моделират с нея). Има употреби в machine learning, в компютърната графика, в алгоритми за препоръки (търсачки примерно), обработка на изображения и много други. @@ -365,7 +365,7 @@ Има по една малка задача всяка седмица, но не са трудни, изисква постоянство. Предметът се минава без твърде много трудности, лекционните записки са много прецизно написани и упражненията са супер. -=[Диференциално и интегрално смятане 1]=: с други думи, реален анализ. +[=Диференциално и интегрално смятане 1=]: с други думи, реален анализ. Главно разглеждаме свойства и операции върху функции и редици числа. В училище учим производни; глаголът да правиш производни разговорно може да се нарече "производиране", обаче терминът е диференциране. Интегрирането е обраното действие на диференцирането, тоест намирането на функция, имайки само нейната производна. @@ -376,7 +376,7 @@ Главната цедка е теорията, на която имаш теоретични задачи, при които дори за 3ка ще трябва да приложиш малко усет към предмета. Като цяло просто изискванията са високи, иначе екипа са готини и бих казал, че оценяването е честно. -=[Дискретни структури]=: този предмет е малко смесица от три предмета - булева алгебра, увод в теория на множествата, комбинаторика и теория на графите. +[=Дискретни структури=]: този предмет е малко смесица от три предмета - булева алгебра, увод в теория на множествата, комбинаторика и теория на графите. От всичките математики, това е може би най-важната за програмиране. В определен смисъл на думата, ДИС се занимава с безкрайно много и безкрайно малки елементи: на една функция може да и подадеш числото 1, но и 1.1, и 1.11 и так. нат., без проблем. Обаче ДСТР разглежда дискретни обекти, тоест някакъв краен брой конкретни неща. @@ -397,7 +397,7 @@ Ама трябва да предупредя, че не получаваш точки за половинчати решения, като цяло или си решил задачата коректно или не. Бих казал че при този предмет се появяват нечестности или прекомерно високи изисквания на моменти, но се минава. -=[Увод в програмирането]=, неговото значение трябва да е очевидно. +[=Увод в програмирането=], неговото значение трябва да е очевидно. Изучава се C++, макар и някои неща да не са направени по най-добрите начини. Налага се да знаеш и ползваш точно нещата, които ти се преподават и нищо друго. Не бих казал, че е лошо направен, има някакво основание за тази методика, обаче някои неща се разглеждат твърде формално и програмирането не се изучава като динамичен предмет, в който може да решиш проблеми по много начини, а като задача по математика, където се изисква определено решение. @@ -410,9 +410,9 @@ ##### Летен семестър -=[Диференциално и интегрално смятане 2]=: директно продължение на ДИС1. +[=Диференциално и интегрално смятане 2=]: директно продължение на ДИС1. -=[Геометрия]=: истинското име на този предмет е аналитична геометрия и няма нищо общо с училищната евклидова геометрия. +[=Геометрия=]: истинското име на този предмет е аналитична геометрия и няма нищо общо с училищната евклидова геометрия. Разглеждаме пространствата и геометричните обекти като по-абстрактни неща, или по-конкретно, разглеждаме повече числата и зависимостите между конкретни обекти. Централно в компютърната графика и всичко около нея (обработка на изображения, 3D моделиране, ...). @@ -420,7 +420,7 @@ Упражненията са супер, има и много добри записки по тях. Минава се без твърде много проблеми. -=[Езици, автомати и изчислимост]=: вторият най-важен предмет от математиките, на английски се казва Theoretical Computer Science. +[=Езици, автомати и изчислимост=]: вторият най-важен предмет от математиките, на английски се казва Theoretical Computer Science. Занимава се с различни теоретични обекти, които могат да правят изчисления върху текстови низове. Всичко свързано с анализ или шаблони върху текст използва нещата тук, а пък и отвъд. Ако някога си чувал за машина на Тюринг, Тюринг-завършеност на програмни езици или проблемът за спирането, от тука идват. @@ -430,7 +430,7 @@ И както по дискретни структури, асистентите не са консистентни и нивото малко криви. Ама в края на деня преподавателите са готини и не искат да прецакват хора, така че се минава спокойно. -=[Обектно ориентирано програмиране]=: това е най-популярният начин/парадигма за програмиране. +[=Обектно ориентирано програмиране=]: това е най-популярният начин/парадигма за програмиране. Обект е групиране на данни с функциите върху тях, като са изпълнени [url https://en.wikipedia.org/wiki/Object-oriented_design#Object-oriented_concepts няколко свойства]. Кажи-речи всяка компания и всеки модерен програмен език, който се използва в индустрията, поддържа ООП. @@ -444,7 +444,7 @@ ##### Зимен семестър -=[Компютърни архитектури]=: описание на хардуера. +[=Компютърни архитектури=]: описание на хардуера. Малко се доближава и до електротехниката, но се разглеждат много фундаменталните хардуерни компоненти и техните функционалности в един компютър. Разглеждаме основните компонентни схеми за изчисления и хардуерно как се ползват и работят нещата. Не е кой знае колко полезен за средния програмист, освен ако не се занимаваш със системно програмиране, ама е много важен фундамент. @@ -453,7 +453,7 @@ Това е първият предмет при който няма задължителни упражнения, но никой не препоръчва да се ходи на избираемия практикум, понеже не е координиран много добре с лекциите и някои неща стават твърде трудни. Иначе минаването е лесно. -=[Основи на компютърната графика]=: има ли изобщо какво да обяснявам. +[=Основи на компютърната графика=]: има ли изобщо какво да обяснявам. Разглеждаме част от математиката, но повече се занимаваме с 3D моделиране и идеите на сложните неща, не толкова тяхното имплементиране. Минаването е лесно, трябва да си малко консистентен със седмичните задачи обаче. @@ -461,14 +461,14 @@ Презентациите в които се намира материала са перфектно направени и упражненията са много приятни. Ето [url https://boytchev.github.io/scorm/ тук] има редици малки задачки/игри с които можеше да изкараш малък бонус към оценката. -=[Структури от данни и програмиране]=: нещо като въведение в дизайн и анализ на алгоритмите. +[=Структури от данни и програмиране=]: нещо като въведение в дизайн и анализ на алгоритмите. Занимаваме се с някои много важни структури от данни, като стек и опашка, и разглеждаме алгоритми върху тях. Супер важно за всеки програмист. Екипът пак е същия, както при УП и ООП, така че мнението ми продължава, но тук поне изискванията за писане на код са по-основателни. Все пак разглеждаме конкретни структури от данни и алгоритми, ако не ги ползваш в решенията на задачи, малко би се обезсмислила цялата история. -=[Функционално програмиране]=: втората най-използвана парадигма след ООП. +[=Функционално програмиране=]: втората най-използвана парадигма след ООП. Идеята е, че разглеждаме всичко като функции, във всеки момент една функция връща нещо или приема нещо и никъде не пазим състояния. Тоест, една стойност се намира или като аргумент или като върната стойност. Също супер важно да се знае и може. @@ -478,7 +478,7 @@ ##### Летен семестър -=[Алгебра 2]=: дефакто разглеждаме теория на групите, което на английски съм го виждал и като "Modern algebra". +[=Алгебра 2=]: дефакто разглеждаме теория на групите, което на английски съм го виждал и като "Modern algebra". Група е някакво множество от елементи и операция върху тях, като за операцията са изпълнени няколко свойства. Допълнително имаме и пръстен, където вече имаш множество и две операции върху тях. Може би звучи странно, но е една от [url https://www.youtube.com/watch?v=mH0oCDa74tE най-интересните и шантави математики]. @@ -487,7 +487,7 @@ Екипът същия като при Алгебра 1, така че нямам оплаквания. Макар че този път няма седмични задачи - ура! -=[Дизайн и анализ на алгоритми]=: също едно име, което обяснява себе си. +[=Дизайн и анализ на алгоритми=]: също едно име, което обяснява себе си. Разглеждаме методиките за сравняване на алгоритми (асимптотика) и как да докажем тяхната коректност. Също разглеждаме доста основни и често използвани алгоритми, както и се допираме до [url https://en.wikipedia.org/wiki/NP_%28complexity%29 NP сложност]. Още един много важен предмет. @@ -497,7 +497,7 @@ Обаче смятам, че на доста моменти навлиза твърде много в математиката и теорията, и има същите проблеми с оценяването както по ДСТР. Цели 15 човека минаха от първия път, така че нивото е горе-долу същото. -=[Изследване на операциите]=: решава оптимизационни задачи, тоест задачи при които искаш минимум или максимум, като за всяка променлива имаш някакво ограничение (на английски се казва Linear Programming, но няма нищо общо с програмиране). +[=Изследване на операциите=]: решава оптимизационни задачи, тоест задачи при които искаш минимум или максимум, като за всяка променлива имаш някакво ограничение (на английски се казва Linear Programming, но няма нищо общо с програмиране). Една оптимизационна задача е примерно ако имаме фабрики за автомобили, всяка произвеждаща различно количество коли и складове в други градове, с различни капацитети, и имаме цената на пътя между градовете и складовете, как най-евтно ще пренесем всички автомобили в складовете. Има употреба ако се опитваш да решиш такъв тип задачи, но ми се струва от по-безполезните неща за един програмист. @@ -505,7 +505,7 @@ Лекторът е готин. Минаването е лесно, нещата не са супер трудни. -=[Компютърни мрежи]=: пак име, което само се обяснява. +[=Компютърни мрежи=]: пак име, което само се обяснява. Абсолютно всичко свързано с интернет и мрежите, от протоколи до методи за маршрутизация. Като КАРХ не е от най-полезните за ежедневието, но е много важен фундамент. @@ -513,7 +513,7 @@ Както и по други предмети, лектора не иска да ни прецаква, затова минаването не е проблем. Даже бих казал, че е твърде лесно. -=[Операционни системи]=: може би най-важният не-математически предмет, ако беше направен свестно. +[=Операционни системи=]: може би най-важният не-математически предмет, ако беше направен свестно. Имам много силно мнение за него, като цяло предмета се свежда до 70% менижиране на процеси, 20% менижиране на памет и 10% случайни неща. Имаше потенциалът да е от най-добрите предмети в целия бакалавър, ама програмата и изпитването беше наистина зле направено. @@ -539,4 +539,4 @@ 2. Студентстването като изживяване е веднъж в живота, все пак характерът става по-издържлив когато те скъсат по няколко изпита, за които си учил много. 3. Каквото и да си говорим, ФМИ е доста авторитетно учебно заведение, макар и диплома за един програмист да не е задължителна, със сигурност ще помогне значително. -И даже бих аргументирал, че е =[по-добре да следваш една година във ФМИ и да се откажеш, отколкото да следваш 4 години и да завършиш в който и да е друг университет!]= +И даже бих аргументирал, че е [=по-добре да следваш една година във ФМИ и да се откажеш, отколкото да следваш 4 години и да завършиш в който и да е друг университет!=] diff --git a/src/blog/friendship-ended-with-funtoo-now-gentoo-is-my-best-friend/index.du b/src/blog/friendship-ended-with-funtoo-now-gentoo-is-my-best-friend/index.du index 783050b..1c6d67b 100644 --- a/src/blog/friendship-ended-with-funtoo-now-gentoo-is-my-best-friend/index.du +++ b/src/blog/friendship-ended-with-funtoo-now-gentoo-is-my-best-friend/index.du @@ -24,18 +24,18 @@ Here is what happened. Before we begin, I want to take a second and explain some Gentoo/Funtoo terminology: :unordered -- `[emerge]` (as a verb): what does "install" mean? I would argue it means copying a program and the file it depends on somewhere on a system, with the goal of being able to run this program. +- [`emerge`] (as a verb): what does "install" mean? I would argue it means copying a program and the file it depends on somewhere on a system, with the goal of being able to run this program. .p Now, in Gentoo and Funtoo, most programs are compiled from source code, so before you install you download it's source and compile. - For this reason, on such systems you would usually say a certain program/package is *[being emerged, not installed]* (and the words comes from the [url https://wiki.gentoo.org/wiki/Emerge package-manager command-line utility of the same name]). + For this reason, on such systems you would usually say a certain program/package is [*being emerged, not installed*] (and the words comes from the [url https://wiki.gentoo.org/wiki/Emerge package-manager command-line utility of the same name]). -- `[ebuild]` (file): the exact steps needed to emerge a package differ from one project to another, but how do you manage packages then? +- [`ebuild`] (file): the exact steps needed to emerge a package differ from one project to another, but how do you manage packages then? The solution is that when you try to emerge something, a special file with detailed instructions is looked up: an ebuild file. - repository tree: the collection of all ebuilds -- `[use]` flags: every program can be built with different flags (aka options), which enable or disable certain features from being available in the result package. +- [`use`] flags: every program can be built with different flags (aka options), which enable or disable certain features from being available in the result package. For example, the text editor [url https://packages.gentoo.org/packages/app-editors/vim vim] supports sound, but not everyone would want to have that feature. @@ -49,18 +49,18 @@ Most packages and their dependencies on Funtoo go unmaintained and untested for Python was stuck at version 3.7, while a lot of packages like barrier, libplacebo, mpv and pulseeffects[$packages-in-repo-tree] required[$required-3.8] at least 3.8. So, with a lot of effort and poking around, I got python 3.8 to work, just barely. -What's even better is that eventually I reached an =[unfixable]= circular python dependency (between dev-python/packaging and dev-python/setuptools). +What's even better is that eventually I reached an [=unfixable=] circular python dependency (between dev-python/packaging and dev-python/setuptools). 'footnote glibc This point may not be completely fair, since Funtoo has a system for [url https://web.archive.org/web/20230528115518/https://projects.funtoo.org/metatools/docs/autogen.html ebuild generation], which means that they might've made configuration changes and/or applied patches which "fix" that version, but still, it really isn't a good look. -Another problem child was glibc, it is *[currently]* at [url https://github.com/funtoo/core-kit/tree/1.4-release/sys-libs/glibc version 2.33-r2], which under Gentoo [url https://gitweb.gentoo.org/repo/gentoo.git/tree/profiles/package.mask#n542 is officially masked and discouraged for usage][$glibc] and wouldn't you know it, also prevents some packages from being compiled (mainly I remember ungoogled-chromium). +Another problem child was glibc, it is [*currently*] at [url https://github.com/funtoo/core-kit/tree/1.4-release/sys-libs/glibc version 2.33-r2], which under Gentoo [url https://gitweb.gentoo.org/repo/gentoo.git/tree/profiles/package.mask#n542 is officially masked and discouraged for usage][$glibc] and wouldn't you know it, also prevents some packages from being compiled (mainly I remember ungoogled-chromium). There were a lot more problematic packages, but I've forgotten most details. What I do remember is that the day I decided to hop to Gentoo, I tried to update my system and yet again I got some sort of issue, either a package couldn't compile properly or there was some dependency conflict. That was preceded by my unsuccessful attempts at getting the kicad package to work a couple of days prior. At that point, this had become completely normal. -=[But]= Funtoo shouldn't be blamed for it! +[=But=] Funtoo shouldn't be blamed for it! ## I didn't follow the wolf pack philosophy @@ -68,20 +68,20 @@ On the [url https://www.funtoo.org/Welcome Welcome] page of Funtoo's website, in This is essentially a document describing how a member of the community should behave, and I didn't follow it. Any member of the pack is supposed to: .unordered -- =[Be Mindful of the Pack]= by tackling challenges with the community\n +- [=Be Mindful of the Pack=] by tackling challenges with the community\n but as I found (package) challenges, I tackled them on my own, not trying to consult anyone or ask for help -- =[Be Interconnected]= by supporting and being supported by the community\n +- [=Be Interconnected=] by supporting and being supported by the community\n but I didn't connect with anyone on my issues -- =[Howl]= by expressing their needs and sharing their "adventures"\n +- [=Howl=] by expressing their needs and sharing their "adventures"\n but I didn't express them and didn't share the work I've done Or more simply put, Funtoo is a small project, and you need to communicate with others to get things done. 'footnote kicad On that aforementioned kicad package, drobbins, the benevolent dictator for life of Funtoo, categorized it as a [url https://bugs.funtoo.org/browse/FL-8435?focusedId=52907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-52907 package which people aren't interested in]. -Another way to look at it is that in a project of this scale, what gets supported is what the community uses, so in a way, I was trying to use Funtoo in the *[wrong]* way. +Another way to look at it is that in a project of this scale, what gets supported is what the community uses, so in a way, I was trying to use Funtoo in the [*wrong*] way. This may sound ridiculous, but then again, they aren't making a project which "just works" for everyone (like Ubuntu or Linux Mint), this is a project by the community for the community. -You can't expect them to support everything that a big-scale distro does, like Gentoo, with a fraction of the manpower, so if nobody supports a package (which exists in the repository tree) that doesn't work and you don't at least speak up, it will probably stay broken[$kicad] (this kind of relates to the =[Is Territorial]= point in the philosophy). +You can't expect them to support everything that a big-scale distro does, like Gentoo, with a fraction of the manpower, so if nobody supports a package (which exists in the repository tree) that doesn't work and you don't at least speak up, it will probably stay broken[$kicad] (this kind of relates to the [=Is Territorial=] point in the philosophy). However, in my defense, I didn't open bug reports or create forum posts because my issues weren't "directly" related to Funtoo, or a normal Funtoo installation. Most of the time I would have an issue with a package, then get it's Gentoo counterpart, try to get all dependencies working one by one, and it will fail with some unsearchable error. @@ -146,8 +146,8 @@ Unfortunately, for Gentoo it's the opposite effect, I couldn't compile most pack .quote package.use > make.conf -There is a big emphasis on writing your use flags in a separate `[/etc/portage/package.use]` file (or make it a folder and add use flags in different subfiles), and to try and change `[/etc/portage/make.conf]` as little as possible. -I generally believe this is a significantly better system than stuffing everything into `[make.conf]`, and it isn't pushed that hard on Gentoo. +There is a big emphasis on writing your use flags in a separate [`/etc/portage/package.use`] file (or make it a folder and add use flags in different subfiles), and to try and change [`/etc/portage/make.conf`] as little as possible. +I generally believe this is a significantly better system than stuffing everything into [`make.conf`], and it isn't pushed that hard on Gentoo. That said, Gentoo still supports it, so I'm not missing out, but I probably wouldn't have used it. diff --git a/src/blog/how-to-encrypt-email/index.du b/src/blog/how-to-encrypt-email/index.du index 5518d55..ec9d546 100644 --- a/src/blog/how-to-encrypt-email/index.du +++ b/src/blog/how-to-encrypt-email/index.du @@ -42,29 +42,29 @@ By far, the easiest way to do this is via the website [url https://pgptool.org/ As an alternative, you can use a desktop program. The most popular one is [url https://www.gnupg.org/ GNU Privacy Guard] (GPG for short). It is [url https://gnupg.org/download/#binary available] on most desktop operating systems, including [url https://gpg4win.org/download.html Windows] and [url https://gpgtools.org/ MacOS]. -The *[Windows]* version comes with a graphical user interface, so it's easiest to use that: +The [*Windows*] version comes with a graphical user interface, so it's easiest to use that: :ordered 1. Open the application "Kleopatra" -2. Click on `[File]` -> `[New Certificate]` +2. Click on [`File`] -> [`New Certificate`] -3. Input your details and press `[OK]` +3. Input your details and press [`OK`] .bulleted - - Feel free to click on `[Advanced Settings]` and look if if the value for `[RSA]` is `[4096 bit]`, the value for `[+ RSA]` is enabled and is `[4096 bits]`, and finally both `[Signing]` and `[Authentication]` are selected + - Feel free to click on [`Advanced Settings`] and look if if the value for [`RSA`] is [`4096 bit`], the value for [`+ RSA`] is enabled and is [`4096 bits`], and finally both [`Signing`] and [`Authentication`] are selected -4. On the next screen, press `[Create]` +4. On the next screen, press [`Create`] 5. You'll be asked for a password. Make one up, and enter it, but do not forget it! .bulleted - - The password is used for your private key. If anyone gets ahold if it, they =[will]= be able to impersonate you. A password makes sure that doesn't happen, at least until you tell everyone that your key was leaked. + - The password is used for your private key. If anyone gets ahold if it, they [=will=] be able to impersonate you. A password makes sure that doesn't happen, at least until you tell everyone that your key was leaked. -6. On the final screen, click `[Finish]` +6. On the final screen, click [`Finish`] -7. To help with the next chapter, we'll extract your public key. In "Kleopatra" you should see a line, containing your name and email. Right-click on it, and select `[Export Certificate]`. +7. To help with the next chapter, we'll extract your public key. In "Kleopatra" you should see a line, containing your name and email. Right-click on it, and select [`Export Certificate`]. -On *[Linux]* and *[MacOS]*, you can use the command line: +On [*Linux*] and [*MacOS*], you can use the command line: :ordered 1. Enter this command in your favorite terminal @@ -90,7 +90,7 @@ Currently, the only one that provides free certificates is [url https://www.acta You should now have a text file with your public key in it. When you want to send an encrypted email to someone, ask them for their public key, and meanwhile send them your public key. It doesn't matter how you do that, even if it's with unencrypted emails. -Remember, =[never]= send your =[private]= key to anyone! +Remember, [=never=] send your [=private=] key to anyone! ## Configuring clients @@ -98,13 +98,13 @@ Now we need to configure your email application to automatically encrypt and dec When writing a message, don't forget to check if encryption is turned on for this email! On most clients, in the compose window, you'll have to select an option to enable encryption, but others do that automatically. -*[Freemium means it has a free and a paid tier. Premium means you have to pay for it. FOSS means it's free and open source. FreemiumOSS means it is free and open source, but also has paid tiers.]* +[*Freemium means it has a free and a paid tier. Premium means you have to pay for it. FOSS means it's free and open source. FreemiumOSS means it is free and open source, but also has paid tiers.*] :table_6 -'define 1 ^[[url #1 1]]^ -'define 2 ^[[url #2 2]]^ -'define 3 ^[[url #3 3]]^ -'define * ^[[url #* *]]^ +'define 1 [^[url #1 1]^] +'define 2 [^[url #2 2]^] +'define 3 [^[url #3 3]^] +'define * [^[url #* *]^] |= Client |= Type @@ -282,7 +282,7 @@ When writing a message, don't forget to check if encryption is turned on for thi |: [url https://github.com/M66B/FairEmail/blob/master/FAQ.md Yes][$*] -<span id="1">^[1]^</span> Available with an extension/plugin\n -<span id="2">^[2]^</span> Available in a paid version of the software (assuming the software is Freemium; this is true for all Premium software)\n -<span id="3">^[3]^</span> Available with a Premium account (even if the software is Free)\n -<span id="*">^[*]^</span> You can read S/MIME messages, but signing and encrypting is a pro feature +<span id="1">[^1^]</span> Available with an extension/plugin\n +<span id="2">[^2^]</span> Available in a paid version of the software (assuming the software is Freemium; this is true for all Premium software)\n +<span id="3">[^3^]</span> Available with a Premium account (even if the software is Free)\n +<span id="*">[^*^]</span> You can read S/MIME messages, but signing and encrypting is a pro feature diff --git a/src/blog/how-to-use-jira/bug.du b/src/blog/how-to-use-jira/bug.du index fcd51e3..d776367 100644 --- a/src/blog/how-to-use-jira/bug.du +++ b/src/blog/how-to-use-jira/bug.du @@ -10,12 +10,12 @@ 'define next_link ./releases.html Releases [$pagination_middle] -The Bug Tracking template is completely different from the [url ./scrum.html Scrum] and [url ./kanban.html Kanban] templates, because it =[offers only issue tracking]=. +The Bug Tracking template is completely different from the [url ./scrum.html Scrum] and [url ./kanban.html Kanban] templates, because it [=offers only issue tracking=]. -=[There are no boards, no cards, no backlog]=. All issues are accessed from the `[Issues]` page from the sidebar. +[=There are no boards, no cards, no backlog=]. All issues are accessed from the [`Issues`] page from the sidebar. [image ./img/issues-sidebar.png] -That's why this template is =[available only when creating a project]=. +That's why this template is [=available only when creating a project=]. -Of course, =[you can add boards at any time]=, but this project template doesn't add any by itself. +Of course, [=you can add boards at any time=], but this project template doesn't add any by itself. diff --git a/src/blog/how-to-use-jira/cards.du b/src/blog/how-to-use-jira/cards.du index 03d0ed4..8a5f1b7 100644 --- a/src/blog/how-to-use-jira/cards.du +++ b/src/blog/how-to-use-jira/cards.du @@ -22,7 +22,7 @@ 3. [url #issue-flagging Issue flagging] 4. [url #basic-issue-information Basic issue information] -=[Each issue is represented as an object with properties]=. More specifically, these objects are called 'cards'. +[=Each issue is represented as an object with properties=]. More specifically, these objects are called 'cards'. [image ./img/kanban-cards.png] @@ -33,11 +33,11 @@ Each card has the following properties: [image ./img/fields-cards.png] :unordered -- =[Project]= - the [url ./projects.html project] this card is stored in +- [=Project=] - the [url ./projects.html project] this card is stored in [image ./img/project-create-card.png] -- =[Issue type]= - the basic purpose of an issue (Improvement, Bug, ...) +- [=Issue type=] - the basic purpose of an issue (Improvement, Bug, ...) [image ./img/issue-types.png] @@ -53,109 +53,109 @@ Each card has the following properties: - [image ./img/sub-task-type.png Sub-task] - an issue that is directly connected to another issue. This is used for when a given issue needs to be broken down into separate even smaller issues. -- =[Summary]= - a (required) brief explanation of the issue +- [=Summary=] - a (required) brief explanation of the issue [image ./img/summary-create-card.png] -- =[Description]= - detailed explanation of the issue +- [=Description=] - detailed explanation of the issue [image ./img/description-create-card.png] -- =[Reporter]= - person who created the issue +- [=Reporter=] - person who created the issue [image ./img/reporter-create-card.png] -- =[Assignee]= - person who will work on the issue +- [=Assignee=] - person who will work on the issue [image ./img/assignee-create-card.png] -- =[Labels]= - tags with which you can organise even more the issue +- [=Labels=] - tags with which you can organise even more the issue [image ./img/label-create-card.png] -- =[Epic link]= - link of issue with type Epic +- [=Epic link=] - link of issue with type Epic [image ./img/epic-link-create-card.png] ## Creating -To create a card yourself, you need to =[press the `[Create]` button on the top bar]=. +To create a card yourself, you need to [=press the [`Create`] button on the top bar=]. [image ./img/create-header.png] ## Viewing -=[All]= cards (issues) can be viewed from a [url ./projects.html project]'s side menu, under 'Issues'. +[=All=] cards (issues) can be viewed from a [url ./projects.html project]'s side menu, under 'Issues'. [image ./img/issues-sidebar.png] -Of course, they can also be viewed through =[[url ./filters.html filters]]= and a =[[url ./projects.html project]'s board]=. +Of course, they can also be viewed through [=[url ./filters.html filters]=] and a [=[url ./projects.html project]'s board=]. ## How to use -By default, opening a card presents, at the top, it's =[key]= (think of it as an ID), +By default, opening a card presents, at the top, it's [=key=] (think of it as an ID), [image ./img/card-key.png] -it's =[summary]= below it, +it's [=summary=] below it, [image ./img/card-summary.png] -options for adding =[attachments]=, =[subtasks]=, =[linking issues]= and =[adding more apps]= (think of apps like extensions), +options for adding [=attachments=], [=subtasks=], [=linking issues=] and [=adding more apps=] (think of apps like extensions), [image ./img/card-attach-subtask.png] -following are the =[description]=, =[actual attachments]=, =[subtasks]=, =[linked issues]=, etc., +following are the [=description=], [=actual attachments=], [=subtasks=], [=linked issues=], etc., [image ./img/desc-att-sub-link.png] -and at the bottom you have the =[activity]=, consisting of =[comments]= on the issue, +and at the bottom you have the [=activity=], consisting of [=comments=] on the issue, [image ./img/activity-comments.png] -=[history]= of things that have happened to that issue, +[=history=] of things that have happened to that issue, [image ./img/activity-history.png] -and =[work logs]= (a bit later we talk about them in more detail). +and [=work logs=] (a bit later we talk about them in more detail). [image ./img/activity-work-log.png] ### Right side -To the right side, you have all of the different =[properties]= (some fields without a value will be hidden). +To the right side, you have all of the different [=properties=] (some fields without a value will be hidden). [image ./img/card-right-side.png] -On the top right you can change =[watch options]= ([url https://www.idalko.com/jira-watch-issues/ watching an issue] means you get notified by all changes done to it), you can =[share]= the card and do =[actions]= (the three dots). +On the top right you can change [=watch options=] ([url https://www.idalko.com/jira-watch-issues/ watching an issue] means you get notified by all changes done to it), you can [=share=] the card and do [=actions=] (the three dots). [image ./img/card-top-right.png] -=[Actions]= are things you can do to the whole card, like moving or deleting it. +[=Actions=] are things you can do to the whole card, like moving or deleting it. [image ./img/card-actions.png] -The most notable options are `[[url https://confluence.atlassian.com/jirasoftwarecloud/logging-work-on-issues-902499028.html Log work]]` and `[Add flag]`. +The most notable options are [`[url https://confluence.atlassian.com/jirasoftwarecloud/logging-work-on-issues-902499028.html Log work]`] and [`Add flag`]. ### Work log -In Jira, you can =[estimate how long an issue will take for it to be resolved]=. This is done through =[logging work]=. +In Jira, you can [=estimate how long an issue will take for it to be resolved=]. This is done through [=logging work=]. -In the `[Log work]` screen, you'll be met with a `[Time spent]` and `[Time remaining]` fields, that you'll need to fill with the appropriate information. +In the [`Log work`] screen, you'll be met with a [`Time spent`] and [`Time remaining`] fields, that you'll need to fill with the appropriate information. [image ./img/time-tracking.png] -The time remaining takes a =[default]= value from the =[previous time log]=, so you don't need to specify it every time. +The time remaining takes a [=default=] value from the [=previous time log=], so you don't need to specify it every time. ### Issue flagging -A =[flagged issue]= is an issue that is very important. Flagged issues are displayed in yellow to signify their needed attention. +A [=flagged issue=] is an issue that is very important. Flagged issues are displayed in yellow to signify their needed attention. [image ./img/flagged-card.png] ### Basic issue information -On the bottom right you can see =[when the issue was created]= and =[when it was last updated]=. You can also access the field configuration menu from the `[Configure]` button. It won't be covered in this tutorial, you can read about it [url https://confluence.atlassian.com/adminjiracloud/changing-a-field-configuration-844500798.html here]. +On the bottom right you can see [=when the issue was created=] and [=when it was last updated=]. You can also access the field configuration menu from the [`Configure`] button. It won't be covered in this tutorial, you can read about it [url https://confluence.atlassian.com/adminjiracloud/changing-a-field-configuration-844500798.html here]. [image ./img/time-and-configure.png] diff --git a/src/blog/how-to-use-jira/components.du b/src/blog/how-to-use-jira/components.du index c696e62..5f22167 100644 --- a/src/blog/how-to-use-jira/components.du +++ b/src/blog/how-to-use-jira/components.du @@ -15,15 +15,15 @@ 1. [url #creating-and-editing Creating and editing] 2. [url #adding-issues Adding issues] -Components are =[yet another way to group issues together]=. They don't have any specific meaning like versions, their usage depends on the project's organisation. +Components are [=yet another way to group issues together=]. They don't have any specific meaning like versions, their usage depends on the project's organisation. ## Creating and editing -Creating and editing them is done from the =[`[Components]` menu in the sidebar]=. +Creating and editing them is done from the [=[`Components`] menu in the sidebar=]. [image ./img/components-sidebar.png] -Creating one is done through the button on the top right (in the center if you don't have any components) by the name of `[Create component]`. +Creating one is done through the button on the top right (in the center if you don't have any components) by the name of [`Create component`]. [image ./img/create-component-empty.png] @@ -33,17 +33,17 @@ Clicking on it presents you with a screen where you input it's information. [image ./img/create-component-page.png] -=[A name is the only requirement]=. You can also add a =[description]=, =[a lead(er) for the component]= and =[person who gets assigned to an issue by default]=. +[=A name is the only requirement=]. You can also add a [=description=], [=a lead(er) for the component=] and [=person who gets assigned to an issue by default=]. ## Adding issues -Adding an issue to a component can be done either =[when creating it]= or =[when viewing it]=. +Adding an issue to a component can be done either [=when creating it=] or [=when viewing it=]. -=[Right under the summary]=, there is a place for indicating a component, named `[Components]`. +[=Right under the summary=], there is a place for indicating a component, named [`Components`]. [image ./img/components-create-card.png] -When viewing an issue, you can add one from the `[Components]` field to the right (you might need to first click on `[Show more fields]`). +When viewing an issue, you can add one from the [`Components`] field to the right (you might need to first click on [`Show more fields`]). [image ./img/show-fields.png] diff --git a/src/blog/how-to-use-jira/dashboards.du b/src/blog/how-to-use-jira/dashboards.du index ab46ac0..ddac024 100644 --- a/src/blog/how-to-use-jira/dashboards.du +++ b/src/blog/how-to-use-jira/dashboards.du @@ -14,52 +14,52 @@ 1. [url #adding-a-dashboard Adding a dashboard] 2. [url #adding-gadgets Adding gadgets] -Dashboards are a =[place where you can view a lot of information]=. +Dashboards are a [=place where you can view a lot of information=]. [image ./img/default-dashboard.png] -Dashboards are composed of =[gadgets]=. +Dashboards are composed of [=gadgets=]. [image ./img/gadgets.png] -Gadgets have functionality for =[displaying certain information]=, like `[Average Age Chart]` or `[Issues in progress]`. Each gadget can be setup to =[take information from one or more projects and/or saved filters]=. +Gadgets have functionality for [=displaying certain information=], like [`Average Age Chart`] or [`Issues in progress`]. Each gadget can be setup to [=take information from one or more projects and/or saved filters=]. ## Adding a dashboard -Dashboard can be added from the top bar, under `[Create dashboard]` in the `[Dashboards]` menu +Dashboard can be added from the top bar, under [`Create dashboard`] in the [`Dashboards`] menu [image ./img/create-dashboard-top.png] -or, if you are already in a dashboard, from `[Create dashboard]` in the three dots menu. +or, if you are already in a dashboard, from [`Create dashboard`] in the three dots menu. [image ./img/create-dashboard-dots.png] ## Adding gadgets -=[Note]=: you cannot add gadgets to the default dashboard. +[=Note=]: you cannot add gadgets to the default dashboard. -You can add gadgets either =[through the `[Add gadget]` button in the top right]= +You can add gadgets either [=through the [`Add gadget`] button in the top right=] [image ./img/add-gadget-top.png] -or, =[if you don't have any gadets]=, =[from the `[add a new gadget]` message(s)]=. +or, [=if you don't have any gadets=], [=from the [`add a new gadget`] message(s)=]. [image ./img/add-a-gadget.png] -After that, you are greeted by a window that =[shows all of the avalable ones]= (you might need to =[press `[Load all gadgets]`]=). +After that, you are greeted by a window that [=shows all of the avalable ones=] (you might need to [=press [`Load all gadgets`]=]). [image ./img/load-all.png] [image ./img/add-gadget.png] -Adding a gadget is as simple as clicking the button `[Add gadget]` next to the name of the gadget you want to add. +Adding a gadget is as simple as clicking the button [`Add gadget`] next to the name of the gadget you want to add. [image ./img/introduction-add.png] -After it is added, you'll =[need to configure it]=, usually a gadget =[requires atleast a filter/project]=. +After it is added, you'll [=need to configure it=], usually a gadget [=requires atleast a filter/project=]. [image ./img/bubble.png] -Options for different gadgets can be found on =[their top right corner, in the three dots menu]=. +Options for different gadgets can be found on [=their top right corner, in the three dots menu=]. [image ./img/bubble-dots.png] diff --git a/src/blog/how-to-use-jira/filters.du b/src/blog/how-to-use-jira/filters.du index 0ec6a9d..f66b78c 100644 --- a/src/blog/how-to-use-jira/filters.du +++ b/src/blog/how-to-use-jira/filters.du @@ -14,31 +14,31 @@ 1. [url #criteria Criteria] 2. [url #jql JQL] -=[Filters work like an advanced issue search that you can save]=. With filters you filter issues from chosen project(s) by their properties (status, type, start date, etc.). +[=Filters work like an advanced issue search that you can save=]. With filters you filter issues from chosen project(s) by their properties (status, type, start date, etc.). -Making filters is done through the `[Advanced issue search]` page, from the `[Filters]` menu. +Making filters is done through the [`Advanced issue search`] page, from the [`Filters`] menu. [image ./img/filters-advanced-issue-search.png] ## Criteria -From here you can see some criteria: `[Project]`, `[Type]`, `[Status]`, `[Assignee]`. +From here you can see some criteria: [`Project`], [`Type`], [`Status`], [`Assignee`]. [image ./img/criteria-advanced-issue-search.png] -Clicking on the criteria will reveal what options you can choose for it. Access to more criteria can be obtained via the `[+ More]` menu. +Clicking on the criteria will reveal what options you can choose for it. Access to more criteria can be obtained via the [`+ More`] menu. [image ./img/plus-more-advanced-issue-search.png] -After configuring your desired options, you can =[save the filter]= and use it later. To do so, simply click on `[Save as]` and enter a name for it. +After configuring your desired options, you can [=save the filter=] and use it later. To do so, simply click on [`Save as`] and enter a name for it. [image ./img/save-as-advanced-issue-search.png] [image ./img/save-filter-filters-advanced-issue-search.png] -You can view all of your filters from the conveniently named `[View all filters]` option in the `[Filters]` menu. +You can view all of your filters from the conveniently named [`View all filters`] option in the [`Filters`] menu. [image ./img/view-all-filters-advanced-issue-search.png] ## JQL -You can do =[more advanced search]= through `[JQL]` (Jira Query Language), but we won't be covering this topic. I can recommend [url https://www.atlassian.com/blog/jira-software/jql-the-most-flexible-way-to-search-jira-14 this article] on the subject. +You can do [=more advanced search=] through [`JQL`] (Jira Query Language), but we won't be covering this topic. I can recommend [url https://www.atlassian.com/blog/jira-software/jql-the-most-flexible-way-to-search-jira-14 this article] on the subject. diff --git a/src/blog/how-to-use-jira/index.du b/src/blog/how-to-use-jira/index.du index a1b3b0f..9ea578d 100644 --- a/src/blog/how-to-use-jira/index.du +++ b/src/blog/how-to-use-jira/index.du @@ -72,4 +72,4 @@ It has a lot of features that can be quite overwhelming for new comers, especially these who are new to project management software. That's why I'm writing this tutorial. -=[Note]=: certain actions can be done only from a project administrator +[=Note=]: certain actions can be done only from a project administrator diff --git a/src/blog/how-to-use-jira/kanban.du b/src/blog/how-to-use-jira/kanban.du index 5e5eb00..0a6e707 100644 --- a/src/blog/how-to-use-jira/kanban.du +++ b/src/blog/how-to-use-jira/kanban.du @@ -15,7 +15,7 @@ 1. [url #create-board Create board] 2. [url #backlog Backlog] -Kanban is a =[way for visually organising work items]= (issues in our case). Kanban consists of =[columns]= and =[cards]=, where cards are the work items and are =[moved from one column to another]= depending on the situation. This should sound =[familiar]=, because that is how [url ./projects.md Boards] work. +Kanban is a [=way for visually organising work items=] (issues in our case). Kanban consists of [=columns=] and [=cards=], where cards are the work items and are [=moved from one column to another=] depending on the situation. This should sound [=familiar=], because that is how [url ./projects.md Boards] work. In a projects that uses the kanban template, boards can access directly all of the available issues. @@ -23,16 +23,16 @@ This tutorial focuses on the basics, but you can find a lot of information in [u ## Create board -This template can be chosen when =[creating a project]= +This template can be chosen when [=creating a project=] [image ./img/choose-classic-template.png] -and =[from the `[Create board]` screen]=. +and [=from the [`Create board`] screen=]. [image ./img/scrum-kanban-board.png] ## Backlog -In kanban, =[the backlog is just another column in your board(s)]=. It can be removed entirely. +In kanban, [=the backlog is just another column in your board(s)=]. It can be removed entirely. [image ./img/backlog-kanban.png] diff --git a/src/blog/how-to-use-jira/pages.du b/src/blog/how-to-use-jira/pages.du index b2e0466..5340091 100644 --- a/src/blog/how-to-use-jira/pages.du +++ b/src/blog/how-to-use-jira/pages.du @@ -10,13 +10,13 @@ 'define next_link ./components.html Components [$pagination_middle] -=[Pages are a place for documents for your team]=. The goal is to have a centralised location where everyone in your team can share knowledge. +[=Pages are a place for documents for your team=]. The goal is to have a centralised location where everyone in your team can share knowledge. [image ./img/test-page.png] -Pages are powered by another Atlasian product, named `[Confluence]`. It is a =[subscription-based software]=, but it does also offer a free 30-day trial. +Pages are powered by another Atlasian product, named [`Confluence`]. It is a [=subscription-based software=], but it does also offer a free 30-day trial. -=[All documents]= (pages) that you write are =[organised into `[Spaces]`]=. When creating a page you can choose one of many templates or just start off with a blank one. +[=All documents=] (pages) that you write are [=organised into [`Spaces`]=]. When creating a page you can choose one of many templates or just start off with a blank one. -=[Confluence won't be covered in this tutorial]=. You can read more about it [url https://www.atlassian.com/software/confluence/guides/get-started/set-up here]. +[=Confluence won't be covered in this tutorial=]. You can read more about it [url https://www.atlassian.com/software/confluence/guides/get-started/set-up here]. diff --git a/src/blog/how-to-use-jira/projects.du b/src/blog/how-to-use-jira/projects.du index ecf5fe9..fd64c86 100644 --- a/src/blog/how-to-use-jira/projects.du +++ b/src/blog/how-to-use-jira/projects.du @@ -23,59 +23,59 @@ -In short, =[projects are a collection of issues]= with added functionality for =[organising them, getting statistics, etc]=. +In short, [=projects are a collection of issues=] with added functionality for [=organising them, getting statistics, etc=]. [image ./img/projects.png] ## Creating a project -To create a project, either =[click on `[Create project]` from the menu `[Projects]` in the top bar]=, +To create a project, either [=click on [`Create project`] from the menu [`Projects`] in the top bar=], [image ./img/create-project-top.png] -or =[click on the `[Create project]` button in the `[View all projects]` page]=. +or [=click on the [`Create project`] button in the [`View all projects`] page=]. [image ./img/view-all-projects-top.png] [image ./img/create-project.png] -=[Note]=: when you =[have created your account]= the first thing you'll see is the `[Create project]` page. +[=Note=]: when you [=have created your account=] the first thing you'll see is the [`Create project`] page. -You'll be met by the `[Choose project type]` screen. From here choose `[Classic project]`, in this tutorial the `[Next-gen project]` types =[won't be covered]=. +You'll be met by the [`Choose project type`] screen. From here choose [`Classic project`], in this tutorial the [`Next-gen project`] types [=won't be covered=]. [image ./img/choose-project-type.png] -After that you'll need to put a =[name]= for your project, set a =[key]= (used as an ID for issues ; it is automatically generated, but you can change it if you want) and select a =[template]=. +After that you'll need to put a [=name=] for your project, set a [=key=] (used as an ID for issues ; it is automatically generated, but you can change it if you want) and select a [=template=]. [image ./img/create-project-new.png] -This tutorial covers =[only]= the three classic software templates: =[[url ./kanban.html Kanban]]=, =[[url ./scrum.html Scrum]]= and =[[url ./bug.html Bug tracking]]=. +This tutorial covers [=only=] the three classic software templates: [=[url ./kanban.html Kanban]=], [=[url ./scrum.html Scrum]=] and [=[url ./bug.html Bug tracking]=]. [image ./img/choose-classic-template.png] -In a nutshell, =[templates]= govern how =[boards and issues should work together]=. Later in the tutorial we cover the differences between these templates. +In a nutshell, [=templates=] govern how [=boards and issues should work together=]. Later in the tutorial we cover the differences between these templates. Projects also have [url ./releases.html Releases], [url ./pages.html Pages] and [url ./components.html Components], that are also explored. ## Boards -Each project contains, amongst many other things, boards. =[Boards are a way to better organise results from [url ./filters.html filters]]=. By default every project gets a board with a filter for all of the project's issues. +Each project contains, amongst many other things, boards. [=Boards are a way to better organise results from [url ./filters.html filters]=]. By default every project gets a board with a filter for all of the project's issues. ### Columns -=[Boards are divided into columns]= that contain the cards (issues). A card can move =[freely]= from one column to another. +[=Boards are divided into columns=] that contain the cards (issues). A card can move [=freely=] from one column to another. [image ./img/SOD.png] -To illustrate how this could be useful, let's say we have three columns: `[TO DO]`, `[DOING]` and `[DONE]`. +To illustrate how this could be useful, let's say we have three columns: [`TO DO`], [`DOING`] and [`DONE`]. [image ./img/todo-doing-done.png] -When you create an issue you initially put it in the `[TO DO]` column. After someone has started working on it, they put the issue in the `[DOING]` column. Finally, when the issue is resolved, it is put in the `[DONE]` column. +When you create an issue you initially put it in the [`TO DO`] column. After someone has started working on it, they put the issue in the [`DOING`] column. Finally, when the issue is resolved, it is put in the [`DONE`] column. -Of course, the name, quantity and purpose of different columns =[depend on the project's organisation]=. +Of course, the name, quantity and purpose of different columns [=depend on the project's organisation=]. -Adding and removing columns can be done from the `[Columns]` tab in the `[Board settings]` menu (three dots on the top right of a board). +Adding and removing columns can be done from the [`Columns`] tab in the [`Board settings`] menu (three dots on the top right of a board). [image ./img/board-settings.png] @@ -83,17 +83,17 @@ Adding and removing columns can be done from the `[Columns]` tab in the `[Board ### Adding more boards to a project -You can also add to a project as many =[[url ./scrum.html Scrum]]= and =[[url ./kanban.html Kanban]]= templated boards as you want. +You can also add to a project as many [=[url ./scrum.html Scrum]=] and [=[url ./kanban.html Kanban]=] templated boards as you want. -This can be done, either while in a board, from =[clicking the three dots and choosing `[Create board]`]= +This can be done, either while in a board, from [=clicking the three dots and choosing [`Create board`]=] [image ./img/create-board.png] -or =[in the sidebar, from the `[Board]` menu]=. +or [=in the sidebar, from the [`Board`] menu=]. [image ./img/sidebar-create-board.png] -After that, you are met with the `[Create a board]` window, where you can choose your template. +After that, you are met with the [`Create a board`] window, where you can choose your template. [image ./img/scrum-kanban-board.png] @@ -102,42 +102,42 @@ Once you've made your choice, you will be met with three options: [image ./img/board-from.png] :unordered -- =[Board created with new Software project]= - creates a new project with a new board (has the name of the project). +- [=Board created with new Software project=] - creates a new project with a new board (has the name of the project). [image ./img/npb.png] -- =[Board from existing project]= - creates a board that gets the filter from another project +- [=Board from existing project=] - creates a board that gets the filter from another project [image ./img/ntb.png] -- =[Board from an existing Saved Filter]= - as it says, you add to the project (indicated in the `[Location]` field) a board based on a saved filter +- [=Board from an existing Saved Filter=] - as it says, you add to the project (indicated in the [`Location`] field) a board based on a saved filter [image ./img/ntb-filter.png] ## Backlog -=[The backlog is a place for issues that outline a general task/feature]=. +[=The backlog is a place for issues that outline a general task/feature=]. -Depending on your project template, the backlog will either be a =[separate window ([url ./scrum.html Scrum])]=, +Depending on your project template, the backlog will either be a [=separate window ([url ./scrum.html Scrum])=], [image ./img/scrum-backlog.png] -=[just a column in a board ([url ./kanban.html Kanban])]=, +[=just a column in a board ([url ./kanban.html Kanban])=], [image ./img/backlog-kanban.png] -or =[nonexistent ([url ./bug.md bug tracking])]=. +or [=nonexistent ([url ./bug.md bug tracking])=]. The purpose of the backlog depends on the template and it is described in the page of each template. ## Add item -=[You can also add some resources to the sidebar of your project]= for everyone to use. That is done through the `[Add Item]` menu. +[=You can also add some resources to the sidebar of your project=] for everyone to use. That is done through the [`Add Item`] menu. [image ./img/add-item-kanban.png] -From here you can =[add a website shortcut]=, simply by putting the web address and giving it a name. +From here you can [=add a website shortcut=], simply by putting the web address and giving it a name. [image ./img/add-item-to-project.png] @@ -147,12 +147,12 @@ The name is used for showing the shortcut on the sidebar. [image ./img/added-site.png] -You can also add a `[Bitbucket]` or `[GitHub]` repository which you can =[leave]= only as a =[shortcut]=, or you can =[integrate]= it so that =[issues are transferred to Jira]=. +You can also add a [`Bitbucket`] or [`GitHub`] repository which you can [=leave=] only as a [=shortcut=], or you can [=integrate=] it so that [=issues are transferred to Jira=]. [image ./img/test-repo.png] [image ./img/test-repo-sidebar.png] -=[Integration won't be covered in this tutorial]=, but I can recommend [url https://www.idalko.com/jira-github-integration/ this] article for `[GitHub]` integration and [url https://www.idalko.com/jira-bitbucket-integration/ this] one for `[Bitbucket]` integration. +[=Integration won't be covered in this tutorial=], but I can recommend [url https://www.idalko.com/jira-github-integration/ this] article for [`GitHub`] integration and [url https://www.idalko.com/jira-bitbucket-integration/ this] one for [`Bitbucket`] integration. -From the `[Add Item]` menu you can also =[toggle the shortcut to [url ./pages.html Pages]]=. +From the [`Add Item`] menu you can also [=toggle the shortcut to [url ./pages.html Pages]=]. diff --git a/src/blog/how-to-use-jira/releases.du b/src/blog/how-to-use-jira/releases.du index 430de92..1642c61 100644 --- a/src/blog/how-to-use-jira/releases.du +++ b/src/blog/how-to-use-jira/releases.du @@ -10,12 +10,12 @@ 'define next_link ./pages.html Pages [$pagination_middle] -The `[Releases]` page in a project shows =[versions]=, the ones in development and the ones that are completed. +The [`Releases`] page in a project shows [=versions=], the ones in development and the ones that are completed. -=[Versions are just a big collection of issues]= and the =[goal of a released version]= is for =[all of it's issues to be resolved]=. It serves as a point in time for the development of a project. +[=Versions are just a big collection of issues=] and the [=goal of a released version=] is for [=all of it's issues to be resolved=]. It serves as a point in time for the development of a project. ## Adding issues to a version -When creating an issue, you can specify a version in the `[Fix versions]` property. +When creating an issue, you can specify a version in the [`Fix versions`] property. [image ./img/fix-versions.png] diff --git a/src/blog/how-to-use-jira/scrum.du b/src/blog/how-to-use-jira/scrum.du index 37ca494..dffe4ec 100644 --- a/src/blog/how-to-use-jira/scrum.du +++ b/src/blog/how-to-use-jira/scrum.du @@ -16,40 +16,40 @@ 2. [url #boards-and-issues Boards and Issues] 3. [url #create-board Create board] -The scrum template is very similar to the kanban template, with one big difference: =[sprints]=. +The scrum template is very similar to the kanban template, with one big difference: [=sprints=]. -=[All issues]= are put into the =[backlog]= (which is now a =[separate page]=). From there, they are organised into =[sprints]=. +[=All issues=] are put into the [=backlog=] (which is now a [=separate page=]). From there, they are organised into [=sprints=]. -In general [url https://www.atlassian.com/agile agile software development], a =[sprint is a small duration of time]= (one to four weeks) where the team focuses on a =[set of tasks]= and at the end everyone =[evaluates the results]= and plans the next sprint. +In general [url https://www.atlassian.com/agile agile software development], a [=sprint is a small duration of time=] (one to four weeks) where the team focuses on a [=set of tasks=] and at the end everyone [=evaluates the results=] and plans the next sprint. -Your =[boards only work on the issues of the currently active sprint]=. +Your [=boards only work on the issues of the currently active sprint=]. ## Backlog -As we've discussed, the =[backlog]= is used for organising =[all issues]= into =[sprints]=. +As we've discussed, the [=backlog=] is used for organising [=all issues=] into [=sprints=]. [image ./img/sample-scrum-backlog.png] -From here you can also organise =[Versions]= (refer to [url ./releases.html Releases]) and =[Epics]= (refer to [url ./cards.html Cards]). An important note is that Epics in this context don't need to have their linked issues in only one sprint. +From here you can also organise [=Versions=] (refer to [url ./releases.html Releases]) and [=Epics=] (refer to [url ./cards.html Cards]). An important note is that Epics in this context don't need to have their linked issues in only one sprint. [image ./img/versions-and-epics.png] -Creating a sprint is done from the conveniently named `[Create sprint]` button. It shows a box on top where you can either move issues from the backlog to the sprint or create entirely new issues. +Creating a sprint is done from the conveniently named [`Create sprint`] button. It shows a box on top where you can either move issues from the backlog to the sprint or create entirely new issues. [image ./img/sample-sprint.png] ## Boards and Issues -As previously mentioned, boards have access only to the issues in the active sprint. This is also reflected in the user interface. After selecting a board from the sidebar, you view it from the `[Active sprints]` page. +As previously mentioned, boards have access only to the issues in the active sprint. This is also reflected in the user interface. After selecting a board from the sidebar, you view it from the [`Active sprints`] page. [image ./img/active-sprints.png] ## Create board -This template can be chosen when =[creating a project]= +This template can be chosen when [=creating a project=] [image ./img/choose-classic-template.png] -and =[from the `[Create board]` screen]=. +and [=from the [`Create board`] screen=]. [image ./img/scrum-kanban-board.png] diff --git a/src/blog/icon-fonts-arent-evil-you-just-have-to-care/index.du b/src/blog/icon-fonts-arent-evil-you-just-have-to-care/index.du index d09c890..35e9fcf 100644 --- a/src/blog/icon-fonts-arent-evil-you-just-have-to-care/index.du +++ b/src/blog/icon-fonts-arent-evil-you-just-have-to-care/index.du @@ -26,16 +26,16 @@ First, we have to get acquaintanced with why I wanted change: before the big rew For [url https://gitlab.com/Syndamia/syndamiadotcom/-/releases/v3.0 quite a while] I've added support for an alternative light theme, but ever since the beginning icons have been an issue. How can you change the color, or more specifically, the internal styling of an SVG? -You have a [url https://stackoverflow.com/questions/22252472/how-can-i-change-the-color-of-an-svg-element couple of options], if you include it with a normal `[<img>]` tag, as I was doing, you could do some [url https://stackoverflow.com/a/53336754 magic with filters] to change the exact color, though this is kinda difficult and [url https://caniuse.com/css-filters browsers support filters since somewhat recently]. +You have a [url https://stackoverflow.com/questions/22252472/how-can-i-change-the-color-of-an-svg-element couple of options], if you include it with a normal [`<img>`] tag, as I was doing, you could do some [url https://stackoverflow.com/a/53336754 magic with filters] to change the exact color, though this is kinda difficult and [url https://caniuse.com/css-filters browsers support filters since somewhat recently]. This is a deal-breaker, because I care about older browsers and without that CSS property, icons become very difficult to see on the light theme. -Another option is to load it with an `[\<object>]`, `[\<embed>]` or `[\<iframe>]` tag, though they all [url https://stackoverflow.com/a/21503151 require JavaScript] to edit the internal styling and have [url https://vecta.io/blog/best-way-to-embed-svg a lot of problems]: +Another option is to load it with an [`\<object>`], [`\<embed>`] or [`\<iframe>`] tag, though they all [url https://stackoverflow.com/a/21503151 require JavaScript] to edit the internal styling and have [url https://vecta.io/blog/best-way-to-embed-svg a lot of problems]: .bulleted -- `[\<object>]` [url https://vecta.io/blog/best-way-to-embed-svg#2-using-an--object--tag causes problems for search engines or the workaround forces downloading multiple files for the same image]. +- [`\<object>`] [url https://vecta.io/blog/best-way-to-embed-svg#2-using-an--object--tag causes problems for search engines or the workaround forces downloading multiple files for the same image]. Worst-case scenario, for every icon you would need two different HTTP requests, which significantly increases required traffic for devices on slow connections, no dice. -- `[\<embed>]` isn't part of the HTML specification, so it could disappear from browsers at any moment and it may have very different behaviours between browsers -- `[\<iframe>]` is [url https://stackoverflow.com/a/23178537 hard to maintain and causes problems for search engines] +- [`\<embed>`] isn't part of the HTML specification, so it could disappear from browsers at any moment and it may have very different behaviours between browsers +- [`\<iframe>`] is [url https://stackoverflow.com/a/23178537 hard to maintain and causes problems for search engines] The final option is putting SVG images directly inline with the rest of the HTML. However, this also comes with it's drawbacks: @@ -72,20 +72,20 @@ This is one of the main issues, outlined in the aforementioned [url https://www. Unicode defines certain characters as part of so-called [url https://en.wikipedia.org/wiki/Private_Use_Areas Private Use Areas] (PUA), meaning those character won't ever have a standard glyph (image) assigned to them and any font can define them freely. The effect is that on different fonts, such a character will appear as a completely different glyph, though most don't define them at all, leaving you with a default blank square. -This is horrible: if the font doesn't get downloaded or if you =[need]= to change it to something you can actually read, you'll get random irrelevant glyphs at best and blank squares everywhere at worst. +This is horrible: if the font doesn't get downloaded or if you [=need=] to change it to something you can actually read, you'll get random irrelevant glyphs at best and blank squares everywhere at worst. To add insult to injury, icon fonts like [url https://fontawesome.com/ font-awesome] contain their icons almost exclusively in the PUA! However, this all can be fixed, at least to an extent. The main tricks are: :numbered -1. =[Adding text to every clickable option]=, where possible. +1. [=Adding text to every clickable option=], where possible. For example, I changed my theme button from an icon to "Dark theme" or "Light theme" (depending on the current theme). .p Even outside this topic, having text instead of icons [url https://dev.to/megazear7/no-icon-web-design-16eb has many benefits], mainly making it easier for users to understand how to interact with the website. -2. =[Putting important navigational and functional icons outside the PUA]= (and leaving decorational ones there). +2. [=Putting important navigational and functional icons outside the PUA=] (and leaving decorational ones there). .p For example, on mobile devices my sidebar is put on the top, but as to not take too much space, it is "folded" up. @@ -100,7 +100,7 @@ The main tricks are: But, to do the second trick, you would need your own custom font. Thankfully, there are programs which can edit already existing ones, so you won't have to know how to make one yourself. I personally really like [url https://tabler-icons.io/ tabler-icons] (and more specifically, [url https://github.com/tabler/tabler-icons/releases/tag/v2.10.0 version 2.10.0]) and for the editing I use [url https://fontforge.org/en-US/ FontForge]. -So, I download the `[.ttf]` version of the font and then a (part of a) [url https://gitlab.com/Syndamia/syndamiadotcom/-/blob/master/FontForge-helper.ff#L37-74 FontForge script I made moves glyphs from the PUA to standard characters]. +So, I download the [`.ttf`] version of the font and then a (part of a) [url https://gitlab.com/Syndamia/syndamiadotcom/-/blob/master/FontForge-helper.ff#L37-74 FontForge script I made moves glyphs from the PUA to standard characters]. ### Screen reader accessibility: almost unavoidable @@ -111,7 +111,7 @@ But SVGs have a title and description tags built-in, existing inside the image f ### File size: fixable with care When every icon is on a separate image, you'll download it only when needed, however with a custom font, you'll always need to download the whole font, which includes icons you don't use. -For the aforementioned tabler-icons, the `[.ttf]` font file is 1.8 MB! +For the aforementioned tabler-icons, the [`.ttf`] font file is 1.8 MB! That is waaaay too much, especially since the font could block rendering of the page. But in reality, if you remove the icons that you don't use, the size difference could actually go in favor of fonts. diff --git a/src/blog/index.du b/src/blog/index.du index 76b3929..cf0bf46 100644 --- a/src/blog/index.du +++ b/src/blog/index.du @@ -4,110 +4,110 @@ Articles detailing personal experiences or exploration of certain topics. \n -#### *[2024]* +#### [*2024*] :defs ; [$bg] 18 Nov   [url /blog/switchut-izgorq Суичът изгоря!] -: `[Shallow dive]` | `[Story]` | `[Networking]` `[Switch]` `[NetworkPartner]` +: [`Shallow dive`] | [`Story`] | [`Networking`] [`Switch`] [`NetworkPartner`] ; [$gb] 06 Oct   [url /blog/the-physics-behind-a-black-hole-shader The physics behind a black hole shader] -: `[Deep dive]` | `[Physics]` | `[General theory of relativity]` `[Celestial mechanics]` `[Gravity]` `[Black Hole]` `[Algorithm]` +: [`Deep dive`] | [`Physics`] | [`General theory of relativity`] [`Celestial mechanics`] [`Gravity`] [`Black Hole`] [`Algorithm`] ; [$gb] 20 Feb   [url /blog/microsoft-and-foss-extinguish Microsoft and FOSS: a fire to be extinguished] -: `[Shallow dive]` | `[Opinion]` | `[Microsoft]` `[GitHub]` `[Linux]` `[FOSS]` +: [`Shallow dive`] | [`Opinion`] | [`Microsoft`] [`GitHub`] [`Linux`] [`FOSS`] -#### *[2023]* +#### [*2023*] :defs ; [$gb] 16 Dec   [url /blog/fix-qc-timeout Fix "qc timeout" kernel log error] -: `[Linux]` | `[kernel]` | `[libata]` `[qc]` `[logs]` `[DMA]` +: [`Linux`] | [`kernel`] | [`libata`] [`qc`] [`logs`] [`DMA`] ; [$gb] 30 Aug   [url /blog/thinkpad-x270-my-favorite-machine ThinkPad X270 - my favorite machine] -: `[Medium dive]` | `[Review]` | `[Lenovo]` `[ThinkPad]` `[Yoga]` +: [`Medium dive`] | [`Review`] | [`Lenovo`] [`ThinkPad`] [`Yoga`] ; [$gb] 19 Jul   [url /blog/icon-fonts-arent-evil-you-just-have-to-care Icon fonts aren't evil, you just have to care] -: `[Shallow dive]` | `[Web development]` | `[Icon font]` `[SVG]` `[Accessibility]` `[FontForge]` +: [`Shallow dive`] | [`Web development`] | [`Icon font`] [`SVG`] [`Accessibility`] [`FontForge`] ; [$bg] 14 Jul   [url /blog/fmi-i-vissheto-obrazovanie-v-programistkata-industriq ФМИ и висшето образование в програмистката индустрия] -: `[Deep dive]` | `[University]` | `[FMI]` `[Education]` +: [`Deep dive`] | [`University`] | [`FMI`] [`Education`] ; [$gb] 28 Jun   [url /blog/fix-network-brother-printers Fix networked Brother printers not working in Linux] -: `[Linux]` | `[CUPS]` | `[Printers]` `[Brother]` `[Network]` `[avahi]` +: [`Linux`] | [`CUPS`] | [`Printers`] [`Brother`] [`Network`] [`avahi`] ; [$gb] 14 Jun   [url /blog/gns3-initsh-no-such-file Fix "exec /gns3/init.sh: no such file or directory"] -: `[Linux]` | `[GNS3]` | `[Docker]` `[busybox]` +: [`Linux`] | [`GNS3`] | [`Docker`] [`busybox`] ; [$gb] 07 Jun   [url /blog/friendship-ended-with-funtoo-now-gentoo-is-my-best-friend Friendship ended with Funtoo, now Gentoo is my best friend] -: `[Shallow dive]` | `[Linux]` | `[Funtoo]` `[Gentoo]` `[portage]` `[packages]` `[emerge]` `[ebuild]` +: [`Shallow dive`] | [`Linux`] | [`Funtoo`] [`Gentoo`] [`portage`] [`packages`] [`emerge`] [`ebuild`] ; [$gb] 01 May   [url /blog/bash-is-weird BASH is weird] -: `[Shallow dive]` | `[bash]` | `[Linux]` `[scripting]` +: [`Shallow dive`] | [`bash`] | [`Linux`] [`scripting`] ; [$gb] 26 Apr   [url /blog/install-drivers-for-epson-scanners Install drivers for Epson scanners] -: `[Linux]` | `[SANE]` | `[Scanners]` `[Epson]` `[epkowa]` `[iscan]` +: [`Linux`] | [`SANE`] | [`Scanners`] [`Epson`] [`epkowa`] [`iscan`] ; [$gb] 25 Apr   [url /blog/managing-apps-with-adb-without-root Managing Android apps with ADB (and without root)] -: `[Android]` | `[ADB]` | `[Apps]` `[Linux]` `[Windows]` +: [`Android`] | [`ADB`] | [`Apps`] [`Linux`] [`Windows`] ; [$gb] 18 Apr   [url /blog/sane-explanation-of-compilers/part-1 Sane explanation of compilers: Part 1] -: `[Deep dive]` | `[Compilers]` | `[C]` `[yacc]` `[bison]` `[math]` `[Trees]` `[Regex]` `[Grammar]` `[Languages]` +: [`Deep dive`] | [`Compilers`] | [`C`] [`yacc`] [`bison`] [`math`] [`Trees`] [`Regex`] [`Grammar`] [`Languages`] ; [$gb] 13 Jan   [url /blog/plan9-in-linux-mouse-menus Plan 9 in Linux: Mouse menus] -: `[Medium dive]` | `[Linux]` | `[Plan 9]` `[mouse]` `[bash]` `[script]` `[X11]` `[openbox]` `[jgmenu]` `[plumber]` +: [`Medium dive`] | [`Linux`] | [`Plan 9`] [`mouse`] [`bash`] [`script`] [`X11`] [`openbox`] [`jgmenu`] [`plumber`] ; [$gb] 01 Jan   [url /blog/virt-manager-freeze-on-browse virt-manager freezing up when clicking Browse in any window] -: `[Linux]` | `[virt-manager]` | `[QEMU/KVM]` `[libvirt]` `[Linux]` `[GTK]` +: [`Linux`] | [`virt-manager`] | [`QEMU/KVM`] [`libvirt`] [`Linux`] [`GTK`] -#### *[2022]* +#### [*2022*] :defs ; [$gb] 23 Dec   [url /blog/2.6-years-of-web-design 2.6 years of web design] -: `[Shallow dive]` | `[Web design]` +: [`Shallow dive`] | [`Web design`] ; [$gb] 13 Dec   [url /blog/when-a-language-forces-simpler-thinking When a language forces simpler thinking] -: `[Shallow dive]` | `[Common Lisp]` | `[Advent of Code]` +: [`Shallow dive`] | [`Common Lisp`] | [`Advent of Code`] ; [$gb] 04 Dec   [url /blog/taming-the-fun-too Taming The Fun-too] -: `[Story]` | `[Funtoo]` | `[Linux]` `[Gentoo]` `[packages]` +: [`Story`] | [`Funtoo`] | [`Linux`] [`Gentoo`] [`packages`] ; [$gb] 01 Nov   [url /blog/turn-off-notifications-windows How to turn off notifications on Windows] -: `[Windows 10]` | `[Settings]` | `[Notifications]` +: [`Windows 10`] | [`Settings`] | [`Notifications`] ; [$gb] 01 Nov   [url /blog/disable-sticky-keys-popup How to disable Sticky Keys prompt] -: `[Windows]` | `[Settings]` | `[Sticky Keys]` +: [`Windows`] | [`Settings`] | [`Sticky Keys`] ; [$gb] 26 Oct   [url /blog/remove-weather-widget How to remove Windows Weather Widget] -: `[Windows 10]` | `[Settings]` | `[Taskbar]` `[Weather Widget]` +: [`Windows 10`] | [`Settings`] | [`Taskbar`] [`Weather Widget`] ; [$gb] 04 Oct   [url /blog/windows-run-dialog Windows Run dialog] -: `[Windows]` | `[Commands]` | `[Run]` `[Settings]` +: [`Windows`] | [`Commands`] | [`Run`] [`Settings`] ; [$gb] 03 Oct   [url /blog/export-skype How to export Skype data] -: `[Skype]` | `[Export]` | `[Archive]` `[skype-parser]` +: [`Skype`] | [`Export`] | [`Archive`] [`skype-parser`] ; [$gb] 16 Sep   [url /blog/how-to-encrypt-email How to encrypt email] -: `[All]` | `[Email]` | `[PGP]` `[S/MIME]` `[Email Client]` `[Gmail]` `[Outlook]` `[Protonmail]` +: [`All`] | [`Email`] | [`PGP`] [`S/MIME`] [`Email Client`] [`Gmail`] [`Outlook`] [`Protonmail`] ; [$gb] 10 Sep   [url /blog/encrypted-email Encrypted email] -: `[Medium dive]` | `[Email]` | `[Encryption]` `[Security]` `[PGP]` `[S/MIME]` `[Protonmail]` `[Tutanota]` +: [`Medium dive`] | [`Email`] | [`Encryption`] [`Security`] [`PGP`] [`S/MIME`] [`Protonmail`] [`Tutanota`] ; [$gb] 30 Jul   [url /blog/fix-no-frame-buffer-plan9 Fix "No frame buffer" error in <span class="no-wrap">Plan 9</span>] -: `[Plan 9]` | `[Configuration]` | `[QEMU/KVM]` `[Linux]` `[monitor]` +: [`Plan 9`] | [`Configuration`] | [`QEMU/KVM`] [`Linux`] [`monitor`] ; [$gb] 30 Jul   [url /blog/install-plan9-with-virt-manager Install <span class="no-wrap">Plan 9</span> with virt-manager] -: `[Plan 9]` | `[Installation]` | `[Setup]` `[QEMU/KVM]` `[virt-manager]` `[Linux]` +: [`Plan 9`] | [`Installation`] | [`Setup`] [`QEMU/KVM`] [`virt-manager`] [`Linux`] -#### *[2020]* +#### [*2020*] :defs ; [$gb] 24 Jul   [url /blog/how-to-use-jira How to use Jira] -: `[Project Management]` | `[Jira]` | `[Agile]` `[Issue tracking]` `[Bug tracking]` `[Kanban]` `[Atlassian]` +: [`Project Management`] | [`Jira`] | [`Agile`] [`Issue tracking`] [`Bug tracking`] [`Kanban`] [`Atlassian`] ; [$gb] 21 May   [url /blog/connect-to-mysql-in-dotnet-ef Connect to Mysql in .NET and Entity Framework] -: `[ASP.Net]` | `[MySQL]` | `[Entity Framework]` `[Pomelo]` +: [`ASP.Net`] | [`MySQL`] | [`Entity Framework`] [`Pomelo`] ; [$gb] 20 May   [url /blog/mundus-first-shot-at-gamedev Mundus: My first shot at game development] -: `[Deep dive]` | `[Gamedev]` | `[2D]` `[Sandbox]` `[Crafting]` `[Building]` `[Fighting]` `[GtkSharp 2.0]` `[C#]` +: [`Deep dive`] | [`Gamedev`] | [`2D`] [`Sandbox`] [`Crafting`] [`Building`] [`Fighting`] [`GtkSharp 2.0`] [`C#`] diff --git a/src/blog/install-drivers-for-epson-scanners/index.du b/src/blog/install-drivers-for-epson-scanners/index.du index faba80e..d6f6486 100644 --- a/src/blog/install-drivers-for-epson-scanners/index.du +++ b/src/blog/install-drivers-for-epson-scanners/index.du @@ -5,7 +5,7 @@ 'define edited 26 April 2023 [$pagenav] -'footnote gentoo-sane On Gentoo the package is `[sane-backends]`, as per the [url https://wiki.gentoo.org/wiki/SANE wiki]. +'footnote gentoo-sane On Gentoo the package is [`sane-backends`], as per the [url https://wiki.gentoo.org/wiki/SANE wiki]. Sometimes your Epson scanner might work out of the box, and sometimes it might not. First, make sure you have [url http://sane-project.org/ SANE] installed on your machine[$gentoo-sane]. @@ -13,15 +13,15 @@ Second look through [url http://www.sane-project.org/sane-mfgs.html#Z-EPSON the ## Complete or Good -'footnote openrc-sane For OpenRC: `[rc-service saned status]` +'footnote openrc-sane For OpenRC: [`rc-service saned status`] If your scanner falls into the first category, labeled "Complete" or "Good", you probably have an issue with SANE. -Make sure the `[saned]` service is running without errors[$openrc-sane]: +Make sure the [`saned`] service is running without errors[$openrc-sane]: ```bash systemctl status saned.service -and make sure the [url http://www.sane-project.org/man/sane-epson2.5.html sane-epson2] (or [url http://www.sane-project.org/man/sane-epson.5.html sane-epson]) back-end is enabled, you should have `[epson2]` (or `[epson]`) without a leading `[#]` inside `[/etc/sane.d/dll.conf]`. +and make sure the [url http://www.sane-project.org/man/sane-epson2.5.html sane-epson2] (or [url http://www.sane-project.org/man/sane-epson.5.html sane-epson]) back-end is enabled, you should have [`epson2`] (or [`epson`]) without a leading [`#`] inside [`/etc/sane.d/dll.conf`]. ## epkowa plus non-free interpreter @@ -30,15 +30,15 @@ If it's unsupported and there is a note .quote supported by the epkowa backend plus non-free interpreter you can still make it work. -You'll have to get the =[non-free]= (free as in [url https://en.wikipedia.org/wiki/Free_software_movement publicly available source code], you don't have to pay for anything) Epson Scan 2 software. +You'll have to get the [=non-free=] (free as in [url https://en.wikipedia.org/wiki/Free_software_movement publicly available source code], you don't have to pay for anything) Epson Scan 2 software. -It can be downloaded from [url https://support.epson.net/linux/en/epsonscan2.php the support site] as a `[deb]` or `[rpm]` package. -If your system doesn't natively work with any of those (i.e. it isn't listed under "Distribution" and isn't some sort of derivative of those), you can still try the `[rpm]` package. +It can be downloaded from [url https://support.epson.net/linux/en/epsonscan2.php the support site] as a [`deb`] or [`rpm`] package. +If your system doesn't natively work with any of those (i.e. it isn't listed under "Distribution" and isn't some sort of derivative of those), you can still try the [`rpm`] package. :ordered -1. Install `[rpm]` with your package manager +1. Install [`rpm`] with your package manager -2. Download the 32 or 64 bit =[[ rpm ]]= package +2. Download the 32 or 64 bit [=[ rpm ]=] package 3. Extract it @@ -51,12 +51,12 @@ tar -xf epsonscan2-bundle-SOMETHING.rpm.tar.gz sudo rpm -Uvh --nodeps ./epsonscan2-bundle-SOMETHING.rpm/core/epsonscan2-SOMETHING.rpm ./epsonscan2-bundle-SOMETHING.rpm/plugins/epsonscan2-non-free-plugin-SOMETHING.rpm -Alternatively, you can install the `[deb]` package with `[dpkg]` or build and install it from [url https://download.ebz.epson.net/man/linux/epsonscan2_e.html#sec5-1-4 source] (source file is available at the bottom of the [url https://support.epson.net/linux/en/epsonscan2.php support site]). +Alternatively, you can install the [`deb`] package with [`dpkg`] or build and install it from [url https://download.ebz.epson.net/man/linux/epsonscan2_e.html#sec5-1-4 source] (source file is available at the bottom of the [url https://support.epson.net/linux/en/epsonscan2.php support site]). 'footnote gentoo-epkowa Surprisingly enough, on my Gentoo installation everything works fine without the package. Either something else is helping me or [url http://www.catb.org/jargon/html/magic-story.html something is in the "more magic" position]... -You will need[$gentoo-epkowa] to install `[iscan]`, which usually provides the aforementioned `[epkowa]` backend. -Also make sure you have `[epkowa]` inside `[/etc/sane.d/dll.conf]` without a leading `[#]`. +You will need[$gentoo-epkowa] to install [`iscan`], which usually provides the aforementioned [`epkowa`] backend. +Also make sure you have [`epkowa`] inside [`/etc/sane.d/dll.conf`] without a leading [`#`]. Finally, only for the very first time after connecting your powered-on scanner, start "Epson Scan 2", select it and press "Next". The drivers should automatically be installed and you can close the window and use your own scanning software of choice afterwards. diff --git a/src/blog/install-plan9-with-virt-manager/index.du b/src/blog/install-plan9-with-virt-manager/index.du index f16c997..c60eb31 100644 --- a/src/blog/install-plan9-with-virt-manager/index.du +++ b/src/blog/install-plan9-with-virt-manager/index.du @@ -10,16 +10,16 @@ 1. [url #creating-the-virtual-machine Creating the virtual machine] 2. [url #installing-plan-9-itself Installing Plan 9 itself] -Installing [url https://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs Plan 9 by Bell Labs] with `[qemu]` itself isn't difficult and there are [url https://9p.io/wiki/plan9/Installing_Plan_9_on_Qemu/ official instructions]. However, when using `[virt-manager]`, there are certain uncertainties that might worry a first-timer and certain issues that arise. +Installing [url https://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs Plan 9 by Bell Labs] with [`qemu`] itself isn't difficult and there are [url https://9p.io/wiki/plan9/Installing_Plan_9_on_Qemu/ official instructions]. However, when using [`virt-manager`], there are certain uncertainties that might worry a first-timer and certain issues that arise. ## Creating the virtual machine We'll be installing Plan 9 with a CD (ISO) image. You can download the latest version (compiled every night) from [url https://9p.io/plan9/download.html here]. For a compressed version and checksums, refer to [url https://9p.io/wiki/plan9/Download/index.html this page]. :ordered -1. Press the *["Create a new virtual machine"]* and select *["Local install media (ISO image or CDROM)"]* +1. Press the [*"Create a new virtual machine"*] and select [*"Local install media (ISO image or CDROM)"*] -2. For the install media select the extracted `[.iso]` CD image of Plan 9 and for operating system chose *["Generic or unknown OS (generic)"]* +2. For the install media select the extracted [`.iso`] CD image of Plan 9 and for operating system chose [*"Generic or unknown OS (generic)"*] 3. For memory select 512 MiB (the default 1024 MiB is also fine) and 1 CPU @@ -27,7 +27,7 @@ We'll be installing Plan 9 with a CD (ISO) image. You can download the latest ve - Plan 9 is stupid lightweight and according to [url https://9p.io/wiki/plan9/Installation_instructions/index.html the installation instructions] you need 16-32 MB of memory, but I still prefer to give it a little more, just in case I decide to do something extreme. - You can also increase these values as much as you like, Plan 9 should be able to handle the more resources -4. If you plan to only test the OS out, choose *["Create a disk image for the virtual machine"]* and enter 2 GiB of size. If you plan more serious use, you might want to follow [url https://9p.io/wiki/plan9/Installing_Plan_9_on_Qemu/ the qemu instructions] and create a larger disk in the `[.raw]` format. +4. If you plan to only test the OS out, choose [*"Create a disk image for the virtual machine"*] and enter 2 GiB of size. If you plan more serious use, you might want to follow [url https://9p.io/wiki/plan9/Installing_Plan_9_on_Qemu/ the qemu instructions] and create a larger disk in the [`.raw`] format. 5. Finally click finish. @@ -45,47 +45,47 @@ I'll show a more abridged version of what you need to do. 2. On the questions "use DMA for ide drive" and "mouseport is" press enter -3. On "vgasize" press enter, or set up a higher (standard) resolution with 24 colors. Examples: `[1920x1080x24]`, `[1280x720x24]` +3. On "vgasize" press enter, or set up a higher (standard) resolution with 24 colors. Examples: [`1920x1080x24`], [`1280x720x24`] .unordered - A very incomplete list can be found [url https://9p.io/wiki/plan9/setting_the_right_monitor_size/index.html here] -4. =[Very important!]= On "monitor" enter `[vesa]`. `[xga]` (or `[vga]`) will work during installation but seem to break when booting the installed OS. +4. [=Very important!=] On "monitor" enter [`vesa`]. [`xga`] (or [`vga`]) will work during installation but seem to break when booting the installed OS. .unordered - - If you mistakenly leave it at `[xga]`, refer to [url /blog/fix-no-frame-buffer-plan9 this tutorial]. + - If you mistakenly leave it at [`xga`], refer to [url /blog/fix-no-frame-buffer-plan9 this tutorial]. From here on out, you press enter at most of the prompts. The following list enumerates all cases where you need to do something else than press enter. :ordered -1. On "Disk partiton" question, enter `[sdC0]` (the option that says Hard Disk on it) +1. On "Disk partiton" question, enter [`sdC0`] (the option that says Hard Disk on it) [image ./img/partdisk-partition.png] -2. On "Install mbr" question, enter `[y]` +2. On "Install mbr" question, enter [`y`] [image ./img/partdisk-mbr.png] -3. When you get ">>>" before the cursor, press w, then enter, then q and finally enter. This should happen twice, when in `[disk/fdisk]` and `[disk/prep]` +3. When you get ">>>" before the cursor, press w, then enter, then q and finally enter. This should happen twice, when in [`disk/fdisk`] and [`disk/prep`] [image ./img/partdisk-fdisk.png] [image ./img/prepdisk-prep.png] -4. On "Distribution disk" type out the one that ends with `[data]` (and potentially has `[cdrom]` besides it). This is most commonly `[/dev/sdC1/data]` +4. On "Distribution disk" type out the one that ends with [`data`] (and potentially has [`cdrom`] besides it). This is most commonly [`/dev/sdC1/data`] [image ./img/mountdist-distribution-disk.png] -5. When you get "/%" before cursor (during mountdisk task) just enter `[exit]` +5. When you get "/%" before cursor (during mountdisk task) just enter [`exit`] [image ./img/mountdist-browse.png] -6. On "Enable boot method" enter `[plan9]` +6. On "Enable boot method" enter [`plan9`] [image ./img/bootsetup-boot-method.png] After finishing the installation and seeing the message "Feel free to shutdown your computer", Force Off the virtual machine and then power it on again. -On boot, on the first prompt press enter, and on the second enter `[glenda]`. Enjoy Plan 9! +On boot, on the first prompt press enter, and on the second enter [`glenda`]. Enjoy Plan 9! diff --git a/src/blog/managing-apps-with-adb-without-root/index.du b/src/blog/managing-apps-with-adb-without-root/index.du index eee78d4..3dd9ae1 100644 --- a/src/blog/managing-apps-with-adb-without-root/index.du +++ b/src/blog/managing-apps-with-adb-without-root/index.du @@ -31,7 +31,7 @@ Windows: Linux (or MacOS): .bulleted -- With your package manager, it should be called `[android-tools]`, `[android-tools-adb]` or `[android-platform-tools]` +- With your package manager, it should be called [`android-tools`], [`android-tools-adb`] or [`android-platform-tools`] - Worst case scenario, download and extract it from [url https://dl.google.com/android/repository/platform-tools-latest-linux.zip here] for Linux, and [url https://dl.google.com/android/repository/platform-tools-latest-darwin.zip here] for MacOS. ## Opening a shell and connecting to your device @@ -40,16 +40,16 @@ ADB is very powerfull, so by default phones don't allow you to connect to the de First, we'll allow such a connection: .numbered -1. Go to `[Settings/About phone]` (depending on your Android skin, this might be located in a slightly different place) +1. Go to [`Settings/About phone`] (depending on your Android skin, this might be located in a slightly different place) 2. Tap "Build number" 7 times, until a message says you're done -3. Navigate to the Developer options, which is often in `[Settings/Developer options]`, but could also be inside the `[Settings/System]` menu +3. Navigate to the Developer options, which is often in [`Settings/Developer options`], but could also be inside the [`Settings/System`] menu 4. Enable the "USB debugging option" (if a popup appears, click OK) ADB is a command-line only tool, so first open a terminal inside the platform-tools directory: .bulleted - On Window, Right-click in the directory and press "Open PowerShell window here" or "Open command window here" or "Open in Terminal" (different OS versions show a different option) -- On Linux (and MacOS), open a terminal window and `[cd]` to the platform-tools directory +- On Linux (and MacOS), open a terminal window and [`cd`] to the platform-tools directory Connect your phone to the computer with a USB cable, change the transfer mode to "File transfer" and in the terminal enter: @@ -59,7 +59,7 @@ adb devices On your phone you should get a poppup asking "Allow USB debugging?", press OK. You should get a "List of devices attached", and it should have one entry (a line below it, with some number and letters and then the word "device"). -'footnote interactive-shell You could just run every command like `[adb shell COMMAND]`, which wouldn't give you an interactive shell, so it is less convinient +'footnote interactive-shell You could just run every command like [`adb shell COMMAND`], which wouldn't give you an interactive shell, so it is less convinient Now, we'll open a shell[$interactive-shell], a program with which to directly enter commands that the device understands: @@ -86,15 +86,15 @@ This command just uninstalls the app for the normal user, meaning it will be bro pm disable --user 0 PACKAGE Disabled PACKAGE, so it wouldn't work but you wouldn't need to reinstall it (just enable it). -Beware that, if it shows some sort of error (anything that isn't "Success"), you'll probably need to use `[disable-user]`, rather than just `[disable]`. +Beware that, if it shows some sort of error (anything that isn't "Success"), you'll probably need to use [`disable-user`], rather than just [`disable`]. -After you're done, you can pretty much just unplug your device, but remember to =[turn back off the "USB debugging" option!]= +After you're done, you can pretty much just unplug your device, but remember to [=turn back off the "USB debugging" option!=] ## What to remove This is a lost of commands, which remove a whole lot of arguably unnecessary apps. -Use =[AT YOUR OWN RISK!]= -Although they shouldn't, they might cause problems =[FOR WHICH I'M NOT RESPONSIBLE!]= +Use [=AT YOUR OWN RISK!=] +Although they shouldn't, they might cause problems [=FOR WHICH I'M NOT RESPONSIBLE!=] :unordered - Facebook @@ -311,5 +311,5 @@ pm uninstall -k --user 0 us.com.dt.iq.appsource.tmobile \n -More information on available package commands can be shown with `[pm help]`. +More information on available package commands can be shown with [`pm help`]. You can learn more about the adb tool from [url https://developer.android.com/studio/command-line/adb developer.android.com]. diff --git a/src/blog/microsoft-and-foss-extinguish/index.du b/src/blog/microsoft-and-foss-extinguish/index.du index 5c4a9bf..f699a64 100644 --- a/src/blog/microsoft-and-foss-extinguish/index.du +++ b/src/blog/microsoft-and-foss-extinguish/index.du @@ -42,7 +42,7 @@ and the list just goes on. GitHub isn't just a public place to view open-source software anymore, if you are a novice developer or you just don't care that much, it will be very easy to associate the FOSS community with the GitHub community. Once you've started using all of those services and tools, there is no coming back, because other repository platforms focus only on repositories. -I mean, [url https://gitlab.com/ GitLab] doesn't offer a developer forum like [url https://docs.github.com/en/discussions/collaborating-with-your-community-using-discussions/about-discussions GitHub Discussions], you won't find a [url https://sourcehut.org/ sourcehut]-branded FOSS newsletter, [url https://sourceforge.net/ SourceForge] won't allow you to add [url https://github.com/abhisheknaiidu/awesome-github-profile-readme animations, graphics, games, etc. on your profile], there isn't a [url https://codeberg.org/ codeberg] [url https://cli.github.com/ command-line repository management app], so *[obviously GitHub is where it's at for FOSS]*. +I mean, [url https://gitlab.com/ GitLab] doesn't offer a developer forum like [url https://docs.github.com/en/discussions/collaborating-with-your-community-using-discussions/about-discussions GitHub Discussions], you won't find a [url https://sourcehut.org/ sourcehut]-branded FOSS newsletter, [url https://sourceforge.net/ SourceForge] won't allow you to add [url https://github.com/abhisheknaiidu/awesome-github-profile-readme animations, graphics, games, etc. on your profile], there isn't a [url https://codeberg.org/ codeberg] [url https://cli.github.com/ command-line repository management app], so [*obviously GitHub is where it's at for FOSS*]. And you'll be introduced to GitHub before any of the others, thanks to the [url https://education.github.com/pack GitHub Student Developer Pack], where students can get free access to a variety of services, or to [url https://docs.github.com/en/education/manage-coursework-with-github-classroom/get-started-with-github-classroom/about-github-classroom GitHub classroom], where newer developers will probably publish their first pieces of code. diff --git a/src/blog/mundus-first-shot-at-gamedev/basic-concepts.du b/src/blog/mundus-first-shot-at-gamedev/basic-concepts.du index e50c2dd..630ed2f 100644 --- a/src/blog/mundus-first-shot-at-gamedev/basic-concepts.du +++ b/src/blog/mundus-first-shot-at-gamedev/basic-concepts.du @@ -27,7 +27,7 @@ Even though the game is quite unfinished, there are still a fair bit of mechanic The in game world (map) is composed of squares, called tiles. Everything is a type of tile. There are two main categories of tiles: items and mobs. Mobs (mobile object for short) are the creatures in the game, while items are everything else, from the tools, to the trees. -There is only one type of mob tile and that is `[MobTiles]`. All mobs, with the exception of the player, have the same functionality and properties: +There is only one type of mob tile and that is [`MobTiles`]. All mobs, with the exception of the player, have the same functionality and properties: :unordered - health - if it drops to or below 0, they die @@ -72,11 +72,11 @@ The in game world (map) is composed of superlayers. Superlayers represent each e Each superlayer is composed of 3 layers: Structure, Mob and Ground. Each one of them contains a specific type of tiles, meaning structure tiles are only stored in "structure" layer, ground tiles only in "ground" layer and mob tiles only in "mob" layer. Even though, they are different layers, there are some rules for the interaction between them: :unordered -- =[Mobs cannot be on top of structures]=, except if the structure is marked as "walkable" +- [=Mobs cannot be on top of structures=], except if the structure is marked as "walkable" -- =[Structures cannot be placed on top of mobs]=. "Walkable" structures can be placed below a mob. +- [=Structures cannot be placed on top of mobs=]. "Walkable" structures can be placed below a mob. -- =[Structures cannot be placed on top of holes]= (empty spots in the ground layer), =[except if they are "climable"]=, in which case they will be placed in the structure layer on the superlayer below. Mobs also cannot reside on top of holes (they fall to the superlayer below) +- [=Structures cannot be placed on top of holes=] (empty spots in the ground layer), [=except if they are "climable"=], in which case they will be placed in the structure layer on the superlayer below. Mobs also cannot reside on top of holes (they fall to the superlayer below) ## Inventory diff --git a/src/blog/mundus-first-shot-at-gamedev/index.du b/src/blog/mundus-first-shot-at-gamedev/index.du index d6eeeec..9c1cabf 100644 --- a/src/blog/mundus-first-shot-at-gamedev/index.du +++ b/src/blog/mundus-first-shot-at-gamedev/index.du @@ -42,7 +42,7 @@ I called it [url https://gitlab.com/Syndamia/Mundus Mundus] and it took me aroun Nevertheless, this journey was very important to me, hence writing this multi-page article. -=[Link to the source code]=: [url https://gitlab.com/Syndamia/Mundus GitLab] +[=Link to the source code=]: [url https://gitlab.com/Syndamia/Mundus GitLab] ## Screenshots @@ -52,4 +52,4 @@ Nevertheless, this journey was very important to me, hence writing this multi-pa <img src="./img/inventory-menu.png" style="height: 100%; flex: 1;"> </div> -*[Screenshots are made on Linux Mint Cinnamon with the Mint-Y theme]* +[*Screenshots are made on Linux Mint Cinnamon with the Mint-Y theme*] diff --git a/src/blog/mundus-first-shot-at-gamedev/introduction.du b/src/blog/mundus-first-shot-at-gamedev/introduction.du index d6eeeec..9c1cabf 100644 --- a/src/blog/mundus-first-shot-at-gamedev/introduction.du +++ b/src/blog/mundus-first-shot-at-gamedev/introduction.du @@ -42,7 +42,7 @@ I called it [url https://gitlab.com/Syndamia/Mundus Mundus] and it took me aroun Nevertheless, this journey was very important to me, hence writing this multi-page article. -=[Link to the source code]=: [url https://gitlab.com/Syndamia/Mundus GitLab] +[=Link to the source code=]: [url https://gitlab.com/Syndamia/Mundus GitLab] ## Screenshots @@ -52,4 +52,4 @@ Nevertheless, this journey was very important to me, hence writing this multi-pa <img src="./img/inventory-menu.png" style="height: 100%; flex: 1;"> </div> -*[Screenshots are made on Linux Mint Cinnamon with the Mint-Y theme]* +[*Screenshots are made on Linux Mint Cinnamon with the Mint-Y theme*] diff --git a/src/blog/mundus-first-shot-at-gamedev/timeline.du b/src/blog/mundus-first-shot-at-gamedev/timeline.du index 5fd66b7..504fe9d 100644 --- a/src/blog/mundus-first-shot-at-gamedev/timeline.du +++ b/src/blog/mundus-first-shot-at-gamedev/timeline.du @@ -15,23 +15,23 @@ As mentioned, I had big plans for Mundus, so I wanted to make sure it would be well planned. But at the same time, the project took too much energy and I often had holes of no development time. This is an overview of the development "cycle" I went through. -.quote *[=[08.02.2020]=]* Day 0, Hour 0 +.quote [*[=08.02.2020=]*] Day 0, Hour 0 At this point of time, I was still studying software development in a national program. On this exact day, we had the first lecture of a new module, where it was announced we would have to make a project for the exam. Up until this point of time, our exams constituted of predefined programming exercises for which we would be given a couple of hours to complete and would be checked by an online platform. I immediately began brainstorming and by the end of the day, I had decided upon the project I would be developing. -.quote *[=[12.02.2020]=]* Day 4 +.quote [*[=12.02.2020=]*] Day 4 Before Mundus I had experimented with making games, but mostly in the command line. This time was going to be different. Up until this day, I was only researching and trying out different technologies to make my game with. -Initially I spent a lot of time with Unity, but the original time constraints and my lack of knowledge with the game engine discouraged me from continuing with it. Subsequently, I got discouraged from using any game engine and settled for `[GtkSharp 2.0]`. Now, this is widget toolkit, not even close to a game engine, but hey, it was much better than the command line, it was simple and shipped with the IDE I was using at the time. +Initially I spent a lot of time with Unity, but the original time constraints and my lack of knowledge with the game engine discouraged me from continuing with it. Subsequently, I got discouraged from using any game engine and settled for [`GtkSharp 2.0`]. Now, this is widget toolkit, not even close to a game engine, but hey, it was much better than the command line, it was simple and shipped with the IDE I was using at the time. This decision proved to have been a mistake down the road, but the clock was ticking and I had no more time to waste. Besides, I also believed that in the end, moving it to something like Unity wouldn't pose too much trouble. Finally, it was time to plan the actual game. -.quote *[=[27.02.2020]=]* Day 19 +.quote [*[=27.02.2020=]*] Day 19 So far I have only done preparation but on this day, I started actual programming. The UI and most of the mechanics were completely sketched. @@ -41,13 +41,13 @@ Concerning the temporary textures, I just drew them in half an hour in GIMP, so The proper textures, I believe, turned out fairly well, given that I've never been good at drawing and this is my very first time trying to draw pixel art. There is no magic behind the process, after scouring the internet for pixel art that looked kinda close to what I imagined, I tried to utilize and mix whatever I found fitting and then just messed around for hours. As you can imagine, this wasn't a very efficient process, and it took me around 1-2 days for both textures. -.quote *[=[28.03.2020]=]* Day 49 +.quote [*[=28.03.2020=]*] Day 49 Slowly and steadily I had been making fine progress, but a lot of issues started to surface. As it turns out, I hadn't thought everything completely through, so I mostly went back to the drawing board. But at the very least, I had some important systems in place, like breaking and placing stuff, proper movement through the map and using items. Also, I had drawn my favorite texture from the whole projects: [url https://gitlab.com/Syndamia/Mundus/-/blob/c47a34847e52ef76361394dba2c4f524a56d1b92/Mundus/Icons/Land/Items/tree.png the tree] <img src="./img/tree-tile.png" class="pixelated-render">. -.quote *[=[06.04.2020]=]* Day 58 +.quote [*[=06.04.2020=]*] Day 58 Things started to take a turn for the better, I had planned everything I needed to plan and spring break had began. A solid week of no high-school made me more productive than ever. Some days I coded for 8 or even 10 hours straight, from morning to evening. Tools, multiple layers and climbing between them, new items and many bug improvements. @@ -59,7 +59,7 @@ However, remember how they extended the spring break by a week? Well, this was c \n -.quote *[=[23.05.2020]=]* Day 105 +.quote [*[=23.05.2020=]*] Day 105 Finally, after so much time, and relative amount of hiccups, Mundus was finished. Or at least, finished enough so I could present it on the exam. And this happened just in the nick of time too, the exam date was in 8 days, on the 31st. diff --git a/src/blog/mundus-first-shot-at-gamedev/user-interface.du b/src/blog/mundus-first-shot-at-gamedev/user-interface.du index 53b8eca..380c136 100644 --- a/src/blog/mundus-first-shot-at-gamedev/user-interface.du +++ b/src/blog/mundus-first-shot-at-gamedev/user-interface.du @@ -27,7 +27,7 @@ The user interface shows how unfinished the whole thing is, you can find many un A lot of the topics covered are explained in more detail in [url ./basic-concepts.html Basic Concepts]. -=[Note:]= all screenshots are made in Linux Mint Cinnamon with Mint-Y theme. +[=Note:=] all screenshots are made in Linux Mint Cinnamon with Mint-Y theme. ## Main screen @@ -35,7 +35,7 @@ A lot of the topics covered are explained in more detail in [url ./basic-concept We start off with the main screen. -Only the `[Create a new game]` button is implemented, although the `[Settings]` one does open a blank window. +Only the [`Create a new game`] button is implemented, although the [`Settings`] one does open a blank window. ## Create new game @@ -43,15 +43,15 @@ Only the `[Create a new game]` button is implemented, although the `[Settings]` Creating a game gives you a couple of options: -`[Game Mode]` - Survival is the only implemented option, where you start with almost no items and have to gather food and materials. Creative was supposed to be the opposite, giving you access to all items and making you invincible. +[`Game Mode`] - Survival is the only implemented option, where you start with almost no items and have to gather food and materials. Creative was supposed to be the opposite, giving you access to all items and making you invincible. -`[Difficulty]` - Higher the difficulty, the more your energy gets depleted and the less trees, boulders and mobs there are. +[`Difficulty`] - Higher the difficulty, the more your energy gets depleted and the less trees, boulders and mobs there are. -`[Screen & Inventory size]` - The screen is where you navigate the in game world. The way the user interface works, both are linked. +[`Screen & Inventory size`] - The screen is where you navigate the in game world. The way the user interface works, both are linked. -`[Map size]` - Map size (in survival mode) is determined by the Screen & Inventory size, the higher the size, the smaller the map. +[`Map size`] - Map size (in survival mode) is determined by the Screen & Inventory size, the higher the size, the smaller the map. -=[Note:]= all game window screenshots are made with the `[Small Game Window]`. +[=Note:=] all game window screenshots are made with the [`Small Game Window`]. ## Game Window @@ -67,7 +67,7 @@ Then you have your health. It represents how much life you have. If it drops to Underneath that, there is your hotbar. It is a part of your inventory. -After that, you have the `[Event log]` button and some of the most recent events. Clicking the button opens a window from which you can checkout everything that has happened. On the sides, you can find the `[Map]` and `[Inv]` toggle buttons and the `[Pause]` and `[Music]` menu buttons. The `[Music]` menu can only play and stop WAV files. +After that, you have the [`Event log`] button and some of the most recent events. Clicking the button opens a window from which you can checkout everything that has happened. On the sides, you can find the [`Map`] and [`Inv`] toggle buttons and the [`Pause`] and [`Music`] menu buttons. The [`Music`] menu can only play and stop WAV files. ## Map menu @@ -75,7 +75,7 @@ After that, you have the `[Event log]` button and some of the most recent events The Map menu is an extension (to the left) of the normal game window. It cannot be opened at the same time as the inventory menu. -At the top, you can see the ground layer tiles. Below it you can find the name of the superlayer you're currently in and your coordinates. At the bottom there are the structure layer tiles and `[There is a hole above player]` field, where you can check whether you are able to ascent a superlayer. +At the top, you can see the ground layer tiles. Below it you can find the name of the superlayer you're currently in and your coordinates. At the bottom there are the structure layer tiles and [`There is a hole above player`] field, where you can check whether you are able to ascent a superlayer. ## Inventory menu @@ -89,4 +89,4 @@ The Inventory menu is an extension (to the right) of the normal game window. Fro Every time you open the crafting menu, it automatically finds all items that you can craft using the items in your "Items inventory". -At the top it shows you what items and how much of them you need to craft the currently selected item. Below that it shows the item that you can craft and the `[Prev]` and `[Next]` buttons for navigating available items to craft. Finally, there is the `[Craft]` button. Clicking it removes the required items and adds the crafted item to your inventory. +At the top it shows you what items and how much of them you need to craft the currently selected item. Below that it shows the item that you can craft and the [`Prev`] and [`Next`] buttons for navigating available items to craft. Finally, there is the [`Craft`] button. Clicking it removes the required items and adds the crafted item to your inventory. diff --git a/src/blog/plan9-in-linux-mouse-menus/index.du b/src/blog/plan9-in-linux-mouse-menus/index.du index ac2672a..e558f6b 100644 --- a/src/blog/plan9-in-linux-mouse-menus/index.du +++ b/src/blog/plan9-in-linux-mouse-menus/index.du @@ -19,7 +19,7 @@ - [url #send Send] - [url #window-management Window management] -'footnote plan9-vs-rio When I say "Plan 9" in the context of graphical stuff, I usually refer to the default window system [url https://9p.io/magic/man2html/1/rio rio]. Similarly to most UNIX-like OSs, it can be changed, but there doesn't seem to be any others out there*[^[citation ^needed]]*. +'footnote plan9-vs-rio When I say "Plan 9" in the context of graphical stuff, I usually refer to the default window system [url https://9p.io/magic/man2html/1/rio rio]. Similarly to most UNIX-like OSs, it can be changed, but there doesn't seem to be any others out there[*[^citation ^needed]*]. Let's begin with an introduction to Plan 9 (from Bell Labs): it is an old UNIX-like operating system from the 90s, where[$plan9-vs-rio] everything is pretty much either text, image or some sort of rectangular box. There are no fancy graphical menus of any kind, no title bars, no file managers and nothing utilizes icons, but the window manager is still stacked. @@ -61,11 +61,11 @@ Finally, the middle mouse button (button 2), shows text-control options, which c 'footnote plumber-in-apps Technically, a plumber just passes messages between applications, so you can configure it to not open a URL but do something else with it in a certain application. However, the aforementioned way is how it works most of the time. -You'll recognise `[cut]`, `[paste]` and `[snarf]` [$snarf], the latter being just another word for copy. +You'll recognise [`cut`], [`paste`] and [`snarf`] [$snarf], the latter being just another word for copy. Since every modern window manager supports those in some form, I'll concentrate on the others.\n -`[plumb]` is the most interesting: it sends the selection to a "plumber" application, which practically[$plumber-in-apps] tries to open or execute it. +[`plumb`] is the most interesting: it sends the selection to a "plumber" application, which practically[$plumber-in-apps] tries to open or execute it. For example, a selected URL will open in the browser, but a selected image file will open in an image viewer.\n -`[send]` enters the selected text as a command in the current shell. +[`send`] enters the selected text as a command in the current shell. ### Usefulness in Linux @@ -119,18 +119,18 @@ This means that the original idea isn't really feasible, but I couldn't really f Plan B: execute the plumbing script on KeyboardKey + Button, but what key should I choose, especially when we're binding the right click? Ctrl + Button3 is used for opening links, Alt + Button3 is reserved for resizing the current window and binding with the Super (Windows) key causes issues with opening of my application menu. -After a lot of research, I found out there is actually a fourth modifier key, called `[Hyper]`, which X11 still supports. +After a lot of research, I found out there is actually a fourth modifier key, called [`Hyper`], which X11 still supports. It's inception come from 1978 with the [url https://en.wikipedia.org/wiki/Space-cadet_keyboard Space-cadet keyboard], but thanks to the popularity of the [url https://en.wikipedia.org/wiki/Model_M_keyboard Model M], modern keyboards don't include it. -All that was left was to assign `[Hyper]` to some key that I don't use, and what better than Caps Lock! +All that was left was to assign [`Hyper`] to some key that I don't use, and what better than Caps Lock! There are [url https://en.jveweb.net/archives/2010/11/making-better-use-of-the-caps-lock-key-in-linux.html many ways to do it], but I prefer using [url https://gitlab.freedesktop.org/xorg/app/setxkbmap setxkbmap]: ``` setxkbmap -option "caps:hyper" -This line is needs to be ran at start of openbox, so it's placed inside `[~/.config/openbox/autostart]`. +This line is needs to be ran at start of openbox, so it's placed inside [`~/.config/openbox/autostart`]. -Now, finally, our sxhkd config looks something like this (I named the script `[plumb.sh]`): +Now, finally, our sxhkd config looks something like this (I named the script [`plumb.sh`]): :code # Hyper_L + Middle mouse button @@ -165,7 +165,7 @@ With that out of the way, all we now need is an actual menu to appear. Luke Smith and Ren Tatsumoto both used [url https://tools.suckless.org/dmenu/ dmenu], which is keyboard driven. As for a mouse-oriented standalone menu, that could be easily configured, all I could find was my current application menu: [url https://jgmenu.github.io/ jgmenu]. -Generally it is meant to serve as an application menu, but with `[--simple]` you can directly echo and pipe to it all menu option and what they do. +Generally it is meant to serve as an application menu, but with [`--simple`] you can directly echo and pipe to it all menu option and what they do. Menu options are formatted as comma-separated (CSV) text, where each option is on a new line, the first item being the name, and the second, the executed command upon press: ``` @@ -176,7 +176,7 @@ Move,echo 3 In this case I'm echo-ing a number, rather than doing an action, for readability and formatting sake. The number is parsed by a switch statement, so all actions are in a single place and can be more easily formatted than if they were inlined in the string. -Via `[--at-pointer]` the menu can spawn right under the pointer. +Via [`--at-pointer`] the menu can spawn right under the pointer. Unfortunately it always spawns in such a way that the pointer is at the top-left corner, I couldn't find a way to make it appear in a way that the first option is below the pointer. Finally, since I use it as an application menu too, I specify a config file which makes it look more like Plan 9's menu (though I've personally omitted the color scheme, since it doesn't fit my normal theme): @@ -206,7 +206,7 @@ For example, if we have a URL we might want the options "Open it in browser" and Or we might want it "ship" it with a lot of possible menu options and let the user decide which ones they need. This is very simple to do, and can be done in many ways. -My preferred way is to have a variable `[menu]` to which different options are appended depending on a regular expression or "flag" (variable). +My preferred way is to have a variable [`menu`] to which different options are appended depending on a regular expression or "flag" (variable). To work with regular expressions more easily, I've made a function which returns a status code depending on matching. All in all, it would look something like this: @@ -222,14 +222,14 @@ All in all, it would look something like this: #### #4 -Finally, we need to execute a selected option, aka put commands in each case of `[\$action]`. +Finally, we need to execute a selected option, aka put commands in each case of [`\$action`]. ##### Open files -Opening a file is very simple, `[xdg-open]` handles opening files by name, with the default program for that file extension. +Opening a file is very simple, [`xdg-open`] handles opening files by name, with the default program for that file extension. However, the script is ran completely independently from the current program, so when we're given only a part of the file path, we need to figure out the rest. -This problem was solved somewhat by Luke Smith, he figured out a way to find (and `[cd]` into) the current directory of the active window (`[pid1]` should be `[pid]`, but you'll see later why I did that change): +This problem was solved somewhat by Luke Smith, he figured out a way to find (and [`cd`] into) the current directory of the active window ([`pid1`] should be [`pid`], but you'll see later why I did that change): ```bash pid=$(xprop -id "$(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}')" | grep -m 1 PID | cut -d " " -f 3) @@ -247,10 +247,10 @@ Terminal plugins/extensions and special application were considered, but they wo 'footnote shell-cwd You could make a proper mechanism, which waits for the file to get updated ([url https://github.com/inotify-tools/inotify-tools inotify-wait]), or for there to be a lockfile, but the overall way it works is the same. I couldn't think of anything better, mostly because the plumber script is a completely separate process from the shell you're in. Maybe there is a way for them to communicate between each other, a bit like microservices? In the end, I settled on a hack: the shell would do the heavy lifting. -My right-click menu combination would be passed to the terminal (and therefore to the shell), and the shell will simultaneously store it's working directory in a file inside `[/tmp]`, which could then be parse by the script. +My right-click menu combination would be passed to the terminal (and therefore to the shell), and the shell will simultaneously store it's working directory in a file inside [`/tmp`], which could then be parse by the script. This isn't ideal, since if the shell is being slow, the script might not wait long enough for the file to get updated, but I couldn't think of anything much better[$shell-cwd] and it does the job. -'footnote escape-sequences The terminal emulator passes keyboard presses to the shell via [url https://en.wikipedia.org/wiki/ANSI_escape_code ANSI escape sequences], which don't support `[Hyper]` bindings. I settled for the next best thing, which is create a different key combination that isn't in use, and make our script "press" that combination upon running. +'footnote escape-sequences The terminal emulator passes keyboard presses to the shell via [url https://en.wikipedia.org/wiki/ANSI_escape_code ANSI escape sequences], which don't support [`Hyper`] bindings. I settled for the next best thing, which is create a different key combination that isn't in use, and make our script "press" that combination upon running. I use zsh, so I implemented it by creating a zsh widget: certain functionality that can be ran by the shell itself and (usually) doesn't need to be executed like a normal program. Examples include key binds, completion, navigation through history, undo and redo. @@ -261,7 +261,7 @@ plumb-store-cwd () { pwd > /tmp/plumb-cwd } zle -N plumb-store-cwd -bindkey "^[[5;7~" plumb-store-cwd # Ctrl+Alt+Page_Up +bindkey "[^[5;7~" plumb-store-cwd # Ctrl+Alt+Page_Up Finally, in our script, we want to read that file, only if we're inside a terminal: @@ -278,7 +278,7 @@ For the uninitiated, [url https://github.com/jordansissel/xdotool xdotool] is a ##### Send Sending the command to the current shell is by far the simplest action. -`[xdotool]` supports "typing out" text, so I'll give it the selection and let it do it's thing: +[`xdotool`] supports "typing out" text, so I'll give it the selection and let it do it's thing: ```bash xdotool type --delay 0 "$selection" @@ -297,7 +297,7 @@ xdotool mousedown 3 xdotool keyup Alt After this is executed, moving the mouse will cause the screen to be resized, the same way if I did the original combination. -Pressing and releasing the mouse button will stop resizing (that's why `[keyup Alt]` is done, because otherwise you would need to also press Alt). +Pressing and releasing the mouse button will stop resizing (that's why [`keyup Alt`] is done, because otherwise you would need to also press Alt). Though it work, it's kind of clunky and the normal Alt+RightClick is arguably simpler and easier to work with. diff --git a/src/blog/remove-weather-widget/index.du b/src/blog/remove-weather-widget/index.du index b8193fc..5e2aa28 100644 --- a/src/blog/remove-weather-widget/index.du +++ b/src/blog/remove-weather-widget/index.du @@ -5,7 +5,7 @@ 'define edited 26 October 2021 [$pagenav] -From June 2021 Microsoft introduced the `[Weather Widget]` on Windows 10. Given that it takes up space on the taskbar [url https://www.howtogeek.com/734461/windows-10s-weather-widget-is-a-mess.-is-windows-11-next/ and is a huge mess], you might want to remove it. +From June 2021 Microsoft introduced the [`Weather Widget`] on Windows 10. Given that it takes up space on the taskbar [url https://www.howtogeek.com/734461/windows-10s-weather-widget-is-a-mess.-is-windows-11-next/ and is a huge mess], you might want to remove it. This is how: @@ -14,6 +14,6 @@ This is how: [image ./img/windows10-taskbar.png] -2. Go up to *[News and interests]*, and then click *[Turn off]* in the popped up window +2. Go up to [*News and interests*], and then click [*Turn off*] in the popped up window [image ./img/remove-newsweather-windows10.png] diff --git a/src/blog/sane-explanation-of-compilers/part-1/index.du b/src/blog/sane-explanation-of-compilers/part-1/index.du index 92ff9b4..e06bad4 100644 --- a/src/blog/sane-explanation-of-compilers/part-1/index.du +++ b/src/blog/sane-explanation-of-compilers/part-1/index.du @@ -50,7 +50,7 @@ Processors work with numbers, every action (instruction) a processor can do is d However, writing code only with numbers is tedious, error-prone and simple stuff sometimes take ages to implement. That is why, over time, programmers have tried to abstract sets of instructions into words and text constructions that are easier to work with. -'footnote how-did-we-get-here Though it's obvious, I would like to point out that modern compilers are most often written in languages that are themselves compiled. You might ask yourself "where did the first compiler come from?" The answer is simple: it was written with "numbers", with direct instructions to the processor, from the time when computers were simple enough that *[all]* programming was done with CPU instructions. +'footnote how-did-we-get-here Though it's obvious, I would like to point out that modern compilers are most often written in languages that are themselves compiled. You might ask yourself "where did the first compiler come from?" The answer is simple: it was written with "numbers", with direct instructions to the processor, from the time when computers were simple enough that [*all*] programming was done with CPU instructions. Thanks to abstraction, programmers have been able to create more and more complicated projects with less and less work, that is more portable and compatible with different machines. The trade-off is that we need to translate our nice programmer code to numbers a CPU would understand. @@ -75,8 +75,8 @@ void f(double d) { could be interpreted either as a: .numbered -1. declaration of variable `[i]`, which is initialized with the value of `[int(d)]` (which just casts `[d]` to an integer), or -2. function declaration, since superfluous parenthesis around function parameter declarations are allowed (meaning it is treated as `[int i(int d)]`) +1. declaration of variable [`i`], which is initialized with the value of [`int(d)`] (which just casts [`d`] to an integer), or +2. function declaration, since superfluous parenthesis around function parameter declarations are allowed (meaning it is treated as [`int i(int d)`]) Note that I'm talking about syntax, the valid selection and layouts of characters, and not semantics, the underlying meaning. Compiled programming languages associate specific templates of code (text) to their "corresponding" machine instructions, there isn't anything special you need to understand in a piece of code. @@ -103,14 +103,14 @@ When a word can be "generated" from the pattern, we say the regex matches the wo At their very base, such a pattern is created with the following rules: :unordered -- [url https://en.wikipedia.org/wiki/Concatenation concatenation] - you can put characters next to each other to form strings, so a normal string like `[accent]` is also a regex.\n +- [url https://en.wikipedia.org/wiki/Concatenation concatenation] - you can put characters next to each other to form strings, so a normal string like [`accent`] is also a regex.\n With braces we can group stuff. - For example, in `[a(cc)ent]` the two "c"s are grouped together. - This is used to form more sophisticated structures later on, but currently it doesn't alter anything, like the braces in `[(1+2)+3]` and `[1+(2+3)]` don't alter the result sum. + For example, in [`a(cc)ent`] the two "c"s are grouped together. + This is used to form more sophisticated structures later on, but currently it doesn't alter anything, like the braces in [`(1+2)+3`] and [`1+(2+3)`] don't alter the result sum. - [url https://en.wikipedia.org/wiki/Alternation_%28formal_language_theory%29 alternation] - allow different (alternative) strings in the same spot.\n We do so with vertical bars (which signify an "or" relationship), the group can be "replaced" with either value. - For example `[acce(n | p)t]`, matches both "acce=[n]=t" or "acce=[p]=t".\n + For example [`acce(n | p)t`], matches both "acce[=n=]t" or "acce[=p=]t".\n There is no limit on how many alternatives you can have and what their lengths are: ```regex @@ -119,9 +119,9 @@ acc(ordingly | ent | urate) matches .bulleted - - "acc=[ordingly]=" - - "acc=[ent]=" and - - "acc=[urate]=". + - "acc[=ordingly=]" + - "acc[=ent=]" and + - "acc[=urate=]". There is no limit on how many groups (with alternation) you can have: @@ -131,15 +131,15 @@ ac(quirem | c | hievem)en(t | ts) matches .bulleted - - "ac=[quirem]=en=[t]=" - - "ac=[quirem]=en=[ts]=" - - "ac=[c]=en=[t]= - - "ac=[c]=en=[ts]= - - "ac=[hievem]=en=[t]=" and - - "ac=[hievem]=en=[ts]=". + - "ac[=quirem=]en[=t=]" + - "ac[=quirem=]en[=ts=]" + - "ac[=c=]en[=t=] + - "ac[=c=]en[=ts=] + - "ac[=hievem=]en[=t=]" and + - "ac[=hievem=]en[=ts=]". - [url https://en.wikipedia.org/wiki/Kleene_star Kleene star] - repeat the preceding letter or group, 0 or more times.\n - An asterisk is used to mark this operation (hence the name, "Kleene =[star]="). + An asterisk is used to mark this operation (hence the name, "Kleene [=star=]"). ```regex accents* @@ -148,9 +148,9 @@ accents* .bulleted - "accent" - - "accent=[s]= - - "accent=[ss]= - - "accent=[sss]= + - "accent[=s=] + - "accent[=ss=] + - "accent[=sss=] - and so on Of course, the asterisk could also be in the middle of the regex, like @@ -162,8 +162,8 @@ ac*ent .bulleted - "acent" - - "ac=[c]=ent" - - "ac=[cc]=ent" + - "ac[=c=]ent" + - "ac[=cc=]ent" - ... With a group we can repeat entire strings, @@ -175,9 +175,9 @@ acc(ent)*s .bulleted - "accs" - - "acc=[ent]=s" - - "acc=[entent]=s - - "acc=[ententent]=s" + - "acc[=ent=]s" + - "acc[=entent=]s + - "acc[=ententent=]s" - ... An alternation allows any alternative to be chosen at any point, so @@ -189,13 +189,13 @@ acce(n | p)*t .bulleted - "accet" - - "acce=[n]=t - - "acce=[p]=t - - "acce=[nn]=t - - "acce=[np]=t" - - "acce=[pn]=t" - - "acce=[pp]=t" - - "acce=[nnn]=t" + - "acce[=n=]t + - "acce[=p=]t + - "acce[=nn=]t + - "acce[=np=]t" + - "acce[=pn=]t" + - "acce[=pp=]t" + - "acce[=nnn=]t" - ... @@ -208,12 +208,12 @@ However, even then regular expressions are fairly weak, they can't match recursi Let's say you want to be able to have math expressions in your language, you can have braces inside braces as much as you like, but in a certain manner: .bulleted -- `[1+2]` is a valid expression -- `[(9-8)+2]` also is valid -- `[((3*3)-(2^3))+2]` is too -- however `[()3*3)-(2^3()+2]` isn't valid +- [`1+2`] is a valid expression +- [`(9-8)+2`] also is valid +- [`((3*3)-(2^3))+2`] is too +- however [`()3*3)-(2^3()+2`] isn't valid -Such a structure is recursive, because it can contain "itself", `[1+2]` can be a standalone math expression, but it can also be contained in another expression, like `[(1+2)*3]`, which itself could be inside another bigger expressions and so on. +Such a structure is recursive, because it can contain "itself", [`1+2`] can be a standalone math expression, but it can also be contained in another expression, like [`(1+2)*3`], which itself could be inside another bigger expressions and so on. For this task we have a whole separate tool: grammars. 'footnote terminals-and-nonterminals Formally, we call the rule "names" nonterminals, the idea being that all normal characters, that could appear in our string, are called terminals, since they would terminate replacement and string generation. For the purposes of this post, I won't use the formal names, with the hope that using less terminology will increase understandability. @@ -223,12 +223,12 @@ Expressions are a concatenation of strings and/or names[$terminals-and-nontermin Names won't appear in our matched strings, the idea is that a name will be replaced with it's expression, kind of like a placeholders. Additionally, there can be multiple rules with the same name, meaning a rule can be replaced by different stuff at any point of the string generation. -'footnote grammar-syntax This is pretty much the mathematical notation, often in CS the Backus-Naur form is used, but I find that a bit harder to read. You might also make the argument that I should use a proper unicode arrow symbol, like `[→]`, but `[->]` is way more convinient. +'footnote grammar-syntax This is pretty much the mathematical notation, often in CS the Backus-Naur form is used, but I find that a bit harder to read. You might also make the argument that I should use a proper unicode arrow symbol, like [`→`], but [`->`] is way more convinient. Always one name is chosen to be the starting point, and generation continues from there. -In math literature, generally we write rules in the form `[Name -> Expression]` [$grammar-syntax], and often names are a single capital letter. -Additionally, often the starting name is called `[S]`. -Finally, in future examples, I'll use the arrow `[⇒]` to show derivations, how the generated string looks after one or two replacements of the name with one of it's expressions. +In math literature, generally we write rules in the form [`Name -> Expression`] [$grammar-syntax], and often names are a single capital letter. +Additionally, often the starting name is called [`S`]. +Finally, in future examples, I'll use the arrow [`⇒`] to show derivations, how the generated string looks after one or two replacements of the name with one of it's expressions. For an example, with the grammar @@ -236,18 +236,18 @@ For an example, with the grammar S -> aSb S -> cc -we can generate the string `[aaaaccbbbb]` (remember, our starting point is `[S]`): +we can generate the string [`aaaaccbbbb`] (remember, our starting point is [`S`]): ```grammar+ S ⇒ aSb ⇒ aaSbb ⇒ aaaSbbb ⇒ aaaaSbbbb ⇒ aaaaccbbbb -or `[accb]`: +or [`accb`]: ```grammar+ S ⇒ aSb ⇒ accb where a, b and c are just English characters. -To simplify our lives, often rules with the same name are merged into one rule, separated by vertical bars (`[S -> aSb | cc]`). +To simplify our lives, often rules with the same name are merged into one rule, separated by vertical bars ([`S -> aSb | cc`]). This is practically alternation but in a different context. As for our math expressions, we could create something like this: @@ -256,16 +256,16 @@ As for our math expressions, we could create something like this: N -> 0 | 1 | 2 | ... all possible numbers E -> N | (E) | E + E | E - E | E * E | E / E | E ^ E -which will successfully be able to match (generate) `[((3 * 3) - (2 ^ 3)) + 2]`: +which will successfully be able to match (generate) [`((3 * 3) - (2 ^ 3)) + 2`]: ```grammar+ E ⇒ E + E ⇒ (E) + N ⇒ (E - E) + 2 ⇒ ((E) - (E)) + 2 ⇒ ((E * E) - (E ^ E)) + 2 ⇒ ((N * N) - (N ^ N)) + 2 ⇒ ((3 * 3) - (2 ^ 3)) + 2 -but there are no expressions (rules) that allow `[()3+3()]` or `[)3(-6]` to be "matched". +but there are no expressions (rules) that allow [`()3+3()`] or [`)3(-6`] to be "matched". ### Lexers and parsers -You might've noticed that for `[N]` I use three dots and the note "all possible numbers" to signify that N can be any positive whole number. +You might've noticed that for [`N`] I use three dots and the note "all possible numbers" to signify that N can be any positive whole number. In practice we need formally define that grammar: ```grammar @@ -273,24 +273,24 @@ N -> 0 | 1 | 2 | ... | 9 | 0N | 1N | 2N | ... | 9N 'footnote regular-grammars Such grammars are called [url https://en.wikipedia.org/wiki/Regular_grammar regular grammars], more formally, every rule has to contain at most one name and that name must be at the start or end of the string characters. -With this you might've realised that grammars can do anything a regular expressions can: concatenation and alternation are "built-in", and the Kleene star can be done with another rule in the form `[R -> strR | str]` [$regular-grammars]. +With this you might've realised that grammars can do anything a regular expressions can: concatenation and alternation are "built-in", and the Kleene star can be done with another rule in the form [`R -> strR | str`] [$regular-grammars]. The reason we use both is that grammars are significantly slower and more complicated in code than regexes. #### Implementational difficulties with grammars -Implementing (very roughly) the regular expression `[acce(n | p)*t]` is quite easy: +Implementing (very roughly) the regular expression [`acce(n | p)*t`] is quite easy: ```c++ 'include ./regex_parser_simple.cpp In brief, for concatenated characters we do a simple comparison per character. -When we reach "\_", which I use to specify we're in the `[(n | p)*]` part of the regex, we do comparisons with the characters n and p as much as we can, after which we continue as normal. +When we reach "\_", which I use to specify we're in the [`(n | p)*`] part of the regex, we do comparisons with the characters n and p as much as we can, after which we continue as normal. Of course, this version only supports one regular expressions, however a "proper" implementation would look conceptually similar: a couple of different loops and equality checks, with maybe an additional array or two. The huge benefit is that that loops and arrays are stupid fast, a (simple) C++ for loop could be translated into [url https://godbolt.org/#g:!%28%28g:!%28%28g:!%28%28h:codeEditor,i:%28filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,selection:%28endColumn:16,endLineNumber:6,positionColumn:16,positionLineNumber:6,selectionStartColumn:16,selectionStartLineNumber:6,startColumn:16,startLineNumber:6%29,source:'//+Type+your+code+here,+or+load+an+example.%0Aint+f%28int+num%29+%7B%0A++++for+%28int+i+%3D+1%3B+i+%3C+100%3B+i%2B%2B%29+%7B%0A++++++++num+*%3D+100%3B%0A++++%7D%0A++++return+num%3B%0A%7D'%29,l:'5',n:'0',o:'C%2B%2B+source+%231',t:'0'%29%29,k:50,l:'4',n:'0',o:'',s:0,t:'0'%29,%28g:!%28%28h:compiler,i:%28compiler:g122,deviceViewOpen:'1',filters:%28b:'0',binary:'1',binaryObject:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'0',trim:'1'%29,flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,libs:!%28%29,options:'',selection:%28endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1%29,source:1%29,l:'5',n:'0',o:'+x86-64+gcc+12.2+%28Editor+%231%29',t:'0'%29%29,k:50,l:'4',n:'0',o:'',s:0,t:'0'%29%29,l:'2',n:'0',o:'',t:'0'%29%29,version:4 a handful of processor instructions]. On the other hand, usually grammars are more complicated and resource-intensive. -Certain ones are simple enough to implement, like `[S -> aSb | cc]`: +Certain ones are simple enough to implement, like [`S -> aSb | cc`]: ```cpp bool matchesp(string str) { @@ -304,16 +304,16 @@ bool matchesp(string str) { 'footnote context-free-grammars Be careful about cases that are too complicated, the grammar I'm showing is "context-free", but that topic is way beyond the scope of this post. -However think about more complicated cases[$context-free-grammars], like `[S -> aSbSa | cc]`. -Implementing this one is quite a bit more difficult, since we don't know where `[b]` is located on the first iteration, it could either be the 4th character `[accb...a]` or the 9th `[aaccbccab...a]`. -Searching for it is also complicated, it could be the first, the last or any other `[b]` in the middle of the string. +However think about more complicated cases[$context-free-grammars], like [`S -> aSbSa | cc`]. +Implementing this one is quite a bit more difficult, since we don't know where [`b`] is located on the first iteration, it could either be the 4th character [`accb...a`] or the 9th [`aaccbccab...a`]. +Searching for it is also complicated, it could be the first, the last or any other [`b`] in the middle of the string. Another difficulty with grammars is ambiguity, let's look at ```grammar E -> E + E | E * E | n -how would it generate `[n + n * n]`? +how would it generate [`n + n * n`]? There are two completely valid ways to do so: ```grammar+ @@ -332,7 +332,7 @@ Let's think a bit more about grammars: they're really good at handling structure Our math expression grammar (from [url #grammars here]) shouldn't really care if we're trying to sum integers or floats or chars[$static-typing], it's important how everything is laid out and that our operations are done with numbers. This is why we're going to separate and generalize the code into [url https://en.wikipedia.org/wiki/Lexical_analysis#Token tokens], basically into building blocks. -As a rough example, we want `[1 + (2 * 3)]` to be transformed into `[NUMBER MATHOP LBRACE NUMBER MATHOP NUMBER RBRACE]`, `[int var = 13;]` into `[TYPE NAME ASSIGNMENT NUMBER]` and so on, where "TYPE", "NUMBER", "NAME", ... are tokens. +As a rough example, we want [`1 + (2 * 3)`] to be transformed into [`NUMBER MATHOP LBRACE NUMBER MATHOP NUMBER RBRACE`], [`int var = 13;`] into [`TYPE NAME ASSIGNMENT NUMBER`] and so on, where "TYPE", "NUMBER", "NAME", ... are tokens. Now we're reducing the amount of "objects" our grammars need to work on: from all characters to many (but significantly fewer) tokens. Also we're simplifying our work, since we're trying to figure out the overall structure, it doesn't matter if we're multiplying or summing numbers, it's important that we're doing a mathematical operation on them. Of course, each token will actually be a pair, containing it's name (NUMBER, TYPE, ...) and it's value, but our grammars will work with the names only and output the actual values at the very end. @@ -340,9 +340,9 @@ Usually we identify at least six token types: .bulleted - identifiers: variable and function names for example -- keywords: `[if]`, `[while]`, `[for]`, `[return]`, ... -- separators: braces, `[;]` -- operators: `[+]`, `[-]`, `[<=]` +- keywords: [`if`], [`while`], [`for`], [`return`], ... +- separators: braces, [`;`] +- operators: [`+`], [`-`], [`<=`] - literals: numbers, strings, characters - comments @@ -387,14 +387,14 @@ We check the first k character of all expressions, and if anyone of them is a na 'snippet 1 2 ./grammar_trace_1.txt is LL(1). - Let's read the input `[(a + a)]` (the "v" points to the symbol we're looking/peeking at): + Let's read the input [`(a + a)`] (the "v" points to the symbol we're looking/peeking at): ```grammar 'snippet 4 8 ./grammar_trace_1.txt - we start with `[S]`, we peek and get the `[(]`, in our production we're looking at a name, S. + we start with [`S`], we peek and get the [`(`], in our production we're looking at a name, S. Let's check the first character of every expression of S. - In the first expression, the first "character" is `[F]`, a name, so we look at every expression for `[F]`. + In the first expression, the first "character" is [`F`], a name, so we look at every expression for [`F`]. There is only one, which is "a", different than "(", no dice. Now we check the second expression for S, it's first character is "(", success! We replace: @@ -402,18 +402,18 @@ We check the first k character of all expressions, and if anyone of them is a na ```grammar 'snippet 10 14 ./grammar_trace_1.txt - Now the first symbol in our production is also `[(]`, so we increment the symbols we're looking/peeking at + Now the first symbol in our production is also [`(`], so we increment the symbols we're looking/peeking at ```grammar 'snippet 16 20 ./grammar_trace_1.txt - we peek and get the `[a]`, in our production the second "character" is the name `[S]`, `[S]` has to become `[a]`. - We do that same check from before, first expression for `[S]` is `[F]`, whose first (and only) expression is `[a]`, success! + we peek and get the [`a`], in our production the second "character" is the name [`S`], [`S`] has to become [`a`]. + We do that same check from before, first expression for [`S`] is [`F`], whose first (and only) expression is [`a`], success! ```grammar 'snippet 22 26 ./grammar_trace_1.txt - The middle characters " + " are matched and at the second `[F]` we check it's expressions, it has only `[a]`, success, replace, end of input, we're done. + The middle characters " + " are matched and at the second [`F`] we check it's expressions, it has only [`a`], success, replace, end of input, we're done. Another LL(1) example can be found in [url http://www.cs.ecu.edu/karl/5220/spr16/Notes/Top-down/LL1.html Karl R. Abrahamson notes]. @@ -425,8 +425,8 @@ C -> c S -> aaB | aaC is LL(3). - For the input `[aab]`, if we look at the first two "a"s, we still don't know which rule to use: `[aaB]` or `[aaC]`. - However if we look at the third symbol, "b", then we can determine that we need `[aaB]`. + For the input [`aab`], if we look at the first two "a"s, we still don't know which rule to use: [`aaB`] or [`aaC`]. + However if we look at the third symbol, "b", then we can determine that we need [`aaB`]. - Usually parsers that implement this procedure are called [url https://en.wikipedia.org/wiki/Recursive_descent_parser recursive descent parsers] @@ -454,9 +454,9 @@ It all boils down to using a whole bunch of conditional statements and tracing w |: 0 |: Nothing; this is the start |: 1 - |: The name `[S]`; the final number should be this + |: The name [`S`]; the final number should be this |: 2 - |: The name `[F]` + |: The name [`F`] |: 3 |: The character "(" |: 4 @@ -504,7 +504,7 @@ It all boils down to using a whole bunch of conditional statements and tracing w 'snippet 16 17 ./grammar_trace_2.txt We have a different state for "(S", because if we didn't, we would've gone to state 1, and could've ended the algorithm then and there, without reading the rest of the input. - Otherwise, we continue as normal, we read the `[+]` and the spaces around it, going to state 6. + Otherwise, we continue as normal, we read the [`+`] and the spaces around it, going to state 6. ``` 'snippet 19 20 ./grammar_trace_2.txt @@ -623,9 +623,9 @@ It all boils down to using a whole bunch of conditional statements and tracing w .bulleted - on every row you have each state - on every column you have each possible value in the string and "$" which signifies the end of the string - - with `[sr]` or `[shift]` (or just with a number) you go to another state - - with `[r]` or `[reduce]` you make the substitution in the current string and go back one state - - `[acc]` or `[accept]` means you've reached the end and the string is valid + - with [`sr`] or [`shift`] (or just with a number) you go to another state + - with [`r`] or [`reduce`] you make the substitution in the current string and go back one state + - [`acc`] or [`accept`] means you've reached the end and the string is valid ##### LR's family @@ -656,7 +656,7 @@ If you want to learn more, I would highly suggest: #### Abstract syntax tree We already decided that the lexer will output tokens (and characters) to the parser, but we didn't talk about what the parser is supposed to output. -It definitely has to be some sort of structural representation of the overall code, for example, for `[3 + 1 * 2]` we have to be able to easily find out what the left and right handsides of the `[+]` and `[*]` are. +It definitely has to be some sort of structural representation of the overall code, for example, for [`3 + 1 * 2`] we have to be able to easily find out what the left and right handsides of the [`+`] and [`*`] are. 'footnote nomnoml The graphics are made with [url https://nomnoml.com/ nomnoml] by [url https://github.com/skanaar Daniel Kallin] @@ -665,7 +665,7 @@ Let's draw out[$nomnoml] this relationship, where the left arrow connects to the [image ./img/tree-simple.svg] Hey, that looks an awful lot like a [url https://en.wikipedia.org/wiki/Tree_%28data_structure%29 tree]! -Trees are nodes, some sort of elements, where there is a connection from one element to some other elements, with the only rule being that cycles =[aren't]= allowed: +Trees are nodes, some sort of elements, where there is a connection from one element to some other elements, with the only rule being that cycles [=aren't=] allowed: [image ./img/tree-cycle.svg] @@ -689,49 +689,49 @@ Let's look at a familiar example: N -> 1 | 2 | 3 E -> N | (E) | E + E | E * E -Let's look at the input string `[2 * (1 + 3)]`, while abstracting ourselves from any particular algorithm: +Let's look at the input string [`2 * (1 + 3)`], while abstracting ourselves from any particular algorithm: :unordered -- we read the `[2]`, that is a number, we add it as a node +- we read the [`2`], that is a number, we add it as a node .p [image ./img/tree-building-1.svg] -- then we read the `[*]`, we now know our expression is in the form `[E* E]`. +- then we read the [`*`], we now know our expression is in the form [`E* E`]. If you think about it, up to this point, we've basically been building a tree for the left handside. - =[If]= the topmost element in that tree is a brace, + [=If=] the topmost element in that tree is a brace, .p [image ./img/tree-building-ex1.svg] - we connect it to the left handside of `[*]`: + we connect it to the left handside of [`*`]: .p [image ./img/tree-building-ex2.svg] - =[Otherwise]= (when it's `[+]` or `[*]` or a number), because of precedence, we'll attach the latest number to the left handside. - However we have to be careful, if something connects to the number, we now need it to connect to the `[*]`.\n - For example, let's say we had `[1 + 2 * 3]`, and we've just read the `[*]`. + [=Otherwise=] (when it's [`+`] or [`*`] or a number), because of precedence, we'll attach the latest number to the left handside. + However we have to be careful, if something connects to the number, we now need it to connect to the [`*`].\n + For example, let's say we had [`1 + 2 * 3`], and we've just read the [`*`]. The tree up to this point would look like, .p [image ./img/tree-building-ex3.svg] - where the latest number we've found was `[2]`, but the `[+]` connects to it. - So, we need to make the `[2]` connect to the left handside of `[*]`, and make `[+]` connect to `[*]` instead of `[2]` + where the latest number we've found was [`2`], but the [`+`] connects to it. + So, we need to make the [`2`] connect to the left handside of [`*`], and make [`+`] connect to [`*`] instead of [`2`] .p [image ./img/tree-building-ex4.svg] - In our original case, nothing connects to the `[2]` in `[2 * (1 + 3)]`, so we can just connect it to the left handside of `[*]` + In our original case, nothing connects to the [`2`] in [`2 * (1 + 3)`], so we can just connect it to the left handside of [`*`] .p [image ./img/tree-building-2.svg] where the three dots signify there isn't anything there (but we expect there to be). Somewhere we'll store that the next element we find has to be connected to the right handside. -- now we read `[(]`, we cannot have it by itself, so we directly decide we're working with `[(E)]` (in our full algorithm we would need a check for existance of matching brace). - We'll create a `[()]` node and because of the last step, we'll connect it to the right handside. +- now we read [`(`], we cannot have it by itself, so we directly decide we're working with [`(E)`] (in our full algorithm we would need a check for existance of matching brace). + We'll create a [`()`] node and because of the last step, we'll connect it to the right handside. .p [image ./img/tree-building-3.svg] - Now, moving forward, we'll be creating a subtree, essentially making a second tree, and after that is done, we'll connect it's topmost element (root) to the `[()]` node. + Now, moving forward, we'll be creating a subtree, essentially making a second tree, and after that is done, we'll connect it's topmost element (root) to the [`()`] node. - and so on. @@ -757,42 +757,42 @@ A lex source file is divided into three parts: ```lex 'include ./template.l -where `[%{%}]` is used for includes and declarations, the rules are your regular expressions and the C code is the general logic of the lexer. -Usually you wouldn't write anything in the C code section, the defaults are fine, but you'll probably need to do one or two includes in the `[%{%}]` section. +where [`%{%}`] is used for includes and declarations, the rules are your regular expressions and the C code is the general logic of the lexer. +Usually you wouldn't write anything in the C code section, the defaults are fine, but you'll probably need to do one or two includes in the [`%{%}`] section. -Rules are in the form `[regex { C_code }]`. +Rules are in the form [`regex { C_code }`]. To simplify your life, you can write only the regex or a part of it inside the "definitions" part of the file, and give it a name to use later. Referencing those names in later regexes is done by surrounding them in curly braces. -Usually the `[C_code]` in the regex would be a return (more commonly called "emit") of a token, which will be available in a header file, but more on that later. +Usually the [`C_code`] in the regex would be a return (more commonly called "emit") of a token, which will be available in a header file, but more on that later. Let's look at a very simple example program: every whole number is printed as "NUMBER", while everything else is printed as-is: ```lex 'include ./example_lex/lexer.l -The syntax `[[0-9]]` is the same as `[(0 | 1 | ... | 9)]`, it works for any letters and is available in all modern regexes. -Note that inside every regex's "body" you have an assortment of variables already set, one of them being `[yytext]` which is just the whole match. -Additionally lex matches the longest possible match, so if we had a rule `[[0-z]]`, only it will be matched. +The syntax [`[0-9]`] is the same as [`(0 | 1 | ... | 9)`], it works for any letters and is available in all modern regexes. +Note that inside every regex's "body" you have an assortment of variables already set, one of them being [`yytext`] which is just the whole match. +Additionally lex matches the longest possible match, so if we had a rule [`[0-z]`], only it will be matched. -If this file is located in `[lexer.l]`, we can transform it into a C file with: +If this file is located in [`lexer.l`], we can transform it into a C file with: ```bash flex lexer.l -Usually the result file is always named `[lex.yy.c]`. +Usually the result file is always named [`lex.yy.c`]. Afterwards, we can compile the C code into a working compiler: ```bash gcc lex.yy.c -lfl -Without the `[-lfl]` flag, we would get a linking error, because of the `[main]` and `[yywrap]` function, which are required but aren't defined in our generated code. +Without the [`-lfl`] flag, we would get a linking error, because of the [`main`] and [`yywrap`] function, which are required but aren't defined in our generated code. There are three ways to fix this problem: :numbered -1. The one I've opted for, use the `[-lfl]` flag to compile our C code with a (flex) library which provides both functions. - Usually the lexer isn't meant to be ran by itself, so for the current time being, `[-lfl]` is the best option, the other two are fine when we get to `[yacc]`. +1. The one I've opted for, use the [`-lfl`] flag to compile our C code with a (flex) library which provides both functions. + Usually the lexer isn't meant to be ran by itself, so for the current time being, [`-lfl`] is the best option, the other two are fine when we get to [`yacc`]. -2. Put `[%option noyywrap]` in the definitions section, which means the lexer will only read one file. +2. Put [`%option noyywrap`] in the definitions section, which means the lexer will only read one file. 3. Define it ourselves. It should return 0 if our lexer should continue with the next given file, after finishing with the current one, or 1 if it should stop execution. @@ -803,7 +803,7 @@ int yywrap() { return 0; } Of course, you can use your lex implementation or C compiler of choice, and there this might not be a problem. -Now, if you run `[./a.out]` you would get a prompt, every line you write will be lexically analyzed and in our case, everything will be printed out. +Now, if you run [`./a.out`] you would get a prompt, every line you write will be lexically analyzed and in our case, everything will be printed out. Entering ``` @@ -854,13 +854,13 @@ A yacc file looks very similarly to a lex one: however rather than definitions you have declarations, and the rules are in a completely different format (because they're grammars). -Token names are defined in `[declarations]`, in the format +Token names are defined in [`declarations`], in the format ```yacc %token NAME1 NAME2 ... -You can also define precedence with `[%left]` and `[%right]`. -There are also other options you can set, like the start name with `[%start]`. +You can also define precedence with [`%left`] and [`%right`]. +There are also other options you can set, like the start name with [`%start`]. Grammars are in the form @@ -876,7 +876,7 @@ name : TOKEN1 | TOKEN3 ; -and it always must end with a `[;]`. +and it always must end with a [`;`]. On each alternation, you can (should) specify a body, which will contain C code to be executed, if this rule is reached ```yacc @@ -896,7 +896,7 @@ N -> 1 | 2 | 3 S -> N | (S + S) | (S * S) First, our tokens, we want to replace all characters with a token. -For 1, 2 and 3, let's use the token name "NUMBER", for "(" and ")", LBRACE and RBRACE accordingly, and since there is no precedence with this grammar, we don't actually care if we have `[(S + S)]` or `[(S * S)]`, so we can assign both `[+]` and `[*]` to the token MATHOP. +For 1, 2 and 3, let's use the token name "NUMBER", for "(" and ")", LBRACE and RBRACE accordingly, and since there is no precedence with this grammar, we don't actually care if we have [`(S + S)`] or [`(S * S)`], so we can assign both [`+`] and [`*`] to the token MATHOP. Meaning, our grammar would behave more like this: ```grammar @@ -904,21 +904,21 @@ N -> 1 | 2 | 3 M -> + | * S -> N | (S M S) -First, we need to make our `[lexer.l]`, it is going to be very simple: +First, we need to make our [`lexer.l`], it is going to be very simple: ```lex 'include ./example_yacc/lexer.l Now, tokens (names) are defined inside grammars, however our lexer needs to emit (return) them. -That's why, when running bison on our `[parser.y]`, we'll also create a C header file, which contains those names already defined, so they're accessible inside `[lexer.l]`. -This file is in the format `[FILENAME.tab.h]`, where `[FILENAME.y]` is our source yacc file. +That's why, when running bison on our [`parser.y`], we'll also create a C header file, which contains those names already defined, so they're accessible inside [`lexer.l`]. +This file is in the format [`FILENAME.tab.h`], where [`FILENAME.y`] is our source yacc file. -Second, we need to make our `[parser.y]`: +Second, we need to make our [`parser.y`]: ```yacc 'include ./example_yacc/parser.y -A quirk with GNU Bison is that you need to declare the function `[yylex]` and `[yyerror]` beforehand, manually define `[yyerror]` and run `[yyparse]` in the main function. +A quirk with GNU Bison is that you need to declare the function [`yylex`] and [`yyerror`] beforehand, manually define [`yyerror`] and run [`yyparse`] in the main function. These are precisely the first 5 and the last 8 lines of code, but for now you don't need to think about them. Let's get to compiling. @@ -932,13 +932,13 @@ then our parser: ```bash bison -d parser.y -where the `[-d]` option means we'll also output the `[parser.tab.h]` header file. +where the [`-d`] option means we'll also output the [`parser.tab.h`] header file. Finally, we compile both of them together into one executable: ```bash gcc lex.yy.c parse.tab.c -lfl -Now when you run `[./a.out]`, if you enter a valid string, you'll see a blank line, but if it isn't valid, you'll get "Error: syntax error". +Now when you run [`./a.out`], if you enter a valid string, you'll see a blank line, but if it isn't valid, you'll get "Error: syntax error". #### Doing it properly @@ -946,8 +946,8 @@ The way we created that lexer and parser worked, but it wasn't very useful and h :ordered 1. When entering a string that isn't matched at all, it gets printed back like nothing happened. - For example, if we enter the letter `[a]` or any string which doesn't have `[(]`, `[)]`, `[1]`, `[2]`, `[3]`, `[+]` or `[-]` characters, it will just get printed back. - Ideally, we want to raise an error, so we're going to add one rule which catches any (non-special) character and throws an error with the built-in `[yy_fatal_error]`: + For example, if we enter the letter [`a`] or any string which doesn't have [`(`], [`)`], [`1`], [`2`], [`3`], [`+`] or [`-`] characters, it will just get printed back. + Ideally, we want to raise an error, so we're going to add one rule which catches any (non-special) character and throws an error with the built-in [`yy_fatal_error`]: ```lex . { yy_fatal_error("Bad character"); } @@ -956,10 +956,10 @@ The way we created that lexer and parser worked, but it wasn't very useful and h Remember that lex matches the longest possible string and if there are multiple rules which match the same amount of characters, only the first one is matched. 2. For every token name, returned by the lexer, we also need to have it's actual value. - We could make a `[struct]`, which holds both a token name and it's value, but there is another [url https://www.gnu.org/software/bison/manual/html_node/Token-Values.html "built-in" mechanism] for that in yacc/Bison. - We would set the global variable `[yylval]` to the token value, and it will be changed for every token. + We could make a [`struct`], which holds both a token name and it's value, but there is another [url https://www.gnu.org/software/bison/manual/html_node/Token-Values.html "built-in" mechanism] for that in yacc/Bison. + We would set the global variable [`yylval`] to the token value, and it will be changed for every token. - By default it's type is `[int]` (in Bison), but usually you would want it to be a [url https://en.wikipedia.org/wiki/Union_type#C/C++ union]. + By default it's type is [`int`] (in Bison), but usually you would want it to be a [url https://en.wikipedia.org/wiki/Union_type#C/C++ union]. Let's make it a union of int and char, though the first part is kind of useless, since we're only working with single digit numbers. \n ```yacc @@ -974,26 +974,26 @@ The way we created that lexer and parser worked, but it wasn't very useful and h RULE1 { yylval.num = 129; return TOKEN; } RULE2 { yylval.chr = 'a'; return TOKEN; } - Inside C blocks for grammar rules we can reference the token values with `[\$i]`, where `[i]` is the i'th "token" in the expression. - For example, in this rule, `[\$1]` would be `[(]`, `[\$3]` would be value of token `[B]` and `[\$5]` would be the value of the rule name: + Inside C blocks for grammar rules we can reference the token values with [`\$i`], where [`i`] is the i'th "token" in the expression. + For example, in this rule, [`\$1`] would be [`(`], [`\$3`] would be value of token [`B`] and [`\$5`] would be the value of the rule name: ```yacc rule : ( A B ) rule ; - You can set rule "return" values by setting the variable `[\$$]`: + You can set rule "return" values by setting the variable [`\$$`]: ```yacc rule : LBRACE rule RBRACE { $$ = 10; } The way you set it's type is discussed later. - However, `[\$i]` isn't of type union, we cannot do something like `[\$i.num]`, it is the precise value that was set for the token. - Therefore, we also need to define which value from the union every token will set, which is done by adding `[<PROPERTY>]` before every defined token (and `[PROPERTY]` is a property name inside the union): + However, [`\$i`] isn't of type union, we cannot do something like [`\$i.num`], it is the precise value that was set for the token. + Therefore, we also need to define which value from the union every token will set, which is done by adding [`<PROPERTY>`] before every defined token (and [`PROPERTY`] is a property name inside the union): ```yacc %token <num> NUMBER <chr> MATHOP <chr> LBRACE <chr> RBRACE - 'footnote better-bison-errors You can add `[%define parse.error verbose]` inside definitions of your yacc file, and it will tell you what character was expected and what character was read. + 'footnote better-bison-errors You can add [`%define parse.error verbose`] inside definitions of your yacc file, and it will tell you what character was expected and what character was read. 3. If we enter one valid math expression, we'll get no error, but when we enter another, we'll get a "syntax error"[$better-bison-errors]. That is because we try to match only one expression, after it is matched our parser is waiting for an end of file character. @@ -1004,11 +1004,11 @@ start : expr | expr start ; - A rule like `[expr : expr expr]` will produce shift/reduce conflicts. - Another option is duplicating our `[expr]` rules and adding `[expr]` in the beginning or end, but that is cumbersome if we want to make changes. + A rule like [`expr : expr expr`] will produce shift/reduce conflicts. + Another option is duplicating our [`expr`] rules and adding [`expr`] in the beginning or end, but that is cumbersome if we want to make changes. 4. We're getting input from the user, but our source text (code) will be in a file. - First, our `[main]` function needs to take program parameters: + First, our [`main`] function needs to take program parameters: ```yacc int main(int argc, char* argv[]) @@ -1023,20 +1023,20 @@ if (input == NULL) { return 1; } - Now for the clever bit, actual parsing in generated code is done on the file `[yyin]`, which by default is the standard user input. + Now for the clever bit, actual parsing in generated code is done on the file [`yyin`], which by default is the standard user input. To read a file, all we need to do is change the value of that variable. Also, that variable is defined externally, so first we need to add to (the top) C section: ```yacc extern FILE* yyin; - and then put in our `[main]`: + and then put in our [`main`]: ```yacc yyin = input; - On \*NIX systems (Linux, MacOS, OpenBSD, ...) you can still use user input by passing the file `[/dev/stdin]`. - If you want your front-end to support multiple files, you would just need to wrap the whole body of main in a `[for]` loop, iterating over the whole `[argv]` array (remember that `[argc]` is the length of the array). + On \*NIX systems (Linux, MacOS, OpenBSD, ...) you can still use user input by passing the file [`/dev/stdin`]. + If you want your front-end to support multiple files, you would just need to wrap the whole body of main in a [`for`] loop, iterating over the whole [`argv`] array (remember that [`argc`] is the length of the array). 5. We need to construct an AST. Since the exact tree structure depends on your needs, I'll make the simplest possible tree in pure C that works for this grammar. @@ -1047,44 +1047,44 @@ yyin = input; #include <stdio.h> 'snippet 2 $ ./proper/tree.c - However, all of this is quite a lot, and it would take a lot of space in `[parser.y]`, so let's separate it into `[tree.c]` and add a header file `[tree.h]` which contains the definitions: + However, all of this is quite a lot, and it would take a lot of space in [`parser.y`], so let's separate it into [`tree.c`] and add a header file [`tree.h`] which contains the definitions: ```c 'snippet 4 15 ./proper/tree.h Of course, we should add some ifndef-def precompiler code, but that isn't relevant for now. - The way we're going to use trees in our grammar is as follows: for the `[NUMBER]` expression of `[expr]`, we'll create a node with the (char) value of the number and "return" it. - For the expression of `[expr]` we'll "return" a node with the value of the math operator and left and right will be the returned values. - Inside start, after we've parsed an `[expr]`, we'll print out the "returned" tree and free it's memory. + The way we're going to use trees in our grammar is as follows: for the [`NUMBER`] expression of [`expr`], we'll create a node with the (char) value of the number and "return" it. + For the expression of [`expr`] we'll "return" a node with the value of the math operator and left and right will be the returned values. + Inside start, after we've parsed an [`expr`], we'll print out the "returned" tree and free it's memory. - I'm putting returned in quotes, because (as mentioned), we'll just be setting the value of `[\$$]`. - `[\$$]`'s type is set with the `[%type]` option, which works exactly like `[%token]`, but with grammar rule names. - However, this means that `[node]` must be available in `[%union]`, which is unfortunate but isn't a problem, we'll just add it. + I'm putting returned in quotes, because (as mentioned), we'll just be setting the value of [`\$$`]. + [`\$$`]'s type is set with the [`%type`] option, which works exactly like [`%token`], but with grammar rule names. + However, this means that [`node`] must be available in [`%union`], which is unfortunate but isn't a problem, we'll just add it. - Now, finally, it's time to include our `[tree.h]` in `[parser.y]`, but we'll also need to include it in `[lexer.l]`. - The reason is that the `[%union]` appears in `[parser.tab.h]`, which means our node structure is referenced in `[parser.tab.h]`, but `[tree.h]` isn't included there. + Now, finally, it's time to include our [`tree.h`] in [`parser.y`], but we'll also need to include it in [`lexer.l`]. + The reason is that the [`%union`] appears in [`parser.tab.h`], which means our node structure is referenced in [`parser.tab.h`], but [`tree.h`] isn't included there. All in all, we'll have 4 source files for our simple front-end: :unordered -- `[lexer.l]` +- [`lexer.l`] ```lex 'include ./proper/lexer.l -- `[parser.y]` +- [`parser.y`] ```yacc 'include ./proper/parser.y -- `[tree.h]` +- [`tree.h`] ```c 'include ./proper/tree.h -- `[tree.c]` +- [`tree.c`] ```c 'include ./proper/tree.c @@ -1095,7 +1095,7 @@ We compile everything: ```bash flex lexer.l && bison -d parser.y && gcc lex.yy.c parser.tab.c tree.c -Now, let's create the file `[test.txt]`: +Now, let's create the file [`test.txt`]: ``` 'include proper/test.txt diff --git a/src/blog/switchut-izgorq/index.du b/src/blog/switchut-izgorq/index.du index 4df8f6b..1f23862 100644 --- a/src/blog/switchut-izgorq/index.du +++ b/src/blog/switchut-izgorq/index.du @@ -11,7 +11,7 @@ Обаче, тъкмо като интернетът се върна и мрежарят беше готов да си тръгне, услугата взе че спря отново. Вече доста изнервен, след като провери шкафът още един път, влезе в сградата, изтръгна старият суич (комутатор, но аз съм отраснал с английските наименования), замени го с нов и всичко тръгна. -Неговият отговор, разбира се, беше че "Суичът е изгорял", заедно с един *[любезен]* коментар как "Тази инсталация вече е стара, трябва да си купите оптичен интернет, за да не ви горят суичовете и да не трябва да идвам аз!" +Неговият отговор, разбира се, беше че "Суичът е изгорял", заедно с един [*любезен*] коментар как "Тази инсталация вече е стара, трябва да си купите оптичен интернет, за да не ви горят суичовете и да не трябва да идвам аз!" Предвидимо, самият суич ни го беше оставил и си тръгна по пътя. Та по-късно през деня седнах с един [url https://www.globalsources.com/AC-DC-adapter/plug-in-AC-DC-Adapter-1188075760p.htm стар AC/DC адаптер] и какво намирам: устройството си работи перфектно. @@ -26,7 +26,7 @@ Благодарение на етикетът, бързо се намира и оригиналната [url https://networkpartner.eu/product/8-port-gb-switch/ уебстраница на която NetworkPartner са го продавали]. Единственият въпрос който остава, е какво е накарало интернетът да спре втория път? -Оригиналната инсталация идва от М-Тел, и техния *[талант]* е решил да остави суичът да си виси във въздуха, държан само от кабелите, които се свързват към него, включително кабела за захранване. +Оригиналната инсталация идва от М-Тел, и техния [*талант*] е решил да остави суичът да си виси във въздуха, държан само от кабелите, които се свързват към него, включително кабела за захранване. Моето предположение е, че захранването просто се е изплъзнало с малко от буксата докато са го оглеждали. diff --git a/src/blog/taming-the-fun-too/index.du b/src/blog/taming-the-fun-too/index.du index bbaa677..07e7b63 100644 --- a/src/blog/taming-the-fun-too/index.du +++ b/src/blog/taming-the-fun-too/index.du @@ -5,13 +5,13 @@ 'define edited 04 December 2022 [$pagenav] -Let's set the scene: it's October of last year and I just began my first year as a university student. For the first time in my life, I was able to meet people who were significantly ~[nerdier]~ cooler than me. +Let's set the scene: it's October of last year and I just began my first year as a university student. For the first time in my life, I was able to meet people who were significantly [~nerdier~] cooler than me. One particular dude I met introduced me to [url https://funtoo.org Funtoo], a boutique fork of [url https://gentoo.org Gentoo]. Now, I'm not a very big fan of distro hopping, it takes too much time and you often find yourself not liking the finished product, resulting in further distro hopping. -However, at that time I was a bit softened by my growing pains with Fedora, the sweat promises of improved efficiency and usability, and the fact that fun is in the name! *[What could go wrong]* :) +However, at that time I was a bit softened by my growing pains with Fedora, the sweat promises of improved efficiency and usability, and the fact that fun is in the name! [*What could go wrong*] :) -So, about a month later I bit the bullet, and installed it on my main computer. It has now been a tad more than a year later and I can comfortably say: *[a lot could go wrong...]* +So, about a month later I bit the bullet, and installed it on my main computer. It has now been a tad more than a year later and I can comfortably say: [*a lot could go wrong...*] \n @@ -19,32 +19,32 @@ In the same way that a distro is made to solve a certain problem, every distro i 'footnote ebuilds Files with instructions and settings for the package manager (portage) on how to build a specific package -Then there's Funtoo. You might reason, since it's a fork of Gentoo, it's big flaw is the fact that you need to compile every package, with the prize being unparalleled efficiency. So did I, but as it turns out there is another, much larger flaw: =[packages]=. +Then there's Funtoo. You might reason, since it's a fork of Gentoo, it's big flaw is the fact that you need to compile every package, with the prize being unparalleled efficiency. So did I, but as it turns out there is another, much larger flaw: [=packages=]. The distribution is a lot smaller than it's big brother so a lot of stuff, understandably, cannot be tested. However, the real kicker is that package ebuilds[$ebuilds] are generated in a different way from Gentoo. This often means that using a Gentoo ebuild will make the problem even worse, but sometimes it does work out. \n The first such problem child was QtWebEngine. As the name suggests, it gives the ability for graphical applications, made with the Qt framework, to render webpages. -I don't *[need]* it for my setup, but there are a couple of useful programs that required it. +I don't [*need*] it for my setup, but there are a couple of useful programs that required it. -What would happen is, after about 3 hours of compiling, the compilation would just stop, without any errors, anywhere. To add insult to injury, because I hadn't set up [url https://ccache.dev/ ccache] at the time, everything would have to be compiled *[all over again]*. +What would happen is, after about 3 hours of compiling, the compilation would just stop, without any errors, anywhere. To add insult to injury, because I hadn't set up [url https://ccache.dev/ ccache] at the time, everything would have to be compiled [*all over again*]. A fairly deep dive into different forums led me to the wondrous conclusion that I needed to remove a certain build flag, which wasn't enabled in the first place... -After *[much]* tweaking and trying, I found out there just wasn't enough memory, the package needed at least 32 GiB (including swap) of memory for a successful compilation... D'oh! -And here comes the really bad part: I had setup a swapfile of adequate size! However, as it turned out, in the configuration I tried loading it before loading the drive it was stored in... =[Double D'OH!!]= +After [*much*] tweaking and trying, I found out there just wasn't enough memory, the package needed at least 32 GiB (including swap) of memory for a successful compilation... D'oh! +And here comes the really bad part: I had setup a swapfile of adequate size! However, as it turned out, in the configuration I tried loading it before loading the drive it was stored in... [=Double D'OH!!=] \n Then came the big boss: python. Now, I wasn't planning on doing any software development with it, but as it turned out, other people had, so certain packages had building issues. And what was the exact issue you might ask? -Well, to put it simply, Funtoo had official ebuilds for python 3.7, but a lot of packages needed at least version 3.8. This time however, I had a *[brilliant]* idea: I would copy Gentoo's python 3.8 ebuilds! +Well, to put it simply, Funtoo had official ebuilds for python 3.7, but a lot of packages needed at least version 3.8. This time however, I had a [*brilliant*] idea: I would copy Gentoo's python 3.8 ebuilds! 'footnote circular-dependency To build package A you'll need to have package B installed. But to build package B, you'll need package A installed. What I didn't realize, was that I had unknowingly opened Pandora's box. -Over time I needed to install more and more python packages from Gentoo, until one day I created an *[unsolvable]* circular dependency[^circular-dependency]. -Usually there are solutions to such situations, but I kid you not, I had tried =[everything]= and =[nothing worked]=. +Over time I needed to install more and more python packages from Gentoo, until one day I created an [*unsolvable*] circular dependency[^circular-dependency]. +Usually there are solutions to such situations, but I kid you not, I had tried [=everything=] and [=nothing worked=]. This time, there isn't even a solution, I just made sure to never upgrade these packages again. Which proved problematic, since these packages were important and over time other stuff broke, but that wouldn't be relevant for long. @@ -64,14 +64,14 @@ Aborting to save your system. "Umm what?" was my reaction too. For reasons not completely clear to me, this turns out to be yet another roadblock. Did I mention a couple applications also stopped working after the upgrade? Unfortunately my believes and ego were firmly set in stone, "Yeah, but I know what I'm doing, I'm downgrading from a non-Funtoo glibc, it will be fine!" -A sanity check override and a package downgrade later, *[it wasn't...]* +A sanity check override and a package downgrade later, [*it wasn't...*] Yes, my system was broken. Very broken. So broken in fact, portage wasn't working, so un-downgrading was not an option. And, of course, booting successfully my machine up ever again wasn't an option either... Thank goodness for [url https://github.com/linuxmint/timeshift Timeshift]'s system restore functionality or I would've had to rebuild my whole system. \n -There are =[a lot]= of other situations in which Funtoo's package difficulties and my sheer incompetence have led to wasted time and broken stuff, but these are the main ones that stand out in my mind (or more accurately, the ones that I still remember). Nowadays I use the distro in a much smarter fashion, with a much tighter grip. +There are [=a lot=] of other situations in which Funtoo's package difficulties and my sheer incompetence have led to wasted time and broken stuff, but these are the main ones that stand out in my mind (or more accurately, the ones that I still remember). Nowadays I use the distro in a much smarter fashion, with a much tighter grip. 'footnote mask All ebuilds that are "masked", will not be used (therefore, corresponding package will not be compiled and installed/upgraded) diff --git a/src/blog/the-physics-behind-a-black-hole-shader/index.du b/src/blog/the-physics-behind-a-black-hole-shader/index.du index 739e546..35c0450 100644 --- a/src/blog/the-physics-behind-a-black-hole-shader/index.du +++ b/src/blog/the-physics-behind-a-black-hole-shader/index.du @@ -30,9 +30,9 @@ I chose to create an interactive and animated black hole demo. The primary idea was to show how the gravitational pull of black holes "bends" light and how the result looks from different points of view. Then in the December of that same year, I sat down and started writing a blog post (as you may notice from the "Created" date), explaining how some of the more complicated parts were made. -Funnily enough, I started finding errors... a *[lot]* of errors. +Funnily enough, I started finding errors... a [*lot*] of errors. -As it turned out, my implementation was completely wrong, but somehow I fudged the formulas around in just the right way to make it *[look]* correct. +As it turned out, my implementation was completely wrong, but somehow I fudged the formulas around in just the right way to make it [*look*] correct. So the post got delayed and sparsely rejuvenated over the following months. For this reason I chose to take up two related electives this year: one on general relativity and one on ray tracing, with the hopes of gaining enough understanding of the material to rework the original solution into something proper. @@ -53,7 +53,7 @@ Using [url [$EFE] Einstein's field equations], we can precisely calculate the cu Obviously we're going to use [url https://en.wikipedia.org/wiki/Schwarzschild_metric Schwarzschild metric] on a (Schwarzschild) black hole. To further simplify our calculations, we can make approximations using [url https://en.wikipedia.org/wiki/Celestial_mechanics celestial mechanics]. -This is not *[necessary]* to understand, but it will make our goal =[much]= clearer. +This is not [*necessary*] to understand, but it will make our goal [=much=] clearer. Now, let's try and unravel everything. @@ -68,8 +68,8 @@ The real crux of the issue came when the same problem occurred with [url https:/ As it turned out, Newton's formulae had only been approximations, they worked when light (and therefore [url https://www.youtube.com/watch?v=msVuCEs8Ydo causality, or the speed at which changes propagate]) had infinite speed. -Albert Einstein's general theory of relativity showed that gravity wasn't a "force which pulled", it was actually an effect which =[bent]= space. -And that only happened because the (=[constant]=) speed of light wasn't infinite. +Albert Einstein's general theory of relativity showed that gravity wasn't a "force which pulled", it was actually an effect which [=bent=] space. +And that only happened because the ([=constant=]) speed of light wasn't infinite. ### What does it mean to bend space? @@ -85,7 +85,7 @@ Imagine two points on a sphere, what is the shortest distance between them? Obviously, it's an arc of a circle and extending it to it's maximum possible length, we get a [url https://en.wikipedia.org/wiki/Great_circle great circle]. [image ./img/Illustration_of_great-circle_distance.svg.png]\n -*[Image by CheCheDaWaff on [url https://commons.wikimedia.org/w/index.php?curid=48187293 Wikipedia]]* +[*Image by CheCheDaWaff on [url https://commons.wikimedia.org/w/index.php?curid=48187293 Wikipedia]*] Now, what does it mean to go "forwards"? On a flat surface, we can define it as "following a (straight) line segment", on our sphere we can say "following an arc of a great circle". @@ -100,15 +100,15 @@ So now we can say "going forwards means going along a geodesic". It's important to note that an arbitrary geodesic doesn't have most properties you might be used to. For example, on a flat surface, we can have parallel lines, but on our sphere, great circles will always intersect[$parallels-of-latitude]. -This is what gravity does, it doesn't pull or push, it *[bends]*, and more precisely, it =[bends geodesics]=. -Furthermore, we live in three spacial dimensions, so we can move in three *[different directions]*. +This is what gravity does, it doesn't pull or push, it [*bends*], and more precisely, it [=bends geodesics=]. +Furthermore, we live in three spacial dimensions, so we can move in three [*different directions*]. The resultant effect is that if you travel perfectly forwards in a spaceship and pass by an object with mass (like a planet) from a close enough distance, your path will be curved, without you steering your ship. -Although not yet mentioned, you need to know that =[photons]= (light) =[don't have mass]=! +Although not yet mentioned, you need to know that [=photons=] (light) [=don't have mass=]! In effect, in a universe where there is only light bouncing around, Newton's equations still work. -On that note, the point that light =[doesn't]= travel at an infinite speed is significant. +On that note, the point that light [=doesn't=] travel at an infinite speed is significant. When the opposite is true, General Theory of Relativity collapses into the Newtonian equations! Going back on track, Einstein gives us the necessary equations for those geodesics, the [url [$EFE] Einstein Field Equations]. @@ -116,8 +116,8 @@ Going back on track, Einstein gives us the necessary equations for those geodesi ### How to handle the EFEs? Although they're called equations the result/output we get from solving them isn't a number! -It's a function, which *[more or less]* takes the parameters of objects in the universe and returns *[how]* they will all behave. -To be more precise, the output isn't *[really]* a function, it's a "metric", which is a distinctly different mathematical object. +It's a function, which [*more or less*] takes the parameters of objects in the universe and returns [*how*] they will all behave. +To be more precise, the output isn't [*really*] a function, it's a "metric", which is a distinctly different mathematical object. 'footnote schwm-assumptions He also assumed the body didn't have an electric charge and the [url https://en.wikipedia.org/wiki/Cosmological_constant cosmological constant] is zero. @@ -135,7 +135,7 @@ Schwarzschild's metric and accompanying black hole properties are the simplest p Let's imagine atoms as a set of glass marbles, scattered on a table: [image https://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/Marbles_from_Indonesia.jpg/1280px-Marbles_from_Indonesia.jpg]\n -*[Image from By Okkisafire on [url https://commons.wikimedia.org/w/index.php?curid=30338734 Wikipedia]]* +[*Image from By Okkisafire on [url https://commons.wikimedia.org/w/index.php?curid=30338734 Wikipedia]*] Now, start pushing from all sides of the table to it's center. In the beginning, you'll mostly roll them, until they all get in contact with each other. @@ -158,24 +158,24 @@ Such an assumption is unthinkable. Then that leaves us with only one solution: laws of matter "break". If nothing can keep the elementary particles "together", so keep matter "together", then the result is a sort of "collapse", all of that matter just "deflates" into a single, infinitely small point (but the amount of mass isn't infinite, it's the sum of mass from the particles that collapsed). -That point is called a =[black hole]=. +That point is called a [=black hole=]. This object is very bizarre, generally it doesn't have too much properties, but the ones it has are really unique. In our case, the only important part is it's effect on gravity, and more precisely, light. -Since a black hole is a single infinitely small point, then all of it's mass is concentrated on that point, making it alter the geodesics in a relatively small area of space =[a lot]=. +Since a black hole is a single infinitely small point, then all of it's mass is concentrated on that point, making it alter the geodesics in a relatively small area of space [=a lot=]. So much so, if you get too close, you will not be able to overwhelm gravity and "merge" into that infinitesimal point: [image https://upload.wikimedia.org/wikipedia/commons/thumb/9/91/CNX_UPhysics_13_07_spacetime.png/800px-CNX_UPhysics_13_07_spacetime.png?20171124170318]\n -*[The white lines are our geodesics]*\n -*[Image by OpenStax University Physics on [url https://commons.wikimedia.org/w/index.php?curid=64307901 Wikipedia]]* +[*The white lines are our geodesics*]\n +[*Image by OpenStax University Physics on [url https://commons.wikimedia.org/w/index.php?curid=64307901 Wikipedia]*] A fascinating realization is that light always travels along geodesics ("forwards"), therefore this extreme bending allows us to view otherwise obstructed objects. We call that effect [url https://en.wikipedia.org/wiki/Gravitational_lens gravitational lensing]. Though not unique to black holes, that's when the effect is strongest: [image https://upload.wikimedia.org/wikipedia/commons/0/02/Gravitational_lens-full.jpg]\n -*[Notice how the gray arrows show the path light travels from a galaxy that is behind (obstructed by) the black hole]* +[*Notice how the gray arrows show the path light travels from a galaxy that is behind (obstructed by) the black hole*] I'll abstain from explaining the specifics of light, but you may think of it as a small particle, "similar" to an electron, travelling through space. In fact, Newton understood light to be just that, and called the underlying particle a "corpuscle". @@ -187,7 +187,7 @@ Two of the most significant things Einstein's theory shows, which I've left out Which also signifies that our geodesics are actually four dimensional, or in other words, gravity also bends the observed passage of time! This is relevant for light, since it's speed is constant and it always travels along a geodesic, but to an outside observer it doesn't look that way. -However, in our simulation, we =[only]= care about how thing look, so it will make our live much simpler if we try to ignore reality wherever we can. +However, in our simulation, we [=only=] care about how thing look, so it will make our live much simpler if we try to ignore reality wherever we can. Therefore, to calculate by how much light will move and change, we'll start with the EFEs and then simplify and approximate until we get something useable. @@ -197,12 +197,12 @@ Let's get down to business, our starting point, the [url https://en.wikipedia.or [image ./img/Schwarzschild-metric-in-Schwarzschild-coordinates-wikipedia.png] -=[YOUCH!]= +[=YOUCH!=] -The variables themselves aren't that bad: `[c]` is the speed of light, <code>τ</code> is time, <code>Ω</code>, `[t]` and `[r]` are Schwarzschild coordinates. +The variables themselves aren't that bad: [`c`] is the speed of light, <code>τ</code> is time, <code>Ω</code>, [`t`] and [`r`] are Schwarzschild coordinates. -However, as you can see, there are two big problems: we have to calculate derivatives (that's what the `[d]` signifies) and convert from Schwarzschild coordinates to normal (euclidean) coordinates, that the computer understands "natively". -This would be =[too slow]= to render in real time. +However, as you can see, there are two big problems: we have to calculate derivatives (that's what the [`d`] signifies) and convert from Schwarzschild coordinates to normal (euclidean) coordinates, that the computer understands "natively". +This would be [=too slow=] to render in real time. Thankfully [url https://github.com/rantonels Riccardo Antonelli] was able to do all of our coordinate conversions and use Newton's ideas to simplify the living crap out of that monster, turning it into something digestible: @@ -229,18 +229,18 @@ Referring to the formula again: [image ./img/riccardo-antonelli-schwarzschild-black-hole-force-field-formula.png] -`[F^[→]^]` returns a force vector (`[F]` for "force" and `[^[→]^]` for "vector"): any force acting on an object has a strength (magnitude) and a direction. +[`F[^→^]`] returns a force vector ([`F`] for "force" and [`[^→^]`] for "vector"): any force acting on an object has a strength (magnitude) and a direction. Imagine you are pushing a box: you are applying some force to it in a "forward" direction. If you pull the box, you'll apply some force in a "backward" direction. This force vector conveys how much and in what direction exactly the black hole is "pulling" on the corpuscle. -Although the function takes in only one argument, `[r]`, that doesn't mean that `[h]` or `[r^[^]^]` aren't also arguments: +Although the function takes in only one argument, [`r`], that doesn't mean that [`h`] or [`r[^^^]`] aren't also arguments: :unordered -- `[r]` is the distance from the center of the black hole (the singularity) to the =[current]= position of the corpuscle. +- [`r`] is the distance from the center of the black hole (the singularity) to the [=current=] position of the corpuscle. -- `[h]` is the magnitude of the [url https://en.wikipedia.org/wiki/Specific_angular_momentum "specific angular momentum"] of the light "particle". +- [`h`] is the magnitude of the [url https://en.wikipedia.org/wiki/Specific_angular_momentum "specific angular momentum"] of the light "particle". .p "Normal" linear momentum specifies how much "force" at what speed it takes to stop (or change) the speed and direction of an object in linear motion (that's why it's in kg\*m/s). @@ -248,7 +248,7 @@ Although the function takes in only one argument, `[r]`, that doesn't mean that How do you forcefully stop it? .p - You can put a *[really]* heavy barrier on the tracks, in front of the train. + You can put a [*really*] heavy barrier on the tracks, in front of the train. Since the train is moving at a really great speed, this barrier will have to be much much heavier (with much more mass) than the train itself. 'footnote hitting-trains Of course, I'm assuming the trains are strong enough they won't break upon the collision. @@ -268,30 +268,30 @@ Although the function takes in only one argument, `[r]`, that doesn't mean that .p The specific angular momentum is the angular momentum of an object, divided by it's mass. It's magnitude kind of tells us which property is more prevalent in the momentum, the mass or the speed. - For the same angular momentum, a long (big magnitude) *[specific]* angular momentum means our object is small and moves fast, while for a short (small magnitude) *[specific]* angular momentum out object is large and moves slowly. + For the same angular momentum, a long (big magnitude) [*specific*] angular momentum means our object is small and moves fast, while for a short (small magnitude) [*specific*] angular momentum out object is large and moves slowly. 'footnote angular-momentum Angular momentum is actually [url https://en.wikipedia.org/wiki/Specific_angular_momentum#Definition defined using the cross product] 'footnote light-has-no-mass As mentioned, light has no mass, so this version of the formula wouldn't work. .p - Another simplification we need to is =[make our black hole stationary]=! + Another simplification we need to is [=make our black hole stationary=]! Then, rather than finding the angular momentum[$angular-momentum] and dividing by the mass[$light-has-no-mass], we'll use another formula: .p [image ./img/specific-angular-momentum-wikipedia.png] .p - where =[in this specific formula only]= `[r]` is the vector from the singularity to the corpuscle and `[v]` is light's velocity. + where [=in this specific formula only=] [`r`] is the vector from the singularity to the corpuscle and [`v`] is light's velocity. .p The cross product returns a vector, so we'll need to take the magnitude of the result and plug that into the formula. - It's also important that =[we calculate it only once, in the beginning]=. + It's also important that [=we calculate it only once, in the beginning=]. So, we shouldn't be calculating the magnitude of the specific angular momentum every time the light "particle" is moved, rather we calculate it once, after it gets close enough to be affected by the black hole. .p You might think that makes no sense, since we cannot divide by zero, so the specific angular momentum shouldn't exist, but then with the cross product we find a value for it. You would be correct: Antonelli does some funky approximations, combining Newtonian physics with General theory of relativity, to make the formula that simple. -- `[r^[^]^]` is the normalized ([url https://en.wikipedia.org/wiki/Unit_vector unit], hence the `[^]` on top) vector from the center of the black hole to the light particle: +- [`r[^^^]`] is the normalized ([url https://en.wikipedia.org/wiki/Unit_vector unit], hence the [`^`] on top) vector from the center of the black hole to the light particle: .p [image ./img/normalize-vector-wikipedia.png] @@ -300,7 +300,7 @@ Finally, putting all needed variables together in one proper function, we get: [image ./img/variables-expanded.png Refer to "Antonelli’s formula - explained" in the Appendix] -As you may notice, this can be simplified, if we substitute `[r^[^]^]`: +As you may notice, this can be simplified, if we substitute [`r[^^^]`]: [image ./img/antonelli-formula-expanded.png Refer to "Antonelli’s formula - simplified" in the Appendix] @@ -325,14 +325,14 @@ The formula for it is: [image ./img/Schwarzschild-radius-wikipedia.png r_s = (2GM)/(c^2)] -where `[G]` is the [url https://en.wikipedia.org/wiki/Gravitational_constant gravitational constant] and `[M]` is the mass of the black hole (in kg). +where [`G`] is the [url https://en.wikipedia.org/wiki/Gravitational_constant gravitational constant] and [`M`] is the mass of the black hole (in kg). The photon sphere is the distance from the singularity, in which photons start orbiting the black hole (and can either escape or pass the event horizon). Formula: [image ./img/photon-sphere-wikipedia.png r = r_s * 3/2] -where `[G]` and `[M]` are the same as before, `[c]` is the speed of light in vacuum and `[r^[s]^]` is the aforementioned Schwarzschild radius. +where [`G`] and [`M`] are the same as before, [`c`] is the speed of light in vacuum and [`r[^s^]`] is the aforementioned Schwarzschild radius. 'footnote isco It's not really true that gravity stopps affecting spacetime after the ISCO, even though things can orbit Earth that doesn't mean that Earth doesn't bend spacetime. However, for the purposes of a simple shader, this assumption produces perfectly useable results. @@ -344,7 +344,7 @@ Formula: Putting them all together, we should expect light to travel like this: [image https://upload.wikimedia.org/wikipedia/commons/2/27/Black_Hole_Shadow.gif] -*[Animation by Hugo Spinelli on [url https://commons.wikimedia.org/w/index.php?curid=138168679 Wikipedia]]* +[*Animation by Hugo Spinelli on [url https://commons.wikimedia.org/w/index.php?curid=138168679 Wikipedia]*] ## Light-bending algorithm @@ -368,7 +368,7 @@ An algorithm doing this would look a bit like this (in pseudocode, inspired by P [image ./img/algorithm.png Refer to "Algorithm" section of the Appendix] -as a reminder, here is the definition of `[F^[→]^]`: +as a reminder, here is the definition of [`F[^→^]`]: [image ./img/antonelli-formula-expanded.png] diff --git a/src/blog/thinkpad-x270-my-favorite-machine/index.du b/src/blog/thinkpad-x270-my-favorite-machine/index.du index 0c268ee..95a7a20 100644 --- a/src/blog/thinkpad-x270-my-favorite-machine/index.du +++ b/src/blog/thinkpad-x270-my-favorite-machine/index.du @@ -30,7 +30,7 @@ Suffice to say, I've wanted to get one for quite a while now, so back in the mid I've used it for the past 3 months, and in all honesty, it's not without it's drawback, but the X270 has easily become my favorite computer. -*[Note: this whole review was written on the aforementioned Thinkpad X270, without external devices (like keyboard or monitor) attached.]* +[*Note: this whole review was written on the aforementioned Thinkpad X270, without external devices (like keyboard or monitor) attached.*] ## Context @@ -44,21 +44,21 @@ Anyway, in all honesty, the only time when I wish for more power is in video gam Summarising, 99% of the time it's hardware is more than sufficient. The Yoga S730 was an "investment" into my future, since at the time I was going to programming lessons (which gave me a lot of the skills I have today) with my dad's laptop. -With this new machine I could go to the lectures and write code freely on a =[very]= fast (considering I was doing C# programming in Visual Studio on Windows 10, speed was always needed) and physically light machine, without being slowed down by the cheap, 4 years old, 16 inch behemoth. +With this new machine I could go to the lectures and write code freely on a [=very=] fast (considering I was doing C# programming in Visual Studio on Windows 10, speed was always needed) and physically light machine, without being slowed down by the cheap, 4 years old, 16 inch behemoth. From this point on, I was hooked on the 13 inch size, which as we all know is [url https://youtu.be/Za_Ul08dtj8?t=1208 the perfect size] and [url https://youtu.be/Q0h8wWlBxY0?t=1672 they should even make laptops that are any bigger]. However, very quickly I found the ultrabook fashion of only including USB-C ports, very annoying to deal with, especially if you don't pay for an all-in-one dongle (which I didn't do for years). -Additionally, the screen had *[no]* anti-gloss coating, so most of the time I was looking at my own reflection, rather than the actual screen contents. +Additionally, the screen had [*no*] anti-gloss coating, so most of the time I was looking at my own reflection, rather than the actual screen contents. Final thought, in the beginning battery life wasn't that much of a problem, but nowadays the battery barely holds for 3-4 hours, and I think a cell inside is failing. ## What I Think -My dream laptop was a "fat" Yoga S730 - 13 inches diagonally (an absolute =[MUST]=) with USB type A ports, a non-glossy display and better battery life. +My dream laptop was a "fat" Yoga S730 - 13 inches diagonally (an absolute [=MUST=]) with USB type A ports, a non-glossy display and better battery life. Let's now consider the Thinkpad in question: .bulleted - 13 inches in size diagonally, -- *[two]* USB type A ports and more +- [*two*] USB type A ports and more - display with an anti-gloss coating - both an external and internal battery (we'll talk about them later), allegedly being able to last 6-8 hours @@ -66,7 +66,7 @@ Absolutely perfect... well, almost. ### Display -By default, the laptop comes with a =[horrible]= 720p TFT display, with =[horrid]= color contrast, brightness and viewing angles. +By default, the laptop comes with a [=horrible=] 720p TFT display, with [=horrid=] color contrast, brightness and viewing angles. Surprisingly enough, online there were 1080p IPS drop-in replacements, and they weren't too expensive: the [url https://www.amazon.de/dp/B07RZQ5LPW/ref=pe_27091401_487024491_TE_item one I got from amazon.de cost me 115 euro] (including the 25 euro international shipping). The laptop itself did cost me ~170 euro, so the screen itself was 2/3 of the laptop price, but at 285 euro total, the deal was still a steal, at least considering where I live at. @@ -122,7 +122,7 @@ But this is in no way a deal-breaker, and the connector is much beefier than nor ### Batteries -Something absolutely amazing is that the X270 comes with two, count them, =[TWO]= batteries - one internal and one (removable) external. +Something absolutely amazing is that the X270 comes with two, count them, [=TWO=] batteries - one internal and one (removable) external. The last time I saw a removable battery was on the old family laptop from 2011, and this one has an additional internal one. Do I even need to explain why this is awesome? @@ -201,7 +201,7 @@ I live in Bulgaria, so depending on where you live, there might be better offers Let's look at the listings in [url https://www.jarcomputers.com/ JAR computers], since I've found their pricing and availability to be quite normal for online shops (and the physical shops almost always offer fewer devices with a much higher price). So, 340 * 2 = 640 euro, or roughly 1300 Bulgarian Lev. -At the time of writing, [url https://www.jarcomputers.com/Laptopi_cat_2.html?ref=all&fprop[4413\][48266\]=48266&fprop[4413\][48256\]=48256&order=-1&&fprice[price-filter-other\]=p_from-1100-p_to-1600 searching for a ~13 inch laptop at around that price range] yields only two results: a [url https://www.jarcomputers.com/microsoft-surface-laptop-go-2-8qc-00024-prod-nbmicrosoft8qc00024.html Microsoft Surface Laptop Go 2] and [url https://www.jarcomputers.com/ms-surface-laptop-go-tnv-00009-prod-nbmicrosofttnv00009.html Microsoft Surface Laptop Go], both of which are on sale (with the second's original price being ~2300 lev, around ~1100 euro, three times the price). +At the time of writing, [url https://www.jarcomputers.com/Laptopi_cat_2.html?ref=all&fprop[4413\][48266\=]48266&fprop[4413\][48256\=]48256&order=-1&&fprice[price-filter-other\=]p_from-1100-p_to-1600 searching for a ~13 inch laptop at around that price range] yields only two results: a [url https://www.jarcomputers.com/microsoft-surface-laptop-go-2-8qc-00024-prod-nbmicrosoft8qc00024.html Microsoft Surface Laptop Go 2] and [url https://www.jarcomputers.com/ms-surface-laptop-go-tnv-00009-prod-nbmicrosofttnv00009.html Microsoft Surface Laptop Go], both of which are on sale (with the second's original price being ~2300 lev, around ~1100 euro, three times the price). Both have soldered on RAM with no slots, so it cannot be upgraded, both have 1536x1024 displays with no anti-glare, that are glued to the screen bezel, both miss the Ethernet and HDMI ports, and since they aren't (older) ThinkPads, you won't get the TrackPoint or mouse buttons or Linux driver support or removable battery. Of course, they have their own positives, the display is a touchscreen and they score [url https://www.cpubenchmark.net/cpu.php?cpu=Intel+Core+i5-1035G1+%40+1.00GHz&id=3558 2.3] and [url https://www.cpubenchmark.net/cpu.php?cpu=Intel+Core+i5-1135G7+%40+2.40GHz&id=3830 3.0] times higher on CPU mark respectively, but still, you get so much more with the ThinkPad for half the price. diff --git a/src/blog/turn-off-notifications-windows/index.du b/src/blog/turn-off-notifications-windows/index.du index cf60632..b85f811 100644 --- a/src/blog/turn-off-notifications-windows/index.du +++ b/src/blog/turn-off-notifications-windows/index.du @@ -8,19 +8,19 @@ What if you need to concentrate on some work, and you don't want to have your notifications show up while doing so? Or, what if some apps just put out notifications too often? Well, this is how to disable notifications: :ordered -1. In the *[Search bar]* type in =[Notification]=. The =[Notification & actions settings]= option should show up, click it +1. In the [*Search bar*] type in [=Notification=]. The [=Notification & actions settings=] option should show up, click it [image ./img/windows-search-notifications.png] -2. If you want to turn off all notifications, switch the =[Get notifications from apps and other senders]= to the *[Off]* position +2. If you want to turn off all notifications, switch the [=Get notifications from apps and other senders=] to the [*Off*] position [image ./img/windows-settings-notifications-off.png] .p - *[Note: "Suggest best ways", "Welcome Experience" and "Tips and tricks" will still show up, you'll have to uncheck those individually]* + [*Note: "Suggest best ways", "Welcome Experience" and "Tips and tricks" will still show up, you'll have to uncheck those individually*] .p - If you want to turn off notifications for specific apps, scroll down to the =[Get notifications from these senders]=, find the applications you want to turn off notifications for and flick the switch + If you want to turn off notifications for specific apps, scroll down to the [=Get notifications from these senders=], find the applications you want to turn off notifications for and flick the switch [image ./img/windows-settings-notifications-application.png] diff --git a/src/blog/when-a-language-forces-simpler-thinking/index.du b/src/blog/when-a-language-forces-simpler-thinking/index.du index d725e3d..fcf3c7e 100644 --- a/src/blog/when-a-language-forces-simpler-thinking/index.du +++ b/src/blog/when-a-language-forces-simpler-thinking/index.du @@ -21,7 +21,7 @@ Name File size sum Subfolder "e" in "a" | | Subfolder "a" in "/" Subfolder "d" in "/" -Now, after parsing a file, you'll need to update the file size sum in the =[current]= folder =[and]= in the =[parent]= folder. +Now, after parsing a file, you'll need to update the file size sum in the [=current=] folder [=and=] in the [=parent=] folder. To do such a thing, you would either need to .bulleted @@ -56,7 +56,7 @@ Now this solution worked great! With this I was able to [url https://gitlab.com/ #### Appendix In the exercise, you have commands for navigating between folders. -Going up a folder is trivial, but folders can have duplicate names if they're inside different parent folders, so going to a sub folder requires to search by it's name *[and]* parent index. +Going up a folder is trivial, but folders can have duplicate names if they're inside different parent folders, so going to a sub folder requires to search by it's name [*and*] parent index. Surprisingly enough, in my solution [url https://gitlab.com/Syndamia/advent-of-code/-/tree/main/2022/Day07/part-one.cl#L15-17 (lines 15-17)], I just search from the end to the beginning of all parsed folders for a name. This works fine for this exact task and exact inputs, however in general this isn't correct. In a structure like this: @@ -92,8 +92,8 @@ $ cd .. $ cd .. $ cd a -'footnote mkfile `[mkfile]` is like `[touch]`, but you could specify a size and the file will be filled with that many zeroes. It seems to exist solely in [url https://docs.oracle.com/cd/E26502_01/html/E29031/mkfile-1m.html Solaris] (as a system administration command) and [url https://ss64.com/osx/mkfile.html MacOS]. I mentioned it and not `[touch]`, since the latter only creates empty files, which wouldn't contribute to the total file size sum. +'footnote mkfile [`mkfile`] is like [`touch`], but you could specify a size and the file will be filled with that many zeroes. It seems to exist solely in [url https://docs.oracle.com/cd/E26502_01/html/E29031/mkfile-1m.html Solaris] (as a system administration command) and [url https://ss64.com/osx/mkfile.html MacOS]. I mentioned it and not [`touch`], since the latter only creates empty files, which wouldn't contribute to the total file size sum. -The last `[\$ cd a]` actually puts you into `[/b/a/]`, not `[/a/]`. +The last [`\$ cd a`] actually puts you into [`/b/a/`], not [`/a/`]. The main thing that saves us (me) is that you can only change directory and list structure (in current directory), so you would only ever be visiting a folder once. -If a folder's contents were `[ls]`'d more than once, or they could change (for example having an `[mkfile]` [$mkfile] command), a proper search would be required. +If a folder's contents were [`ls`]'d more than once, or they could change (for example having an [`mkfile`] [$mkfile] command), a proper search would be required. diff --git a/src/blog/windows-run-dialog/index.du b/src/blog/windows-run-dialog/index.du index 5e71234..c5de7b1 100644 --- a/src/blog/windows-run-dialog/index.du +++ b/src/blog/windows-run-dialog/index.du @@ -19,17 +19,17 @@ -On Windows, most often you run an application by finding and double-clicking it's `[.exe]` file. What a lot of people don't realise is that you can launch any application or open any file you want by typing a single command. That can be achieved inside the =[Run dialog]=. +On Windows, most often you run an application by finding and double-clicking it's [`.exe`] file. What a lot of people don't realise is that you can launch any application or open any file you want by typing a single command. That can be achieved inside the [=Run dialog=]. ## Opening the Run dialog To open the Run dialog, you can either: -*[A)]* Press `[Win + R]` key combination +[*A)*] Press [`Win + R`] key combination or -*[B)]* Right click on the Windows menu, and then press `[Run]` +[*B)*] Right click on the Windows menu, and then press [`Run`] [image ./img/open-run-windows-menu.png] @@ -39,85 +39,85 @@ or ### Folders -You can open any folder by typing in it's =[full path]=. So, if you have a folder named `[Work]` inside your `[Documents]` folder, the full path will be something like `[C:\Users\John\Documents\Work\\]`. +You can open any folder by typing in it's [=full path=]. So, if you have a folder named [`Work`] inside your [`Documents`] folder, the full path will be something like [`C:\Users\John\Documents\Work\\`]. -If your desired folder is directly in your account folder, so `[Desktop]`, `[Documents]`, `[Pictures]`, etc. you can just type in the name of the folder. For example, if you want to open your `[Pictures]` folder, just type in `[pictures]` and it will be opened. +If your desired folder is directly in your account folder, so [`Desktop`], [`Documents`], [`Pictures`], etc. you can just type in the name of the folder. For example, if you want to open your [`Pictures`] folder, just type in [`pictures`] and it will be opened. There are, of course, some more special location, some of which are: .table_2 |= Command |= Location -|: `[%ProgramFiles%]` +|: [`%ProgramFiles%`] |: Program Files Folder -|: `[%AppData%]` +|: [`%AppData%`] |: User's App Data Folder -=[Bonus]=: `[%appdata%\Microsoft\Windows\Start Menu]` will open the Start Menu folder, from which you can edit what goes inside your start menu. +[=Bonus=]: [`%appdata%\Microsoft\Windows\Start Menu`] will open the Start Menu folder, from which you can edit what goes inside your start menu. ### Programs -You can always run any application by typing in it's full path. So, to launch something like FireFox, you'll need to type in `[C:\Program Files\Mozilla Firefox\firefox.exe]`. +You can always run any application by typing in it's full path. So, to launch something like FireFox, you'll need to type in [`C:\Program Files\Mozilla Firefox\firefox.exe`]. But, whats more important is that you can more easily launch some Windows apps, like Calculator or Control Panel. Here is a list of commands and the application they launch: .table_2 |= Command |= Application -|: `[calc]` +|: [`calc`] |: Calculator -|: `[mspaint]` +|: [`mspaint`] |: Microsoft Paint -|: `[snippingtool]` +|: [`snippingtool`] |: Snipping Tool -|: `[notepad]` +|: [`notepad`] |: Notepad -|: `[sndvol]` +|: [`sndvol`] |: Volume Mixer -|: `[soundrecroder]` +|: [`soundrecroder`] |: Sound Recorder -|: `[wuapp]` +|: [`wuapp`] |: Windows Updates -|: `[shutdown]`\* +|: [`shutdown`]\* |: Shutdown or restart computer |: |: -|: `[cmd]` +|: [`cmd`] |: Command Prompt -|: `[powershell]` +|: [`powershell`] |: Windows PowerShell -|: `[control]` +|: [`control`] |: Control Panel -|: `[taskmgr]` +|: [`taskmgr`] |: Task Manager -|: `[msinfo32]` +|: [`msinfo32`] |: System Information -|: `[winver]` +|: [`winver`] |: Windows Version Window -|: `[cleanmgr]` +|: [`cleanmgr`] |: Disk Cleanup -|: `[dfrgui]` +|: [`dfrgui`] |: Disk Cleanup (defragmentation) -|: `[mstsc]` +|: [`mstsc`] |: Remote Desktop Connection |: |: -|: `[regedit]` +|: [`regedit`] |: Registry Editor -|: `[msconfig]` +|: [`msconfig`] |: System Configuration Settings -|: `[dcomcnfg]` +|: [`dcomcnfg`] |: Component Services -|: `[sigverif]` +|: [`sigverif`] |: File Signature Verification Tool -\*: The `[shutdown]` command [url https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/shutdown requires parameters]: +\*: The [`shutdown`] command [url https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/shutdown requires parameters]: .bulleted -- `[/s]` will shutdown in one minute -- `[/r]` will restart in one minute -- `[/t]` specifies after what amount of time to shutdown or restart (a number needs to be entered afterwards, so `[/t 0]` for immediate execution) -- `[/f]` forces running applications to close (might result in data loss!) +- [`/s`] will shutdown in one minute +- [`/r`] will restart in one minute +- [`/t`] specifies after what amount of time to shutdown or restart (a number needs to be entered afterwards, so [`/t 0`] for immediate execution) +- [`/f`] forces running applications to close (might result in data loss!) ### Windows settings @@ -126,46 +126,46 @@ There are also many "shortcuts" to different Windows settings windows. Those inc .table_2 |= Command |= Setting -|: `[mmsys.cpl]` +|: [`mmsys.cpl`] |: Sound Properties -|: `[powercfg.cpl]` +|: [`powercfg.cpl`] |: Power Options -|: `[timedate.cpl]` +|: [`timedate.cpl`] |: Time and Date Options -|: `[ncpa.cpl]` +|: [`ncpa.cpl`] |: Network Connections |: |: -|: `[inetcpl.cpl]` +|: [`inetcpl.cpl`] |: Internet Properties -|: `[compmgmt.msc]` +|: [`compmgmt.msc`] |: Computer Manager -|: `[devmgmt.msc]` +|: [`devmgmt.msc`] |: Device Manager -|: `[diskmgmt.msc]` +|: [`diskmgmt.msc`] |: Disk Management -|: `[firewall.cpl]` +|: [`firewall.cpl`] |: Windows Firewall |: |: -|: `[sysdm.cpl]` +|: [`sysdm.cpl`] |: System Properties -|: `[services.msc]` +|: [`services.msc`] |: Services -|: `[comexp.msc]` +|: [`comexp.msc`] |: Component Services -|: `[gpedit.msc]` +|: [`gpedit.msc`] |: Group Policy Editor -|: `[lusrmgr.msc]` +|: [`lusrmgr.msc`] |: Local Users and Groups -|: `[certmgr.msc]` +|: [`certmgr.msc`] |: Certificate Manager -|: `[taskschd.msc]` +|: [`taskschd.msc`] |: Task Scheduler -|: `[fsmgmt.msc]` +|: [`fsmgmt.msc`] |: Shared Folders -=[Note]=: `[cpl]` stands for *[Control Panel Item]* and `[msc]` stands for *[Microsoft System Configuration]*. +[=Note=]: [`cpl`] stands for [*Control Panel Item*] and [`msc`] stands for [*Microsoft System Configuration*]. ## For more |