<?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: Lorenzo Felletti</title>
    <description>The latest articles on DEV Community by Lorenzo Felletti (@lorenzofelletti).</description>
    <link>https://dev.to/lorenzofelletti</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%2F486947%2F52554c9e-015a-4b32-bc85-037aeef8a7d7.jpg</url>
      <title>DEV Community: Lorenzo Felletti</title>
      <link>https://dev.to/lorenzofelletti</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lorenzofelletti"/>
    <language>en</language>
    <item>
      <title>How to Create a Bluetooth LE Scanner for Android</title>
      <dc:creator>Lorenzo Felletti</dc:creator>
      <pubDate>Thu, 31 Aug 2023 17:37:15 +0000</pubDate>
      <link>https://dev.to/lorenzofelletti/how-to-create-a-bluetooth-le-scanner-for-android-77d</link>
      <guid>https://dev.to/lorenzofelletti/how-to-create-a-bluetooth-le-scanner-for-android-77d</guid>
      <description>&lt;p&gt;Creating a Bluetooth LE scanner for Android is not too complicated. What you need is some understanding of the Android architecture and of Java/Kotlin.&lt;/p&gt;

&lt;p&gt;The most difficult part of building such an app would be…managing the permissions, or even finding what are the required permissions (at least for me).&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Need to Follow This Tutorial
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  Android Studio installed on your computer&lt;/li&gt;
&lt;li&gt;  A BLE enabled smartphone for testing running Android 12 (or later)&lt;/li&gt;
&lt;li&gt;  A basic understanding of Kotlin (or Java, at least)&lt;/li&gt;
&lt;li&gt;  A (very) basic understanding of how to create a UI in Android&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating the Project
&lt;/h2&gt;

&lt;p&gt;I will assume that you already know how to create a project in Android Studio, so create a new project, choose &lt;em&gt;Empty Activity&lt;/em&gt;, and name it whatever you like, I named mine &lt;em&gt;SimpleBleScanner&lt;/em&gt;. Also, select &lt;em&gt;API 31&lt;/em&gt; as the &lt;em&gt;Minimum SDK&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
I know that requiring Android 12 could be a bit too tight of a requirement, but this choice was made to be able to experiment with the latest features.&lt;br&gt;&lt;br&gt;
Anyway, if you have the necessity to use an earlier version of the SDK, I think you won’t have to change much of the code.&lt;/p&gt;
&lt;h2&gt;
  
  
  Managing the Permissions
&lt;/h2&gt;

&lt;p&gt;First, we are going to declare in the Manifest (&lt;code&gt;AndroidManifest.xml&lt;/code&gt;) all the permissions we will use in the application. In particular, for Bluetooth LE scanning, the minimum required permissions are the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.BLUETOOTH_ADMIN"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.BLUETOOTH_CONNECT"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.BLUETOOTH_SCAN"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.ACCESS_COARSE_LOCATION"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.ACCESS_FINE_LOCATION"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As weird as it might sound, access to coarse and fine location is required in order to use BLE.&lt;/p&gt;

&lt;p&gt;Next, inside the package containing the &lt;code&gt;MainActivity&lt;/code&gt;, I chose to create another package named &lt;code&gt;permissions&lt;/code&gt;, in which to put all the permission utilities.&lt;/p&gt;

&lt;p&gt;Inside this newly created package, create two Kotlin objects named &lt;code&gt;PermissionsUtilities&lt;/code&gt; and &lt;code&gt;BleScanRequiredPermissions&lt;/code&gt;. These two objects will help us in managing the permissions without writing too much code inside the  &lt;code&gt;MainActivity&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;BleScanRequiredPermissions&lt;/code&gt; will contain only the array of the permissions we are going to require for our app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;permissions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;arrayOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;Manifest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BLUETOOTH_SCAN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;Manifest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ACCESS_COARSE_LOCATION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;Manifest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ACCESS_FINE_LOCATION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;Manifest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BLUETOOTH_ADMIN&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;&lt;code&gt;PermissionsUtilities&lt;/code&gt;, on the other hand, is a more complex object, containing all the utility functions to manage permissions in our application.&lt;br&gt;&lt;br&gt;
Anyway, the focus of the article is not on permissions handling, so I will go fast on this part. Feel free to check the &lt;code&gt;permissions&lt;/code&gt; package by yourself if interested.&lt;/p&gt;

&lt;p&gt;The main functions of this module are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
* Checks for a set of permissions. If not granted, the user is asked to grant them.
*
* @param activity The activity that is requesting the permissions
* @param permissions The permissions to be checked
* @param requestCode The request code to be used when requesting the permissions
*/&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;checkPermissions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Activity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;requestCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="cm"&gt;/**
* Checks whether a set of permissions is granted or not
*
* @param context The context to be used for checking the permissions
* @param permissions The permissions to be checked
*
* @return true if all permissions are granted, false otherwise
*/&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;checkPermissionsGranted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;):&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;

&lt;span class="cm"&gt;/**
* Checks the result of a permission request, and dispatches the appropriate action
*
* @param requestCode The request code of the permission request
* @param grantResults The results of the permission request
* @param onGrantedMap maps the request code to the action to be performed if the permissions are granted
* @param onDeniedMap maps the request code to the action to be performed if the permissions are not granted
*/&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;dispatchOnRequestPermissionsResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;requestCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grantResults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;IntArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;onGrantedMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;()&lt;/span&gt; &lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
    &lt;span class="n"&gt;onDeniedMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;()&lt;/span&gt; &lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="cm"&gt;/**
* Checks whether a permission is granted in the context
*
* @param context The context to be used for checking the permission
* @param permission The permission to be checked
*
* @return true if the permission is granted, false otherwise
*/&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;checkPermissionGranted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;

&lt;span class="cm"&gt;/**
* Checks the results of a permission request
*
* @param grantResults The results of the permission request
*
* @return true if all permissions were granted, false otherwise
*/&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;checkGrantResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grantResults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;IntArray&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Otherwise, you could check this article about a permission management library I made, and try to use it instead… &lt;a href="https://medium.com/geekculture/android-permissions-made-easy-d5e3e81ba2ac"&gt;Android Permissions Made Easy&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scanning for devices
&lt;/h2&gt;

&lt;p&gt;To manage the scanning, we will create a new package named &lt;code&gt;blescanner&lt;/code&gt;, containing two sub-packages named &lt;code&gt;model&lt;/code&gt; and &lt;code&gt;adapter&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
The &lt;code&gt;model&lt;/code&gt; the classes modeling the &lt;code&gt;BleDevice&lt;/code&gt; and the  &lt;code&gt;BleScanCallback&lt;/code&gt;, while the &lt;code&gt;adapter&lt;/code&gt; will contain the  &lt;code&gt;BleDeviceAdapter&lt;/code&gt;, used as adapter for the &lt;code&gt;RecyclerView&lt;/code&gt; showing the results of the scan.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;//BleDevice.kt&lt;/span&gt;
&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;BleDevice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;companion&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;createBleDevicesList&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;MutableList&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BleDevice&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&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;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// BleDeviceAdapter.kt&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BleDeviceAdapter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BleDevice&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RecyclerView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Adapter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BleDeviceAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ViewHolder&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;inner&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ViewHolder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;itemView&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RecyclerView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ViewHolder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;itemView&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;deviceNameTextView&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;TextView&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;itemView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;findViewById&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TextView&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;device_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onCreateViewHolder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ViewGroup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viewType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;ViewHolder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;context&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;inflater&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LayoutInflater&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;deviceView&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inflater&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inflate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;device_row_layout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&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;ViewHolder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deviceView&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onBindViewHolder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;holder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;BleDeviceAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ViewHolder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;device&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;textView&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;holder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deviceNameTextView&lt;/span&gt;
        &lt;span class="n"&gt;textView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getItemCount&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Int&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;devices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&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;Other than these three classes, we will create a  &lt;code&gt;BleScanManager&lt;/code&gt;, that will manage the scanning.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;BleScanManager&lt;/code&gt; class contains various members to manage the scanning state and what to do before/after the scanning.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BleScanManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;btManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;BluetoothManager&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;scanPeriod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DEFAULT_SCAN_PERIOD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;scanCallback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;BleScanCallback&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BleScanCallback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;btAdapter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;btManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;adapter&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;bleScanner&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;btAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bluetoothLeScanner&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;beforeScanActions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MutableList&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;()&lt;/span&gt; &lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;afterScanActions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MutableList&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;()&lt;/span&gt; &lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="cm"&gt;/** True when the manager is performing the scan */&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;scanning&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;handler&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Looper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getMainLooper&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * Scans for Bluetooth LE devices and stops the scan after [scanPeriod] seconds.
     * Does not checks the required permissions are granted, check must be done beforehand.
     */&lt;/span&gt;
    &lt;span class="nd"&gt;@SuppressLint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MissingPermission"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;scanBleDevices&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;stopScan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;scanning&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;
            &lt;span class="n"&gt;bleScanner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stopScan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scanCallback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;// execute all the functions to execute after scanning&lt;/span&gt;
            &lt;span class="nf"&gt;executeAfterScanActions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// scans for bluetooth LE devices&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scanning&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;stopScan&lt;/span&gt;&lt;span class="p"&gt;()&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="c1"&gt;// stops scanning after scanPeriod millis&lt;/span&gt;
            &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postDelayed&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nf"&gt;stopScan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;scanPeriod&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;// execute all the functions to execute before scanning&lt;/span&gt;
            &lt;span class="nf"&gt;executeBeforeScanActions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="c1"&gt;// starts scanning&lt;/span&gt;
            &lt;span class="n"&gt;scanning&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
            &lt;span class="n"&gt;bleScanner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startScan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scanCallback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&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;The constructor will take as input a &lt;code&gt;BluetoothManager&lt;/code&gt;, a scan period (set to a default value if omitted), and a list of actions to do before and after the scanning. The list of actions is nothing but a list of functions that will be invoked before/after the scanning start.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Handler&lt;/code&gt; is used to schedule the stopping of the scan after the scan period time.&lt;/p&gt;

&lt;p&gt;The companion object of the &lt;code&gt;BleScanManager&lt;/code&gt; will contain the default value of the scan period, and a function to execute the list of actions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;companion&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;DEFAULT_SCAN_PERIOD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;executeListOfFunctions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;toExecute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;()&lt;/span&gt; &lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;toExecute&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;()&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;The last lines to complete the &lt;code&gt;BleScanManager&lt;/code&gt; are the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;executeBeforeScanActions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;executeListOfFunctions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;beforeScanActions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;executeAfterScanActions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;executeListOfFunctions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;afterScanActions&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;h2&gt;
  
  
  The Main Activity
&lt;/h2&gt;

