<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Radu-Alexandru B</title>
    <description>The latest articles on DEV Community by Radu-Alexandru B (@radualexandrub).</description>
    <link>https://dev.to/radualexandrub</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F472790%2F2d3623e2-ccd7-4458-b2a7-48b0ae92176b.jpg</url>
      <title>DEV Community: Radu-Alexandru B</title>
      <link>https://dev.to/radualexandrub</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/radualexandrub"/>
    <language>en</language>
    <item>
      <title>Running a Node.js App (Angular/React) on Android using Termux</title>
      <dc:creator>Radu-Alexandru B</dc:creator>
      <pubDate>Fri, 29 Sep 2023 16:25:52 +0000</pubDate>
      <link>https://dev.to/radualexandrub/running-a-nodejs-app-angularreact-on-android-using-termux-5abi</link>
      <guid>https://dev.to/radualexandrub/running-a-nodejs-app-angularreact-on-android-using-termux-5abi</guid>
      <description>&lt;p&gt;Hello everyone!&lt;/p&gt;

&lt;p&gt;In this tutorial, we will run an Angular Node App (and also a React App) on Android, and host it on localhost by using the Termux app. We will also use the Acode Editor application to browse and easily change our code files. &lt;strong&gt;NO ROOT IS NEEDED&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The chances of encountering any issues that may affect your Android device are minimal to none. However, I'm not responsible for any damage, data loss, or malfunction that may occur to your Android device after following this tutorial.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any Android device running Android 10 and up. In my case I will either use a &lt;a href="https://www.gsmarena.com/compare.php3?idPhone1=11841&amp;amp;idPhone2=11343&amp;amp;idPhone3=12217" rel="noopener noreferrer"&gt;Lenovo Tab P11 Pro 8GB in Productivity Mode&lt;/a&gt; or a &lt;a href="https://www.gsmarena.com/compare.php3?idPhone1=11841&amp;amp;idPhone2=10377&amp;amp;idPhone3=12024" rel="noopener noreferrer"&gt;Samsung Galaxy S20 FE 6GB in DeX Mode&lt;/a&gt; with a Bluetooth Mouse &amp;amp; Keyboard connected&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://f-droid.org/packages/com.termux/" rel="noopener noreferrer"&gt;Termux App from F-Droid&lt;/a&gt; - Currently on Version &lt;a href="https://github.com/termux/termux-app/releases" rel="noopener noreferrer"&gt;0.118.0&lt;/a&gt; (118) - Added on 2022-01-11&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://f-droid.org/packages/com.foxdebug.acode/" rel="noopener noreferrer"&gt;Acode Editor App from F-Droid&lt;/a&gt; - Currently on Version 1.8.6 (312) - Added on 2023-09-01&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;Table of Contents:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Installing Termux

&lt;ul&gt;
&lt;li&gt;Installing apt package manager and other dependencies&lt;/li&gt;
&lt;li&gt;Installing Nodejs&lt;/li&gt;
&lt;li&gt;Installing and Running Angular (ng)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Installing Acode Editor App&lt;/li&gt;

&lt;li&gt;

Installing other packages in Termux

&lt;ul&gt;
&lt;li&gt;Running React App (npx)&lt;/li&gt;
&lt;li&gt;Installing Java&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Conclusions&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installing Termux
&lt;/h2&gt;

&lt;p&gt;First, we need to install &lt;a href="https://f-droid.org/packages/com.termux/" rel="noopener noreferrer"&gt;Termux (terminal) App from F-Droid&lt;/a&gt; * (or from the &lt;a href="https://github.com/termux/termux-app/releases" rel="noopener noreferrer"&gt;Termux GitHub Repository&lt;/a&gt;). We will not install the Termux from Google Play Store due to lack of updates there.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;* Please make sure that you don't press the big blue "Download F-Droid" button as it will download the F-Droid store instead of the Termux App!&lt;br&gt;
Currently latest available version as of now (September 24, 2023) is Termux Version 0.118.0 (118) added on 2022-01-11&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Installing apt package manager and other dependencies
&lt;/h3&gt;

&lt;p&gt;Now that we are in the Termux app on our Android device, we can run the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Update and upgrade Termux's &lt;code&gt;pkg&lt;/code&gt; package manager&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

pkg update &lt;span class="nt"&gt;-y&lt;/span&gt;
pkg upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: In Termux you can click and hold to show the copy/paste menu (in order to copy-paste these commands)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;code&gt;apt&lt;/code&gt; Package Manager as well as updating and upgrading (Note that we add the &lt;code&gt;-y&lt;/code&gt; option to automatically say "yes" to the install when asked)&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

pkg &lt;span class="nb"&gt;install &lt;/span&gt;apt &lt;span class="nt"&gt;-y&lt;/span&gt;
apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt update &lt;span class="nt"&gt;-y&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;code&gt;openssl-tool&lt;/code&gt; dependency&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

apt &lt;span class="nb"&gt;install &lt;/span&gt;openssl-tool &lt;span class="nt"&gt;-y&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Some other packages might come in handy, such as &lt;code&gt;git&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

apt &lt;span class="nb"&gt;install &lt;/span&gt;git &lt;span class="nt"&gt;-y&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Installing Nodejs
&lt;/h3&gt;

&lt;p&gt;Now, time to actually install &lt;strong&gt;Node.js&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We just need to run:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

apt &lt;span class="nb"&gt;install &lt;/span&gt;nodejs


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;And check the installed version&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

node &lt;span class="nt"&gt;--version&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb5x6zfy2jnuwcx0a76ro.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb5x6zfy2jnuwcx0a76ro.jpg" alt="Running Node 20 in Android Termux"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: If we want a different version of Node.js&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can get the apt package for nodejs 16 by running the following and update the apt package manager including this version&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

curl &lt;span class="nt"&gt;-sL&lt;/span&gt; https://deb.nodesource.com/setup_16.x | bash -

apt update


&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;And then just install it&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

apt &lt;span class="nb"&gt;install &lt;/span&gt;nodejs

node &lt;span class="nt"&gt;--version&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Resource: &lt;a href="https://computingforgeeks.com/how-to-install-node-js-on-ubuntu-debian/?expand_article=11" rel="noopener noreferrer"&gt;https://computingforgeeks.com/how-to-install-node-js-on-ubuntu-debian/?expand_article=11&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h3&gt;
  
  
  Installing and Running Angular (ng)
&lt;/h3&gt;

&lt;p&gt;Let's install Angular "globally" by running:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @angular/cli


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

ng version


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And also let's create a quick demo project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, let's create a separate folder&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;mkdir &lt;/span&gt;projects
&lt;span class="nb"&gt;cd &lt;/span&gt;projects/


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;And create a new Angular app within &lt;code&gt;angularapp&lt;/code&gt; directory&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

ng new angularapp
&lt;span class="nb"&gt;cd &lt;/span&gt;angularapp/


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Now let's run locally this Angular app. The default Android browser should open to &lt;a href="http://localhost:4200/" rel="noopener noreferrer"&gt;http://localhost:4200/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

ng serve &lt;span class="nt"&gt;--open&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs572rkdfff6k542ncid9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs572rkdfff6k542ncid9.jpg" alt="Running Angular App in Android using Termux"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Installing Acode Editor App
&lt;/h2&gt;

&lt;p&gt;With &lt;a href="https://f-droid.org/packages/com.foxdebug.acode/" rel="noopener noreferrer"&gt;Acode App from F-Droid&lt;/a&gt; installed, we can now browse through Termux's created directories and files within its emulated storage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyco4uynpp21bufn9tdt8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyco4uynpp21bufn9tdt8.jpg" alt="Running Angular App in Android using Termux"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And of course, edit files and see changes in real-time (without refreshing the app).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyr4axcgn47ea44dzby2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyr4axcgn47ea44dzby2.jpg" alt="Running Angular App in Android using Termux"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Installing other packages in Termux
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Running React App (npx)
&lt;/h3&gt;

&lt;p&gt;We can also create a React application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Just run the following (also write "y" if prompted to install the "create-react-app" package)&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx create-react-app reactapp


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;cd &lt;/span&gt;reactapp


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Then run it on &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm start


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F77jbhifiq2zggsqp9yn4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F77jbhifiq2zggsqp9yn4.jpg" alt="Running React App in Android with Termux"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h3&gt;
  
  
  Installing Java
&lt;/h3&gt;

&lt;p&gt;As a bonus, we can also install other APT packages such as openjdk to run Java:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can search any available packages within APT (compatible with an ARM-based CPU) by running &lt;code&gt;apt search java&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;We see that we can install Java 17 by running&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

apt &lt;span class="nb"&gt;install &lt;/span&gt;openjdk-17


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

javac &lt;span class="nt"&gt;--version&lt;/span&gt;
java &lt;span class="nt"&gt;--version&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Now let's do a quick test&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;cd &lt;/span&gt;projects/
&lt;span class="nb"&gt;mkdir &lt;/span&gt;javaapp &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;javaapp


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;By writing a fast &lt;a href="https://www.w3schools.com/java/" rel="noopener noreferrer"&gt;hello world example&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

vi Hello.java

&lt;span class="c"&gt;# Note, you can also install vim by running&lt;/span&gt;
apt &lt;span class="nb"&gt;install &lt;/span&gt;vim


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hello&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;cat &lt;/span&gt;Hello.java


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Compile and run&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;

&lt;span class="n"&gt;javac&lt;/span&gt; &lt;span class="nc"&gt;Hello&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;
&lt;span class="n"&gt;java&lt;/span&gt; &lt;span class="nc"&gt;Hello&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4gt9zn1aya5fph6tm2c.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4gt9zn1aya5fph6tm2c.jpg" alt="Running Java 17 in Termux on Android"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;I wrote this mini tutorial as I didn't see that many quick tutorials on this topic so I thought I should write my own (or at least for my future self).&lt;/p&gt;

&lt;p&gt;The little mind-boggling idea is the mobile devices that we use every day (smartphones, tablets) are getting more powerful year by year - e.g. see the &lt;a href="https://nanoreview.net/en/soc-compare/qualcomm-snapdragon-875-vs-qualcomm-snapdragon-8-gen-2" rel="noopener noreferrer"&gt;performance comparison between Snapdragon 888 (2020) vs Snapdragon 8 Gen 2 (2022)&lt;/a&gt; - therefore it feels like those devices aren't used by full their extent.&lt;/p&gt;

&lt;p&gt;Performance-wise, mid-range devices (such as Lenovo Tab P11, Samsung Tab S7 FE, Xiaomi Pad 6, or Samsung Galaxy S21 FE) are on pair with budget laptops from around 2020 (at least from the bench scores).&lt;/p&gt;

&lt;p&gt;However, the weird part is that I use my budget laptop for multitasking tens of heavy-load applications. On a laptop equipped with a quad-core Intel I5 gen 10 CPU with 16GB of RAM (that scores around 3000 MultiCore points in Geekbench 5) I always have 20-30 Chrome tabs open while running 2 to 3 FullStack Docker Apps (with MySQL/Java/Nodejs and other microservices), while also playing videos in the background and compiling with maven java projects, while also doing some quick edits in Excel (Sheets) or Word (Docs) - and the performance/smoothness is fine (not great, but okay). So why can't we use our mobile devices as well for all these tasks?&lt;/p&gt;

&lt;p&gt;Maybe the mobile devices are still early for such tasks and the software is not yet there. Maybe the limiting factor is the different architecture (ARM based on RISC vs. x86 based on CISC), however, Apple's M1/M2 chips might have proved this wrong. Maybe the general public will never use their smart devices for high-load multitasking and productivity work (and only use them for media consumption and fast email/news checking, as these devices were intended).&lt;/p&gt;

&lt;p&gt;We will see. &lt;/p&gt;

&lt;p&gt;Until then, I hope that this article at least sparked some curiosity!&lt;/p&gt;

&lt;p&gt;Have a great day!&lt;br&gt;
Radu&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>android</category>
      <category>webdev</category>
      <category>node</category>
    </item>
    <item>
      <title>Top 8 macros for Developers to maximize their productivity with AHK</title>
      <dc:creator>Radu-Alexandru B</dc:creator>
      <pubDate>Thu, 12 Nov 2020 13:13:55 +0000</pubDate>
      <link>https://dev.to/radualexandrub/top-8-macros-for-developers-to-maximize-their-productivity-with-ahk-5bfj</link>
      <guid>https://dev.to/radualexandrub/top-8-macros-for-developers-to-maximize-their-productivity-with-ahk-5bfj</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;span&gt;Cover Photo by &lt;a href="https://unsplash.com/@kensuarez?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Ken Suarez&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/mechanical-keyboard?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Short short Intro&lt;/li&gt;
&lt;li&gt;1. Run command prompt in the currently focused folder&lt;/li&gt;
&lt;li&gt;2. Run command prompt followed by certain commands&lt;/li&gt;
&lt;li&gt;3. Search on Google the currently selected text&lt;/li&gt;
&lt;li&gt;4. Open applications/websites using shortcuts&lt;/li&gt;
&lt;li&gt;5. Open new explorer window with the same path as the currently focused folder&lt;/li&gt;
&lt;li&gt;6. Copy to clipboard the HEX color of the pixel under your cursor&lt;/li&gt;
&lt;li&gt;7. Adjust the main volume using the mouse scroll wheel&lt;/li&gt;
&lt;li&gt;8. Auto-complete syntaxes with Hotstrings&lt;/li&gt;
&lt;li&gt;
Honorable mentions

&lt;ul&gt;
&lt;li&gt;Put PC to sleep&lt;/li&gt;
&lt;li&gt;Empty recycle bin&lt;/li&gt;
&lt;li&gt;Get the current date/hour&lt;/li&gt;
&lt;li&gt;Use arrow keys as Home/End while holding RAlt&lt;/li&gt;
&lt;li&gt;Disable CapsLock key&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Fin&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Short short Intro
&lt;/h2&gt;

&lt;p&gt;In this post, we'll summarize all the macros created with &lt;a href="https://www.autohotkey.com/" rel="noopener noreferrer"&gt;AutoHotKey (AHK)&lt;/a&gt; in the previous parts (+extras). However, there is no need to read those parts as I'll provide a fast and short step by step guide on how to set AHK. &lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Run command prompt in the currently focused folder
&lt;/h2&gt;