&lt;p&gt;The main activity will contain the code that “connects” all the modules we created so far:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  the module managing the permissions&lt;/li&gt;
&lt;li&gt;  the BLE scan manager&lt;/li&gt;
&lt;li&gt;  the adapter for the &lt;code&gt;RecyclerView&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code is pretty straightforward, the only two methods are the &lt;code&gt;onCreate&lt;/code&gt; and the &lt;code&gt;onRequestPermissionResult&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainActivity&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AppCompatActivity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;lateinit&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;btnStartScan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Button&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;lateinit&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;btManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;BluetoothManager&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;lateinit&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;bleScanManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;BleScanManager&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;lateinit&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;foundDevices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MutableList&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BleDevice&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nd"&gt;@SuppressLint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NotifyDataSetChanged"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"MissingPermission"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@RequiresApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;VERSION_CODES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;S&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;setContentView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activity_main&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// RecyclerView handling&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;rvFoundDevices&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;findViewById&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rv_found_devices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;RecyclerView&lt;/span&gt;
        &lt;span class="n"&gt;foundDevices&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BleDevice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createBleDevicesList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;adapter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BleDeviceAdapter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foundDevices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;rvFoundDevices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;adapter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;adapter&lt;/span&gt;
        &lt;span class="n"&gt;rvFoundDevices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layoutManager&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LinearLayoutManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// BleManager creation&lt;/span&gt;
        &lt;span class="n"&gt;btManager&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getSystemService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BluetoothManager&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;bleScanManager&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BleScanManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;btManager&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scanCallback&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BleScanCallback&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isNullOrBlank&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="nd"&gt;@BleScanCallback&lt;/span&gt;

            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;device&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BleDevice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;foundDevices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;foundDevices&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;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notifyItemInserted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foundDevices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}))&lt;/span&gt;

        &lt;span class="c1"&gt;// Adding the actions the manager must do before and after scanning&lt;/span&gt;
        &lt;span class="n"&gt;bleScanManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;beforeScanActions&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;btnStartScan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isEnabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;bleScanManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;beforeScanActions&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;foundDevices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notifyDataSetChanged&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;bleScanManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;afterScanActions&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;btnStartScan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isEnabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Adding the onclick listener to the start scan button&lt;/span&gt;
        &lt;span class="n"&gt;btnStartScan&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;findViewById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;btn_start_scan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;btnStartScan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setOnClickListener&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Checks if the required permissions are granted and starts the scan if so, otherwise it requests them&lt;/span&gt;
            &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PermissionsUtilities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;checkPermissionsGranted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;BleScanRequiredPermissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;permissions&lt;/span&gt;
            &lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;true&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bleScanManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scanBleDevices&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;false&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;PermissionsUtilities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;checkPermissions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BleScanRequiredPermissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BLE_PERMISSION_REQUEST_CODE&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@RequiresApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;VERSION_CODES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;S&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onRequestPermissionsResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;requestCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;grantResults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;IntArray&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onRequestPermissionsResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grantResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;dispatchOnRequestPermissionsResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;requestCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;grantResults&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;onGrantedMap&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mapOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BLE_PERMISSION_REQUEST_CODE&lt;/span&gt; &lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;bleScanManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scanBleDevices&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
            &lt;span class="n"&gt;onDeniedMap&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mapOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BLE_PERMISSION_REQUEST_CODE&lt;/span&gt; &lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s"&gt;"Some permissions were not granted, please grant them and try again"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LENGTH_LONG&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;companion&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;BLE_PERMISSION_REQUEST_CODE&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&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;The latter is used to manage what to do “after” requesting the permissions to the user, while the former sets the ground for the application by setting the &lt;code&gt;RecyclerView&lt;/code&gt; adapter, creating the &lt;code&gt;BleScanManager&lt;/code&gt;, and setting the &lt;code&gt;onClickListener&lt;/code&gt; for the button to start the scan.&lt;/p&gt;

&lt;p&gt;Right after the &lt;code&gt;BleScanManager&lt;/code&gt; is created, we add to it &lt;code&gt;before&lt;/code&gt;/&lt;code&gt;afterScanActions&lt;/code&gt; the code to enable/disable the scan button — because we want to disable the scan button while we’re performing it.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;onClickListener&lt;/code&gt; to start the scan checks first that the required permissions are granted, and, if so, it proceeds to start the scan, otherwise it starts permissions request flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  The GUI
&lt;/h2&gt;

&lt;p&gt;The GUI will be very (very) simple, just a &lt;code&gt;Button&lt;/code&gt; to start the scanning, and a &lt;code&gt;RecyclerView&lt;/code&gt; to show the scanning results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;
&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;androidx.constraintlayout.widget.ConstraintLayout&lt;/span&gt; &lt;span class="na"&gt;xmlns:android=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/apk/res/android"&lt;/span&gt;
    &lt;span class="na"&gt;xmlns:app=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/apk/res-auto"&lt;/span&gt;
    &lt;span class="na"&gt;xmlns:tools=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/tools"&lt;/span&gt;
    &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"match_parent"&lt;/span&gt;
    &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"match_parent"&lt;/span&gt;
    &lt;span class="na"&gt;tools:context=&lt;/span&gt;&lt;span class="s"&gt;".MainActivity"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;Button&lt;/span&gt;
        &lt;span class="na"&gt;android:id=&lt;/span&gt;&lt;span class="s"&gt;"@+id/btn_start_scan"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt;
        &lt;span class="na"&gt;android:text=&lt;/span&gt;&lt;span class="s"&gt;"@string/btn_start_scan_text"&lt;/span&gt;
        &lt;span class="na"&gt;app:layout_constraintBottom_toBottomOf=&lt;/span&gt;&lt;span class="s"&gt;"parent"&lt;/span&gt;
        &lt;span class="na"&gt;app:layout_constraintEnd_toEndOf=&lt;/span&gt;&lt;span class="s"&gt;"parent"&lt;/span&gt;
        &lt;span class="na"&gt;app:layout_constraintHorizontal_bias=&lt;/span&gt;&lt;span class="s"&gt;"0.498"&lt;/span&gt;
        &lt;span class="na"&gt;app:layout_constraintStart_toStartOf=&lt;/span&gt;&lt;span class="s"&gt;"parent"&lt;/span&gt;
        &lt;span class="na"&gt;app:layout_constraintTop_toTopOf=&lt;/span&gt;&lt;span class="s"&gt;"parent"&lt;/span&gt;
        &lt;span class="na"&gt;app:layout_constraintVertical_bias=&lt;/span&gt;&lt;span class="s"&gt;"0.844"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;TextView&lt;/span&gt;
        &lt;span class="na"&gt;android:id=&lt;/span&gt;&lt;span class="s"&gt;"@+id/lbl_scan_results"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"163dp"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"19dp"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_marginTop=&lt;/span&gt;&lt;span class="s"&gt;"28dp"&lt;/span&gt;
        &lt;span class="na"&gt;android:clickable=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
        &lt;span class="na"&gt;android:gravity=&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt;
        &lt;span class="na"&gt;android:text=&lt;/span&gt;&lt;span class="s"&gt;"@string/tw_scan_results_title"&lt;/span&gt;
        &lt;span class="na"&gt;android:textSize=&lt;/span&gt;&lt;span class="s"&gt;"16sp"&lt;/span&gt;
        &lt;span class="na"&gt;app:layout_constraintEnd_toEndOf=&lt;/span&gt;&lt;span class="s"&gt;"parent"&lt;/span&gt;
        &lt;span class="na"&gt;app:layout_constraintStart_toStartOf=&lt;/span&gt;&lt;span class="s"&gt;"parent"&lt;/span&gt;
        &lt;span class="na"&gt;app:layout_constraintTop_toTopOf=&lt;/span&gt;&lt;span class="s"&gt;"parent"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;androidx.recyclerview.widget.RecyclerView&lt;/span&gt;
        &lt;span class="na"&gt;android:id=&lt;/span&gt;&lt;span class="s"&gt;"@+id/rv_found_devices"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"375dp"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"516dp"&lt;/span&gt;
        &lt;span class="na"&gt;app:layout_constraintBottom_toTopOf=&lt;/span&gt;&lt;span class="s"&gt;"@+id/btn_start_scan"&lt;/span&gt;
        &lt;span class="na"&gt;app:layout_constraintEnd_toEndOf=&lt;/span&gt;&lt;span class="s"&gt;"parent"&lt;/span&gt;
        &lt;span class="na"&gt;app:layout_constraintHorizontal_bias=&lt;/span&gt;&lt;span class="s"&gt;"0.444"&lt;/span&gt;
        &lt;span class="na"&gt;app:layout_constraintStart_toStartOf=&lt;/span&gt;&lt;span class="s"&gt;"parent"&lt;/span&gt;
        &lt;span class="na"&gt;app:layout_constraintTop_toBottomOf=&lt;/span&gt;&lt;span class="s"&gt;"@+id/lbl_scan_results"&lt;/span&gt;
        &lt;span class="na"&gt;app:layout_constraintVertical_bias=&lt;/span&gt;&lt;span class="s"&gt;"0.0"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/androidx.constraintlayout.widget.ConstraintLayout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other than the &lt;code&gt;activity_main.xml&lt;/code&gt; we will need another layout file to define the layout of a &lt;code&gt;RecyclerView&lt;/code&gt; row.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;
&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;LinearLayout&lt;/span&gt;
    &lt;span class="na"&gt;xmlns:android=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/apk/res/android"&lt;/span&gt;
    &lt;span class="na"&gt;android:orientation=&lt;/span&gt;&lt;span class="s"&gt;"horizontal"&lt;/span&gt;
    &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"match_parent"&lt;/span&gt;
    &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt;
    &lt;span class="na"&gt;android:paddingTop=&lt;/span&gt;&lt;span class="s"&gt;"10dp"&lt;/span&gt;
    &lt;span class="na"&gt;android:paddingBottom=&lt;/span&gt;&lt;span class="s"&gt;"10dp"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;TextView&lt;/span&gt;
        &lt;span class="na"&gt;android:id=&lt;/span&gt;&lt;span class="s"&gt;"@+id/device_name"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"0dp"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_weight=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
        &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/LinearLayout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;This is all to create a simple Bluetooth LE scanner app in Android.&lt;br&gt;&lt;br&gt;
The results will look something like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GmAYwrU3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:875/1%2AO_3WualBNIkvummQJpHhXw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GmAYwrU3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:875/1%2AO_3WualBNIkvummQJpHhXw.png" alt="final result" width="800" height="1548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The application's UI while performing a scan&lt;/p&gt;

&lt;p&gt;As you can see, the app is very simple on the UI side, this because I wanted to focus more on the functionality. If you want, feel free to fork the  &lt;a href="https://github.com/lorenzofelletti/SimpleBleScanner"&gt;repo&lt;/a&gt;  and improve the application’s UI, or extend its functionalities.&lt;/p&gt;

&lt;p&gt;This is all for this article, I hope you enjoyed reading it and that you found it useful. Let me know with a comment!&lt;/p&gt;




&lt;p&gt;Cover image by &lt;a href="https://unsplash.com/it/@zarakvg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Zarak Khan&lt;/a&gt; on &lt;a href="https://unsplash.com/it/foto/dV5fxEZaS1A?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>kotlin</category>
      <category>tutorial</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Load Environment on Directory Change</title>
      <dc:creator>Lorenzo Felletti</dc:creator>
      <pubDate>Mon, 21 Aug 2023 08:34:08 +0000</pubDate>
      <link>https://dev.to/lorenzofelletti/load-environment-on-directory-change-2a21</link>
      <guid>https://dev.to/lorenzofelletti/load-environment-on-directory-change-2a21</guid>
      <description>&lt;h2&gt;
  
  
  Change  &lt;code&gt;gcloud&lt;/code&gt;  context,  &lt;code&gt;az&lt;/code&gt;  login, Kubernetes context, set environment variables, and more just changing directory
&lt;/h2&gt;

&lt;p&gt;During a typical day at work, I often need to change between two, or even three different repos, each with its relative  &lt;code&gt;gcloud&lt;/code&gt;, or  &lt;code&gt;az&lt;/code&gt;, or whatever configuration, its Kubernetes context, and so on.&lt;/p&gt;

&lt;p&gt;At the beginning, I find it really frustrating and time-consuming to backward-search in history the commands I needed to run to be able to perform my tasks.&lt;/p&gt;

&lt;p&gt;Out of frustration, I decided that I needed to find a way to be able to automate this boring task, and I came up with a simple solution that both saves me a lot of time when I need to switch context, but also helps me to track the steps needed to reach a certain configuration, in case I need to replicate it on another project.&lt;/p&gt;

&lt;p&gt;After some stack-overflowing, I created these very simple zsh functions (portable to bash with little to no effort), to load hidden scripts on directory change. In particular, the two functions are named  &lt;code&gt;cda&lt;/code&gt;  (that stands for  &lt;code&gt;cd&lt;/code&gt;  and activate, or whatever), and  &lt;code&gt;sayonara&lt;/code&gt;  (that means  &lt;em&gt;goodbye&lt;/em&gt;  in Japanese):&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;# sourcing hidden files on cd&lt;/span&gt;
&lt;span class="k"&gt;function &lt;/span&gt;cda&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; PATHS&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;PATHS&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s1"&gt;'.'&lt;/span&gt;, &lt;span class="s1"&gt;'.vscode'&lt;/span&gt; &lt;span class="s1"&gt;'.idea'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  
        &lt;span class="nb"&gt;builtin cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return  

        for &lt;/span&gt;p &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PATHS&lt;/span&gt;&lt;span class="s2"&gt;[@]"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do  
                &lt;/span&gt;&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;hidden&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/.hidden.env"&lt;/span&gt;  
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$hidden&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;  
                &lt;span class="k"&gt;then  
                        &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="nv"&gt;$p&lt;/span&gt;  
                &lt;span class="k"&gt;fi  
        done&lt;/span&gt;  
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Cleaning up when leaving, sourcing actions to do (like deactivate venv)  &lt;/span&gt;
&lt;span class="k"&gt;function &lt;/span&gt;sayonara&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; PATHS&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;PATHS&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s1"&gt;'.'&lt;/span&gt;, &lt;span class="s1"&gt;'.vscode'&lt;/span&gt; &lt;span class="s1"&gt;'.idea'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  

        &lt;span class="k"&gt;for &lt;/span&gt;p &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PATHS&lt;/span&gt;&lt;span class="s2"&gt;[@]"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do  
                &lt;/span&gt;&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;hidden&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/.hidden.out.env"&lt;/span&gt;  
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$hidden&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;  
                &lt;span class="k"&gt;then  
                        &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="nv"&gt;$p&lt;/span&gt;  
                &lt;span class="k"&gt;fi  
        done  

        if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"$#"&lt;/span&gt; &lt;span class="nt"&gt;-gt&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;".."&lt;/span&gt;  

        &lt;span class="nb"&gt;builtin cd&lt;/span&gt; &lt;span class="nv"&gt;$dest&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;  
&lt;span class="o"&gt;}&lt;/span&gt;  
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;sayo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sayonara"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command  &lt;code&gt;sayonara&lt;/code&gt;  was also aliased with  &lt;code&gt;sayo&lt;/code&gt;  for the sake of brevity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not Just Overriding &lt;code&gt;cd&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;I  &lt;em&gt;could&lt;/em&gt;  have named the  &lt;code&gt;cda&lt;/code&gt;  function  &lt;code&gt;cd&lt;/code&gt;  and I could have sourced hidden files completely transparently to the user (I am only taking into account the  &lt;code&gt;cda&lt;/code&gt;  function now, as the other is used more rarely), and initially this was the case. In fact, the  &lt;code&gt;cda&lt;/code&gt;  function is written in a way that supports exactly this — note that I do not use  &lt;code&gt;cd&lt;/code&gt;  but  &lt;code&gt;builtin cd&lt;/code&gt;  instead, otherwise an infinite loop would be caused — but this can cause you problems if you have multiple shells opened, and you visit different directories with a hidden env file.&lt;br&gt;&lt;br&gt;
Let’s suppose, for example, that you need to work in  &lt;code&gt;dir1&lt;/code&gt;  with the hidden environment  &lt;code&gt;env1&lt;/code&gt;  and you’re working on this, but you need to visit code in  &lt;code&gt;dir2&lt;/code&gt;  with hidden env  &lt;code&gt;env2&lt;/code&gt;. With the hidden env being sourced on  &lt;code&gt;cda&lt;/code&gt;, you  &lt;code&gt;cda&lt;/code&gt;  in  &lt;code&gt;dir1&lt;/code&gt;, and “only”  &lt;code&gt;cd&lt;/code&gt;  in  &lt;code&gt;dir2&lt;/code&gt;, and you have no problems. But, if instead you named the function  &lt;code&gt;cd&lt;/code&gt;, when you  &lt;code&gt;cd&lt;/code&gt;  in  &lt;code&gt;dir1&lt;/code&gt;  &lt;code&gt;env1&lt;/code&gt;  is sourced, but, when you move to  &lt;code&gt;dir2&lt;/code&gt;,  &lt;code&gt;env2&lt;/code&gt;  will be sourced, potentially overriding some configurations of  &lt;code&gt;env1&lt;/code&gt;  (like the Kubernetes context, or the  &lt;code&gt;gcloud&lt;/code&gt;  configuration).&lt;/p&gt;

&lt;p&gt;Thus, for this problem, I preferred to give up on the dream of writing  &lt;code&gt;cd&lt;/code&gt;  and having the right configuration always ready to use, and  &lt;em&gt;“settled”&lt;/em&gt;  for the still very good solution of  &lt;code&gt;cda&lt;/code&gt;-ing into a directory when I want its environment to be activated, and  &lt;code&gt;cd&lt;/code&gt;-ing into it when I just want to visit it.&lt;/p&gt;

</description>
      <category>bash</category>
      <category>cloud</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Android Permissions Made Easy</title>
      <dc:creator>Lorenzo Felletti</dc:creator>
      <pubDate>Mon, 12 Dec 2022 23:45:09 +0000</pubDate>
      <link>https://dev.to/lorenzofelletti/android-permissions-made-easy-bpf</link>
      <guid>https://dev.to/lorenzofelletti/android-permissions-made-easy-bpf</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;One library to rule them all&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Handling the permission requests in Android is &lt;strong&gt;not&lt;/strong&gt; as straightforward as I thought it should be, &lt;em&gt;especially&lt;/em&gt; for beginners. Thus, I decided to write a small library to help in managing them.&lt;/p&gt;