&lt;p&gt;If you don't have AutoHotKey installed, simply download it from &lt;a href="https://www.autohotkey.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;, then run the setup. Now we just need to create a file with &lt;code&gt;.ahk&lt;/code&gt; extension (eg. &lt;code&gt;myMacros.ahk&lt;/code&gt;). After you run this file (double click it), a small green H icon will pop up letting you know that the script is running in the background. Now, let's open the &lt;code&gt;.ahk&lt;/code&gt; file with any text editor and add these lines:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

^!u::     ; Use ctrl+alt+u to open cmd in current selected folder
{
  Send, !d
  Send, ^c
  Sleep 50
  Run cmd, %clipboard%
  Return
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Feb6ltqy8tkw1455p41tq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Feb6ltqy8tkw1455p41tq.jpg" alt="AHK icon running in the background"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Save this file, and click on &lt;code&gt;Reload This Script&lt;/code&gt; from the AHK icon. Now, open any folder, and press &lt;code&gt;ctrl+alt+u&lt;/code&gt; to open cmd prompt with the folder's current path:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fp5avwg7kled2ugltzx0l.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fp5avwg7kled2ugltzx0l.gif" alt="Open command prompt in the current folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also keep in mind the key notations in AHK for &lt;code&gt;Control&lt;/code&gt;, &lt;code&gt;Shift&lt;/code&gt;, &lt;code&gt;Windows&lt;/code&gt;, and &lt;code&gt;Alt&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key notation in AHK&lt;/th&gt;
&lt;th&gt;Actual Key&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;^&lt;/td&gt;
&lt;td&gt;Control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;+&lt;/td&gt;
&lt;td&gt;Shift&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;!&lt;/td&gt;
&lt;td&gt;Alt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;#&lt;/td&gt;
&lt;td&gt;Windows Key&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Run command prompt followed by certain commands
&lt;/h2&gt;

&lt;p&gt;From now on we will reopen &lt;code&gt;myMacros.ahk&lt;/code&gt; with a text editor, and we'll just keep adding more macros, save the file, then click on &lt;code&gt;Reload this Script&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;We can add more commands after opening the command prompt. For example, we can run &lt;code&gt;git status&lt;/code&gt; right after (or &lt;code&gt;npm start&lt;/code&gt;, &lt;code&gt;python ./manage.py runserver&lt;/code&gt; etc):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

^!+u::     ; Use ctrl+alt+shift+u to open cmd in current selected folder and run git status
{
  Send, !d
  Send, ^c
  Sleep 50
  Run cmd, %clipboard%
  Sleep 100
  Send, git status
  Sleep 100
  Send, {Enter}
  Return
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Or, if you use &lt;a href="https://jupyter.org/" rel="noopener noreferrer"&gt;Jupyter Notebook&lt;/a&gt; in a specific drive partition and/or environment, instead of opening it with command prompt, you can just use a shortcut like &lt;code&gt;ctrl+alt+j&lt;/code&gt; (or even &lt;code&gt;ctrl+win+j&lt;/code&gt; or whatever you want) and write all the corresponding commands automatically. Just add this macro:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

^!j::                                  ; use ctrl+alt+j
{                                      ; to open jupyter notebook in g: in tf_gpu conda env
  Run cmd, g:
  Sleep 100
  Send, activate tf_gpu
  Sleep 1000
  Send, {Enter}
  Send, jupyter notebook
  Sleep 2000
  Send, {Enter}
  Return
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Or you can fast open Python in command prompt by pressing &lt;code&gt;ctrl+alt+p&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

^!p::                                  ; use ctrl+alt+p
{                                      ; to open cmd prompt in python
  Run cmd, C:\Users\MyUserName
  Sleep 100
  Send, python
  Sleep 100
  Send, {Enter}
  Return
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhd3rv8ix9fxiuo64zhil.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhd3rv8ix9fxiuo64zhil.gif" alt="Open Python Shortcut Windows"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  3. Search on Google the currently selected text
&lt;/h2&gt;

&lt;p&gt;Add these lines in your &lt;code&gt;myMacros.ahk&lt;/code&gt; to search on Google the selected text using &lt;code&gt;Ctrl+Alt+c&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

^!c:: ; use ctrl+alt+c to search on google
{
  Send, ^c
  Sleep 50
  Run, http://www.google.com/search?q=%clipboard%
  Return
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you have a mouse with 3 side buttons, you can even assign this macro by pressing Left Click while holding the middle left-sided mouse button (&lt;a href="https://dev.to/radualexandrub/embrace-mouse-macros-into-your-dev-life-to-increase-your-productivity-with-ahk-part-2-358j"&gt;More details in my previous post&lt;/a&gt;):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

XButton2 &amp;amp; LButton:: ; Search currently selected text on Google
{
  Send, ^c
  Sleep 100
  If InStr(clipboard, "http")
    Run, %clipboard%
  Else
    Run, https://www.google.com/search?q=%clipboard%
  Return
}

; Note: if the selected text is a link, open it in a new tab
; Otherwise, search the selected text on Google


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can also search on other websites, such as &lt;a href="https://www.pexels.com/" rel="noopener noreferrer"&gt;Pexels&lt;/a&gt; and &lt;a href="https://unsplash.com/" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

^#u:: ; use ctrl+win+u to search on Unsplash
{
  Send, ^c
  Sleep 50
  Run, https://unsplash.com/s/photos/%clipboard%
  Return
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

^#p:: ; use ctrl+win+p to search on Pexels
{
  Send, ^c
  Sleep 50
  Run, https://www.pexels.com/search/%clipboard%
  Return
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Open applications/websites using shortcuts
&lt;/h2&gt;

&lt;p&gt;We can open any application using any shortcut key. For reference, we can use the following keys (without overwriting the system's shortcuts):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;RAlt+(anyKeyLetter)&lt;/code&gt; or &lt;code&gt;RAlt+(anyNumber)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl+Alt+(anyKey)&lt;/code&gt; (But be aware that some applications might use these key combinations, &lt;a href="https://defkey.com/search?irq=ctrl+alt+d" rel="noopener noreferrer"&gt;you can check using DefKey.com&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+Shift+Alt+(anyKey)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Alt+Shift+(anyKey)&lt;/code&gt; (&lt;a href="https://defkey.com/search?irq=alt+shift" rel="noopener noreferrer"&gt;Check here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+Win+(anyKey)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+Win+Alt+(anyKey)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are some examples:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

^#1::Run "https://mail.google.com/mail/u/0/#inbox"   ; use ctrl+win+1 to open gmail 1
^#2::Run "https://mail.google.com/mail/u/1/#inbox"   ; use ctrl+win+2 to open gmail 2
^#3::Run "https://translate.google.ro/?hl=ro&amp;amp;tab=wT" ; use ctrl+win+3 to open Google Translate

^+!1::Run "https://www.google.com"      ; use ctrl+shift+alt+1
^+!2::Run "https://dev.to"              ; use ctrl+shift+alt+2
^+!3::Run "https://www.linkedin.com"    ; use ctrl+shift+alt+3
^+!4::Run "https://www.spotify.com/"    ; use ctrl+shift+alt+4
^+!5::Run "https://www.mixcloud.com/"   ; use ctrl+shift+alt+5
^+!6::Run "https://www.freecodecamp.org/learn/"

^!t::Run cmd, C:\Users\Username         ; use ctrl+alt+t to run Cmd
^!w::Run winamp.exe                     ; use ctrl+alt+w to run Winamp
^!s::Run C:\Program Files\Sublime Text 3\sublime_text.exe
^!v::Run C:\Users\Username\AppData\Local\Programs\Microsoft VS Code\Code.exe


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Open new explorer window with the same path as the currently focused folder
&lt;/h2&gt;

&lt;p&gt;I often use &lt;code&gt;Win+E&lt;/code&gt; default shortcut to open the Explorer, but oftentimes I need to open a new window within the same location to move/organize some files. So why not use &lt;code&gt;Ctrl+Win+E&lt;/code&gt; shortcut to do that?&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

^#e::                                  ; use ctrl+win+e 
{                                      ; to open new explorer window with the same selected folder
  Send, !d
  Sleep 50
  Send, ^c
  Sleep 100
  Run, Explorer "%clipboard%" 
  Return
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can do even more by opening the new explorer and have both windows side by side, and even have the new window go up one level:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

^+#e::                                  ; use ctrl+shift+win+e 
{                                       ; to open new explorer window with the same selected folder
  Send, #{Left}
  Sleep 50  
  Send, !d
  Sleep 50
  Send, ^c
  Sleep 100
  Run, Explorer "%clipboard%"
  Sleep 900
  Send, !{Up}
  Sleep 600
  Send, #{Right}
  Return
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxtjf86n9etbqa8cis3hz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxtjf86n9etbqa8cis3hz.gif" alt="Open new Explorer with same path"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  6. Copy to clipboard the HEX color of the pixel under your cursor
&lt;/h2&gt;

&lt;p&gt;We can copy the HEX color under our cursor using &lt;code&gt;Ctrl+Win+LeftClick&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

; Copy to clipboard the HEX color of the pixel under your cursor using CTRL+Win+LeftClick
^#LButton::
{
  MouseGetPos, MouseX, MouseY
  PixelGetColor, color, %MouseX%, %MouseY%, RGB
  StringLower, color, color
  clipboard := SubStr(color, 3)
  Return
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyof70dn80nmdwpinkguc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyof70dn80nmdwpinkguc.gif" alt="Copy HEX Color under cursor"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  7. Adjust the main volume using the mouse scroll wheel
&lt;/h2&gt;

&lt;p&gt;You can adjust your main volume with key combinations such as &lt;code&gt;RAlt &amp;amp; NumpadAdd&lt;/code&gt;/&lt;code&gt;RAlt &amp;amp; NumpadSub&lt;/code&gt;, or with your mouse wheel while holding &lt;code&gt;Right Alt&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

RAlt &amp;amp; WheelUp::Volume_Up
RAlt &amp;amp; WheelDown::Volume_Down


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Or, you can hold down one of the side buttons on your mouse while scrolling (if you have such a mouse)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

XButton1 &amp;amp; WheelUp::Volume_Up
XButton1 &amp;amp; WheelDown::Volume_Down


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can also play/pause our current playing song using a left-side mouse button:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

XButton1::Media_Play_Pause


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can do so much more using our side mouse buttons! You can read more about mouse macros &lt;a href="https://dev.to/radualexandrub/embrace-mouse-macros-into-your-dev-life-to-increase-your-productivity-with-ahk-part-2-358j"&gt;in my previous post&lt;/a&gt;.&lt;/p&gt;



&lt;h2&gt;
  
  
  8. Auto-complete syntaxes with Hotstrings
&lt;/h2&gt;

&lt;p&gt;These are not exactly keyboard shortcuts, but rather abbreviations expansions. More important, we can use any keywords that we like in order to auto-complete syntaxes such as print statements and loops, in any programming language:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

:*:printc::printf('%d\n', num);

:*:logjs::
{
Send, console.log();{Left}{Left}
Return
}

:*:printjava::
{
Send, System.out.println();{Left}{Left}
Return
}

:*:writecs::
{
Send, Console.WriteLine();{Left}{Left}
Return
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fazuphfte69qj4p877p5m.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fazuphfte69qj4p877p5m.gif" alt="Print statements shortcuts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

::forC::
(
for (int i = 0; i &amp;lt; n; i++) {
)

::forJs::
(
for (let i = 0; i &amp;lt; arr.length; i++) {
)

::forPy::for i in range(0, len(arr)):

:*:forMatlab::
(
for i = 1:step:length(arr)

end
)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fewbj31huxilnmxr7ifss.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fewbj31huxilnmxr7ifss.gif" alt="Loops autocomplete using AutoHotKey"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

::switchJs::
(
switch() {
case 0:

break;
case 1:

break;
default:
)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqmc1fsmsowwkosdzbhv1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqmc1fsmsowwkosdzbhv1.gif" alt="Switch Case autocomplete shortcut"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've made a complete guide on using AutoHotKey's hotstrings &lt;a href="https://dev.to/radualexandrub/use-hotstrings-in-your-dev-life-to-increase-your-daily-productivity-with-ahk-3l79"&gt;here&lt;/a&gt;.&lt;/p&gt;



&lt;h2&gt;
  
  
  Honorable mentions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Put PC to sleep
&lt;/h3&gt;

&lt;p&gt;We can get our PC into sleep mode by using a key shortcut like &lt;code&gt;RAlt+PauseKey&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

; Put PC in sleep mode
RAlt &amp;amp; Pause::DllCall("PowrProf\SetSuspendState", "int", 0, "int", 0, "int", 0)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Empty recycle bin
&lt;/h3&gt;

&lt;p&gt;We can empty the recycle bin by using &lt;code&gt;WinKey+Del&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

#Del::FileRecycleEmpty ; use win+del to empty recycle bin


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Get the current date/hour
&lt;/h3&gt;

&lt;p&gt;We can use AutoHotKey's Hotstrings to write the current system's date &amp;amp; time:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

:*:datenow::
{
  FormatTime, DateString, , dddd, MMMM dd, yyyy
  Send %DateString%
  Return
}

:*:timenow::
{
  FormatTime, DateString, , HH:mm
  Send %DateString%
  Return
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjkewuta2lfzpzle855va.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjkewuta2lfzpzle855va.gif" alt="Shortcut for Date and Time"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

:*:datetoday::
{
  FormatTime, DateString, , yyyy-MM-dd
  Send %DateString%
  Return
}

:*:datetmr::
{
  Date += 1, Days
  FormatTime, DateString, %Date%, yyyy-MM-dd
  Send %DateString%
  Reload ; Return and clear variables
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faur0yiwlnfjokybft6ss.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faur0yiwlnfjokybft6ss.gif" alt="Shortcut for Date and Time Excel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Use arrow keys as Home/End while holding RAlt
&lt;/h3&gt;

&lt;p&gt;If you like cutting, pasting, and selecting lots of text. These "macros" might be handy:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

; Arrow keys as Home/End
RAlt &amp;amp; Left::
{
  If GetKeyState("Shift", "P")
    Send +{Home}
  Else
    Send {Home}
  Return
}
RAlt &amp;amp; Right::
{
  If GetKeyState("Shift", "P")
    Send +{End}
  Else
    Send {End}
  Return
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Disable CapsLock key
&lt;/h3&gt;

&lt;p&gt;Well, if you find yourself accidentally switching the CapsLock state from time to time... you can actually disable it completely. At the very first beginning of the &lt;code&gt;.ahk&lt;/code&gt; file, just add the following:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

; Set Lock Keys permanently off
SetCapsLockState, AlwaysOff
Return


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is especially useful if we are using 60% keyboards. However, if you need to use CapsLock now and then, you can make it a little harder to toggle it's state, by pressing &lt;code&gt;Alt+CapsLock&lt;/code&gt; instead:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

; Set Lock Keys permanently off by default
SetCapsLockState, AlwaysOff
Return

Alt &amp;amp; CapsLock::
If GetKeyState("CapsLock","T")
  SetCapsLockState, AlwaysOff
Else
  SetCapsLockState, On
Return


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can find more on AHK's &lt;code&gt;GetKeyState()&lt;/code&gt; &lt;a href="https://www.autohotkey.com/docs/commands/GetKeyState.htm" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fin
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft2t3zpzrges0132q9fn9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft2t3zpzrges0132q9fn9.jpg" alt="Mountains photo"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;span&gt;Mountains Photo by &lt;a href="https://unsplash.com/@vorosbenisop?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Benjamin Voros&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/mountains?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That was it! I'm hoping that you found some of these macros actually useful in your day to day life... or maybe you got some other ideas for your workflow.&lt;/p&gt;

&lt;p&gt;Have a wonderful day,&lt;br&gt;
R.B.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>productivity</category>
      <category>autohotkey</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Use HotStrings in your Dev Life to increase your daily Productivity with AHK</title>
      <dc:creator>Radu-Alexandru B</dc:creator>
      <pubDate>Sat, 07 Nov 2020 13:21:34 +0000</pubDate>
      <link>https://dev.to/radualexandrub/use-hotstrings-in-your-dev-life-to-increase-your-daily-productivity-with-ahk-3l79</link>
      <guid>https://dev.to/radualexandrub/use-hotstrings-in-your-dev-life-to-increase-your-daily-productivity-with-ahk-3l79</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover Photo by &lt;a href="https://www.pexels.com/photo/orange-cat-foot-on-laptop-keyboard-1440387/" rel="noopener noreferrer"&gt;Александар Цветановић&lt;/a&gt; on &lt;a href="https://www.pexels.com/" rel="noopener noreferrer"&gt;Pexels&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What are AHK's HotStrings?&lt;/li&gt;
&lt;li&gt;Hotstrings we are going to create&lt;/li&gt;
&lt;li&gt;Hotstrings types&lt;/li&gt;
&lt;li&gt;Creating our Hotstrings&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What are AHK's HotStrings?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.autohotkey.com/docs/Hotstrings.htm" rel="noopener noreferrer"&gt;HotStrings&lt;/a&gt; in &lt;a href="https://www.autohotkey.com/" rel="noopener noreferrer"&gt;AutoHotKey&lt;/a&gt; "shortcuts" that are  mainly used to expand (or auto-replace) abbreviations as you type them:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcrhu97l30wk4tikr5oaf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcrhu97l30wk4tikr5oaf.gif" alt="Using hotstrings abbreviation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hotstrings can be also used to launch any scripted actions (like the &lt;em&gt;macros&lt;/em&gt; used in the previous posts).&lt;/p&gt;




&lt;h2&gt;
  
  
  Hotstrings we are going to create
&lt;/h2&gt;

&lt;p&gt;Let's see what Hotstrings we are going to create today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some basic HTML tags for anchors, lists&lt;/li&gt;
&lt;li&gt;Autocomplete syntaxes for print, loops, conditionals, functions in your favorite programming language&lt;/li&gt;
&lt;li&gt;Dates in any format that we want (eg. &lt;code&gt;dddd, MMMM dd, yyyy, HH:mm&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Hotstrings types
&lt;/h2&gt;

&lt;p&gt;Before we jump in to create some HotStrings, let's see a few differences between the two types of HotStrings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hotstrings that are triggered &lt;em&gt;after&lt;/em&gt; pressing an ending character (eg &lt;code&gt;Space&lt;/code&gt;, &lt;code&gt;.&lt;/code&gt;, or &lt;code&gt;Enter&lt;/code&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;::forloop::for (let i = 0; i &amp;lt; arr.length; i++) {
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Hotstrings that are triggered right after you wrote them (they contain an &lt;code&gt;*&lt;/code&gt; - asterisk)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:*:printc::printf('%d\n', num);

:*:&amp;lt;a&amp;gt;::&amp;lt;a href="" title=""&amp;gt;&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay, why is this important?&lt;br&gt;
Well, if we are going to use only hotstrings that are triggered right after writing them (&lt;code&gt;*&lt;/code&gt;), we have to make sure don't use keywords containing other used keywords inside them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:*:printMe::console.log();
:*:printMeToo::System.out.println(); 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;printMeToo&lt;/code&gt; hotstring will never be triggered, because &lt;code&gt;printMe&lt;/code&gt; will always trigger before we can write 'Too'.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fib2mf970r85dd5sv9ebj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fib2mf970r85dd5sv9ebj.gif" alt="Using AHK for Java"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Femug8s6zmxkq6d87l0oz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Femug8s6zmxkq6d87l0oz.gif" alt="Using AHK Hotstrings for JavaScript"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that hotstrings aren't case sensitive by default (&lt;a href="https://www.autohotkey.com/docs/Hotstrings.htm" rel="noopener noreferrer"&gt;you can read more here but it's not mandatory for our next hotstrings&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Another important aspect of these types of hotstring is their usage in different text editors. For example, we would use a hotstring triggered after &lt;code&gt;Enter&lt;/code&gt; for &lt;code&gt;for loops&lt;/code&gt;, because the editor will auto-close the brackets.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvl7tufanq79rut8zjq2z.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvl7tufanq79rut8zjq2z.gif" alt="Using Hotstrings for JavaScript"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating our Hotstrings
&lt;/h2&gt;

&lt;p&gt;Okaay, we already saw a few hotstrings. Let's jump into creating more! As we noticed, a hotstring starts with &lt;code&gt;::&lt;/code&gt;, followed by their triggering keyword, then &lt;code&gt;::&lt;/code&gt; again, and ends with the actual string used. So the syntax looks more or less like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;::Keyword::String
:*:Keyword2::String2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, it's important to note that if we want to create hotstrings that use multiple lines, we need to use parentheses &lt;code&gt;( )&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;::quickfox::
(
The quick brown fox jumps over the lazy dog.
But no one asks how the fox feels...
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F35fh0zrc60cnh14okf7a.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F35fh0zrc60cnh14okf7a.gif" alt="Autocomplete quick brown fox"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or another example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:*:mysignature::
(
Yours faithfully,
John Doe

john.doe@domain.com
www.johnnydoe.com
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F12i7i3z1wzch8iil82el.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F12i7i3z1wzch8iil82el.gif" alt="Autocomplete signature in mail"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;Good, let's quickly write some auto-completion for HTML tags:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:*:&amp;lt;a&amp;gt;::&amp;lt;a href="" title=""&amp;gt;&amp;lt;/

::&amp;lt;ulli&amp;gt;::
(
&amp;lt;ul class="navbar-nav"&amp;gt;
&amp;lt;li class="nav-item"&amp;gt;&amp;lt;a href=""&amp;gt;&amp;lt;/&amp;lt;/
&amp;lt;li class="nav-item"&amp;gt;&amp;lt;a href=""&amp;gt;&amp;lt;/&amp;lt;/
&amp;lt;li class="nav-item"&amp;gt;&amp;lt;a href=""&amp;gt;&amp;lt;/&amp;lt;/
&amp;lt;/
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz1kewlhrgpjoftx4f2lz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz1kewlhrgpjoftx4f2lz.gif" alt="Autocomplete HTML tags using AutoHotKey"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, the hotstrings for HTML tags really depend on the text editor that is currently used... For example, &lt;a href="https://www.sublimetext.com/" rel="noopener noreferrer"&gt;Sublime Text&lt;/a&gt; auto-closes opened tags after writing &lt;code&gt;&amp;lt;/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Hmm, okay:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let's write a print statement in the following languages: C, Matlab, JavaScript, Java, C#:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:*:printc::printf('%d\n', num);
:*:printm::fprintf('%d\n', num);

:*:logjs::
{
Send, console.log();{Left}{Left}
Return
}

:*:printjava::
{
Send, System.out.println();{Left}{Left}
Return
}

:*:writec#::
{
Send, Console.WriteLine();{Left}{Left}
Return
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3mhycsibxwfuwc1zvv6k.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3mhycsibxwfuwc1zvv6k.gif" alt="Print statements using AutoHotKey"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nice. "Debugging" will be a little easier now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj3n72czl2sllp6yc6ed5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj3n72czl2sllp6yc6ed5.jpg" alt="Debuggig using prints"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay sorry for that. Note that for JS, Java and C# we used multiple instructions (macros) instead of a simple string (we used these a lot in previous parts of this post).&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;Let's see how we will write some &lt;code&gt;loops&lt;/code&gt; in C, JavaScript, Python, and Matlab.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;::forC::
(
for (int i = 0; i &amp;lt; n; i++) {
)

::forJs::
(
for (let i = 0; i &amp;lt; arr.length; i++) {
)

::forPy::for i in range(0, len(arr)):

:*:forMatlab::
(
for i = 1:step:length(arr)

end
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fewbj31huxilnmxr7ifss.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fewbj31huxilnmxr7ifss.gif" alt="Loops autocomplete using AutoHotKey"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;Finally, let's see a really useful feature of hotstrings, namely: Date types. Let's write the following scripts:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:*:datenow::
{
  FormatTime, DateString, , dddd, MMMM dd, yyyy
  Send %DateString%
  Return
}

:*:timenow::
{
  FormatTime, DateString, , HH:mm
  Send %DateString%
  Return
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjkewuta2lfzpzle855va.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjkewuta2lfzpzle855va.gif" alt="Shortcut for Date and Time"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.autohotkey.com/docs/commands/FormatTime.htm" rel="noopener noreferrer"&gt;Here's more info about dates and time formating in AHK&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's see another useful scenario for using dates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:*:datetoday::
{
  FormatTime, DateString, , yyyy-MM-dd
  Send %DateString%
  Return
}

:*:datetmr::
{
  Date += 1, Days
  FormatTime, DateString, %Date%, yyyy-MM-dd
  Send %DateString%
  Reload ; Return and clear variables
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faur0yiwlnfjokybft6ss.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faur0yiwlnfjokybft6ss.gif" alt="Shortcut for Date and Time Excel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that for &lt;code&gt;datetmr&lt;/code&gt; we now used &lt;a href="https://www.autohotkey.com/docs/Variables.htm" rel="noopener noreferrer"&gt;AHK variables&lt;/a&gt; such as &lt;code&gt;%Date%&lt;/code&gt; in our script, and we also used &lt;code&gt;Reload&lt;/code&gt; instead of &lt;code&gt;Return&lt;/code&gt;. If we use &lt;code&gt;Return&lt;/code&gt;, we won't clear the created &lt;code&gt;%Date%&lt;/code&gt; variable, and each time we wrote &lt;code&gt;datetmr&lt;/code&gt; hotstring, we will get the next day of the day before and so on. &lt;/p&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1s60py6uektux3mxxlln.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1s60py6uektux3mxxlln.jpg" alt="The End graphics"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;a href="https://www.vecteezy.com/free-vector/movie" rel="noopener noreferrer"&gt;"The End" Movie Vector by Vecteezy&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This was the last part of my &lt;strong&gt;&lt;em&gt;AutoHotKey series for increasing productivity&lt;/em&gt;&lt;/strong&gt;. I hope that I got some of you into using macros and how beneficial they could be in multiple scenarios, or at least you got some other ideas for automating boring stuff with them.&lt;/p&gt;

&lt;p&gt;Okay done. Happy coding and keep improving!&lt;br&gt;
R.B.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>productivity</category>
      <category>autohotkey</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Embrace Mouse Macros into your Dev Life to increase your Productivity with AHK - Part 2</title>
      <dc:creator>Radu-Alexandru B</dc:creator>
      <pubDate>Fri, 30 Oct 2020 18:41:31 +0000</pubDate>
      <link>https://dev.to/radualexandrub/embrace-mouse-macros-into-your-dev-life-to-increase-your-productivity-with-ahk-part-2-358j</link>
      <guid>https://dev.to/radualexandrub/embrace-mouse-macros-into-your-dev-life-to-increase-your-productivity-with-ahk-part-2-358j</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;span&gt;Cover Photo by &lt;a href="https://unsplash.com/@impulse9696?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Davide Boscolo&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Short Intro&lt;/li&gt;
&lt;li&gt;
Setting up Mouse Macros

&lt;ul&gt;
&lt;li&gt;What macros we will create?&lt;/li&gt;
&lt;li&gt;Mouse buttons we can map&lt;/li&gt;
&lt;li&gt;Setting up a convention&lt;/li&gt;
&lt;li&gt;Mapping our mouse&lt;/li&gt;
&lt;li&gt;Productive Scenarios&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Bonus Macro for Front-end Devs&lt;/li&gt;

&lt;li&gt;Full code from this post&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;Short Intro&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;As we saw in our previous part of this post, we can achieve quite a few things with AutoHotKey keyboard macros. In this part, we will focus more on using combinations of a &lt;em&gt;3-sided-button mouse&lt;/em&gt;. If you don't have such a mouse, well, don't worry, you can assign the following macros to any other keyboard keys you want (as discussed earlier), however, the prices of these type of mice are really cheap (starting from $10 for any &lt;em&gt;"gaming"&lt;/em&gt; one, yet reliable). We'll later see some use-case scenarios for why such a mouse could be a real value for your general increase in productivity.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;Mouse Macros we will create&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Hoping that you skipped the long "short" intro, let's look into the mouse macros we'll create today (macros that &lt;em&gt;don't require any interaction with a keyboard&lt;/em&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adjust the main volume by holding a side key while scrolling&lt;/li&gt;
&lt;li&gt;Play/Pause our current song with a side key (Youtube, Spotify, Apple Music, Mixcloud, anything.)&lt;/li&gt;
&lt;li&gt;Screenshot an area with the help of &lt;a href="https://app.prntscr.com/en/index.html" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;LightShot&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Copy any text/image and Paste it from clipboard&lt;/li&gt;
&lt;li&gt;Scroll back and forth through (Browser/Text Editor) tabs by holding a side key while scrolling&lt;/li&gt;
&lt;li&gt;Close a (Browser) tab&lt;/li&gt;
&lt;li&gt;Reopen a closed Browser tab (that was closed accidentally or that we actually needed)&lt;/li&gt;
&lt;li&gt;Search a selected text on Google (we will the same method as we saw in the previous post)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;Mouse key we can map&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Every mouse with 3 side buttons will have the default functions of &lt;code&gt;Browser Go Back one page&lt;/code&gt;, &lt;code&gt;Browser Go Forward&lt;/code&gt;, and a &lt;code&gt;Control&lt;/code&gt; key. With AutoHotKey we can remap those Browser buttons. The &lt;code&gt;Control&lt;/code&gt; button (set by default) is actually useful for selecting multiple files, zoom in/out, or select/edit multiple lines of code simultaneously in &lt;a href="https://www.sublimetext.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;Sublime Text&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; (In &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;VSCode&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; we would use &lt;code&gt;Alt+Click&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzc0t3zyz580kp7fvwol5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzc0t3zyz580kp7fvwol5.jpg" alt="Mouse with 3 side buttons"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.autohotkey.com/docs/KeyList.htm#mouse" rel="noopener noreferrer"&gt;AHK notations for all of our mouse buttons&lt;/a&gt; are the following:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key notation in AHK&lt;/th&gt;
&lt;th&gt;Actual Mouse Key&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;LButton RButton MButton&lt;/td&gt;
&lt;td&gt;Left, Right, Middle buttons&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WheelDown WheelUp&lt;/td&gt;
&lt;td&gt;Our scroll wheel, obviously&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XButton1&lt;/td&gt;
&lt;td&gt;4th mouse button, typically performs the Browser_Back function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XButton2&lt;/td&gt;
&lt;td&gt;5th mouse button, typically performs the Browser_Forward function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WheelLeft WheelRight&lt;/td&gt;
&lt;td&gt;Not real buttons, but they can be used as hotkeys to scroll to left or right&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;Setting up a convention&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Is totally up to you to choose the key combinations of the previously mentioned buttons. However, I've created a small convention that I'll use in this post:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkhi392fi3gyy8or0tfoj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkhi392fi3gyy8or0tfoj.jpg" alt="Mouse macros convention"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;Mapping our mouse&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Firstly, we need again to keep in mind the key notations in AHK for &lt;code&gt;Control&lt;/code&gt;, &lt;code&gt;Shift&lt;/code&gt;, &lt;code&gt;Windows&lt;/code&gt;, and &lt;code&gt;Alt&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key notation in AHK&lt;/th&gt;
&lt;th&gt;Actual Key&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;^&lt;/td&gt;
&lt;td&gt;Control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;+&lt;/td&gt;
&lt;td&gt;Shift&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;!&lt;/td&gt;
&lt;td&gt;Alt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;#&lt;/td&gt;
&lt;td&gt;Windows Key&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And we'll also need to create a new &lt;code&gt;.ahk&lt;/code&gt; file named &lt;code&gt;mouseMacros.ahk&lt;/code&gt; (or we could just use the &lt;code&gt;myMacros.ahk&lt;/code&gt; from the previous post and add the new macros there).&lt;/p&gt;

&lt;p&gt;Finally, let's map our mouse. We'll start with our "5th mouse button" (&lt;code&gt;XButton1&lt;/code&gt;) used for our Media macros.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To play/pause our currently playing media (song), we'll just write:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XButton1::Media_Play_Pause
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;We will also write the following lines to adjust our main volume:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XButton1 &amp;amp; WheelUp::Volume_Up
XButton1 &amp;amp; WheelDown::Volume_Down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty straightforward I'd say. Let's save our file, and just double click it to open with AutoHotKey. The green 'H' icon will pop up letting us know that the script is running in the background:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftnxsdvlu7ej6axn6s3w5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftnxsdvlu7ej6axn6s3w5.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, we can start playing our favorite songs/playlists and hold &lt;code&gt;XButton1&lt;/code&gt; while scrolling to see our volume changing.&lt;/p&gt;

&lt;p&gt;Cool, let's add the next macros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Presuming that we installed &lt;a href="https://app.prntscr.com/en/index.html" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;LightShot&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;, a very handy screenshot tool for Windows, we'll use the Middle mouse button to take a screenshot. And, let's also write the Copy (with left-click) and Paste (right-click) functions, while holding &lt;code&gt;XButton1&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XButton1 &amp;amp; MButton::PrintScreen         ; Take screenshot
XButton1 &amp;amp; LButton::Send, ^c            ; Copy
XButton1 &amp;amp; RButton::^v                  ; Paste
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save this file, and click on &lt;code&gt;"Reload This Script"&lt;/code&gt; option from the AHK icon.&lt;/p&gt;

&lt;p&gt;Great! Next time when we are helping or asking somebody for help by sending a screenshot, we'll no longer take a picture with our phone, we'll just send a properly cropped screenshot instead, only by using our mouse!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkb7m68r98t4yddqtg2u8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkb7m68r98t4yddqtg2u8.gif" alt="Screenshot Copy Paste just by using Mouse"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's now add macros to the &lt;code&gt;XButton2&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By default, if we press &lt;code&gt;CTRL+TAB&lt;/code&gt; (&lt;code&gt;^Tab&lt;/code&gt;) or &lt;code&gt;CTRL+SHIFT+TAB&lt;/code&gt; (&lt;code&gt;^+Tab&lt;/code&gt;) in our Browser (eg. Chrome), we can go forward/backward one tab at a time. Let's add the following lines in order to go through tabs by scrolling with our mouse wheel (while holding &lt;code&gt;XButton2&lt;/code&gt;):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XButton2 &amp;amp; WheelUp::^+Tab               ; Scroll through Browser tabs
XButton2 &amp;amp; WheelDown::^Tab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;We also know we can open Open a new tab (&lt;code&gt;CTRL+T&lt;/code&gt; or &lt;code&gt;^t&lt;/code&gt;), close the current tab (&lt;code&gt;CTRL+W&lt;/code&gt; or &lt;code&gt;^w&lt;/code&gt;), and reopen a closed tab (&lt;code&gt;CTRL+SHIFT+T&lt;/code&gt; or &lt;code&gt;^+t&lt;/code&gt;). We will map these keys into our mouse like this:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XButton2::^t                            ; New tab
XButton2 &amp;amp; RButton::^w                  ; Close current tab
XButton2 &amp;amp; MButton::^+t                 ; Reopen last tab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, we will also use our useful macro to search on Google the currently selected text by pressing &lt;code&gt;XButton2&lt;/code&gt; and &lt;code&gt;Left Click&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XButton2 &amp;amp; LButton::                    ; Search currently selected text on Google
{
  Send, ^c
  Sleep 50
  Run, https://www.google.com/search?q=%clipboard%
  Return
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect. Let's save and reload the script... and also take it to a test drive!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhrofkuazxy0q6ksixfb4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhrofkuazxy0q6ksixfb4.gif" alt="Google Errors just by pressing a button"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Et voilà, we've successfully mapped our mouse.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;Productive Scenarios&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Okay, long talk ahead. After all those mappings, you may ask: "How the hell will I remember all these key combinations? My mouse/keyboard feels now like a puzzle that can do more harm than good with a wrong key press"... and yes, I would understand that. But, once you really start using these macros (one at a time), you will start getting comfortable. In a short period of time (maybe days or weeks), those macros will become second nature to you.&lt;/p&gt;

&lt;p&gt;Let's assume the following scenario: You are running a newly written code, but you encounter an error. Let's assume that your usual workflow is to search on Google for that error, open a few tabs, close other tabs, copy and paste some lines of code, and repeat until you solve that one error. Now, we all know that we usually encounter dozens of errors, therefore our majority of time is all about searching for fixes. &lt;/p&gt;

&lt;p&gt;What if each time we encounter an error, we would execute the whole workflow just by some clicks with our mouse? while we are concentrating more on the solution?&lt;/p&gt;

&lt;p&gt;Let's see how our earlier mapped macros could help us in this scenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, we run our code, error pops up: We just select the whole error text with our mouse, click both &lt;code&gt;sideClick+leftClick&lt;/code&gt; and google solutions opens&lt;/li&gt;
&lt;li&gt;Now we are going to open a bunch of new tabs (using our &lt;code&gt;middleClick&lt;/code&gt;) with some solutions (StackOverflow, GitHub, Dev, etc)&lt;/li&gt;
&lt;li&gt;Now we are scrolling through tabs (&lt;code&gt;sideClick+mouseWheel&lt;/code&gt;) and fast reading solutions, some of them may contain code that we might want to copy and paste (&lt;code&gt;sideClick+left/rightClick&lt;/code&gt;) into our project&lt;/li&gt;
&lt;li&gt;We are closing some of the irrelevant tabs with &lt;code&gt;sideClick+leftClick&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;We might realize that we actually needed a previously closen tab: &lt;code&gt;sideClick+middleClick&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;We might encounter a video tutorial on the way: &lt;code&gt;sideClick&lt;/code&gt; (to pause the currently playing song), open tutorial, adjust volume (&lt;code&gt;sideClick+mouseWheel&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Repeat (without even touching the keyboard)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;Bonus Macro for Front-end Devs&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Okay, here's one more useful macro for the front-end devs out there: We can copy to clipboard the HEX color of the current pixel under our cursor using &lt;code&gt;CTRL+Win+LeftClick&lt;/code&gt; (or any other keys you want):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;^#LButton::
{
  MouseGetPos, MouseX, MouseY
  PixelGetColor, color, %MouseX%, %MouseY%, RGB
  StringLower, color, color
  clipboard := SubStr(color, 3)
  Return
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's a showcase:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb4iduhtg9d0910vvzovz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb4iduhtg9d0910vvzovz.gif" alt="Copy Paste color under cursor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;Full code from this post&lt;/a&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XButton1::Media_Play_Pause
XButton1 &amp;amp; WheelUp::Volume_Up
XButton1 &amp;amp; WheelDown::Volume_Down
XButton1 &amp;amp; MButton::PrintScreen         ; Take screenshot
XButton1 &amp;amp; LButton::Send, ^c            ; Copy
XButton1 &amp;amp; RButton::^v                  ; Paste

XButton2 &amp;amp; WheelUp::^+Tab               ; Scroll through Browser tabs
XButton2 &amp;amp; WheelDown::^Tab
XButton2::^t                            ; New tab
XButton2 &amp;amp; RButton::^w                  ; Close current tab
XButton2 &amp;amp; MButton::^+t                 ; Reopen last tab
XButton2 &amp;amp; LButton::                    ; Search currently selected text on Google
{
  Send, ^c
  Sleep 50
  Run, https://www.google.com/search?q=%clipboard%
  Return
}

; Copy to clipboard the HEX color of the pixel under your cursor using CTRL+Win+LeftClick
^#LButton::
{
  MouseGetPos, MouseX, MouseY
  PixelGetColor, color, %MouseX%, %MouseY%, RGB
  StringLower, color, color
  clipboard := SubStr(color, 3)
  Return
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay done, that was it! In the next part, we'll finally cover AutoHotKey's &lt;strong&gt;&lt;em&gt;HotStrings&lt;/em&gt;&lt;/strong&gt;, hopefully as short as possible.&lt;/p&gt;

&lt;p&gt;Keep improving yourself,&lt;br&gt;
R.B.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>showdev</category>
      <category>autohotkey</category>
      <category>macros</category>
    </item>
    <item>
      <title>Embrace Keyboard Macros into your Dev Life with AutoHotKey - Part 1</title>
      <dc:creator>Radu-Alexandru B</dc:creator>
      <pubDate>Fri, 23 Oct 2020 09:06:30 +0000</pubDate>
      <link>https://dev.to/radualexandrub/embrace-macros-hotstrings-into-your-dev-life-with-autohotkey-part-1-4f7n</link>
      <guid>https://dev.to/radualexandrub/embrace-macros-hotstrings-into-your-dev-life-with-autohotkey-part-1-4f7n</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;a href="https://www.pexels.com/photo/black-lighted-gaming-keyboard-841228/" rel="noopener noreferrer"&gt;Cover image by Karol D, on Pexels.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Contents:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is AutoHotKey? What can I do with it?&lt;/li&gt;
&lt;li&gt;Installation&lt;/li&gt;
&lt;li&gt;Keyboard keys and combinations that you can map/remap&lt;/li&gt;
&lt;li&gt;Mapping our first keys&lt;/li&gt;
&lt;li&gt;Full code from this post&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;What is AutoHotKey?
&lt;/h2&gt;

&lt;p&gt;Without any blah-blah, &lt;a href="https://www.autohotkey.com/" rel="noopener noreferrer"&gt;AutoHotKey (AHK)&lt;/a&gt; is a scripting/interpreted language, that you can write in a script that will continuously run in the background when you open it (but don't worry, you have 100% control of this script). Every function that you'll write will have a set of instructions that will trigger on a &lt;strong&gt;&lt;em&gt;keystroke&lt;/em&gt;&lt;/strong&gt; or a certain &lt;strong&gt;&lt;em&gt;combination of keystrokes&lt;/em&gt;&lt;/strong&gt; that you press at a time.&lt;/p&gt;

&lt;p&gt;Okey-dokey, so what?&lt;/p&gt;

&lt;p&gt;This means you can create &lt;em&gt;macros&lt;/em&gt; (with key shortcuts) that activate some certain actions, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;select a word -&amp;gt; copy it -&amp;gt; open google on new chrome tab -&amp;gt; paste that word -&amp;gt; search it and show google results (all in less than 200milisecods)&lt;/li&gt;
&lt;li&gt;open a new tab with your favorite website&lt;/li&gt;
&lt;li&gt;open command prompt using &lt;code&gt;CTRL+ALT+T&lt;/code&gt; shortcut&lt;/li&gt;
&lt;li&gt;open command prompt with the path of &lt;strong&gt;&lt;em&gt;the currently selected directory&lt;/em&gt;&lt;/strong&gt; and run a command (like &lt;code&gt;npm start&lt;/code&gt; or &lt;code&gt;git status&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Adjust volume while &lt;strong&gt;&lt;em&gt;holding a key+scrolling mouse wheel&lt;/em&gt;&lt;/strong&gt; (the key could even be one of the side keys of your mouse, more on that later)&lt;/li&gt;
&lt;li&gt;Empty recycle bin by pressing &lt;code&gt;WIN+DEL&lt;/code&gt; (or any key combo you wish), anytime, anywhere&lt;/li&gt;
&lt;li&gt;Put PC into sleep mode (if you don't have the &lt;code&gt;FN-Sleep&lt;/code&gt; key)&lt;/li&gt;
&lt;li&gt;Auto rewrite 'brb' to 'be right back'... or...&lt;/li&gt;
&lt;li&gt;Autocomplete a for loop (or anything) syntax (any language, any text editor) just by writing &lt;code&gt;forjs&lt;/code&gt;, &lt;code&gt;forc&lt;/code&gt;, &lt;code&gt;ifelsepy&lt;/code&gt;, or any &lt;strong&gt;&lt;em&gt;hotstring&lt;/em&gt;&lt;/strong&gt; you'd ever want to use&lt;/li&gt;
&lt;li&gt;The sky is your limit, also &lt;a href="https://www.autohotkey.com/docs/Tutorial.htm" rel="noopener noreferrer"&gt;the docs&lt;/a&gt; and &lt;a href="https://www.autohotkey.com/boards/" rel="noopener noreferrer"&gt;the community&lt;/a&gt; are really great. There are high chances that any question you'd have, you'll find it answered.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Installation
&lt;/h2&gt;

&lt;p&gt;Simply download and run the setup from &lt;a href="https://www.autohotkey.com/" rel="noopener noreferrer"&gt;AutoHotKey.com&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Keyboard keys and combinations that you can map/remap
&lt;/h2&gt;

&lt;p&gt;You can &lt;code&gt;remap any key/combination keys&lt;/code&gt; or &lt;code&gt;map any combination of keys without a default function&lt;/code&gt;. Here are some of my key/keys combination that I recommend mapping:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.typinglounge.com%2Fwp-content%2Fuploads%2F2018%2F08%2Fnumber-pad-10-keys.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.typinglounge.com%2Fwp-content%2Fuploads%2F2018%2F08%2Fnumber-pad-10-keys.jpg" alt="Numpad"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;1) You can remap your Numpad keys (if you don't use them), or you can remap your Numpad keys &lt;strong&gt;&lt;em&gt;while Numlock is off&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;With Numlock off&lt;/th&gt;
&lt;th&gt;With Numlock on&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;NumpadIns&lt;/td&gt;
&lt;td&gt;Numpad0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NumpadEnd&lt;/td&gt;
&lt;td&gt;Numpad1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NumpadDown&lt;/td&gt;
&lt;td&gt;Numpad2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NumpadPgDn&lt;/td&gt;
&lt;td&gt;Numpad3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NumpadLeft&lt;/td&gt;
&lt;td&gt;Numpad4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NumpadClear&lt;/td&gt;
&lt;td&gt;Numpad5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NumpadRight&lt;/td&gt;
&lt;td&gt;Numpad6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NumpadHome&lt;/td&gt;
&lt;td&gt;Numpad7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NumpadUp&lt;/td&gt;
&lt;td&gt;Numpad8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NumpadPgUp&lt;/td&gt;
&lt;td&gt;Numpad9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NumpadDel&lt;/td&gt;
&lt;td&gt;NumpadDot&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In total, we can have up to 22 keys to assign macros with our Numpad.&lt;/p&gt;

&lt;p&gt;2) You can map (unused) keyboard combinations like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;RAlt+(anyKeyLetter)&lt;/code&gt; or &lt;code&gt;RAlt+(number)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CTRL+Alt+(anyKey)&lt;/code&gt; or even &lt;code&gt;CTRL+SHIFT+ALT+(anyKey)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, we have lots of alternatives when choosing our future keys to have macros.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Mapping our first keys
&lt;/h2&gt;

&lt;p&gt;Ok, enough talking - let's get into code and actually do something! &lt;/p&gt;

&lt;p&gt;To start writing a script we just need to create a new file with a &lt;code&gt;.ahk&lt;/code&gt; extension. The first things we need to have in mind are some key notations we will use:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key notation in AHK&lt;/th&gt;
&lt;th&gt;Actual Key&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;^&lt;/td&gt;
&lt;td&gt;Control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;+&lt;/td&gt;
&lt;td&gt;Shift&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;!&lt;/td&gt;
&lt;td&gt;Alt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;#&lt;/td&gt;
&lt;td&gt;Windows Key&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Now, let's make some of the macros I mentioned earlier:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Let's say, we want to map &lt;code&gt;CTRL+ALT+T&lt;/code&gt; to open our command prompt, just like in Linux&lt;/strong&gt;
In our newly created &lt;code&gt;myMacros.ahk&lt;/code&gt; file &lt;em&gt;(that you can open with Notepad, Notepad++ or any text editor)&lt;/em&gt;, we just need to write the following:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;^!t::Run cmd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all! Save it, and, if you already installed AutoHotKey, you can double-click this new file, and a small green H icon will pop up:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9m5553ssoahwv8keguy8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9m5553ssoahwv8keguy8.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This means our script is now running in the background! And, if you press &lt;code&gt;CTRL+ALT+T&lt;/code&gt; (&lt;code&gt;^!t&lt;/code&gt; in AHK's notation), you should see the Command Prompt that opens. Nice! Let's do more. Reopen &lt;code&gt;myMacros.ahk&lt;/code&gt;, and let's add some more macros.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Let's say, any time you press &lt;code&gt;CTRL+ALT++SHIFT+T&lt;/code&gt;, we open our PowerShell (instead of our command prompt)&lt;/strong&gt;... But also, let's make it that every time we open our PowerShell, we want it opened to &lt;code&gt;C:\Users\MyUserName&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; Also, this is a comment in AHK, it starts with ; and can be added anywhere

; use ctrl+alt+t to open Cmd Prompt in C:\Users\Radu location
^!t::Run cmd, C:\Users\Radu

; use ctrl+shift+alt+t to open PowerShell
^+!t:: Run powershell, C:\Users\Radu 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect, save it and click on the &lt;code&gt;Reload this script&lt;/code&gt; option (that we saw earlier) from the taskbar.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Let's say that we want to open Google.com or Dev.to every time we press &lt;code&gt;CTRL+ALT+1&lt;/code&gt; or &lt;code&gt;CTRL+ALT+2&lt;/code&gt;&lt;/strong&gt;. Just add to our existing code, these lines, then reload:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;^!1::Run "https://www.google.com" ; use ctrl+alt+1
^!2::Run "https://dev.to"         ; use ctrl+alt+2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Let's say that we want to adjust our Main Volume every time we are holding &lt;code&gt;ALT&lt;/code&gt; while &lt;code&gt;scrolling with our mouse wheel&lt;/code&gt;&lt;/strong&gt;. Add to our existing code, these lines, then reload:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Alt &amp;amp; WheelUp::Volume_Up          ; use Alt+MouseWheel to adjust volume
Alt &amp;amp; WheelDown::Volume_Down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty good stuff so far, I'd say... But, we can do even more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2esgcsxzi1a3kj76v3ba.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2esgcsxzi1a3kj76v3ba.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Let's say that.. every time we select any text, we want to search for it on Google immediately by pressing &lt;code&gt;CTRL+ALT+C&lt;/code&gt;&lt;/strong&gt;... Well, now we are going to write an entire function, within curly brackets, that ends with &lt;code&gt;Return&lt;/code&gt;. Let's add these lines to our &lt;code&gt;myMacros.ahk&lt;/code&gt;, save and reload:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; use ctrl+alt+c to search on Google the currently selected text
^!c::
{
  Send, ^c
  Sleep 50
  Run, https://www.google.com/search?q=%clipboard%
  Return
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Awesome!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Let's empty recycle bin by pressing &lt;code&gt;WIN+DEL&lt;/code&gt;&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#Del::FileRecycleEmpty ; use win+del
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.autohotkey.com/docs/commands/Shutdown.htm" rel="noopener noreferrer"&gt;Let's put our PC in Sleep mode&lt;/a&gt; by using &lt;code&gt;RightALT+s&lt;/code&gt;&lt;/strong&gt;. Note that we can also be specific about our choice of keys by saying the exact name of the key (&lt;code&gt;RAlt&lt;/code&gt;) in combination (&lt;code&gt;&amp;amp;&lt;/code&gt;) with &lt;code&gt;s&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RAlt &amp;amp; s:: DllCall("PowrProf\SetSuspendState", "int", 0, "int", 0, "int", 0)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Finally, let's open the command prompt in our currently selected folder&lt;/strong&gt;. To do that, we know that by pressing &lt;code&gt;Alt+d&lt;/code&gt; when having a folder opened will focus on &lt;em&gt;folder's path&lt;/em&gt;. So our steps sound like this: &lt;em&gt;Focus on folder's path, copy it to clipboard, run cmd within that path&lt;/em&gt;. So, this is the function we are looking for:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;^!u::     ; Use ctrl+alt+u to open cmd in current selected folder
{
  Send, !d
  Send, ^c
  Sleep 50
  Run cmd, %clipboard%
  Return
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, open a folder, press &lt;code&gt;CTRL+ALT+U&lt;/code&gt;, and see what happens. It's a really handy little shortcut, eh?&lt;br&gt;&lt;br&gt;
We can even make it more powerful by saying to write a specific command for us, like &lt;code&gt;git status&lt;/code&gt;, and also execute it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;^!i::     ; Use ctrl+alt+i to open cmd in current selected folder
{
  Send, !d
  Send, ^c
  Sleep 50
  Run cmd, %clipboard%
  Sleep 100
  Send, git status
  Sleep 100
  Send, {Enter}
  Return
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay now, we are approaching the end of this post. Bellow, you'll find our full code from &lt;code&gt;myMacros.ahk&lt;/code&gt; with all the things we accomplished.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;And that's it... &lt;em&gt;for now&lt;/em&gt;! In the next part of this post, we will use AutoHotKey to generate some autocompletion on each keyword (&lt;em&gt;Hot String&lt;/em&gt;) that we'll write. We will also look and some macros that we can use with a mouse that has up to 9 buttons (the ones with 3 side buttons).&lt;/p&gt;

&lt;p&gt;However, until then... There are a lot (I mean, &lt;strong&gt;&lt;em&gt;a lot&lt;/em&gt;&lt;/strong&gt;) of other articles on AutoHotKey with the best macros ever imagined. AutoHotKey is a scripting language, so it has &lt;code&gt;variables&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt; loops, &lt;code&gt;conditionals&lt;/code&gt;, &lt;code&gt;booleans&lt;/code&gt;, and even more... So it's a lot to take in.&lt;/p&gt;

&lt;p&gt;I'll leave here some more interesting articles on this topic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.autohotkey.com/docs/KeyList.htm" rel="noopener noreferrer"&gt;List of Keys (Keyboard, Mouse, and Joystick)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.maketecheasier.com/favorite-autohotkey-scripts/" rel="noopener noreferrer"&gt;12 Favorite AutoHotKey Scripts You Can Use to Make Life Easier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.makeuseof.com/tag/10-cool-autohotkey-scripts-make/" rel="noopener noreferrer"&gt;10+ Cool AutoHotkey Scripts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jszapp.com/autohotkey-10-handy-autohotkey-scripts-make-life-easier/" rel="noopener noreferrer"&gt;10 Handy AHK Scripts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.windowscentral.com/best-windows-10-keyboard-shortcuts" rel="noopener noreferrer"&gt;List of all Windows 10 keyboard shortcuts - to not overwrite them with AHK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/koepalex/autohotkey-markdown" rel="noopener noreferrer"&gt;AutoHotKey for writing MarkDown&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Full code from this post
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; List of keyboard buttons
; ^ = Control
; + = Shift
; ! = Alt
; # = Win (Windows key)

^!t::Run cmd, C:\Users\Radu                    ; use ctrl+alt+t to open Cmd Prompt in C:\Users\Radu location
^+!t:: Run powershell, C:\Users\Radu           ; use ctrl+shift+alt+t to open PowerShell

; use win+del to empty recycle bin
#Del::FileRecycleEmpty

; use RightAlt+s to put PC on sleep mode
RAlt &amp;amp; s:: DllCall("PowrProf\SetSuspendState", "int", 0, "int", 0, "int", 0)

^!1::Run "https://www.google.com"              ; use ctrl+alt+1
^!2::Run "https://dev.to"                      ; use ctrl+alt+2
^!3::Run notepad.exe, WinActivate notepad.exe  ; Open and focus on notepad.exe

Alt &amp;amp; WheelUp::Volume_Up                       ; use Alt+MouseWheel to adjust volume
Alt &amp;amp; WheelDown::Volume_Down

^!c::     ; use ctrl+alt+c to search on Google the currently selected text
{
  Send, ^c
  Sleep 50
  Run, https://www.google.com/search?q=%clipboard%
  Return
}

^!u::     ; Use ctrl+alt+u to open cmd in currently selected folder
{
  Send, !d
  Send, ^c
  Sleep 50
  Run cmd, %clipboard%
  Return
}

^!i::     ; Use ctrl+alt+i to open cmd in currently selected folder
{
  Send, !d
  Send, ^c
  Sleep 50
  Run cmd, %clipboard%
  Sleep 100
  Send, git status
  Sleep 100
  Send, {Enter}
  Return
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Oh, almost forgot: I mentioned that you can use &lt;em&gt;single key macros&lt;/em&gt; using the Numpad (with or without NumLock switched on). For all the macros mentioned earlier, just replace the key combo with a Numpad key, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NumpadIns::Run cmd, C:\Users\Radu                    ; use Numpad 0 (NumLock off) to open Cmd Prompt

NumpadDel::     ; use Numpad dot (NumLock off) to search on Google the currently selected text
{
  Send, ^c
  Sleep 50
  Run, https://www.google.com/search?q=%clipboard%
  Return
}

; etc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okaay. Twas a long post. Have a nice day. Bye.&lt;br&gt;
R.B.&lt;/p&gt;

</description>
      <category>autohotkey</category>
      <category>productivity</category>
      <category>macros</category>
      <category>lifehacks</category>
    </item>
    <item>
      <title>How to add Like/Unlike button to your Django Blog</title>
      <dc:creator>Radu-Alexandru B</dc:creator>
      <pubDate>Wed, 14 Oct 2020 11:45:03 +0000</pubDate>
      <link>https://dev.to/radualexandrub/how-to-add-like-unlike-button-to-your-django-blog-5gkg</link>
      <guid>https://dev.to/radualexandrub/how-to-add-like-unlike-button-to-your-django-blog-5gkg</guid>
      <description>&lt;p&gt;In this mini-tutorial, we will add a Like/Unlike functionality to our Django Blog. As a note, we will implement this feature while using a class-based view for our BlogPost DetailView.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;2nd NOTE: Unfortunately, we cannot avoid the page refresh after every click of Like/Unlike button. In order to skip the refresh, it is needed to implement the whole functionality of Like/Unlike button inside our blogpost-detail HTML, using Ajax.js. This mini-tutorial will not focus on this type of implementation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's get started, first, in our &lt;code&gt;models.py&lt;/code&gt; we need to add to our BlogPost model the following fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# models.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;likes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ManyToManyField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;related_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;blogpost_like&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;number_of_likes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;"likes"&lt;/strong&gt; is a Many-to-many relationship with our User model, meaning that users (objects) can have multiple likes, and blog posts can have multiple likes. The function &lt;strong&gt;number_of_likes&lt;/strong&gt; will return the number of likes of the current blog post object.&lt;/p&gt;

&lt;p&gt;After every change in the models.py file, we need to open our terminal and make the migrations to our database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# CLI/Terminal&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;C:&lt;span class="se"&gt;\P&lt;/span&gt;rojects&lt;span class="se"&gt;\.&lt;/span&gt;..&lt;span class="se"&gt;\Y&lt;/span&gt;ourDjangoAppMainFolder
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; python manage.py makemigrations
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; python manage.py migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's now make a function-based view for our Like button functionality. In your &lt;code&gt;view.py&lt;/code&gt; file, right before (or after) your BlogPost DetailView class, define a BlogPostLike function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.shortcuts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_object_or_404&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.http&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HttpResponseRedirect&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;BlogPostLike&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_object_or_404&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;blogpost_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;HttpResponseRedirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;blogpost-detail&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="p"&gt;)]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;'blogpost_id'&lt;/em&gt;&lt;/strong&gt; will be our button identification in our &lt;code&gt;blogpost_detail.html&lt;/code&gt;. Every time a logged-in user clicks the Like button, we will retrieve his id and then will check if that user already liked or not the current blogpost (more specifically: &lt;em&gt;if like from user x exists, then remove like from current blogpost, else, add like from user x to current blogpost&lt;/em&gt;). Then we will redirect the user to the same blogpost page (like a refresh of that page). &lt;/p&gt;

&lt;p&gt;Now, it the same &lt;code&gt;view.py&lt;/code&gt; file, where we've implemented our BlogPost DetailView, we need to add to our get_context_data the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogPostDetailView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DetailView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BlogPost&lt;/span&gt;
    &lt;span class="c1"&gt;# template_name = MainApp/BlogPost_detail.html
&lt;/span&gt;    &lt;span class="c1"&gt;# context_object_name = 'object'
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_context_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_context_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;likes_connected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_object_or_404&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pk&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;liked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;likes_connected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;liked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;number_of_likes&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;likes_connected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number_of_likes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;post_is_liked&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;liked&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Within our &lt;code&gt;get_context_data&lt;/code&gt; function, we will retrieve the current blogpost primary key, and we will check if the currently logged-in user has liked or not this blog post. We will store in a local variable this statement, to send it further as a context to our HTML-based blogpost_detail. We will also retrieve the number of likes (calling the earlier written function) in order to display the number of likes directly in our HTML template.&lt;/p&gt;

&lt;p&gt;Let's also add this new function-based view to our &lt;code&gt;urls.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# urls.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.views&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;BlogPostLike&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;blogpost-like/&amp;lt;int:pk&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BlogPostLike&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;blogpost_like&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, to our &lt;code&gt;blogpost_detail.html&lt;/code&gt; let's write in the DjangoTemplateLanguage the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- LIKES --&amp;gt;&lt;/span&gt;
{% if user.is_authenticated %}
  &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"{% url 'blogpost_like' object.id %}"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    {% csrf_token %}

    {% if post_is_liked %}
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"blogpost_id"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"{{object.id}}"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-info"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Unlike&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    {% else %}
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"blogpost_id"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"{{object.id}}"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-info"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Like&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    {% endif %}
  &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
{% else %}
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-outline-info"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% url 'login' %}?next={{request.path}}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Log in to like this article!&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&lt;/span&gt;
{% endif %}
&lt;span class="nt"&gt;&amp;lt;strong&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-secondary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ number_of_likes }} Like{{ number_of_likes|pluralize }}&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we are done!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fp2MbD-FCURo62GmLBI-OEpMXvXI2A5zDQAHDfJ41etEAQrBhZT9KKEzCpJ0LLyi_m2QGC3Dbdsk8-XIzNincoozjCgCGKc1jK77sBC_Ki2I07GBI3v1oy1Ex9FRuQYOigsD3gpQmAHE%3Dw2400" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fp2MbD-FCURo62GmLBI-OEpMXvXI2A5zDQAHDfJ41etEAQrBhZT9KKEzCpJ0LLyi_m2QGC3Dbdsk8-XIzNincoozjCgCGKc1jK77sBC_Ki2I07GBI3v1oy1Ex9FRuQYOigsD3gpQmAHE%3Dw2400" alt="Example of Like Button"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>blog</category>
    </item>
    <item>
      <title>Get started with Git CLI and use these workflows in your everyday projects</title>
      <dc:creator>Radu-Alexandru B</dc:creator>
      <pubDate>Mon, 05 Oct 2020 11:46:14 +0000</pubDate>
      <link>https://dev.to/radualexandrub/begginer-get-started-with-git-cli-and-use-these-workflows-in-your-everyday-projects-bk0</link>
      <guid>https://dev.to/radualexandrub/begginer-get-started-with-git-cli-and-use-these-workflows-in-your-everyday-projects-bk0</guid>
      <description>&lt;p&gt;I know, I know, there are a lot of mini-tutorials, cheatsheets, and howto's about Git, but some of those are really crazy! I can't see how a beginner that gives Git a try would start learning &lt;em&gt;first&lt;/em&gt; about cherry-pick and commit amends or whatever. So, presuming that you know Git as a version control system (if not, just watch &lt;a href="https://youtu.be/OdbBmvfThJY"&gt;this 12min intro from Telusko&lt;/a&gt;), but you never started using CLI commands, I'll write here some notes that got me going into using Git in all my personal projects!&lt;/p&gt;

&lt;h2&gt;
  
  
  Here's the contents:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;git help&lt;/li&gt;
&lt;li&gt;set up global configuration variables&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;git init&lt;/strong&gt; VS.  &lt;strong&gt;git clone&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;git status&lt;/li&gt;
&lt;li&gt;git diff&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;git work-flow (on master branch)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;git add -A&lt;/li&gt;
&lt;li&gt;git commit&lt;/li&gt;
&lt;li&gt;git log&lt;/li&gt;
&lt;li&gt;git push&lt;/li&gt;
&lt;li&gt;git remote&lt;/li&gt;
&lt;li&gt;git pull&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Schema: Working Directory, Staging Area, Git Remote Repository&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;time to create a new branch!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;git branch, git checkout&lt;/li&gt;
&lt;li&gt;merge a branch: git merge (+mini-work-flow)&lt;/li&gt;
&lt;li&gt;delete a branch&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;git &lt;strong&gt;Complete Work-flow&lt;/strong&gt; - work from another branch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;create a new repo from a locally existing/completed project (mini-work-flow)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;&lt;strong&gt;locally mistakes that could've been made&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;we need to discard changes to a modified file/files with &lt;code&gt;git checkout -- .&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;we mess up a commit -m message; modify the last commit message without doing another commit&lt;/li&gt;
&lt;li&gt;we forgot to add a file to the last commit&lt;/li&gt;
&lt;li&gt;we made commits to the master branch instead of our working branch&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;types of git resets (soft, mixed, hard)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fatal/big whoops: we did a hard reset on some changes but we realized that we actually need them: &lt;code&gt;git reflog&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;undoing a commit after pushing to remote server. Fix without &lt;strong&gt;changing the git history&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;using the &lt;strong&gt;&lt;code&gt;git stash&lt;/code&gt;&lt;/strong&gt; command&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;git help
&lt;/h3&gt;

&lt;p&gt;Display help (all commands) in CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nb"&gt;help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check Git version installed on PC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git help used on &lt;em&gt;commands&lt;/em&gt; will display the help info in a new Browser tab (Chrome/Firefox/Edge etc). This will be really handy to understand all those parameters used in various commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nb"&gt;help&lt;/span&gt; &amp;lt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;# is the same as git &amp;lt;command&amp;gt; --help&lt;/span&gt;

&lt;span class="c"&gt;# eg:&lt;/span&gt;
git &lt;span class="nb"&gt;help &lt;/span&gt;config
git config &lt;span class="nt"&gt;--help&lt;/span&gt; &lt;span class="c"&gt;# is the same as git help config&lt;/span&gt;
git add &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Set up global configuration variables
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Needed to push local repository to GitHub remote server&lt;/li&gt;
&lt;li&gt;Also useful when working in a team to see who changed the code (with the &lt;strong&gt;blame&lt;/strong&gt; command aka 'see who and when was this file last modified')&lt;/li&gt;
&lt;li&gt;For &lt;strong&gt;&lt;em&gt;name&lt;/em&gt;&lt;/strong&gt;: you can choose any name, it can be different from your github account&lt;/li&gt;
&lt;li&gt;For &lt;strong&gt;&lt;em&gt;email&lt;/em&gt;&lt;/strong&gt;: it must be the exact same email used on your github account
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name &lt;span class="s2"&gt;"John Doe"&lt;/span&gt; 
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email &lt;span class="s2"&gt;"JohnDoe97@gmail.com"&lt;/span&gt; 

git config &lt;span class="nt"&gt;--list&lt;/span&gt; &lt;span class="c"&gt;# list all configurations you made&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Create own local empty repository &lt;strong&gt;&lt;em&gt;init&lt;/em&gt;&lt;/strong&gt; VS. &lt;strong&gt;&lt;em&gt;clone&lt;/em&gt;&lt;/strong&gt; an existing repository as a local repository in your PC
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create own local empty repo (&lt;strong&gt;&lt;em&gt;init&lt;/em&gt;&lt;/strong&gt;) (it will create a new folder &lt;strong&gt;&lt;em&gt;.git&lt;/em&gt;&lt;/strong&gt; with all the informations about that repo):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;my_new_project_folder_name
git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Copy/Download an existing repo (&lt;strong&gt;&lt;em&gt;clone&lt;/em&gt;&lt;/strong&gt;) (this will also copy all of the earlier commits/history made to that repository)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;url&amp;gt; &amp;lt;optional:where_to_clone&amp;gt;
&lt;span class="c"&gt;# eg:&lt;/span&gt;
git clone https://github/username/android-app AndroidAppFolder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;git status
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git keeps track of modified/added/removed files and also which files are [are not] tracked.&lt;br&gt;
However, sometimes you don't want to track some files (eg. personal files, personal configurations files, cache files auto-generated after each build) =&amp;gt; create &lt;strong&gt;&lt;em&gt;.gitignore&lt;/em&gt;&lt;/strong&gt; file where you can write the files you don't want to include (ignore them forever):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mystuff.txt
*.pyc
.DS_Store
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;^^ These files won't show up anymore when calling &lt;strong&gt;&lt;em&gt;git status&lt;/em&gt;&lt;/strong&gt;.&lt;br&gt;
Also, .gitignore should be included (&lt;em&gt;git add .gitignore&lt;/em&gt;) to prevent a team collaborating on a project from committing generated cache files =&amp;gt; don't add .gitignore to .gitignore itself lol.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;git diff
&lt;/h3&gt;

&lt;p&gt;Git diff shows the changes made to the code within modified files (git status shows only which files have been modified/created).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Git work-flow (on master branch)
&lt;/h2&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add files to the staging area (= add all the files that are ready to be commited except the files from &lt;em&gt;.gitignore&lt;/em&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nt"&gt;-A&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Commit all the files added (tracked files) to the local repository.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Message from this commit"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add all the files to the staging area then commit:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Message from this commit"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Git reset [file.ext] will make all the files [or only file.ext] untracked (out of the staging area) =&amp;gt; The changes to that file.ext will not be committed!
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reset &lt;span class="o"&gt;[&lt;/span&gt;file.ext]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git log shows all the made commits (with a hash number, author, date of each commit). By default, the log opens in Vim text editor, if installed.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log
git log &lt;span class="nt"&gt;-3&lt;/span&gt; &lt;span class="c"&gt;# shows last 3 commits&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin master
&lt;span class="c"&gt;# git push -u &amp;lt;remote&amp;gt; &amp;lt;branch&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;# -u or --set-upstream is to save/add upstream (tracking) reference(the &amp;lt;remote&amp;gt; and &amp;lt;branch&amp;gt;), in order to just write "git push" without specifying again the &amp;lt;remote&amp;gt; and &amp;lt;branch&amp;gt; &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git remote shows all the remotes (GitHub repositories) where you can push the last (local) commit. Git remote -v is for verbose (all info about the remotes).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote
git remote &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To add a remote:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote add origin https://github.com/username/projectname/.git
&lt;span class="c"&gt;# git remote add &amp;lt;new_branch_name&amp;gt; &amp;lt;link_to_repository&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OBS: When cloning a remote (a GitHub repository) with git clone, a remote named "origin" will be available by default.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
Get (locally) the last state (last changes/updates) of the project if someone made changes on the global repository (the remote to github.com server):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git pull origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this error occurs when pulling: &lt;strong&gt;&lt;em&gt;"your local changes to the following files would be overwritten by merge"&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;you&lt;/strong&gt; want to &lt;strong&gt;drop/overwrite all the changes made from the local repository and get the latest updates from the global repository&lt;/strong&gt;, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Drop local changes, revert to the HEAD reference (last local commit in the master branch)&lt;/span&gt;
git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; &lt;span class="c"&gt;# NEVER USE: git checkout HEAD^ file/to/overwrite&lt;/span&gt;
git pull origin master
&lt;span class="c"&gt;# HEAD^ is short for HEAD^1, which means the one commit before HEAD. You could also do HEAD^2 for the commit before that one&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Or, discard/give up all the changes (modified files) and go back to the last (local) commit state of files:&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NOTE1: git checkout HEAD^ filename (will overwrite the file to the state of &lt;em&gt;commit before&lt;/em&gt; last local commit in the master branch)&lt;br&gt;&lt;br&gt;
NOTE2: git checkout HEAD^ &lt;strong&gt;without specifying a file&lt;/strong&gt; will &lt;strong&gt;DROP THE WHOLE LAST COMMIT!!! and will revert to the commit before last commit&lt;/strong&gt; (however you will be in a detached head state branch, so you can revert this action by just changing back to the master branch: git checkout master)&lt;br&gt;&lt;br&gt;
NOTE3: git checkout HEAD^1 is roughly the same as git reset HEAD^1, but:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use reset if you want to undo the staging of a modified file !!!&lt;/li&gt;
&lt;li&gt;Use checkout if you want to discard changes to unstaged file/s !!! (however it is still possible to recover lost files with git reflog and cherry-pick, check
locally mistakes section.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Schema: Working Directory, Staging Area, Git Remote Repository
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s6RQ2Rr5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh3.googleusercontent.com/qcd6flsLsxXl7xKIiICiPI76B-CfVPqjHg-a4zaYzW1OtNRrnS6DDfUvRYQ2tlefL1r_3Zr0GQGX9Pu-wdk7j5GclUcupWdPaLshka62qk3_X-flSWX1v4KFVZmMpcd5eVYpdME6pyU%3Dw2400" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s6RQ2Rr5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh3.googleusercontent.com/qcd6flsLsxXl7xKIiICiPI76B-CfVPqjHg-a4zaYzW1OtNRrnS6DDfUvRYQ2tlefL1r_3Zr0GQGX9Pu-wdk7j5GclUcupWdPaLshka62qk3_X-flSWX1v4KFVZmMpcd5eVYpdME6pyU%3Dw2400" width="880" height="744"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Create a new branch from CLI
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a&gt;&lt;/a&gt;git branch, git checkout
To create and move to a new branch:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch &amp;lt;new_branch_name&amp;gt;
git checkout &amp;lt;new_branch_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Show all branches/active branch with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch
git branch &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a&gt;&lt;/a&gt;Merge a branch: git merge (mini-workflow)
If all your modifications to the code are great and pass all the (unit) tests, merge your branch with the master branch:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout master &lt;span class="c"&gt;# change to master branch&lt;/span&gt;
git pull origin master &lt;span class="c"&gt;# get last updates before making any changes to master&lt;/span&gt;
git branch &lt;span class="nt"&gt;--merged&lt;/span&gt; &lt;span class="c"&gt;# show branches that are/aren't merged with master branch&lt;/span&gt;
git merge &amp;lt;my_new_branch_ive_worked_on&amp;gt;
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a&gt;&lt;/a&gt;Delete a branch (mini-workflow)
After you added the features from your branch and merged with master, you can &lt;strong&gt;delete&lt;/strong&gt; your branch you worked on:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch &lt;span class="nt"&gt;--merged&lt;/span&gt;
git branch &lt;span class="nt"&gt;-d&lt;/span&gt; &amp;lt;my_branch_ive_worked_on&amp;gt; &lt;span class="c"&gt;# locally delete the branch&lt;/span&gt;
git branch &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="c"&gt;# show all branches: we still have &amp;lt;my_branch&amp;gt; globally&lt;/span&gt;
git push origin &lt;span class="nt"&gt;--delete&lt;/span&gt; &amp;lt;my_branch_ive_worked_on&amp;gt; &lt;span class="c"&gt;# globally/definitely delete the branch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Git &lt;strong&gt;Complete Workflow&lt;/strong&gt; - Work from another branch
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email
git clone &amp;lt;url&amp;gt; &amp;lt;where_to_clone&amp;gt;
git branch &amp;lt;my_new_branch_name&amp;gt;
git checkout my_new_branch
&lt;span class="c"&gt;# (make changes to the code ...)&lt;/span&gt;
git status
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add @function in views.py | Solve bug in models.py that fixes #8"&lt;/span&gt;
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin my_new_branch
&lt;span class="c"&gt;# (wait for unit tests to complete)&lt;/span&gt;
&lt;span class="c"&gt;# (if all unit tests pass, then do these)&lt;/span&gt;
git checkout master
git pull origin master
git merge my_new_branch
git push origin master
&lt;span class="c"&gt;# (now time to delete my_new_branch)&lt;/span&gt;
git branch &lt;span class="nt"&gt;-d&lt;/span&gt; my_new_branch
git branch &lt;span class="nt"&gt;-a&lt;/span&gt;
git push origin &lt;span class="nt"&gt;--delete&lt;/span&gt; my_new_branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Create a new repo from a locally existing/completed project (mini-workflow)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;On GitHub.com website:

&lt;ul&gt;
&lt;li&gt;Create a new repository (write name &amp;amp; description)&lt;/li&gt;
&lt;li&gt;(optional) Create a Readme.MD file&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;On CLI (locally):

&lt;ul&gt;
&lt;li&gt;Open the terminal in that folder/project's path&lt;/li&gt;
&lt;li&gt;Write the following commands:
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
git remote add origin https://github.com/username/projectname/.git
git remote &lt;span class="nt"&gt;-v&lt;/span&gt;
git pull origin master &lt;span class="c"&gt;# needed to update the commit history of new repo (especially if Readme.MD or LICENSE was created)&lt;/span&gt;
git status
git add &lt;span class="nt"&gt;-A&lt;/span&gt;
git status
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial commit from local project"&lt;/span&gt;
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Locally Mistakes that could've been made
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;If we made changes to a single_file but then we don't want to keep the changes to that file anymore (we want to undo/go back):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout single_file.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if we want to discard all changes/modifications to our files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, if we want to delete/get rid of untracked files (newly created files):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clean &lt;span class="nt"&gt;-fd&lt;/span&gt; &lt;span class="c"&gt;# force directories&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;We mess up a commit -m message. We want to modify the last commit message without doing another commit
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;WARNING: The following commands in this section will change the hash of previous commits =&amp;gt; THIS WILL CHANGE &lt;em&gt;GIT HISTORY&lt;/em&gt; =&amp;gt; IF OTHER PEOPLE WILL PULL THE CHANGES AFTER EXECUTING THESE COMMANDS, THE CHANGED HISTORY COULD CAUSE BIG PROBLEMS TO THEIR REPOSITORIES. We can only change git history when we're the only one owners of the repository.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;--amend&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Corrected commit message"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;We forgot to add a file to the last commit. We want the add the file without committing again.
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add file.c &lt;span class="c"&gt;# get the file in the staging area&lt;/span&gt;
git commit &lt;span class="nt"&gt;--amend&lt;/span&gt; &lt;span class="c"&gt;# this will add the new file to last commit, also it opens a log in Vim, exit with :wq&lt;/span&gt;
git log &lt;span class="nt"&gt;--stat&lt;/span&gt; &lt;span class="c"&gt;# show file changes in commits&lt;/span&gt;
&lt;span class="c"&gt;# The last commit hash will be changed, so the git history will be changed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;We made commits to the master branch instead of our working branch. Fix: we "move" a commit(hash) to the master and return the state of the master branch
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# from master's branch&lt;/span&gt;
git log
&lt;span class="c"&gt;# grab/copy (the first 6-7 characters of) the commit hash that we want to cherry-pick&lt;/span&gt;
&lt;span class="c"&gt;# change to our working branch&lt;/span&gt;
git checkout &lt;span class="o"&gt;[&lt;/span&gt;my-branch-name]
git cherry-pick 1b818d3b
git log

&lt;span class="c"&gt;# Now delete the commit from master&lt;/span&gt;
git checkout master 
git log
&lt;span class="c"&gt;# grab/copy the hash of the commit before our wrong commit&lt;/span&gt;
git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; 2e75207
git log
git clean &lt;span class="nt"&gt;-fd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;WARNING: Again, this will change git history and will cause consequences when working in a team!!! I'll write some alternatives in the next sections.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Types of git resets
&lt;/h2&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;SOFT RESET&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="c"&gt;# grab the hash of the commit we want to keep, the commits after that commit will be removed&lt;/span&gt;
git reset &lt;span class="nt"&gt;--soft&lt;/span&gt; 2e7520782

git log
git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Git soft reset&lt;/strong&gt; will set us back to the specified commit BUT will keep the modified and new files from the unwanted commits (the ones we removed) in the &lt;strong&gt;&lt;em&gt;staging area&lt;/em&gt;&lt;/strong&gt; ("added files ready to be committed" area) - we still didn't lose our work, but we can discard with &lt;code&gt;git reset HEAD -- .&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;MIXED RESET&lt;/em&gt;&lt;/strong&gt; (DEFAULT)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="c"&gt;# grab the hash of the commit we want to keep, the commits after that commit will be removed&lt;/span&gt;
git reset 2e7520782

git log
git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Git mixed/default reset&lt;/strong&gt; will set us back to the specified commit BUT will keep the modified and new files from the unwanted commits (the ones we removed) in the &lt;strong&gt;&lt;em&gt;working directory&lt;/em&gt;&lt;/strong&gt; ("untracked files, before executing add -A" area) - we still didn't lose our work, but we can discard with &lt;code&gt;git checkout -- .&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;HARD RESET&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="c"&gt;# grab the hash of the commit we want to keep, the commits after that commit will be removed&lt;/span&gt;
git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; 2e7520782

git log
git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Git hard reset&lt;/strong&gt; will set us back to the specified commit AND will make all the changes in files to match the state that they were in the specified commit - we've lost our work.&lt;br&gt;&lt;br&gt;
However, a hard reset will not affect untracked files (newly created files from the unwanted commits, but it's irrelevant if we didn't create any new files). We can get rid of these untracked files with &lt;code&gt;git clean -fd&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
NOTE: &lt;code&gt;git clean -fd&lt;/code&gt; could be useful when we accidentally unzip an archive in a project directory (local repo) and we don't want to manually delete all the new files created.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;&lt;strong&gt;Fatal: We did a hard reset on some changes but we realized that we actually need them: &lt;code&gt;git reflog&lt;/code&gt; (or we deleted last commits)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This "fix" works if we screwed up with &lt;code&gt;git checkout HEAD^1&lt;/code&gt; or &lt;code&gt;git reset --hard HEAD^&lt;/code&gt;. (HEAD^ is short for/same with HEAD^1).&lt;br&gt;&lt;br&gt;
Luckily, git garbage collector (gc) collects/deletes (forever) lost commits after 30 days (IF WE DIDN'T ALREADY RAN &lt;code&gt;git gc&lt;/code&gt; COMMAND).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reflog
&lt;span class="c"&gt;# grab the hash before executed reset command&lt;/span&gt;
git checkout &lt;span class="o"&gt;[&lt;/span&gt;0c8189]
git log &lt;span class="c"&gt;# happily see our changes back &lt;/span&gt;

git branch
&lt;span class="c"&gt;# HOWEVER, we're in a detached head state - we are on a branch that would be trashed in the future, so we need to save those changes in a newly-created branch&lt;/span&gt;
git branch backup
git checkout master
git branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we've successfully recovered our lost changes, we can merge the backup branch with master (&lt;code&gt;git merge backup&lt;/code&gt;) &lt;strong&gt;OR&lt;/strong&gt; if our changes are already in master branch (do check), we can delete the backup branch (&lt;code&gt;git branch -d backup&lt;/code&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Undoing a commit after pushing to remote server. Fix &lt;strong&gt;without changing the git history&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Undo a commit (when other people already pulled the changes), without rewriting the git history. We use &lt;code&gt;git revert&lt;/code&gt; to create a new commit on top that reverses the changes of earlier commits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="c"&gt;# select the commit hash THAT WE WANT TO UNDO (the wrong commit)&lt;/span&gt;
git revert &lt;span class="o"&gt;[&lt;/span&gt;1b818d3] &lt;span class="c"&gt;# will also show a message in Vim, :wq to exit&lt;/span&gt;
git log &lt;span class="c"&gt;# you can see the new revert commit&lt;/span&gt;

&lt;span class="c"&gt;# You can also see the revert diff&lt;/span&gt;
git diff &lt;span class="o"&gt;[&lt;/span&gt;1b818d3] &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;hash &lt;/span&gt;from revert commit]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Using the &lt;strong&gt;&lt;code&gt;git stash&lt;/code&gt;&lt;/strong&gt; command ("temporary" commits)
&lt;/h2&gt;

&lt;p&gt;Useful for changes that you are not ready to commit yet, but you need to switch branches (or revert back to another code) work temporarily in another part of the project.&lt;br&gt;
NOTE: If you don't commit your changes (modified files) and you switch to another branch, your code will be lost.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch my_branch
git checkout my_branch
&lt;span class="c"&gt;# Make changes to the code, realize you have to switch branch for a moment&lt;/span&gt;
git stash save &lt;span class="s2"&gt;"Worked on login function"&lt;/span&gt;
&lt;span class="c"&gt;# git diff / git status will show "working tree clean" -&amp;gt; after pushing to stash, all modifications to files are gone.&lt;/span&gt;

&lt;span class="c"&gt;# You can now switch branches / cherry-pick commits / work on other part of project, when you come back:&lt;/span&gt;
&lt;span class="c"&gt;# Option 1:&lt;/span&gt;
git stash list
git stash apply stash@&lt;span class="o"&gt;{&lt;/span&gt;0&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="c"&gt;# after executing this, the saved stash will still be listed in stash list&lt;/span&gt;
&lt;span class="c"&gt;# Option 2:&lt;/span&gt;
git stash pop &lt;span class="c"&gt;# grabs the very first (top) stash, applies changes then drops that stash from stash list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also drop/delete stashes in stash list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash list
git stash drop stash@&lt;span class="o"&gt;{&lt;/span&gt;2&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Or delete all the stashes in the list (assume that all those changes were junk/no longer needed)&lt;/span&gt;
git stash clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NOTE: You can't merge two stashes (eg. &lt;code&gt;git stash pop&lt;/code&gt; twice) -&amp;gt; will show &lt;em&gt;Error: files would be overwritten by merge, please commit your changes or stash them before you merge&lt;/em&gt;.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;NOTE: &lt;strong&gt;The same stash list is accessible to every branch&lt;/strong&gt; =&amp;gt; Useful scenario: If you've written all your changes to code in a wrong branch (master) you need to commit to another branch, just stash the changes &lt;code&gt;git stash save "Worked on login function"&lt;/code&gt;, &lt;code&gt;git checkout another_branch&lt;/code&gt;, then grab changes from the stack (&lt;code&gt;stash apply stash@{?}&lt;/code&gt;/&lt;code&gt;stash pop&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits / Notes taken from these tutorials (which I highly recommend for more in-depth explanations):
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youtu.be/WbwIoQYP6no"&gt;(51m) Git Tutorials for Beginners from Telusko&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/playlist?list=PL-osiE80TeTuRUfjRe54Eea17-YfnOOAx"&gt;(1h24m) Git Tutorials from Corey Schafer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/playlist?list=PLRqwX-V7Uu6ZF9C0YMKuns9sLDzK6zoiV"&gt;(2h16m) Git and GitHub from The Coding Train&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to create a Comment Section for your Django Blog!</title>
      <dc:creator>Radu-Alexandru B</dc:creator>
      <pubDate>Mon, 28 Sep 2020 11:53:16 +0000</pubDate>
      <link>https://dev.to/radualexandrub/how-to-create-a-comment-section-for-your-django-blog-3egp</link>
      <guid>https://dev.to/radualexandrub/how-to-create-a-comment-section-for-your-django-blog-3egp</guid>
      <description>&lt;p&gt;Hi!&lt;/p&gt;

&lt;p&gt;This mini-tutorial will focus on creating a Comment Section for &lt;strong&gt;adding&lt;/strong&gt; (without update/delete) comments to each blog post. We will implement this feature while using a &lt;em&gt;class-based&lt;/em&gt; view, namely our &lt;strong&gt;&lt;em&gt;BlogPost DetailView&lt;/em&gt;&lt;/strong&gt;, mine's looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# MainApp/models.py
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;subtitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;date_posted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SET_NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ImageField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upload_to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;blog_images&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                              &lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;gd_storage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__str__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_absolute_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;blogpost-detail&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pk&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;# MainApp/views.py
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogPostDetailView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DetailView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BlogPost&lt;/span&gt;
    &lt;span class="c1"&gt;# template_name = MainApp/BlogPost_detail.html
&lt;/span&gt;    &lt;span class="c1"&gt;# context_object_name = 'object'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;First things first: we need to create our BlogComment model in our &lt;code&gt;models.py&lt;/code&gt;. We can personalize our model in any way we want, I'll stick to the basics of a comment and will add the following fields: &lt;em&gt;author&lt;/em&gt;, &lt;em&gt;content/body&lt;/em&gt;, and &lt;em&gt;a date&lt;/em&gt; (when the comment was posted):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# models.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogComment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;blogpost_connected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;related_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;comments&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;date_posted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__str__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blogpost_connected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Every BlogComment will have an id (foreign key) of its BlogPost (a BlogPost can have multiple BlogComments), and if a BlogPost is deleted, then all the BlogComments that were linked to that BlogPost will be deleted (on_delete == CASCADE).&lt;/li&gt;
&lt;li&gt;The author will also be a foreign key to the whole User object (that has its User id, username, email, etc), therefore a User can have multiple comments.&lt;/li&gt;
&lt;li&gt;We will also add the magic method &lt;strong&gt;str&lt;/strong&gt;() to view the comments in a more readable way (instead of viewing the object type) when we are making queries from our CLI/Admin panel).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2F69xf-pQkvH4LVRLar9gbwykflgcAa7tNOctrErrlH4NMmiPbwWy8XpgApwU7SbtB2ZyxUVCoo0-GKFknOmkHUQ52pUInuZF57UWJbZrQ9JJCWJsIGtXZJ_Qxiaz4uXe2ZV0W2gXLa-I%3Dw2400" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2F69xf-pQkvH4LVRLar9gbwykflgcAa7tNOctrErrlH4NMmiPbwWy8XpgApwU7SbtB2ZyxUVCoo0-GKFknOmkHUQ52pUInuZF57UWJbZrQ9JJCWJsIGtXZJ_Qxiaz4uXe2ZV0W2gXLa-I%3Dw2400" alt="Database Diagram for our comment"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;models.py&lt;/code&gt;, in our BlogPost model, we can also write a function that will return the number of comments of a blog post:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# models.py
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;

    &lt;span class="nd"&gt;@property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;number_of_comments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;BlogComment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blogpost_connected&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After every change in the models.py file, we need to open our terminal and make the migrations to our database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# CLI/Terminal&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;C:&lt;span class="se"&gt;\P&lt;/span&gt;rojects&lt;span class="se"&gt;\.&lt;/span&gt;..&lt;span class="se"&gt;\Y&lt;/span&gt;ourDjangoAppMainFolder
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; python manage.py makemigrations
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; python manage.py migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Let's create a new form class: In the same folder as our models.py, create a new file named &lt;code&gt;forms.py&lt;/code&gt;, where we'll write the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# forms.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;forms&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BlogComment&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NewCommentForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelForm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BlogComment&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Très bien, now we can add to our &lt;a href="https://docs.djangoproject.com/en/3.1/topics/class-based-views/generic-display/#adding-extra-context" rel="noopener noreferrer"&gt;get_context_data&lt;/a&gt; function within our class-based view BlogPost DetailView, in views.py, the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BlogComment&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.forms&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;NewCommentForm&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogPostDetailView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DetailView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BlogPost&lt;/span&gt;
    &lt;span class="c1"&gt;# template_name = MainApp/BlogPost_detail.html
&lt;/span&gt;    &lt;span class="c1"&gt;# context_object_name = 'object'
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_context_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_context_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;comments_connected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BlogComment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;blogpost_connected&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_object&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;order_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-date_posted&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;comments&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;comments_connected&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_authenticated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;comment_form&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NewCommentForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we will retrieve all the comments from our current BlogPost object, store them (the query) in a local variable &lt;em&gt;comments_connected&lt;/em&gt;, then send it further as a context to our HTML-based blogpost_detail.&lt;/p&gt;

&lt;p&gt;However, in order to post comments directly from our class-based BlogPost DetailView, we also need to define a &lt;strong&gt;post method&lt;/strong&gt; to receive the context from our form (situated in this view/html). Therefore, in the same class, we need to add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogPostDetailView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DetailView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt; 

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_context_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;new_comment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BlogComment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                  &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                  &lt;span class="n"&gt;blogpost_connected&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_object&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="n"&gt;new_comment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Finally, in our &lt;code&gt;blogpost_detail.html&lt;/code&gt; let's write in the DjangoTemplateLanguage the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- COMMENTS  --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Leave your comment!&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"comments_section"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  {% if user.is_authenticated %}
  &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    {% csrf_token %}
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-group"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      {{ comment_form }}
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-info"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Add comment &lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"fas fa-comments"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
  {% else %}
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-outline-info"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% url 'login' %}?next={{request.path}}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Log in to add a comment!&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&lt;/span&gt;
  {% endif %}

  {% if comments %}
  &lt;span class="nt"&gt;&amp;lt;strong&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-secondary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ object.number_of_comments }} Comment{{ object.number_of_comments|pluralize }}&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;hr&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
    {% for comment in comments %}
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;           
     &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;strong&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-info"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ comment.author }} &lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;small&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-muted"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ comment.date_posted }}&lt;span class="nt"&gt;&amp;lt;/small&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
          {{ comment.content|safe }}
        &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    {% endfor %}
  &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
  {% else %}
    &lt;span class="nt"&gt;&amp;lt;strong&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-secondary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;No comments yet...&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;
  {% endif %}

&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sooo, there's a lot of code there, let's go through some parts of it step by step:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first thing that we do is to check if the user is authenticated: if True, then show the user a form where he can write the content of his new comment. if False, then show the user a button that redirects him to the Login page. Also, it's important that after a user logs into his account to redirect him to the earlier blog post that he wanted to post a comment, so we'll add to our redirect link &lt;code&gt;"?next={{request.path}}"&lt;/code&gt; where request.path is the current page path (e.g. localhost/blogpost/7)&lt;/li&gt;
&lt;li&gt;Then we check if our current blogpost has any comments, if not, we'll put in our HTML "No comments yet..", but if we have any comments, we will then write the number of comments and then we will loop through each of them and show its author, date, and content.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Perfect, so we are almost done! However, this comment section will look rather dull... Therefore we need to create some styling, that we can find on Google or... &lt;a href="https://www.bootdey.com/snippets/view/Simple-Comment-panel#html" rel="noopener noreferrer"&gt;here&lt;/a&gt; (thanks to &lt;a href="https://www.bootdey.com/" rel="noopener noreferrer"&gt;bootdey.com&lt;/a&gt;)! To integrate it, we just need to add the CSS code in our &lt;code&gt;blogpost_detail.html&lt;/code&gt; and the corresponding tags in our &lt;code&gt;&amp;lt;div&amp;gt; and &amp;lt;ul&amp;gt;&lt;/code&gt; (list) sections, following their example.&lt;/p&gt;

&lt;p&gt;Nice, now we are done! Hope you will find this useful. 😁&lt;br&gt;
You can see a live example of this comment section on my blog: &lt;a href="https://codingtranquillity.herokuapp.com/" rel="noopener noreferrer"&gt;codingtranquillity.herokuapp.com&lt;/a&gt;... where you can also find more articles like this! &lt;/p&gt;

&lt;p&gt;Have a nice day and... Happy coding!&lt;br&gt;
R.B.&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>blog</category>
    </item>
    <item>
      <title>How to add sitemap.xml to your Django Blog and make it work on Heroku (SEO)</title>
      <dc:creator>Radu-Alexandru B</dc:creator>
      <pubDate>Mon, 21 Sep 2020 14:16:11 +0000</pubDate>
      <link>https://dev.to/radualexandrub/how-to-add-sitemap-xml-to-your-django-blog-and-make-it-work-on-heroku-4o11</link>
      <guid>https://dev.to/radualexandrub/how-to-add-sitemap-xml-to-your-django-blog-and-make-it-work-on-heroku-4o11</guid>
      <description>&lt;p&gt;Okay, I've spent a little to much time to figure this out, but here's my version of the &lt;strong&gt;Simplest Way to Add sitemap.xml to a Django App that is hosted on Heroku&lt;/strong&gt;. This will also solve the error: &lt;em&gt;"Internal Error 500"&lt;/em&gt; when trying to access /sitemap.xml from Heroku live app (production).&lt;/p&gt;

&lt;p&gt;First things first, make sure you have what to serve as static or as dynamic links. In this example, I'll add to my sitemap.xml my dynamically created BlogPosts and 3 more static pages: Main/Index.html, About.html and Contact.html. So let's get started:&lt;/p&gt;

&lt;p&gt;Firstly we need to add to our &lt;strong&gt;settings.py&lt;/strong&gt; file the followings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# settings.py
&lt;/span&gt;&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;

    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.sitemaps&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.sites&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;SITE_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, locally, we need to open our terminal and run python manage.py migrate. This will add to our local database the Sites model.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2FC3AInAsgFAdAaP86bFDSOD6_qtn5BH79zckFBMhS7VbHjnyMDtNwf4YTgTD9vOPKgRyuVSRXhcBFrud5JBUl0NGIEJyeMgVr3Twb0noWmKxJttwFw20XD3Ty9FZRpEvMHQksFCihYK0%3Dw2400" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2FC3AInAsgFAdAaP86bFDSOD6_qtn5BH79zckFBMhS7VbHjnyMDtNwf4YTgTD9vOPKgRyuVSRXhcBFrud5JBUl0NGIEJyeMgVr3Twb0noWmKxJttwFw20XD3Ty9FZRpEvMHQksFCihYK0%3Dw2400" alt="Sites table"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We observe that the first entry in Sites table (with SITE_ID == 1) is "example.com"... We will later change that in production when we'll push to Heroku.&lt;/p&gt;

&lt;p&gt;Now, we need to create a new file in our MainApp (Django App that we created at beginning of our project when we ran ./manage.py startapp MainApp), namely ../MainApp/&lt;strong&gt;sitemaps.py&lt;/strong&gt;. Here we'll add the followings, we can also refer to the &lt;a href="https://docs.djangoproject.com/en/3.1/ref/contrib/sitemaps/" rel="noopener noreferrer"&gt;documentation on Django Sitemaps&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# sitemaps.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.sitemaps&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Sitemap&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.shortcuts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BlogPost&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogPostSitemap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Sitemap&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;changefreq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weekly&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StaticViewSitemap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Sitemap&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;changefreq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;monthly&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;index&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;about&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;contact&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to add our continuingly generated sitemap.xml to our MainApp/&lt;strong&gt;urls.py&lt;/strong&gt;. So we need to add these lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# urls.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.sitemaps.views&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sitemap&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.sitemaps&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BlogPostSitemap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StaticViewSitemap&lt;/span&gt;

&lt;span class="n"&gt;sitemaps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;posts&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BlogPostSitemap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;static&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;StaticViewSitemap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sitemap.xml&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sitemap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sitemaps&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sitemaps&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good. We can check that sitemap.xml is displayed in our local server by running &lt;em&gt;python ./manage.py runserver&lt;/em&gt; and access our &lt;em&gt;&lt;a href="http://localhost:8000/sitemap.xml" rel="noopener noreferrer"&gt;http://localhost:8000/sitemap.xml&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Aaand we are done! almost. Now we can finally push our code to Heroku, in the classic way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; git status
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; git add &lt;span class="nt"&gt;-A&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add sitemap.xml to Django App"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; git push heroku master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But here's the catch... Now when we are trying to access &lt;em&gt;&lt;a href="https://myappname.herokuapp.com/sitemap.xml" rel="noopener noreferrer"&gt;https://myappname.herokuapp.com/sitemap.xml&lt;/a&gt;&lt;/em&gt; we get an "INTERNAL SERVER ERROR (500)". Also, if we try to access our Sites model in our Admin page, we get the same error. &lt;/p&gt;

&lt;p&gt;But why's that?&lt;/p&gt;

&lt;p&gt;When we pushed our code to Heroku, our heroku server calls the "makemigrations" command from our manage.py, but we didn't manually created (wrote any code) to our models.py file, so makemigrations will return &lt;em&gt;"No changes detected"&lt;/em&gt;, therefore will not run "migrate" command.&lt;/p&gt;

&lt;p&gt;So, we need to manually run migrate command from our heroku server. To do that, we simply call in our terminal these commands in our django project folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; heroku run bash
&lt;span class="nv"&gt;$ &lt;/span&gt;python manage.py migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's all. But now we also need to access again our admin page from our heroku deployed app, and change that first entry from Sites model from &lt;em&gt;"example.com"&lt;/em&gt; to &lt;em&gt;"myappname.herokuapp.com"&lt;/em&gt;. Then, we'll have to run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; heroku restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now we are really done. We can access our sitemap from &lt;em&gt;myappname.herokuapp.com/sitemap.xml&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I hope this mini-tutorial will help someone one day. It will certain help me to not struggle again if I encounter again this problem. &lt;/p&gt;

&lt;p&gt;Happy coding,&lt;/p&gt;

&lt;p&gt;R.B.&lt;/p&gt;

</description>
      <category>django</category>
      <category>heroku</category>
      <category>sitemap</category>
      <category>seo</category>
    </item>
  </channel>
</rss>