&lt;p&gt;The library is very simple to use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  choose a request code for each group of permissions you are going to ask altogether, and define an array containing those permissions (for example, if the application has a button enabling Bluetooth, and a view showing the user location on a map, you would create a  &lt;code&gt;BLUETOOTH_REQUEST_CODE = 1&lt;/code&gt;  and a  &lt;code&gt;LOCATION_REQUEST_CODE = 2&lt;/code&gt;, and define two arrays  &lt;code&gt;BLUETOOTH_PERMISSIONS = arrayOf(...)&lt;/code&gt;, and  &lt;code&gt;LOCATION_PERMISSIONS = arrayOf(...)&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;  create in the  &lt;code&gt;Activity&lt;/code&gt;  that you want to request the permissions a  &lt;code&gt;PermissionManager&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;permissionsManager&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PermissionManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&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;  Using the provided DSL, build an appropriate dispatcher&lt;/li&gt;
&lt;li&gt;  where you want to check or grant the permissions, call the manager’s  &lt;code&gt;checkRequestAndDispatch&lt;/code&gt;  method
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;permissionManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;checkRequestAndDispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BLUETOOTH_REQUEST_CODE&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;  override the Activity’s  &lt;code&gt;onRequestPermissionsResult&lt;/code&gt;  and add to it the line
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;permissionManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchOnRequestPermissionsResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grantResults&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;  enjoy!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Dispatcher’s DSL
&lt;/h2&gt;

&lt;p&gt;The DSL to build the dispatcher has a few functions that helps to create the dispatcher in a human-readable way. The following is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="n"&gt;permissionManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;buildRequestResultsDispatcher&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nf"&gt;withRequestCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BLUETOOTH_REQUEST_CODE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="nf"&gt;checkPermissions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BLUETOOTH_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="nf"&gt;doOnGranted&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                &lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;d&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TAG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Bluetooth permission granted"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
                &lt;span class="c1"&gt;// something ...  &lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;  
            &lt;span class="nf"&gt;doOnDenied&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                &lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;d&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TAG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Bluetooth permission denied"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
                &lt;span class="c1"&gt;// something else ...  &lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;  
        &lt;span class="p"&gt;}&lt;/span&gt;  
        &lt;span class="nf"&gt;withRequestCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LOCATION_REQUEST_CODE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="nf"&gt;checkPermissions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LOCATION_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="nf"&gt;doOnGranted&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                &lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;d&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TAG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Location permission granted"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
                &lt;span class="c1"&gt;// something ...  &lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;  
            &lt;span class="nf"&gt;doOnDenied&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                &lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;d&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TAG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Location permission denied"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
                &lt;span class="c1"&gt;// something else ...  &lt;/span&gt;
            &lt;span class="p"&gt;}&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;Inside &lt;code&gt;buildRequestResultsDispatcher&lt;/code&gt;, you can define as many as you want &lt;code&gt;withRequestCode(requestCode)&lt;/code&gt; blocks, each containing the permissions to check (&lt;code&gt;checkPermissions&lt;/code&gt;) and the behavior to dispatch in case all the permissions are granted (&lt;code&gt;doOnGranted&lt;/code&gt;), or some were not (&lt;code&gt;doOnDenied&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;checkRequestAndDispatch&lt;/code&gt; Method
&lt;/h2&gt;

&lt;p&gt;This method does two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  it checks if the permissions were already granted, and if so it dispatches the same action associated in the dispatcher to the  &lt;code&gt;doOnGranted&lt;/code&gt;  for the given request code&lt;/li&gt;
&lt;li&gt;  otherwise, it asks for the permissions that are not granted; and it would be the overridden  &lt;code&gt;onRequestPermissionsResult&lt;/code&gt;  to dispatch the appropriate action after the permission request.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How To Use The Library
&lt;/h2&gt;

&lt;p&gt;The library is deployed on &lt;a href="https://jitpack.io/#lorenzofelletti/permissions" rel="noopener noreferrer"&gt;Jitpack&lt;/a&gt;, and you can easily add it to your project by adding to your  &lt;code&gt;settings.gradle&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;    &lt;span class="n"&gt;dependencyResolutionManagement&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="o"&gt;...&lt;/span&gt;  
        &lt;span class="n"&gt;repositories&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
            &lt;span class="o"&gt;...&lt;/span&gt;  
            &lt;span class="n"&gt;maven&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="s1"&gt;'https://jitpack.io'&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;p&gt;And to your module level  &lt;code&gt;build.gradle&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;    &lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
        &lt;span class="o"&gt;...&lt;/span&gt;  
        &lt;span class="n"&gt;implementation&lt;/span&gt; &lt;span class="s1"&gt;'com.github.lorenzofelletti:permissions:0.4.2'&lt;/span&gt;  
    &lt;span class="o"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The showRationaleDialog Function
&lt;/h2&gt;

&lt;p&gt;It is recommended that you also manage the  &lt;code&gt;shouldShowRequestPermissionRationale&lt;/code&gt;, so since version  &lt;code&gt;0.3.0&lt;/code&gt;  it is possible to do it. Two DSL functions are defined to do this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;rationale&lt;/code&gt;  — suitable for the cases when you need the maximum configurability, but you should manage “manually” some things, such as calling  &lt;code&gt;permissionManager.checkRequestAndDispatch&lt;/code&gt;  again if needed with the  &lt;code&gt;comingFromRationale&lt;/code&gt;  flag set to  &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;showRationaleDialog&lt;/code&gt;  — suitable in all the cases when what you want is to show a dialog with a message. In that case, everything is already set up to function properly, you don’t have to do anything but choosing the message.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An example of the latter is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="n"&gt;permissionManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;buildRequestResultsDispatcher&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nf"&gt;withRequestCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LOCATION_REQUEST_CODE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="nf"&gt;checkPermissions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LOCATION_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="nf"&gt;showRationaleDialog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Location permissions are needed for this feature."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="nf"&gt;doOnGranted&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                &lt;span class="c1"&gt;// something ...  &lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;  
            &lt;span class="nf"&gt;doOnDenied&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                &lt;span class="c1"&gt;// something else ...  &lt;/span&gt;
            &lt;span class="p"&gt;}&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;The library is still very young and new features may be added in the future, as well as the existing features may be modified.&lt;/p&gt;




&lt;p&gt;Please let me know your opinion on this simple library and if you want any feature added to it.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Cover image by &lt;a href="https://unsplash.com/@markkoenig?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Mark König&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/permission?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>gratitude</category>
    </item>
    <item>
      <title>How to Build a RegEx Engine in Python (Part 7: The Backtracking System)</title>
      <dc:creator>Lorenzo Felletti</dc:creator>
      <pubDate>Mon, 12 Dec 2022 23:27:05 +0000</pubDate>
      <link>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-part-7-the-backtracking-system-2nhi</link>
      <guid>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-part-7-the-backtracking-system-2nhi</guid>
      <description>&lt;p&gt;In this article, we will complete our regex engine with the backtracking system.&lt;br&gt;&lt;br&gt;
This article is the seventh part of my series on how to build a regular expression engine, so if this is the first article you read, I advise you to read the previous ones and then come back to this one.&lt;/p&gt;

&lt;p&gt;The backtracking feature was one of the most difficult to implement and is by far the most interesting feature of this project.&lt;/p&gt;

&lt;p&gt;Before coming up with the final and (&lt;em&gt;hopefully&lt;/em&gt;) correct version of the backtracking system, I implemented a couple of “partially correct” solutions, each of them not working in some edge cases.&lt;/p&gt;

&lt;p&gt;To find out all these bugs, testing was crucial, and mainly unit testing. If you don’t already use unit tests in your projects, I strongly suggest you start using them.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Backtrack?
&lt;/h2&gt;

&lt;p&gt;To figure out when it is proper to backtrack, and when it is not, is not a trivial task, but it is the first thing you have to sort out when implementing backtracking.&lt;/p&gt;

&lt;p&gt;First, you have to understand what your engine can or cannot already do, to not implement the same feature twice.&lt;/p&gt;

&lt;p&gt;For example, our engine so far can already do  &lt;em&gt;some&lt;/em&gt;  backtracking: in case of an or (OrNode), if the left branch fails it tries to match the right branch, so we don’t have to implement this in our backtracking system.&lt;/p&gt;

&lt;p&gt;When trying to match a  &lt;em&gt;regular expression&lt;/em&gt; to a given string, let’s call it  &lt;em&gt;test string&lt;/em&gt;, and you have an engine requiring backtracking (as we saw in part 6) you have to operate these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Start from index 0 of the test string, and the leftmost leaf of the AST representing the  &lt;em&gt;regex&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  Read the first character of the test string  and the leftmost leaf of the AST&lt;/li&gt;
&lt;li&gt;  Do they match? If yes, move on (index 1 or the test string, next leaf in the AST), if not try to backtrack&lt;/li&gt;
&lt;li&gt;  If backtracking fails, then you have a complete fail: the test string does not match the regex.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Backtracking&lt;/em&gt;&lt;/strong&gt;  is possible if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  I matched an element more times than the minimum number of times it has to be matched(e.g. we have an A to be matched 1+ times, and we matched it more than once)&lt;/li&gt;
&lt;li&gt;  An element B is matched the minimum number of times, but a previous element A is matched more than the minimum number of times.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Groups Sweet Groups!
&lt;/h2&gt;

&lt;p&gt;Our  &lt;code&gt;match_group&lt;/code&gt;  function walks the AST going down a level every time a non-leaf node is encountered, by calling itself recursively.&lt;br&gt;&lt;br&gt;
So, from a  &lt;code&gt;match_group&lt;/code&gt;  function call point of view, “the world is flat” — what it does is just to iterate through its children, children that are all at the same depth in the AST.&lt;br&gt;&lt;br&gt;
The only difference is that a leaf node is encountered there isn’t another function call to get to the new state, while when a non-leaf is found, another  &lt;code&gt;match_group&lt;/code&gt;  is called, and at the end of its execution, the upper level gets the new state.&lt;/p&gt;

&lt;p&gt;For a single  &lt;code&gt;match_group&lt;/code&gt;  there is no tree, just a list of elements to iterate through.&lt;br&gt;&lt;br&gt;
And we can exploit this to make our backtracking system also “flat”, meaning that it takes care of only one level.&lt;/p&gt;

&lt;p&gt;So, we will define a “flat” backtracking system, and every “level” (i.e.  &lt;code&gt;match_group&lt;/code&gt;) will have its own.&lt;br&gt;&lt;br&gt;
In doing this, we greatly simplify the backtracking system responsibility, but without losing generality, because the call stack will take care of executing the operations in the right order. In a way, the “depth management” part of our system comes “for free”, thanks to the call stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Backtrack?
&lt;/h2&gt;

&lt;p&gt;Thanks to the fact that our engine works with groups, we don’t have to create “global” backtracking, but just a system capable of handling backtracking inside a group.&lt;/p&gt;

&lt;p&gt;To backtrack, we have to  &lt;strong&gt;&lt;em&gt;store&lt;/em&gt;&lt;/strong&gt; somewhere the information about the  &lt;strong&gt;&lt;em&gt;explored path(s)&lt;/em&gt;&lt;/strong&gt;, and we also need a  &lt;strong&gt;&lt;em&gt;strategy to explore&lt;/em&gt;&lt;/strong&gt;  all the possible paths.&lt;/p&gt;

&lt;p&gt;The information to store is pretty simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  An array (that we will use as a stack — called  &lt;code&gt;backtrack_stack&lt;/code&gt;) containing one element for every visited node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each element of the array, representing a visited node, must contain the following information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  the visited node(you don’t even need the whole node, but only its index in the  &lt;em&gt;children array&lt;/em&gt; — the aforementioned array on which  &lt;code&gt;match_group&lt;/code&gt;operates)&lt;/li&gt;
&lt;li&gt;  how many times have you matched a node&lt;/li&gt;
&lt;li&gt;  the minimum amount of times it must be matched&lt;/li&gt;
&lt;li&gt;  an array of how many characters were consumed each time it was matched.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it, this is all the information we need to store in the  &lt;em&gt;backtrack stack&lt;/em&gt; every time we visit a node.&lt;/p&gt;

&lt;p&gt;A  &lt;em&gt;backtrack stack&lt;/em&gt;  will be created for each  &lt;code&gt;match_group&lt;/code&gt;  invocation, tracking only the path explored for sibling nodes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let’s Backtrack
&lt;/h2&gt;

&lt;p&gt;Now, with the backtrack stack so defined and the backtracking rules I described earlier, we can state that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; When there is a request for backtracking and the  &lt;em&gt;element&lt;/em&gt;  on top of the  &lt;em&gt;stack&lt;/em&gt;  is matched more times than the minimum, the last consumption must be removed from its consumption list and the consumed characters of the test string updated as follows:
&lt;code&gt;test_str_consumed_characters -= last_consumption&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; When there is a request for backtracking and the  &lt;em&gt;element&lt;/em&gt;  on top of the  &lt;em&gt;stack&lt;/em&gt;  is already matched the minimum number of times, the element should be removed and the consumed characters of the test string updated as follows:
&lt;code&gt;foreach consumption in consumed_list_of_the_element: test_str_consumed_characters -= consumption&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; When there is a request for backtracking on an empty  &lt;em&gt;backtrack stack&lt;/em&gt;, all the possible paths have been explored and the request must cause the failure of the match (i.e.  &lt;em&gt;regex&lt;/em&gt;  and  &lt;em&gt;test string&lt;/em&gt;  doesn’t match).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By applying these simple three rules in our code, and exploiting the recursion of  &lt;code&gt;match_group&lt;/code&gt;, we cover all the possible backtracking cases we can encounter, and we obtain the  &lt;em&gt;full-fledged&lt;/em&gt;  RegEx Engine that was our goal to build.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With this article we finished building the RegEx Engine we wanted to build, thus this article concludes this series.&lt;/p&gt;

&lt;p&gt;However, if one day I will want to deepen aspects of this project I didn’t so far, I cannot rule out that I will write other articles about this topic, but for now, the series is complete enough in my opinion.&lt;/p&gt;

&lt;p&gt;Let me know if you liked this series of articles, or if you have any suggestions or doubts about the topics discussed here.&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>regex</category>
    </item>
    <item>
      <title>How to Build a RegEx Engine in Python (Part 6: the engine)</title>
      <dc:creator>Lorenzo Felletti</dc:creator>
      <pubDate>Mon, 12 Dec 2022 23:23:58 +0000</pubDate>
      <link>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-part-6-the-engine-1nc</link>
      <guid>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-part-6-the-engine-1nc</guid>
      <description>&lt;p&gt;It is finally time to write about the engine of the regex engine we’re building.&lt;/p&gt;

&lt;p&gt;As we already saw, the parser produces an AST as a result of the parsing of a regular expression.&lt;br&gt;&lt;br&gt;
Now, the engine has to check whether a given string matches or not a regex.&lt;br&gt;&lt;br&gt;
To do so, the engine uses the AST representation of the regex, which &lt;strong&gt;extracts&lt;/strong&gt; the fundamental features/elements of the regular expression, and tries to “find” if the test string has them.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Engine
&lt;/h2&gt;

&lt;p&gt;The engine is again a Python class, having a fundamental method match, which is a closure containing the engine and all the needed auxiliary methods.&lt;/p&gt;

&lt;p&gt;Match signature:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;match&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;re&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Match Semantic
&lt;/h3&gt;

&lt;p&gt;The semantic we will give to the match method is the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  it returns on the first occurrence of the regex in the string&lt;/li&gt;
&lt;li&gt;  if there is no match, it tries again shifting the input string one character to the right (that is, moving the string one character to the right) until it reaches the end of the string.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is, if the input string is  &lt;code&gt;abac&lt;/code&gt;  and the regex is  &lt;code&gt;c&lt;/code&gt;, on the first attempt  &lt;code&gt;abac&lt;/code&gt;  won’t match  &lt;code&gt;c&lt;/code&gt;, so match tries again, but shifting  &lt;code&gt;abac&lt;/code&gt;  one character to the right this time, so tries to match  &lt;code&gt;bac&lt;/code&gt;  with  &lt;code&gt;c&lt;/code&gt;, resulting in another fail, so it tries again with  &lt;code&gt;ac&lt;/code&gt;  and  &lt;code&gt;c&lt;/code&gt;  (failing), and, lastly, it tries  &lt;code&gt;c&lt;/code&gt;  with  &lt;code&gt;c&lt;/code&gt;, resulting in a match, thus returning true.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fcs2kn49tngn8ewzsl6mu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fcs2kn49tngn8ewzsl6mu.png" alt="The  raw `match` endraw  function so far." width="800" height="686"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;match&lt;/code&gt; function so far.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  How To Match
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;match_group&lt;/code&gt;  is the most important method of the engine.&lt;/p&gt;

&lt;p&gt;It works by iterating through an AST node’s children, and by calling itself recursively when a  &lt;code&gt;GroupNode&lt;/code&gt;  is found or, with some differences, when an  &lt;code&gt;OrNode&lt;/code&gt;  is found.&lt;/p&gt;

&lt;p&gt;If an  &lt;code&gt;OrNode&lt;/code&gt;  is found, it checks if the left children (the one in position 0) matches, if it doesn’t, it tries the right one.&lt;/p&gt;

&lt;p&gt;When a leaf node is found (&lt;code&gt;ElementNode&lt;/code&gt;, …) it tries to match it.&lt;/p&gt;

&lt;p&gt;After every match, the  &lt;code&gt;str_i&lt;/code&gt;  (the index of the string) is increased of the matched characters.&lt;br&gt;&lt;br&gt;
The string index is set to position 0 (or the first position to consider more in general) at the beginning, and is kind of a “global variable”, but local to the match function.&lt;/p&gt;

&lt;p&gt;The mechanism of the recursive calls makes it easy to manage the “point in the tree” and “point in the string” considered. It also allows you to think of each group as a separate entity, making it easier to follow mentally the code execution.&lt;/p&gt;

&lt;p&gt;Obviously, this isn’t the whole engine, because as stated in the first article, we will need a backtracking system to assure to explore all the possible paths to match the string.&lt;/p&gt;

&lt;h3&gt;
  
  
  A little problem
&lt;/h3&gt;

&lt;p&gt;In fact, the semantic of leaf nodes and groups is to match them to the most characters possible by default, and while this is convenient most of the time, there are some edge cases in which this won’t lead to a correct answer.&lt;/p&gt;

&lt;p&gt;Let’s examine this example:&lt;/p&gt;

&lt;p&gt;If you have a regex  &lt;code&gt;a+ab&lt;/code&gt;  and a test string  &lt;code&gt;aab&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  the resulting AST will consist of a  &lt;code&gt;GroupNode&lt;/code&gt;, with three children, all leaves&lt;/li&gt;
&lt;li&gt;  a first  &lt;code&gt;a&lt;/code&gt;  to be matched [1, +∞[ times&lt;/li&gt;
&lt;li&gt;  a second  &lt;code&gt;a&lt;/code&gt;  to be matched exactly one time&lt;/li&gt;
&lt;li&gt;  a final  &lt;code&gt;b&lt;/code&gt;  to be matched exactly one time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;During the execution of our match function as presented, this is what will happen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;match_group&lt;/code&gt;  is called and start iterating on its children&lt;/li&gt;
&lt;li&gt;  the first  &lt;code&gt;a&lt;/code&gt;  element is matched as much as possible, so two times  &lt;code&gt;aa&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  then the engine tries to match the second  &lt;code&gt;a&lt;/code&gt;  element, but it fails as now the only left character is a  &lt;code&gt;b&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  false would be returned, but we all know the correct answer is true.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is because of the semantics we gave to our match function. What we would like the system to do is to “try another way”:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  since the first element could accept 1 or more occurrences of the letter  &lt;code&gt;a&lt;/code&gt;, and it matched two of them, we would like to be able to tell it “hey, please try by matching it one time less”&lt;/li&gt;
&lt;li&gt;  in this case, the first  &lt;code&gt;a&lt;/code&gt;  would be matched one time, leaving enough room to fit the second  &lt;code&gt;a&lt;/code&gt;  element, and then also the  &lt;code&gt;b&lt;/code&gt;  element, our third and last&lt;/li&gt;
&lt;li&gt;  this process worked, and so the answer would be true, as it should be.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This process is called backtracking and will be the topic of the next article, for now, let’s ignore the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Overall, we covered pretty much everything we needed to cover to explain the behavior of the match method.&lt;/p&gt;

&lt;p&gt;The skeleton of our code will look something like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fv0j7ioyf8db3uxbb6bju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fv0j7ioyf8db3uxbb6bju.png" alt=" raw `match` endraw  function’s structure." width="800" height="820"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;match&lt;/code&gt; function’s structure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the next article, we will cover the interesting topic of backtracking and will complete our regex engine.&lt;/p&gt;

</description>
      <category>gratitude</category>
    </item>
    <item>
      <title>How to Build a RegEx Engine in Python (Part 5: Parser conclusion)</title>
      <dc:creator>Lorenzo Felletti</dc:creator>
      <pubDate>Mon, 12 Dec 2022 23:17:38 +0000</pubDate>
      <link>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-part-5-parser-conclusion-2g3o</link>
      <guid>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-part-5-parser-conclusion-2g3o</guid>
      <description>&lt;p&gt;In this article, we’ll dig rapidly through the code of the parser, which will produce the AST we discussed in the previous article in output.&lt;/p&gt;

&lt;p&gt;This will hopefully be the last piece about the parser, and then we’ll move on to the engine and the juicy part, the backtracking system.&lt;/p&gt;

&lt;p&gt;So, the parser is contained in the Pyrser class, as we already saw in Part 3, which has the method parse, that takes as input a regular expression in the form of a string, and gives us the corresponding AST in output.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pyrser structure
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vz8Ho1pa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tq93hon22kg3hy8bchai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vz8Ho1pa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tq93hon22kg3hy8bchai.png" alt=" raw `Pyrser` endraw  structure." width="800" height="1174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Pyrser&lt;/code&gt; structure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We already spoke about the various functions and what is their purpose in previous articles.&lt;br&gt;&lt;br&gt;
Now we will look closer to the code of some of them. I will not explain what each line does, this isn’t the purpose of this series of articles, but I will rather express some final thoughts after.&lt;br&gt;&lt;br&gt;
If you’re not super interested in the code, feel free to skip reading through it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parse Regex Sequence
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pc2_wp10--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fr37zvwlbnygqklg7d4t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pc2_wp10--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fr37zvwlbnygqklg7d4t.png" alt=" raw `parse_re_seq` endraw  code." width="800" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;parse_re_seq&lt;/code&gt; code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Parse Group
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZPfLRXY0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/afa3lcrkctuchlezvjpp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZPfLRXY0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/afa3lcrkctuchlezvjpp.png" alt=" raw `parse_group` endraw  code." width="800" height="646"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;parse_group&lt;/code&gt; code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Parse Element
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X0pdz8tG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lih3843aceojmy7ahali.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X0pdz8tG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lih3843aceojmy7ahali.png" alt=" raw `parse_el` endraw  code." width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;parse_el&lt;/code&gt; code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Final Words
&lt;/h2&gt;

&lt;p&gt;In conclusion, the parser was not as hard to code as hard to debug.&lt;br&gt;&lt;br&gt;
When I first coded it I did it quickly and without having a perfectly clear idea in mind of what I wanted in output.&lt;/p&gt;

&lt;p&gt;In fact, the  &lt;code&gt;parse_re&lt;/code&gt;  function is indeed a leftover of an error:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  in the beginning, the  &lt;code&gt;^&lt;/code&gt;  and  &lt;code&gt;$&lt;/code&gt;  symbols were meant to be “absolute”, meaning that once typed, they would have been applied to every single regex in the sequence&lt;/li&gt;
&lt;li&gt;  This meant that a regex such as &lt;code&gt;^a|b$&lt;/code&gt; returned false on test string &lt;code&gt;cb&lt;/code&gt;, while it should return true because that &lt;code&gt;b&lt;/code&gt; must be at the beginning isn’t specified in the second regex, but this original implementation maintained the “match start” from the other one&lt;/li&gt;
&lt;li&gt;  This happened because at the beginning I thought that should be the “right” behavior, and I created the RE node of the AST just for this purpose.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I later realized that this behavior was confusing and didn’t make any sense, so I had to figure out a way to change it, possibly maintaining the RE node, because the engine was already coded and using it.&lt;/p&gt;

&lt;p&gt;In the end,  &lt;code&gt;parse_re&lt;/code&gt;  remained, completely emptied of any behavior, useless, for the sake of compatibility with the — already working — engine.&lt;/p&gt;

&lt;p&gt;Apart from this, the parser and the AST does a really good job overall, and coding a TDRDP parser isn’t so hard once you figured out a good grammar, which is no joke for non-trivial projects.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>python</category>
      <category>regex</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Build a RegEx Engine in Python (Part 4: The AST)</title>
      <dc:creator>Lorenzo Felletti</dc:creator>
      <pubDate>Fri, 11 Nov 2022 09:23:43 +0000</pubDate>
      <link>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-2eki</link>
      <guid>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-2eki</guid>
      <description>&lt;p&gt;In this article, I will present you the process I followed to end up with the final AST of the solution, and which are its strength and flaws (because yes, following my articles you won’t create a perfect solution, sorry).&lt;/p&gt;

&lt;p&gt;So, let’s start with the &lt;em&gt;logic blocks&lt;/em&gt; I wanted to have to build my AST.&lt;br&gt;&lt;br&gt;
I felt I needed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  a Group block (to group various elements)&lt;/li&gt;
&lt;li&gt;  an Element block, or more in general a Leaf block (used for elements, wildcards, match start/end, range elements, …)&lt;/li&gt;
&lt;li&gt;  an Or block, to express the alternative&lt;/li&gt;
&lt;li&gt;  a Regex block, to express the “single point of entry” (kinda useless, it will turn out)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, each regex will have a root node called &lt;code&gt;RE&lt;/code&gt;, the fancy name I chose for the top-level block acting as a single point of entry.&lt;br&gt;&lt;br&gt;
This node is actually quite useless, but also harmless, and in the next article, I will briefly discuss why it stayed in the final solution.&lt;/p&gt;

&lt;p&gt;Having these blocks clear in mind, I created this hierarchy of Python classes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--l9b_O6af--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fxqaecyhftkgmf2xi52r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l9b_O6af--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fxqaecyhftkgmf2xi52r.png" alt="Hierarchy of AST nodes." width="800" height="816"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The base class is the &lt;code&gt;ASTNode&lt;/code&gt;, and the RE, Group, and Or nodes directly inherit from it.&lt;/p&gt;

&lt;p&gt;All the other nodes will be leaves of our AST, meaning they will not have children nodes, so I created the intermediate class &lt;code&gt;LeafNode&lt;/code&gt; (inheriting from &lt;code&gt;ASTNode&lt;/code&gt;) from which they all inherit, and that serves as a base class to group them all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Oops, I made a mistake, and then another (maybe)
&lt;/h2&gt;

&lt;p&gt;I decided on the fly that it would have been good for the &lt;code&gt;RE&lt;/code&gt; node to only have one child, so I called this property &lt;code&gt;child&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Following the same idea, the &lt;code&gt;GroupNode&lt;/code&gt; has a children property named &lt;code&gt;children&lt;/code&gt;, and the &lt;code&gt;OrNode&lt;/code&gt; has two properties &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt; for its children.&lt;/p&gt;

&lt;p&gt;This was making total sense in my mind, until I had to code the engine, in which, as we will see, we want to iterate through the children of these nodes.&lt;/p&gt;

&lt;p&gt;You can guess the error now: having all these different names for (basically) the same property is not a good design choice.&lt;br&gt;&lt;br&gt;
You cannot write &lt;code&gt;node.children&lt;/code&gt; and move on, you have to check the type of the node, and then access the children using the right field name.&lt;/p&gt;

&lt;p&gt;This would make the code more error-prone, uselessly longer, and unnecessarily leads to WET code.&lt;/p&gt;

&lt;p&gt;We need to DRY this code, but how? We need to call all these properties with the same name: &lt;code&gt;children&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But the parser is already using the &lt;code&gt;child&lt;/code&gt;, &lt;code&gt;children&lt;/code&gt;, &lt;code&gt;left&lt;/code&gt;, and &lt;code&gt;right&lt;/code&gt; properties, and it would be painful to rewrite the code using the newborn property.&lt;br&gt;&lt;br&gt;
This is when I had the “eureka!”:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Just add the children property to every class and handle the mapping &lt;em&gt;under the hood&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A (mostly harmless) flaw
&lt;/h2&gt;

&lt;p&gt;The problem is that, as it is implemented, if someone changes, for example, the right child using the &lt;code&gt;node.right&lt;/code&gt; property after the node is created the change is not propagated to the &lt;code&gt;children&lt;/code&gt; property, and vice-versa.&lt;/p&gt;

&lt;p&gt;This is an error, actually, but I was too lazy to figure out a different solution, and after all, changing a node after its creation doesn’t make much sense, so we can supersede this error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;To conclude, the AST hierarchy we created is good enough to don’t end up being an obstacle to our project, even if it has a couple flaws, not very relevant in our context.&lt;/p&gt;

&lt;p&gt;Anyway, it is crucial to notice these flaws, and trying to avoid making the mistakes leading to them next time would be good for sure.&lt;/p&gt;




&lt;p&gt;Cover image by  &lt;a href="https://unsplash.com/@korpa?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Jr Korpa&lt;/a&gt; on &lt;a href="https://unsplash.com/@korpa?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>regex</category>
      <category>python</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Build a RegEx Engine in Python (Part 3: TDRDP)</title>
      <dc:creator>Lorenzo Felletti</dc:creator>
      <pubDate>Sat, 03 Jul 2021 14:49:05 +0000</pubDate>
      <link>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-part-3-tdrdp-1jg5</link>
      <guid>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-part-3-tdrdp-1jg5</guid>
      <description>&lt;p&gt;In the previous articles we spoke about how to define our grammar, how to build the lexer, and a bit about Python strings.&lt;/p&gt;

&lt;p&gt;In this article, we will finally begin the parser, the second-hardest part of the project (the first is the engine).&lt;/p&gt;

&lt;h2&gt;
  
  
  TDRDP
&lt;/h2&gt;

&lt;p&gt;TDRDP stands for &lt;strong&gt;Top-Down Recursive Descent Parsing&lt;/strong&gt; — a useful technique to create a parser.&lt;/p&gt;

&lt;p&gt;I won’t get into the details of when and how you can apply this technique, there’s already plenty of good articles about it, explaining it way better than I could.&lt;/p&gt;

&lt;p&gt;Anyway, luckily (😉) the grammar we built in the first article supports it.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to TDRDP
&lt;/h3&gt;

&lt;p&gt;To implement a recursive-descent parser, we have to create a function for each non-terminal symbol of the grammar.&lt;/p&gt;

&lt;p&gt;So, in our project, a function to parse the RE non-terminal, one for the GROUP, one for the RANGE_EL and so on.&lt;/p&gt;

&lt;p&gt;As you noticed, in the techniques’ acronym appear the infamous word ‘recursive’ (and now you’re all scared).&lt;/p&gt;

&lt;p&gt;Now you’re probably curious about where the recursion comes up. Well, it turns out the recursion come up in the functions calls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each function can call the functions of the non-terminals that appears in its productions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, our grammar has the production rule &lt;code&gt;RE_SEQ ::= '^'? GROUP ‘$'? ('|' RE_SEQ)?&lt;/code&gt; in which two non-terminals appear on the right side, &lt;code&gt;RANGE_EL&lt;/code&gt; and &lt;code&gt;RE_SEQ&lt;/code&gt; itself. In this case, the function corresponding to the non-terminals &lt;code&gt;RANGE_EL&lt;/code&gt; and &lt;code&gt;RE_SEQ&lt;/code&gt; itself can be called, hence the recursion.&lt;/p&gt;

&lt;p&gt;To use TDRDP, once all these functions are created, we call the top-level production, serving as an entry point, which in our case is the one corresponding to the non-terminal RE and the recursive calls will take care of the entire process of parsing by themselves.&lt;/p&gt;

&lt;p&gt;At the end, the function we called will return us the result of the parsing, whether it is a boolean, or something more complex like an AST as it is in our case.&lt;/p&gt;

&lt;h3&gt;
  
  
  AST
&lt;/h3&gt;

&lt;p&gt;The AST, Abstract Syntax Tree, is a tree representation of &lt;em&gt;something&lt;/em&gt;, in our case of the regular expression we are parsing.&lt;/p&gt;

&lt;p&gt;Quoting &lt;a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree"&gt;Wikipedia&lt;/a&gt;: &lt;em&gt;“The syntax is “abstract” in the sense that it does not represent every detail appearing in the real syntax, but rather just the structural or content-related details. For instance, grouping parentheses are implicit in the tree structure, so these do not have to be represented as separate nodes.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It is composed of nodes in a hierarchy, with a root node at the top:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;every node has one parent, except for the root node&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nodes can have zero or more children&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;if a node does not have children, it is called a **leaf **node.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qUORnwI5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3216/1%2AHRM6oYn0zPW4Vt6GKMJDIQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qUORnwI5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3216/1%2AHRM6oYn0zPW4Vt6GKMJDIQ.png" width="800" height="780"&gt;&lt;/a&gt;&lt;br&gt;Abstract Syntax Tree example.
  &lt;/p&gt;

&lt;p&gt;In the above example, we have a regular expression and a possible corresponding AST. The root node is RE, and following the hierarchy to the leaves, you will notice that the leaves have always some letters behind, that are the possible matches for the given element.&lt;/p&gt;

&lt;p&gt;You’ll also notice that the left-most leaf letter (A) corresponds to the first letter appearing in the regex, the second with the second, and the right-most leaf with the last one, a range element accepting letters between A and C.&lt;/p&gt;

&lt;p&gt;Our goal in the next articles will be to define an AST similar to this, and then to make the parser capable of building it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structure of our Parser
&lt;/h2&gt;

&lt;p&gt;Without digging into the details, we can already create a skeleton for our parser.&lt;/p&gt;

&lt;p&gt;We’ll start by creating a class called Pyrser (because I’m a funny person) and defining a &lt;strong&gt;init&lt;/strong&gt; method and a parse function, inside which we will define all the functions we need to implement a TDRD parser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1OmhUQlV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3024/1%2A50ON_XzLle-w_-T66zI4Wg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1OmhUQlV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3024/1%2A50ON_XzLle-w_-T66zI4Wg.png" width="800" height="898"&gt;&lt;/a&gt;&lt;br&gt;Pyrser structure.
  &lt;/p&gt;

&lt;p&gt;I hope you’re familiar with the concept of closure, because we’re going to use it a lot in our project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Utilities
&lt;/h3&gt;

&lt;p&gt;Let’s discuss the utilities first.&lt;/p&gt;

&lt;p&gt;We will use the first utility function &lt;code&gt;get_range_str&lt;/code&gt; when we will parse range elements ([a-m|0-3]) to get the number/letters contained in a given range.&lt;/p&gt;

&lt;p&gt;The second utility &lt;code&gt;next_tkn_initializer&lt;/code&gt; is a closure returning a function that, when called, set the current token to the next one to parse. Although not fundamental, this function is very convenient, as you will notice.&lt;/p&gt;

&lt;h3&gt;
  
  
  A function for each non-terminal
&lt;/h3&gt;

&lt;p&gt;As you can see there is a function for each non-terminal of our grammar (except SPECIAL, that was only introduced to denote the special symbols, and QTIFIER that is replaced by parse_curly because the quantifiers &lt;code&gt;? * +&lt;/code&gt; will be parsed inside parse_group for simplicity and the only quantifiers needing a special treatment are only that specified with the curly brace syntax &lt;code&gt;{3} {2,3} {3,} {,3}&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Each function of a non-terminal symbol returns an ASTNode object, we will see how it is done in the next article.&lt;/p&gt;

&lt;p&gt;For this article, we won’t go deeper into the actual implementation of the parser because we need a good AST implementation first.&lt;/p&gt;




&lt;p&gt;Cover Image by &lt;a href="https://unsplash.com/@marius"&gt;Marius Masalar&lt;/a&gt; on &lt;a href="https://unsplash.com"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>regex</category>
      <category>programming</category>
      <category>parsing</category>
    </item>
    <item>
      <title>How to Make a Bar Chart Race With Python in 2 Minutes</title>
      <dc:creator>Lorenzo Felletti</dc:creator>
      <pubDate>Sat, 19 Jun 2021 21:35:41 +0000</pubDate>
      <link>https://dev.to/lorenzofelletti/how-to-make-a-bar-chart-race-with-python-in-2-minutes-4999</link>
      <guid>https://dev.to/lorenzofelletti/how-to-make-a-bar-chart-race-with-python-in-2-minutes-4999</guid>
      <description>&lt;h2&gt;
  
  
  How to create a cool bar chart race animation the easiest way.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt; having Python installed on your pc or being registered for Google Colaboratory.&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 0
&lt;/h1&gt;

&lt;p&gt;First create a new directory for the project (if you use Google Colaboratory skip to step 1)&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Then create a new virtual environment, and activate it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python3 -m venv venv
source venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Step 1
&lt;/h1&gt;

&lt;p&gt;If you haven’t already, install pandas&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Install the library we’ll use to create the bar chart race named, you won’t guess it, bar_chart_race&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Step 2
&lt;/h1&gt;

&lt;p&gt;Now that we have the necessary libraries installed, let’s load our data.&lt;/p&gt;

&lt;p&gt;In this tutorial, we’ll create a bar chart animation of the 2020 MotoGP World Championship’s title race. If you’re not familiar with this sport — that’s bad — don’t worry.&lt;br&gt;
I will sum it up briefly for you to better understand what the data means.&lt;/p&gt;
&lt;h2&gt;
  
  
  How MotoGP works
&lt;/h2&gt;

&lt;p&gt;MotoGP is the premier class of motorcycle road racing. A championship is held every year and consists of many races (or Grand Prix). After each Grand Prix, each rider gains some points depending on his final position at the GP. At the end of the season, the rider with the most point wins the championship.&lt;/p&gt;

&lt;p&gt;The point system in use since 1993 is the following:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwf2hmvafy5nnwz83053c.png" 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%2Fwf2hmvafy5nnwz83053c.png" alt="1_fF8ZmCdekNvNOqRSpmEMsw"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The dataset
&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%2Fuploads%2Farticles%2Fkhbp03pwtujvoutv9xo7.png" 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%2Fkhbp03pwtujvoutv9xo7.png" alt="1_Ae6Xx-cugqR_oSVK0S4tBg (1)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the dataset &lt;a href="https://gist.github.com/lorenzofelletti/36df65f62e927108b628614030a25cda" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Step 3
&lt;/h1&gt;

&lt;p&gt;Now the cool part: coding!&lt;/p&gt;
&lt;h2&gt;
  
  
  Import the libraries
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;bar_chart_race&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;bcr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Load the dataset
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;./2020-championship.csv&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;race&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;h2&gt;
  
  
  Let the magic happen
&lt;/h2&gt;

&lt;p&gt;The final result is only one line of code away&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="n"&gt;bcr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar_chart_race&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;df&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2020 MotoGP Championship Race&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;h&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;desc&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_bars&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;steps_per_period&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;period_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, we’ve done with the coding. You can save and run the program, and you will obtain as output the bar chart race video.&lt;/p&gt;

&lt;h1&gt;
  
  
  Done!
&lt;/h1&gt;

&lt;p&gt;Congrats, you’ve finished. As easy as that.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ZVJ2n3m-bug"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;That was just a short introduction to this library. You can unleash your imagination creating much more advanced races with it.&lt;/p&gt;

</description>
      <category>python</category>
      <category>chart</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Build a RegEx Engine in Python (Part 2.1: Python strings)</title>
      <dc:creator>Lorenzo Felletti</dc:creator>
      <pubDate>Tue, 01 Jun 2021 10:12:16 +0000</pubDate>
      <link>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-39a2</link>
      <guid>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-39a2</guid>
      <description>&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;Previous episodes recap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We want to build a RegEx Engine.&lt;/li&gt;
&lt;li&gt;In the first episode we briefly spoke about the grammar we want to recognize.&lt;/li&gt;
&lt;li&gt;In the second episode we built the lexer (the first of three components we need, the others are the parser, and finally the engine).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This episode is kind of a spin-off, as it isn’t much centered on the RegEx itself, as we will explore Python strings, using the project just as an excuse to learn something new.&lt;/p&gt;




&lt;h1&gt;
  
  
  Dear Py\thon
&lt;/h1&gt;

&lt;p&gt;Aaagh…Python strings…&lt;/p&gt;

&lt;p&gt;The problem with what we created so far is that a string in Python, by default, treats the ‘\’ as an escape.&lt;/p&gt;

&lt;p&gt;Thus, in our implementation, the lexer can't read ‘\’, then the following character, and finally decide the meaning of it.&lt;/p&gt;

&lt;p&gt;For example, if we escape, for whatever reason, the letter ‘c’ we will get the correct output (an ElementToken with char field = ‘c’), but for the wrong reason. But, if we escape the escape character ‘\’, writing ‘\’, we will note an unexpected behavior:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EcRE5gZL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pacb30xj0e2g44fgrykh.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EcRE5gZL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pacb30xj0e2g44fgrykh.jpeg" width="800" height="609"&gt;&lt;/a&gt;&lt;br&gt;The scanned tokens vs. the expected ones. The hole between b and c is a ‘\t’, while we wanted a ‘\’.
  &lt;/p&gt;

&lt;p&gt;The scanned tokens vs. the expected ones. The hole between b and c is a ‘\t’, while we wanted a ‘\’.&lt;/p&gt;

&lt;p&gt;Why is this happening? Is there a bug in the Lexer implementation we have done so far?&lt;/p&gt;

&lt;p&gt;The answer is no, there’s no bug in the implementation.&lt;/p&gt;

&lt;p&gt;The problem is that Python escaped the escape character for us, so our lexer read ‘\’ as one character, a backslash, and our lexer will escape the next character.&lt;/p&gt;

&lt;p&gt;But, this is not the behavior we wanted. We wanted to escape a backslash, not the character following the escaped backslash.&lt;/p&gt;

&lt;p&gt;Luckily, it is not difficult to ‘fix’ this behavior, and we have at least two ways to do this.&lt;/p&gt;

&lt;h1&gt;
  
  
  First Way
&lt;/h1&gt;

&lt;p&gt;The first way is to simply pass the lexer a raw string instead of a string. To do this it is sufficient to prefix the string with an r:&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="n"&gt;lexer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s"&gt;'ab\\tc'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Doing this way, unfortunately, the user must remember to pass a raw string instead of a string to the lexer whenever needed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Second Way
&lt;/h1&gt;

&lt;p&gt;The problem with the first solution is that the user may forget about this particular and his regex will show unexpected behavior.&lt;/p&gt;

&lt;p&gt;Maybe we should prevent it and automatically, and always, interpret the string as raw, thus preventing this strange behavior to ever happen.&lt;/p&gt;

&lt;p&gt;To achieve this, we should build a function that “convert” our string representation to raw and call it right away before the lexer does any processing.&lt;/p&gt;

&lt;p&gt;To do that, we should do something like this [1]:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;str_to_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;raw_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s"&gt;'\b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s"&gt;'\a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s"&gt;'\f'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s"&gt;'\r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s"&gt;'\t'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s"&gt;'\v'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;ord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;raw_map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;ord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this way, the passed regex is “converted“ to a raw string, and interpreted as raw.&lt;/p&gt;

&lt;p&gt;The problem with this approach is that it is extremely hacky, as you should extend raw_map to include every possible escape sequence.&lt;/p&gt;

&lt;p&gt;This solution would be very specific on the particular Python implementation, something you should generally avoid whenever possible.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The first solution is most likely the one you want, because of how hacky the second is, but you’re free to implement the solution you prefer or find a better one on your own.&lt;/p&gt;




&lt;h1&gt;
  
  
  Resources
&lt;/h1&gt;

&lt;p&gt;[1] &lt;a href="https://stackoverflow.com/questions/21605526/how-to-create-raw-string-from-string-variable-in-python"&gt;How to create raw string from string variable in python?&lt;/a&gt; — Stack Overflow — Stack Overflow&lt;/p&gt;




&lt;p&gt;Cover by &lt;a href="https://unsplash.com/@pankajpatelW"&gt;Pankaj Patel&lt;/a&gt; on &lt;a href="https://unsplash.com"&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>regex</category>
      <category>strings</category>
    </item>
    <item>
      <title>How to Build a RegEx Engine in Python (Part 2: The Lexer)</title>
      <dc:creator>Lorenzo Felletti</dc:creator>
      <pubDate>Sun, 23 May 2021 22:08:06 +0000</pubDate>
      <link>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-part-2-the-lexer-2b4n</link>
      <guid>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-part-2-the-lexer-2b4n</guid>
      <description>&lt;p&gt;In the previous article, we spoke about grammar and what we need to complete this project.&lt;/p&gt;

&lt;p&gt;It’s now time to finally dig into the coding part.&lt;/p&gt;

&lt;h1&gt;
  
  
  Set Up The Environment
&lt;/h1&gt;

&lt;p&gt;To set up the environment we first need to create a folder for the project and the virtualenv we’ll use for it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir pyregex  
cd pyregexpython3 -m venv venv  
source venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For this project, we will use a couple of python libraries:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip3 install numpy  
pip3 install autopep8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Autopep8 isn’t needed for the project itself, but I use it to help me with keeping formatting uniform throughout the codebase.&lt;/p&gt;

&lt;p&gt;On the other hand, we’ll use NumPy to build the AST.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Folder Structure
&lt;/h2&gt;

&lt;p&gt;Inside pyregex, we create an src folder where we will place all our code.&lt;/p&gt;

&lt;p&gt;The __init__.py files you see are empty files needed by python to navigate through the project.&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%2Fpoyovpjh5kt7bm0qmz20.jpeg" 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%2Fpoyovpjh5kt7bm0qmz20.jpeg" alt="The folder structure of the project."&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h1&gt;
  
  
  Building The Lexer
&lt;/h1&gt;
&lt;h2&gt;
  
  
  What Is a Lexer
&lt;/h2&gt;

&lt;p&gt;A Lexer (or Scanner) is a component that takes a string as input and outputs a list (array, or whatever) of tokens, i.e. “category of words, logical tokens, of a grammar”.&lt;/p&gt;
&lt;h2&gt;
  
  
  A brief example:
&lt;/h2&gt;

&lt;p&gt;Input string:&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%2Ftmnkrmgd5rxms238lx8r.png" 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%2Ftmnkrmgd5rxms238lx8r.png" alt="Input string example."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;English language lexer output:&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%2F45jb0tlx30lvq8e2bk46.png" 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%2F45jb0tlx30lvq8e2bk46.png" alt="English Language Lexer tokens list output."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Tokens
&lt;/h2&gt;

&lt;p&gt;Our lexer will have to recognize different types of tokens (character, parenthesis, brackets, escape, …).&lt;/p&gt;

&lt;p&gt;To do so we first need to define a hierarchy of tokens types.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;




&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the list above you can see the hierarchy of tokens we’re going to create and a few implemented token classes. (Remember that the complete code is available &lt;a href="https://github.com/lorenzofelletti/pyregex" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;For many of the tokens, I created first a base class to represent the type and then more specialized ones for the actual char we choose to be the one representing the type.&lt;br&gt;&lt;br&gt;
This wasn’t strictly necessary, but adds not much work and may help you keep the code coherent and makes it easy to overload token types (maybe one day I will want ‘#’ to be an escape too for some reason).&lt;/p&gt;
&lt;h2&gt;
  
  
  Finally the Lexer
&lt;/h2&gt;

&lt;p&gt;The lexer itself is a quite simple component.&lt;/p&gt;

&lt;p&gt;In a file named lexer.py, we create the class Lexer which will implement the scan method that will take a string as input and outputs a NumPy array of the tokens recognized.&lt;/p&gt;

&lt;p&gt;To recognize the tokens the Lexer iterate through each character of the input string and assigns it the corresponding token.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As you can see it is pretty straightforward. The only two tricky points are the handling of the escape, ‘^’ and curly brace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The escape&lt;/strong&gt;&lt;br&gt;
To handle the escape I created a support variable escape_found which is set to false at the end of each while loop.&lt;/p&gt;

&lt;p&gt;When an escape it’s actually found, the variable is set to true and the continue clause immediately after restarting the loop without setting it to false again. Thanks to this, in the next iteration, the variable value would be true, thus triggering the specific condition (if escape_found).&lt;/p&gt;

&lt;p&gt;The code specific to the condition is then executed and, since there is no continuity, the end of the loop code is reached and escape_found is set again to false.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The ‘^’&lt;/strong&gt;&lt;br&gt;
This is by far the most interesting in my opinion because the reality is that, unless you find it as the first character, you can’t be sure if what you found is a negation, like in &lt;code&gt;[^abc]&lt;/code&gt; (i.e. match a char that is anything but a, b, or a match start token in a subsequent regex, like in &lt;code&gt;^abc$|^012$&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;Since this is impossible to tell, in our implementation each ‘^’ after index 0 is recognized by the lexer as a Circumflex (NotToken), and then it will be the parser to have the final word on the question.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Left curly brace&lt;/strong&gt;&lt;br&gt;
When a left curly brace ‘{‘ is met, we enter to a kind of “sub-grammar” that recognizes the quantifier {min, max} (with min or max eventually omitted).&lt;/p&gt;

&lt;p&gt;Thus, the number of allowed tokens tightens, and it is always good to recognize early badly formatted regexes.&lt;/p&gt;

&lt;p&gt;Because, if you can eliminate some grammar errors in the Lexer, which is fairly simple, you won’t have to check for the same error again in the Parser, which is already more complex by itself, reducing (by a tiny bit) the complexity of it.&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;As you probably noted, the Lexer is a very simple component to design and implement.&lt;/p&gt;

&lt;p&gt;Harder times will come as we’ll design and implement the Parser, and even harder with the engine (and the backtracking system above all).&lt;/p&gt;

&lt;p&gt;I hope you enjoyed reading this article. For this part I think we did enough, don’t hesitate to ask me questions if something isn’t clear to you, I’ll be glad to answer any questions!&lt;/p&gt;




&lt;p&gt;Cover Image by &lt;a href="https://unsplash.com/@sweetheartshi?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;鏡飛 匙&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/neon?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>regex</category>
      <category>lexer</category>
    </item>
    <item>
      <title>How to Build a RegEx Engine in Python (Part 1: The Grammar)</title>
      <dc:creator>Lorenzo Felletti</dc:creator>
      <pubDate>Sun, 23 May 2021 21:47:59 +0000</pubDate>
      <link>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-part-1-the-grammar-2coa</link>
      <guid>https://dev.to/lorenzofelletti/how-to-build-a-regex-engine-in-python-part-1-the-grammar-2coa</guid>
      <description>&lt;p&gt;In this series of articles, we will follow the steps to build a RegEx Engine in Python. I chose &lt;strong&gt;Python&lt;/strong&gt; over the many alternatives for a few reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; It is well integrated with the Linux command line&lt;/li&gt;
&lt;li&gt; Because yes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In a way, I find Python to be a “less verbose version of Java” and a “less confusing version of JavaScript”, which were the other two alternatives I considered.&lt;/p&gt;

&lt;p&gt;Please let me explain before get mad at me.&lt;br&gt;&lt;br&gt;
Before starting this project I had no idea how things should be done, how to code the various modules, and so on.&lt;br&gt;&lt;br&gt;
I had to figure everything out by myself.&lt;/p&gt;

&lt;p&gt;And, when I don’t know how to do things exactly, I find JS a bit too confusing, it’s just a feeling, not a universal truth, and I find that with Java I can organize my ideas better.&lt;/p&gt;

&lt;p&gt;But, since I don’t like how verbose and limiting Java is in some way, but wanted classes, and I love having functions as first-class citizens, Python seemed like the perfect blend to me.&lt;/p&gt;

&lt;p&gt;Anyway, it’s now time to start with the project itself.&lt;/p&gt;




&lt;h1&gt;
  
  
  What We Need
&lt;/h1&gt;

&lt;p&gt;To match a string with a regular expression of our will we need to complete a few steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;understand&lt;/strong&gt; the regular expression&lt;/li&gt;
&lt;li&gt; create an &lt;strong&gt;internal representation&lt;/strong&gt; of it (so that we can see if a passed string match with it)&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;match&lt;/strong&gt; the string with the regex, using the internal representation we built of it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To complete the &lt;em&gt;first two steps&lt;/em&gt; we need two components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  a &lt;strong&gt;Lexer&lt;/strong&gt; (or scanner) to parse the regex in tokens (“words”, generic “pieces of information”). As an example in the sentence “I am beautiful, very beautiful” each word (“I”, “am”, …) is a token of type “word” and the comma is a token of type “punctuation”&lt;/li&gt;
&lt;li&gt;  a &lt;strong&gt;Parser&lt;/strong&gt; which read all the tokens in sequence and “understands” them, building while doing so an internal representation of the regex (which will be a tree, called Abstract Syntax Tree, AST for the friends).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To accomplish the &lt;em&gt;third step&lt;/em&gt; we need to build a component able to take as input the AST built by the Parser and a string, and visiting the tree to match each leaf of the tree with some part of the string (and something more, we will discuss later).&lt;br&gt;&lt;br&gt;
This component is named:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Engine&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  The Roadmap
&lt;/h1&gt;

&lt;p&gt;So, now that we know the modules we will have to code, let’s build a roadmap:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;em&gt;define the&lt;/em&gt; RegEx &lt;em&gt;grammar&lt;/em&gt; we want to recognize&lt;/li&gt;
&lt;li&gt; &lt;em&gt;build the lexer&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt; &lt;em&gt;build the parser&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt; &lt;em&gt;build the engine&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;&lt;em&gt;enjoy&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h1&gt;
  
  
  The Grammar
&lt;/h1&gt;

&lt;p&gt;It’s now time to discuss the &lt;strong&gt;grammar&lt;/strong&gt; we want to recognize.&lt;/p&gt;

&lt;p&gt;I assume you know what a formal grammar is and that you understand the &lt;em&gt;EBNF&lt;/em&gt; notation, if not, &lt;em&gt;DON’T PANIC&lt;/em&gt;, google it.&lt;/p&gt;

&lt;p&gt;The regex grammar we will recognize is the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Aj6VzQkd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z41uvy6ncr1seo530nzm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Aj6VzQkd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z41uvy6ncr1seo530nzm.png" alt="The grammar."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Top-level production &lt;em&gt;RE ::= RE_SEQ&lt;/em&gt; is indeed useless but is there because I used it in one of the early versions of the project and I was too lazy to remove it later. Anyway, it is completely harmless, I promise, and it will cost you just a couple of lines of code and only one more call on the stack during execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Grammar Explained
&lt;/h2&gt;

&lt;p&gt;The features that the described grammar will be able to implement are the following:&lt;/p&gt;

&lt;p&gt;So, valid regexes are:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--502nyz5H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/3108/1%255C%2Apg7KhpwIY84iy9hq0dkiyQ.png" class="article-body-image-wrapper"&gt;&lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--502nyz5H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/3108/1%255C%2Apg7KhpwIY84iy9hq0dkiyQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Examples of recognized regexes.&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;You can browse the code of the final result &lt;a href="https://github.com/lorenzofelletti/pyregex"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I think that can be enough for the first part, more in the next articles of the series.&lt;/p&gt;

&lt;p&gt;In the &lt;em&gt;next article&lt;/em&gt;, we will set up the environment and start coding, starting from the lexer.&lt;/p&gt;

&lt;p&gt;See you soon! I hope you &lt;em&gt;enjoyed&lt;/em&gt; this read!&lt;/p&gt;

&lt;p&gt;Please feel free to reply if you don’t understand something, need some hints, whatever. I’ll be glad to answer you.&lt;/p&gt;




&lt;p&gt;Cover Image by &lt;a href="https://unsplash.com/@pankajpatel?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Pankaj Patel&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/json?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>regex</category>
      <category>coding</category>
    </item>
  </channel>
</rss>
