<?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>Forem: Ingi</title>
    <description>The latest articles on Forem by Ingi (@ingigauti).</description>
    <link>https://forem.com/ingigauti</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%2F1374202%2F436f1f4a-2244-420c-b532-e6d6447dc872.jpg</url>
      <title>Forem: Ingi</title>
      <link>https://forem.com/ingigauti</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ingigauti"/>
    <language>en</language>
    <item>
      <title>Security is a Mess – How Plang Helps Fix It</title>
      <dc:creator>Ingi</dc:creator>
      <pubDate>Mon, 19 May 2025 11:03:26 +0000</pubDate>
      <link>https://forem.com/ingigauti/security-is-a-mess-how-plang-helps-fix-it-11nh</link>
      <guid>https://forem.com/ingigauti/security-is-a-mess-how-plang-helps-fix-it-11nh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post dives into Plang, an intent-based programming language that interprets natural language. For more, visit &lt;a href="https://plang.is" rel="noopener noreferrer"&gt;plang.is&lt;/a&gt; or &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%201.md" rel="noopener noreferrer"&gt;get started here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Security is hard. As developers, we’re not exactly great at it. The issue is that security is binary - it either works 100% or it doesn’t at all. If there’s a flaw in your code, an attacker could gain full access to your system. Worse, you can never truly prove that something is 100% secure. All you can do is try to prevent every possible way in, which requires a lot of experience and a lot of eyes on the code. The only thing that gets you closer to 100% is time and scrutiny.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scrutiny &amp;amp; Time
&lt;/h2&gt;

&lt;p&gt;That’s the key to secure code: experienced developers looking at it, lots of them, and enough time passing without a breach. We never &lt;em&gt;know&lt;/em&gt; it’s secure. We can only hope.&lt;/p&gt;

&lt;h2&gt;
  
  
  The State of Development
&lt;/h2&gt;

&lt;p&gt;If I asked 10 developers to write code that reads a file into a variable, I’d get 10 different implementations. Some would be buggy. Some would be insecure. That’s where we are today.&lt;/p&gt;

&lt;h2&gt;
  
  
  LLM Coding
&lt;/h2&gt;

&lt;p&gt;If you use an LLM to write the same thing, it’s the same story. Ask 10 times, and you’ll get 10 different versions-some with security flaws, some with bugs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plang
&lt;/h2&gt;

&lt;p&gt;Plang is intent-based programming. That means the developer just describes what they want to happen, and Plang handles it. For example, reading a file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- read file.txt into %content%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The intent here is simple: read the contents of &lt;code&gt;file.txt&lt;/code&gt; into the variable &lt;code&gt;%content%&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now here’s the key part: no matter how many developers write this in Plang, or how they phrase it, it will &lt;em&gt;always&lt;/em&gt; result in the same underlying code. You can &lt;a href="https://github.com/PLangHQ/plang/blob/3c1d89c9148a063bd6e916b802950626d5143fed/PLang/Modules/FileModule/Program.cs#L204" rel="noopener noreferrer"&gt;view it yourself here&lt;/a&gt; (if you’re technical enough to follow it).&lt;/p&gt;

&lt;p&gt;That’s huge. No matter how many billions of lines are written to read files in Plang, they’ll all run through the same ~40 lines of code. (It’s 40 lines because the file module does more than just reading-there’s more to discover.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Higher Risk Examples
&lt;/h2&gt;

&lt;p&gt;Reading a file is simple. Not typically a big security concern. So let’s take a more sensitive example: password hashing.&lt;/p&gt;

&lt;p&gt;Hashing passwords isn’t trivial. You need to &lt;em&gt;really&lt;/em&gt; know what you’re doing. Most people don’t. And here are some ways you can get completely SCREWED:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the wrong algorithm? You’re screwed.&lt;/li&gt;
&lt;li&gt;Don’t use a salt? Screwed.&lt;/li&gt;
&lt;li&gt;Use the same salt every time? Screwed.&lt;/li&gt;
&lt;li&gt;Use a bad salt? Screwed.&lt;/li&gt;
&lt;li&gt;Too few iterations? Screwed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m not even an expert in hashing, so this list is probably missing a few traps.&lt;/p&gt;

&lt;p&gt;Ask 10 developers or an LLM 10 times to write a password hashing function, and you’ll get 20 different versions. LLMs might actually outperform humans here-but there’s still variance and risk.&lt;/p&gt;

&lt;p&gt;In Plang, here’s how you do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- hash %password%, write to %hashedPassword%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You just want the password hashed. If you're curious about the details, &lt;a href="https://github.com/PLangHQ/plang/blob/3c1d89c9148a063bd6e916b802950626d5143fed/PLang/Modules/CryptographicModule/Program.cs#L122" rel="noopener noreferrer"&gt;you can read the source code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, I’m no specialist, so maybe it’s wrong. But the good news? It’s open source. Anyone can scrutinize it. Experts can review and improve it. I’m not one of them-but plenty of people are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usernames and Passwords = BAD
&lt;/h2&gt;

&lt;p&gt;Oh boy. Usernames and passwords. What a nightmare.&lt;/p&gt;

&lt;p&gt;They’re a pain for developers to manage, and they’re the weakest link in most systems. The solution? Public/private key cryptography. PGP (Pretty Good Privacy) has been around since the '90s and was basically that. But it was never made easy for developers to implement, so usernames and passwords stuck around.&lt;/p&gt;

&lt;p&gt;Here’s where Plang shines again: all developers use the &lt;em&gt;same&lt;/em&gt; code when writing functionality. That includes HTTP requests.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- get https://jsonplaceholder.typicode.com/posts/, write to %posts%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="//HttpRequests.md"&gt;More on HTTP here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This uniformity opens up new possibilities. Plang can automatically sign every request. The developer doesn’t have to think about it. On the server side, that request includes the &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/Identity.md" rel="noopener noreferrer"&gt;identity of the sender&lt;/a&gt;. No username or password needed.&lt;/p&gt;

&lt;p&gt;Since every HTTP request in Plang runs through &lt;a href="https://github.com/PLangHQ/plang/blob/3c1d89c9148a063bd6e916b802950626d5143fed/PLang/Modules/HttpModule/Program.cs#L19" rel="noopener noreferrer"&gt;the same code&lt;/a&gt;, it can be reviewed, audited, and made secure by experienced eyes.&lt;/p&gt;

&lt;p&gt;Removing usernames and passwords removes a &lt;em&gt;massive&lt;/em&gt; security hole from your system.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Security, Fewer Bugs
&lt;/h2&gt;

&lt;p&gt;All of this leads to one simple conclusion:&lt;/p&gt;

&lt;p&gt;Plang apps have fewer bugs and are more secure.&lt;/p&gt;




&lt;p&gt;This article &lt;/p&gt;

</description>
      <category>plang</category>
      <category>security</category>
    </item>
    <item>
      <title>Plang Trick: Database Selection Made Easy</title>
      <dc:creator>Ingi</dc:creator>
      <pubDate>Thu, 13 Feb 2025 10:16:18 +0000</pubDate>
      <link>https://forem.com/ingigauti/plang-trick-database-selection-made-easy-1d6a</link>
      <guid>https://forem.com/ingigauti/plang-trick-database-selection-made-easy-1d6a</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post dives into Plang, an intent-based programming language that interprets natural language. For more, visit &lt;a href="https://plang.is" rel="noopener noreferrer"&gt;plang.is&lt;/a&gt; or &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%201.md" rel="noopener noreferrer"&gt;get started here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you get data from a database in Plang, it always comes as a list—even if you’re only selecting one row using a &lt;strong&gt;primary key&lt;/strong&gt;. That means if the database returns just one result, it’s still treated as a &lt;strong&gt;list with one item&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Basic Example: Getting a User&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you want to grab a user’s &lt;strong&gt;ID&lt;/strong&gt; and &lt;strong&gt;name&lt;/strong&gt;, you would normally do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database
- select id, name from users where %userId%, write to %users%
- write out "Name of user: %users[0].name% and id: %users[0].id%"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since &lt;strong&gt;%users%&lt;/strong&gt; is a list, you have to access the first item using &lt;strong&gt;%users[0]%.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Shortcut: Directly Using Variables&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Instead of dealing with a list, you can tell Plang to return &lt;strong&gt;just one row&lt;/strong&gt; and automatically store the values into variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database
- select id, name from users where %userId%, return 1
- write out "Name of user: %name% and id: %id%"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plang will detect which columns you're selecting and &lt;strong&gt;create variables for them&lt;/strong&gt;, making your code cleaner and easier to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Custom Variable Names&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You can also rename the columns while selecting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database
- select id as userId, name as fullName from users where %userId%, return 1
- write out "Name of user: %fullName% and id: %userId%"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, instead of using &lt;strong&gt;%id%&lt;/strong&gt; and &lt;strong&gt;%name%&lt;/strong&gt;, you can refer to them as &lt;strong&gt;%userId%&lt;/strong&gt; and &lt;strong&gt;%fullName%&lt;/strong&gt;—whatever makes sense for your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why This Trick is Useful&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No need to handle lists when dealing with single rows.&lt;/li&gt;
&lt;li&gt;Makes your code &lt;strong&gt;shorter and cleaner&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Lets you use &lt;strong&gt;custom variable names&lt;/strong&gt; for better readability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A nice little trick to make database queries in Plang &lt;strong&gt;way simpler!&lt;/strong&gt; 🚀&lt;/p&gt;

</description>
      <category>plang</category>
      <category>database</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How I Use Plang for System Administration</title>
      <dc:creator>Ingi</dc:creator>
      <pubDate>Tue, 29 Oct 2024 12:25:53 +0000</pubDate>
      <link>https://forem.com/ingigauti/how-i-use-plang-for-system-administration-kle</link>
      <guid>https://forem.com/ingigauti/how-i-use-plang-for-system-administration-kle</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post dives into Plang, an intent-based programming language that interprets natural language. For more, visit &lt;a href="https://plang.is" rel="noopener noreferrer"&gt;plang.is&lt;/a&gt; or &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%201.md" rel="noopener noreferrer"&gt;get started here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Plang is a powerful tool, especially when it comes to system administration. Its ability to operate at the programming layer while leveraging various tools gives developers—and sysadmins —an impressive level of control and efficiency.&lt;/p&gt;

&lt;p&gt;In system administration, scripts simplify repetitive tasks, and I use Plang specifically to deploy apps to servers. My Plang apps are pretty straightforward, so they don’t need the heavy-duty CI/CD pipeline, which would just add unnecessary complexity.&lt;/p&gt;

&lt;p&gt;So, how does it work?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Plan
&lt;/h2&gt;

&lt;p&gt;My goal is to take the &lt;code&gt;app&lt;/code&gt; folder from my development machine and set it up on a Linux server. Here’s what needs to happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Zip the &lt;code&gt;app&lt;/code&gt; folder to &lt;code&gt;app.zip&lt;/code&gt;, excluding any &lt;code&gt;.db&lt;/code&gt; and &lt;code&gt;*.sqlite&lt;/code&gt; files.&lt;/li&gt;
&lt;li&gt;Connect to my Linux server via SFTP.&lt;/li&gt;
&lt;li&gt;Upload &lt;code&gt;app.zip&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Clear out any old &lt;code&gt;.build&lt;/code&gt; files to avoid using outdated code.&lt;/li&gt;
&lt;li&gt;Unzip &lt;code&gt;app.zip&lt;/code&gt; on the server.&lt;/li&gt;
&lt;li&gt;Set the correct file permissions.&lt;/li&gt;
&lt;li&gt;Optionally update the Plang runtime.&lt;/li&gt;
&lt;li&gt;Confirm the Plang runtime is working.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you’re doing this setup for the first time, it's common to miss a step or two—don’t worry. The flexibility of Plang makes it easy to adjust on the fly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Deployment
&lt;/h2&gt;

&lt;p&gt;Let’s walk through the deployment by setting up a &lt;code&gt;Deploy.goal&lt;/code&gt; file on my computer, and the first line is simply &lt;code&gt;Deploy&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Zipping the App
&lt;/h3&gt;

&lt;p&gt;We’ll start by creating a zip file of the app directory, which is in the same location as &lt;code&gt;Deploy.goal&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- zip "./" to "deploy/app.zip", exclude ".db", "*.sqlite", overwrite file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Let's stop here. If you are familiar with programming, you will probably be thinking what is the syntax here? How do I &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/modules/PLang.Modules.CompressionModule.md" rel="noopener noreferrer"&gt;know how to structure this zip command&lt;/a&gt;, but here is the thing. Plang does not have strict syntax, it's all about what would you like to happen. Instead of &lt;code&gt;zip "./" to "deploy/app.zip"&lt;/code&gt;, you say &lt;code&gt;compress the folder I am in and save it to app.zip&lt;/code&gt;. Because &lt;code&gt;plang&lt;/code&gt; takes your intent and converts it to code. Let's continue.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Connecting via SFTP
&lt;/h3&gt;

&lt;p&gt;Next, I connect to the server using SFTP. I’ve set up a private key with a passphrase for secure access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- read file '/events/key', into %sshPrivateKey%
- connect to sftp, 
    host: 185.248.121.67, port: 28781, username: root, 
    private key: %sshPrivateKey%, private key passphrase: %Settings.PrivateKeyPassphrase%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we’re logged into the server, we can start deploying.&lt;/p&gt;

&lt;h3&gt;
  
  
  Uploading and Setting Up
&lt;/h3&gt;

&lt;p&gt;First, let’s upload the zip file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- upload 'deploy/app.zip' through sftp to '/home/plang/app.zip'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, we’ll run a few Linux commands to clean up any previous &lt;code&gt;.build&lt;/code&gt; folder and unzip the new code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- run ssh command, "rm -rf /home/plang/app/.build"
- run ssh command, 'unzip -o /home/plang/app.zip -d /home/plang/app'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Updating the Plang Runtime
&lt;/h3&gt;

&lt;p&gt;For flexibility, I’ve added an option to update the Plang runtime. If I run the script with &lt;code&gt;plang=1&lt;/code&gt;, it triggers the update:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- if %plang% = 1 then SetupPlang
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s create the &lt;code&gt;SetupPlang&lt;/code&gt; goal.&lt;/p&gt;

&lt;h3&gt;
  
  
  The SetupPlang Goal
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;SetupPlang&lt;/code&gt; goal takes care of a few critical steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Downloads the latest version of Plang for Linux.&lt;/li&gt;
&lt;li&gt;Unzips &lt;code&gt;plang.zip&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Sets execution permissions for &lt;code&gt;plang&lt;/code&gt; and &lt;code&gt;selenium-manager&lt;/code&gt; (I use a browser in my app).&lt;/li&gt;
&lt;li&gt;Runs &lt;code&gt;plang --version&lt;/code&gt; to validate the installation and manages any errors (like creating a symlink or installing i18n).&lt;/li&gt;
&lt;li&gt;Restarts the service if it’s running or notifies me if it isn’t installed.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SetupPlang
- run ssh command, 'wget -O /home/plang/plang.zip https://github.com/PLangHQ/plang/releases/latest/download/plang-linux-x64.zip'
- run ssh command, 'unzip -o /home/plang/plang.zip -d /home/plang/plang'
- run ssh command, 'chmod +x /home/plang/plang/plang'
- run ssh command, 'chmod +x /home/plang/plang/selenium-manager/linux/selenium-manager'
- run ssh command, 'plang --version'
    on error message 'No such file or', call CreateSymbolicLink then retry 
    on error message 'command not found', call CreateSymbolicLink then retry 
    on error message contains 'Couldn't find a valid ICU package', call InstallICU then retry
- run ssh command, 'sudo systemctl restart plang', write to %serviceRestart%
    on error message  'plang.service not found', call ServiceNotInstalled ignore error
- write out %serviceRestart%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case of errors, I have additional commands to handle them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CreateSymbolicLink
- write out 'Creating symbolic link'
- run ssh command, 'sudo ln -s /home/plang/plang/plang /usr/local/bin/plang' 
        on error  message contains 'File exists', ignore the error 

InstallICU
- write out 'Installing ICU'
- run ssh command 'sudo dnf install -y libicu'

ServiceNotInstalled
- write out 'Plang service not installed'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, to confirm the Plang runtime is installed, I run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- run ssh command, 'plang --version', write to %plangVersion%
- write out "App updated at %Now% - %plangVersion%"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running and Updating
&lt;/h2&gt;

&lt;p&gt;Before building, you’ll need to set up the &lt;code&gt;SshModule&lt;/code&gt; in your &lt;code&gt;.module&lt;/code&gt; folder. Head over to &lt;a href="https://github.com/PLangHQ/modules/tree/main/SshModule" rel="noopener noreferrer"&gt;SshModule on GitHub&lt;/a&gt;, build the project, and copy the &lt;code&gt;.dll&lt;/code&gt; and &lt;code&gt;.deps&lt;/code&gt; files into your &lt;code&gt;.module&lt;/code&gt; folder (if you don’t have one yet, just create it).&lt;/p&gt;

&lt;p&gt;Once the code is ready, I build it:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;And then, to deploy both the app and Plang runtime, I run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;plang Deploy &lt;span class="nv"&gt;plang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I only need to update the app, I just execute:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Here’s an example of the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App updated at 29.10.2024 10:57:05 - plang version: 0.15.3.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Full Code for Reference
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Deploy
- zip "./" to "deploy/app.zip", exclude ".db", "*.sqlite", overwrite file
- read file '/events/key', into %sshPrivateKey%
- connect to sftp, 
    host: myhost.server.com, port: 22, username: root, 
    private key: %sshPrivateKey%, private key passphrase: %Settings.PrivateKeyPassphrase%
- upload 'deploy/app.zip' through sftp to '/home/plang/app.zip'
- run ssh command, "rm -rf /home/plang/app/.build"
- run ssh command, 'unzip -o /home/plang/app.zip -d /home/plang/app'
- if %plang% = 1 then SetupPlang
- run ssh command, 'plang --version', write to %plangVersion%
- write out "App updated at %Now% - %plangVersion%"

SetupPlang
- run ssh command, 'wget -O /home/plang/plang.zip https://github.com/PLangHQ/plang/releases/latest/download/plang-linux-x64.zip'
- run ssh command, 'unzip -o /home/plang/plang.zip -d /home/plang/plang'
- run ssh command, 'chmod +x /home/plang/plang/plang'
- run ssh command, 'chmod +x /home/plang/plang/selenium-manager/linux/selenium-manager'
- run ssh command, 'plang --version'
    on error message 'No such file or', call CreateSymbolicLink then retry 
    on error message 'command not found', call CreateSymbolicLink then retry 
    on error message contains 'Couldn't find a valid ICU package', call InstallICU then retry
- run ssh command, 'sudo systemctl restart plang', write to %serviceRestart%
    on error message  'plang.service not found', call ServiceNotInstalled ignore error
- write out %serviceRestart%    

CreateSymbolicLink
- write out 'Creating symbolic link'
- run ssh command, 'sudo ln -s /home/plang/plang/plang /usr/local/bin/plang' 
        on error  message contains 'File exists', ignore the error 

InstallICU
- write out 'Installing ICU'
- run ssh command 'sudo dnf install -y libicu'

ServiceNotInstalled
- write out 'Plang service not installed'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using Plang in system administration is a real timesaver, making deployment as efficient and straightforward as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits
&lt;/h2&gt;

&lt;p&gt;Using Plang for deployment keeps things simple and readable, cutting down on complexity while making it easier to manage. With Plang’s clear, natural syntax, I can lay out each deployment step almost as if I’m writing in plain language, which makes everything easy to follow and adjust when needed. The modular setup lets me break tasks down, making it easier to tweak specific steps and handle errors. Plang’s built-in retry and error-handling functions add stability, catching issues automatically when they come up. &lt;/p&gt;

&lt;p&gt;With flexible variable management, Plang also lets me store command outputs for later use, which is super handy for connecting steps and external systems. Plus, if I need to keep track of metadata or deployment logs, Plang’s built-in database support has that covered without any extra setup. Overall, Plang simplifies deployment scripts with smart, high-level abstractions, trimming down the code compared to traditional scripting languages and saving me serious development time.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Information
&lt;/h2&gt;

&lt;p&gt;Interested in learning more about Plang? Here are some useful resources to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%202.md" rel="noopener noreferrer"&gt;Basic Concepts and Lessons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/Todo_webservice.md" rel="noopener noreferrer"&gt;Todo Example&lt;/a&gt; to build a simple web service&lt;/li&gt;
&lt;li&gt;Explore the &lt;a href="https://github.com/PLangHQ/" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; for source code&lt;/li&gt;
&lt;li&gt;Join our &lt;a href="https://discord.gg/A8kYUymsDD" rel="noopener noreferrer"&gt;Discord Community&lt;/a&gt; for discussions and support&lt;/li&gt;
&lt;li&gt;Or chat with the &lt;a href="https://chatgpt.com/g/g-Av6oopRtu-plang-help-code-generator" rel="noopener noreferrer"&gt;Plang Assistant&lt;/a&gt; to get help with code generation&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>plang</category>
      <category>automation</category>
    </item>
    <item>
      <title>In Theory: Interoperability</title>
      <dc:creator>Ingi</dc:creator>
      <pubDate>Fri, 11 Oct 2024 15:17:37 +0000</pubDate>
      <link>https://forem.com/ingigauti/in-theory-interoperability-2d3e</link>
      <guid>https://forem.com/ingigauti/in-theory-interoperability-2d3e</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post dives into Plang, an intent-based programming language that interprets natural language. For more, visit &lt;a href="https://plang.is" rel="noopener noreferrer"&gt;plang.is&lt;/a&gt; or &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%201.md" rel="noopener noreferrer"&gt;get started here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;"Interoperability" sounds like a big word, but it's really just a fancy way of saying you can move data from one system to another, without a ton of hassle.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge of Moving Data
&lt;/h2&gt;

&lt;p&gt;Back in the early days of software, getting data from one system into another was next to impossible. Each app had its own format, and if you wanted to pull out information, you'd need to know the ins and outs of that system—something only the developers or a few elite hackers could figure out.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Progress We've Made
&lt;/h2&gt;

&lt;p&gt;Fast forward to today, and things have gotten a lot better. We now have standards like JSON, REST APIs, XML, and SQL databases that make it easier to transfer data between systems. These technologies give us the raw data we need to get info from one platform and put it into another.&lt;/p&gt;

&lt;p&gt;But here’s the catch: this only works if you can actually access the raw data. Even now, you still need someone with technical expertise to pull the data out of one system and load it into another. It’s not like these systems are just going to talk to each other by themselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Behind Closed Doors
&lt;/h2&gt;

&lt;p&gt;Things get a lot trickier when the data you need is locked behind some kind of barrier—like inside a desktop application or hidden away on a website. In those cases, extracting the data can be really hard. So, what do we do? We use people. Humans have to open the website, search for the data, and manually copy it over.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Data Locked in Our Heads
&lt;/h2&gt;

&lt;p&gt;And then there’s the trickiest type of data: what’s locked inside our own brains. People carry knowledge around with them that’s essential for decision-making, but trying to get that knowledge out is tough. Only recently has technology advanced enough to listen to someone speaking into a mic and transcribe their words.&lt;/p&gt;

&lt;h2&gt;
  
  
  An Impossible Problem?
&lt;/h2&gt;

&lt;p&gt;I came across this quote in &lt;a href="https://hardcoresoftware.learningbyshipping.com/p/222-automating-processes-with-software" rel="noopener noreferrer"&gt;an article on automation&lt;/a&gt; that stuck with me:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"No amount of software is going to get you out of there because it is piecing together a bunch of inputs and outputs that are outside the bounds of a system."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The part about "outside the bounds of a system" really hit home. It’s true—no matter how good your software is, there’s always going to be some website or desktop app with data hidden away, or a phone call from a customer that throws everything off. You just can’t build software to handle every single piece of data, everywhere it exists. It seems impossible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Or Is It?
&lt;/h2&gt;

&lt;p&gt;Let’s explore this idea with a bit of code in Plang. Imagine a scenario where:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You get info from a customer by voice.&lt;/li&gt;
&lt;li&gt;You pull their data from an API.&lt;/li&gt;
&lt;li&gt;You log into a government website to fetch more details.&lt;/li&gt;
&lt;li&gt;You open a desktop app to grab additional info.&lt;/li&gt;
&lt;li&gt;Then you combine all this into a single response for the user.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s how you might do that in Plang:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Start
- use 'input' as audio
- use 'output' as audio
- ask "Please tell me your SSN", write to %audio%
- convert %audio% to text, write to %user%
- [llm] system: analyze the input, figure out his SSN
        user: %user%
        scheme: {ssn:string}
- call goal GetUserInfo
- call goal BrowseGovernment
- call goal OpenDesktopApp
- call goal StoreInfo
- call RespondToUser

GetUserInfo
- get http://myinternal.webservice/?ssn=%ssn%, write to %userInfo%

BrowseGovernment
- go to https://goverment.org
- set #username = %Settings.Username%
- set #password = %Settings.Password%
- click #login
- go to https://goverment.org/user/%ssn%
- extract #medicalInfo into %medicalInfo%
- extract #visionInfo into %visionInfo%

OpenDesktopApp
- run myapp.exe, maximize and focus
- click on 1200, 300 / put focus on input box
- type in %ssn%
- click on 1200, 500 / click the search button
- take screenshot, save to file/screenshot.jpg
- [llm] system: analyze the screenshot and give me the text
        user: file/screenshot.jpg
        scheme: { userGlasses: string, userStrength: string }

StoreInfo
- insert into user, %ssn%, %userInfo%, %medicalInfo%, %visionInfo%, %userGlasses%, %userStrength%

RespondToUser
- [llm] system: create a response to user from data
        user: %userInfo%, %medicalInfo%, %visionInfo%, %userGlasses%, %userStrength%
        write to %response%
- convert %response% to audio, write to %audioResponse%
- write out %audioResponse%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In just over 40 lines of code, we’ve pulled data from four very different sources: a voice input, an API, a website, and a desktop application. We’ve brought all that data together in one place to give a single response to the user.&lt;/p&gt;

&lt;p&gt;Now, let’s dive into what each piece of the code does next…&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Go Over the Code
&lt;/h2&gt;

&lt;p&gt;Let's break down what each part of the Plang code does:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- use 'input' as audio, from default mic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We start by changing the default input. Normally, Plang takes input from the terminal, but here, we're telling it to use the microphone for audio input. This allows us to capture what the user says.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- use 'output' as audio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly, we're switching the output to audio. Instead of outputting text to a screen, the program will convert text into an audio stream, which will be played back to the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- ask "Please tell me your SSN", write to %audio%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line sends a spoken request to the user, asking for their SSN. The user's response is captured as audio and stored in the &lt;code&gt;%audio%&lt;/code&gt; variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- convert %audio% to text, write to %user%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we have the user's spoken response, we convert the audio to text and store it in the &lt;code&gt;%user%&lt;/code&gt; variable so that we can process it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- [llm] system: analyze the input, figure out his SSN
        user: %user%
        scheme: {ssn:string}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we ask a large language model (LLM) to analyze the user’s text input to extract the SSN. The result is stored in the &lt;code&gt;%ssn%&lt;/code&gt; variable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is written as if everything goes perfectly. In reality, you'd need error handling for cases where the user gives invalid input or doesn't follow the expected format.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- call goal GetUserInfo
- call goal BrowseGovernment
- call goal OpenDesktopApp
- call goal StoreInfo
- call RespondToUser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then call a series of predefined "goals" that perform various tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GetUserInfo&lt;/code&gt; fetches customer data from an internal REST API.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BrowseGovernment&lt;/code&gt; logs into a government website to retrieve data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OpenDesktopApp&lt;/code&gt; interacts with a desktop app to pull more info.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;StoreInfo&lt;/code&gt; saves all the collected data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RespondToUser&lt;/code&gt; gives a response back to the user.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GetUserInfo
&lt;/h3&gt;

&lt;p&gt;This is a straightforward REST API call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- get http://myinternal.webservice/?ssn=%ssn%, write to %userInfo%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We query an internal web service using the SSN as the parameter and store the returned user information in the &lt;code&gt;%userInfo%&lt;/code&gt; variable.&lt;/p&gt;

&lt;h3&gt;
  
  
  BrowseGovernment
&lt;/h3&gt;

&lt;p&gt;This section automates logging into a government website and pulling specific data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- go to https://goverment.org
- set #username = %Settings.Username%
- set #password = %Settings.Password%
- click #login
- go to https://goverment.org/user/%ssn%
- extract #medicalInfo into %medicalInfo%
- extract #visionInfo into %visionInfo%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We navigate to the government website, input login credentials stored in the &lt;code&gt;Settings&lt;/code&gt;, and then log in. Once logged in, we navigate to a page containing the user’s info based on their SSN. We then extract the medical and vision data, saving them into &lt;code&gt;%medicalInfo%&lt;/code&gt; and &lt;code&gt;%visionInfo%&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenDesktopApp
&lt;/h3&gt;

&lt;p&gt;Interacting with desktop apps is a bit trickier, so we simulate mouse movements and clicks by using pixel coordinates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- run myapp.exe, maximize and focus
- click on 1200, 300 / put focus on input box
- type in %ssn%
- click on 1200, 500 / click the search button
- take screenshot, save to file/screenshot.jpg
- [llm] system: analyze the screenshot and give me the text
        user: file/screenshot.jpg
        scheme: { userGlasses: string, userStrength: string }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We launch the desktop app &lt;code&gt;myapp.exe&lt;/code&gt;, maximize the window, and focus on it. Then we simulate clicking at specific coordinates to place the cursor in the input box and enter the SSN. After clicking "Search," we take a screenshot of the results.&lt;/p&gt;

&lt;p&gt;Since we can’t directly extract the data from a desktop app, we upload the screenshot to the LLM, which performs optical character recognition (OCR) to analyze the text in the image. This gives us the variables &lt;code&gt;%userGlasses%&lt;/code&gt; and &lt;code&gt;%userStrength%&lt;/code&gt;, which hold the extracted data.&lt;/p&gt;

&lt;h3&gt;
  
  
  StoreInfo
&lt;/h3&gt;

&lt;p&gt;Now that we've gathered all the information, we store it in a database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;StoreInfo
- insert into user, %ssn%, %userInfo%, %medicalInfo%, %visionInfo%, %userGlasses%, %userStrength%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we insert the SSN, user info, medical data, vision data, and any additional information (like the user's glasses prescription and strength) into the user database.&lt;/p&gt;

&lt;h3&gt;
  
  
  RespondToUser
&lt;/h3&gt;

&lt;p&gt;Finally, we respond to the user by creating a custom response based on the data we’ve collected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RespondToUser
- [llm] system: create a response to user from data
        user: %userInfo%, %medicalInfo%, %visionInfo%, %userGlasses%, %userStrength%
        write to %response%
- convert %response% to audio, write to %audioResponse%
- write out %audioResponse%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We ask the LLM to generate a response that summarizes all the information we've gathered. The LLM crafts the message using the &lt;code&gt;%userInfo%&lt;/code&gt;, &lt;code&gt;%medicalInfo%&lt;/code&gt;, &lt;code&gt;%visionInfo%&lt;/code&gt;, and other data. Once the response is created, we convert it to audio and play it back to the user.&lt;/p&gt;

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

&lt;p&gt;This entire flow—from gathering audio input to pulling data from various sources and returning a spoken response—happens in around 40 lines of code, demonstrating how powerful interoperability using plang can be.&lt;/p&gt;

&lt;p&gt;The title of this article is "In Theory: Interoperability" because, in reality, you can't do all this in Plang today. &lt;/p&gt;

&lt;p&gt;What’s missing is the ability to listen to a user, convert their audio to text, and automate desktop interaction. These pieces just need to be built—there are no real technical barriers. Once those modules are in place, the code you see above should work just fine.&lt;/p&gt;

&lt;p&gt;You then of course have all the exceptions to handle, errors, when do you know when user has stopped speaking and so on. &lt;/p&gt;

&lt;h2&gt;
  
  
  More Information
&lt;/h2&gt;

&lt;p&gt;Interested in learning more about Plang? Here are some useful resources to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%202.md" rel="noopener noreferrer"&gt;Basic Concepts and Lessons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/Todo_webservice.md" rel="noopener noreferrer"&gt;Todo Example&lt;/a&gt; to build a simple web service&lt;/li&gt;
&lt;li&gt;Explore the &lt;a href="https://github.com/PLangHQ/" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; for source code&lt;/li&gt;
&lt;li&gt;Join our &lt;a href="https://discord.gg/A8kYUymsDD" rel="noopener noreferrer"&gt;Discord Community&lt;/a&gt; for discussions and support&lt;/li&gt;
&lt;li&gt;Or chat with the &lt;a href="https://chatgpt.com/g/g-Av6oopRtu-plang-help-code-generator" rel="noopener noreferrer"&gt;Plang Assistant&lt;/a&gt; to get help with code generation&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>plang</category>
      <category>data</category>
      <category>interoperability</category>
    </item>
    <item>
      <title>Introduction to Plang: Master Coding Quickly and Easily!</title>
      <dc:creator>Ingi</dc:creator>
      <pubDate>Thu, 03 Oct 2024 18:51:17 +0000</pubDate>
      <link>https://forem.com/ingigauti/introduction-to-plang-master-coding-quickly-and-easily-4mp4</link>
      <guid>https://forem.com/ingigauti/introduction-to-plang-master-coding-quickly-and-easily-4mp4</guid>
      <description>&lt;h2&gt;
  
  
  What is Plang?
&lt;/h2&gt;

&lt;p&gt;Imagine telling a computer what to do as easily as giving instructions to a friend. That’s exactly what &lt;strong&gt;Plang&lt;/strong&gt; allows you to do! With Plang, you can write out tasks in simple steps, and the computer follows your instructions without the need for complicated coding. Just use plain language to command the computer!&lt;/p&gt;

&lt;p&gt;Ready to dive into a fun project that’ll get you hooked on programming? Let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Prepare to Write Your First Program
&lt;/h2&gt;

&lt;p&gt;Before we begin coding in &lt;strong&gt;Plang&lt;/strong&gt;, you'll need to install it on your computer. But don’t worry, it’s a breeze! Just follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Download Plang:&lt;/strong&gt; Head to &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/Install.md" rel="noopener noreferrer"&gt;Plang's GitHub page&lt;/a&gt; and follow the simple installation guide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a Project Folder:&lt;/strong&gt; Set up a folder on your computer for all your Plang programs. Give it a fun name like "MyFirstPlang."&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 2: Writing Your First Program
&lt;/h2&gt;

&lt;p&gt;Let’s start by creating a program that asks for your name and age, and then responds with a message. You’ll save this in a file called &lt;strong&gt;Start.goal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here’s what the code looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Start
- ask "What is your name?", write to %name%
- ask "How old are you?", write to %age%
- write out "Hello, %name%! You are %age% years old."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What does this code do?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;First, the program &lt;strong&gt;asks&lt;/strong&gt; for your name and age.&lt;/li&gt;
&lt;li&gt;Then, it &lt;strong&gt;prints&lt;/strong&gt; a message like: "Hello, Alex! You are 10 years old."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s that simple! When you run the program, the computer will interact with you and display the answers you provide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Saving and Running Your Program
&lt;/h2&gt;

&lt;p&gt;Now let’s run your program:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Save your file&lt;/strong&gt; as &lt;code&gt;Start.goal&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open your terminal (or command prompt)&lt;/strong&gt; and navigate to your project folder.&lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;plang build&lt;/code&gt; to build your program.&lt;/li&gt;
&lt;li&gt;Run it by typing &lt;code&gt;plang&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once you do this, the program will ask for your name and age, and display the message you’ve written.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Interacting with Files
&lt;/h2&gt;

&lt;p&gt;What if you want the program to interact with a file, like updating today’s date in a document? Let’s see how that works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Start
- read file 'diary.txt', into %content%
- set %content% = "Hello diary"
- save %content% to 'diary.txt', overwrite file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reads&lt;/strong&gt; a file called &lt;code&gt;diary.txt&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adds 'Hello diary'&lt;/strong&gt; to the content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Saves&lt;/strong&gt; the updated content back to the file.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 5: Build a To-Do List App
&lt;/h2&gt;

&lt;p&gt;Let’s create something useful: a simple To-Do list app!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Set up a database&lt;/strong&gt; for your tasks:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Setup
- create table tasks, columns: task(string, not null), due_date(datetime)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Now let’s &lt;strong&gt;add tasks&lt;/strong&gt; and &lt;strong&gt;display them&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Start
- insert into tasks, task='Do homework', due_date=%Now+2hours%
- insert into tasks, task='Feed the dog', due_date=%Now+30minutes%
- select * from tasks, write to %allTasks%
- write out %allTasks%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run this, the program will save tasks like "Do homework" and "Feed the dog" and display them on the screen. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Connecting Your Program to the Web
&lt;/h2&gt;

&lt;p&gt;Let’s make things more interesting by getting data from the internet! Here’s an example that pulls posts from a website:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Start
- get https://jsonplaceholder.typicode.com/posts, write to %posts%
- write out %posts%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will grab &lt;strong&gt;posts&lt;/strong&gt; from the web and &lt;strong&gt;display&lt;/strong&gt; them in your program, making it feel like a mini web browser!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Understanding Goals and Steps
&lt;/h2&gt;

&lt;p&gt;In Plang, everything revolves around &lt;strong&gt;goals&lt;/strong&gt; and &lt;strong&gt;steps&lt;/strong&gt;. A &lt;strong&gt;goal&lt;/strong&gt; is like the main task you want to accomplish, and the &lt;strong&gt;steps&lt;/strong&gt; are the smaller actions needed to achieve it. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Goal: "Create a task."&lt;/li&gt;
&lt;li&gt;Steps: "Ask for task name, ask for due date, save task to list."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s like following a recipe, breaking things down into clear instructions that are easy to follow.&lt;/p&gt;

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

&lt;p&gt;With &lt;strong&gt;Plang&lt;/strong&gt;, programming becomes simple, fun, and approachable. By breaking tasks down into clear steps, you can accomplish a lot without needing to learn complex commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create your own project:&lt;/strong&gt; Maybe a program to track your favorite games or books!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explore Plang’s capabilities:&lt;/strong&gt; Try adding more functionality, like &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/modules/PLang.Modules.MessageModule.md" rel="noopener noreferrer"&gt;sending a message&lt;/a&gt; or &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/modules/PLang.Modules.ScheduleModule.md" rel="noopener noreferrer"&gt;setting reminders&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share your project:&lt;/strong&gt; Show your friends how easy and exciting coding can be!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Questions to Think About:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What other projects could you build using Plang’s goals and steps?&lt;/li&gt;
&lt;li&gt;How could you expand your &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/Todo_webservice.md" rel="noopener noreferrer"&gt;To-Do list app&lt;/a&gt;, like adding task deletion or reminders?&lt;/li&gt;
&lt;li&gt;Can you write a program that helps you with daily tasks like homework or scheduling?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  More Information
&lt;/h2&gt;

&lt;p&gt;Interested in learning more about Plang? Here are some useful resources to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%202.md" rel="noopener noreferrer"&gt;Basic Concepts and Lessons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/Todo_webservice.md" rel="noopener noreferrer"&gt;Todo Example&lt;/a&gt; to build a simple web service&lt;/li&gt;
&lt;li&gt;Explore the &lt;a href="https://github.com/PLangHQ/" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; for source code&lt;/li&gt;
&lt;li&gt;Join our &lt;a href="https://discord.gg/A8kYUymsDD" rel="noopener noreferrer"&gt;Discord Community&lt;/a&gt; for discussions and support&lt;/li&gt;
&lt;li&gt;Or chat with the &lt;a href="https://chatgpt.com/g/g-Av6oopRtu-plang-help-code-generator" rel="noopener noreferrer"&gt;Plang Assistant&lt;/a&gt; to get help with code generation&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>plang</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>In Theory: Automatic Unit Testing with Plang</title>
      <dc:creator>Ingi</dc:creator>
      <pubDate>Mon, 16 Sep 2024 09:14:41 +0000</pubDate>
      <link>https://forem.com/ingigauti/in-theory-automatic-unit-testing-with-plang-cek</link>
      <guid>https://forem.com/ingigauti/in-theory-automatic-unit-testing-with-plang-cek</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post dives into Plang, an intent-based programming language that interprets natural language. For more, visit &lt;a href="https://plang.is" rel="noopener noreferrer"&gt;plang.is&lt;/a&gt; or &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%201.md" rel="noopener noreferrer"&gt;get started here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Plang, you can bind events to goals and steps, which opens up a fascinating possibility for automatic testing. Let's walk through an example, starting with something simple: adding two numbers.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Simple Example: Adding Two Numbers
&lt;/h3&gt;

&lt;p&gt;Here’s a basic code snippet in Plang:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AddTwoNumbers
- %num1% + %num2%, write to %sum%
- write out %sum%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To build automatic unit tests, let's first think about the usual process of testing logic manually. Without automation, you’d run something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;plang &lt;span class="nv"&gt;num1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nv"&gt;num2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would output:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Automating the Process
&lt;/h3&gt;

&lt;p&gt;Because Plang lets us bind events to steps, we can automate this process. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Events
- before each step, call PrepareUnitTest
- after each step, call MakeUnitTest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s how it works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;PrepareUnitTest&lt;/code&gt; goal stores the variables in the current step.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;MakeUnitTest&lt;/code&gt; goal captures the output, like the value of &lt;code&gt;%sum%&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once that’s in place, we can even ask the &lt;a href="https://chatgpt.com/share/66e7f108-4690-8003-ac91-7d4f99a50da7" rel="noopener noreferrer"&gt;LLM to generate unit tests&lt;/a&gt; for us. This results in a JSON file with the relevant test values.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Developer’s Interface
&lt;/h3&gt;

&lt;p&gt;At this point, a developer would likely need a simple interface—a GUI—to tweak those values, add new tests, or remove unnecessary ones. Each module would define its own rules for unit testing, especially for handling I/O operations like HTTP requests, which would require special considerations.&lt;/p&gt;

&lt;p&gt;With this setup, automatic testing becomes a streamlined part of the development process, enhancing efficiency and reliability in Plang projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Theory
&lt;/h2&gt;

&lt;p&gt;This post is titled &lt;code&gt;In Theory&lt;/code&gt; because, at this point, automatic unit testing with Plang is just that—a theory. It hasn’t been implemented or tested yet, but there’s no reason it couldn’t be. The concept is sound; it’s just a matter of engineering time.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Information
&lt;/h2&gt;

&lt;p&gt;Interested in learning more about Plang? Here are some useful resources to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%202.md" rel="noopener noreferrer"&gt;Basic Concepts and Lessons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/Todo_webservice.md" rel="noopener noreferrer"&gt;Todo Example&lt;/a&gt; to build a simple web service&lt;/li&gt;
&lt;li&gt;Explore the &lt;a href="https://github.com/PLangHQ/" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; for source code&lt;/li&gt;
&lt;li&gt;Join our &lt;a href="https://discord.gg/A8kYUymsDD" rel="noopener noreferrer"&gt;Discord Community&lt;/a&gt; for discussions and support&lt;/li&gt;
&lt;li&gt;Or chat with the &lt;a href="https://chatgpt.com/g/g-Av6oopRtu-plang-help-code-generator" rel="noopener noreferrer"&gt;Plang Assistant&lt;/a&gt; to get help with code generation&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>plang</category>
      <category>programming</category>
      <category>testing</category>
    </item>
    <item>
      <title>I love how clean Plang is</title>
      <dc:creator>Ingi</dc:creator>
      <pubDate>Mon, 09 Sep 2024 10:34:47 +0000</pubDate>
      <link>https://forem.com/ingigauti/i-love-how-clean-plang-is-59ob</link>
      <guid>https://forem.com/ingigauti/i-love-how-clean-plang-is-59ob</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article explores Plang, an intent-based programming language designed to interpret natural language. For more information, visit &lt;a href="https://plang.is" rel="noopener noreferrer"&gt;plang.is&lt;/a&gt; or &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%201.md" rel="noopener noreferrer"&gt;take your first steps&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I am creating an app. It's a great way to develop the language. If it's not supported and I feel like it works, I will implement it&lt;/p&gt;

&lt;p&gt;So I am setting up monitoring on variables in GUI. React style.&lt;/p&gt;

&lt;p&gt;It goes like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Start
- monitor %number1%, %number2%, call Calculate
/ more code

Calculate
- set %number1% + %number2%, as %sum%
- set #sum = %sum% / we are setting(updating) the GUI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So in few lines you are monitoring the variables. Amazing. Plang still blows my mind.&lt;/p&gt;

&lt;p&gt;Now I have this project, and I know I am monitoring somewhere variables, so I search for it.&lt;/p&gt;

&lt;p&gt;And the results, 3, that is it. And it's clean&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgju4h7qzoz9ckct9ghr2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgju4h7qzoz9ckct9ghr2.png" alt="Search results for  raw `monitor` endraw " width="313" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I just liked that.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>plang</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>In Theory: Self-Correcting Software - Part 2</title>
      <dc:creator>Ingi</dc:creator>
      <pubDate>Sat, 07 Sep 2024 15:32:09 +0000</pubDate>
      <link>https://forem.com/ingigauti/in-theory-self-correcting-software-part-2-5gc2</link>
      <guid>https://forem.com/ingigauti/in-theory-self-correcting-software-part-2-5gc2</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article explores Plang, an intent-based programming language designed to interpret natural language. For more information, visit &lt;a href="https://plang.is" rel="noopener noreferrer"&gt;plang.is&lt;/a&gt; or &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%201.md" rel="noopener noreferrer"&gt;take your first steps&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In a &lt;a href="https://dev.to/ingigauti/in-theory-self-correcting-software-16bh"&gt;previous article on self-correcting software&lt;/a&gt;, I demonstrated how Plang code can self-correct. It was a simple proof of concept, but let's dive deeper into how this works.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Plang Works
&lt;/h3&gt;

&lt;p&gt;Plang compiles into JSON files—essentially instructions—that are saved into a &lt;code&gt;.pr&lt;/code&gt; file. This &lt;code&gt;.pr&lt;/code&gt; file tells the Plang runtime how to execute your code. Keep this &lt;code&gt;.pr&lt;/code&gt; file in mind as it plays a crucial role in what follows.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example of a Basic Instruction:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- read file.txt to %content%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would generate a JSON instruction like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ModuleType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"FileModule"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"FunctionName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ReadTextFile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"file.txt"&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Plang runtime will load the appropriate &lt;a href="https://github.com/PLangHQ/plang/tree/main/Documentation/modules#file" rel="noopener noreferrer"&gt;FileModule&lt;/a&gt;, and if you examine the &lt;a href="https://github.com/PLangHQ/plang/blob/main/PLang/Modules/FileModule/Program.cs" rel="noopener noreferrer"&gt;Program.cs&lt;/a&gt; file, you'll find a method called &lt;code&gt;ReadTextFile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is where Plang is currently at, in version 0.1.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Challenge: Refactoring and Compatibility
&lt;/h3&gt;

&lt;p&gt;Now, imagine we want to refactor the method name from &lt;code&gt;ReadTextFile&lt;/code&gt; to &lt;code&gt;ReadContentOfTextFile&lt;/code&gt; in the &lt;a href="https://github.com/PLangHQ/plang/blob/main/PLang/Modules/FileModule/Program.cs" rel="noopener noreferrer"&gt;Program.cs&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Any Plang code that uses the old method name(&lt;code&gt;ReadTextFile&lt;/code&gt;) will break and throw an error like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error:
    Message: Method 'ReadTextFile' could not be found. 'ReadTextFile' is defined in your instruction file
    Key: MissingMethod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;a href="https://dev.to/ingigauti/in-theory-self-correcting-software-16bh"&gt;previous article&lt;/a&gt;, I showed how Plang can bind events to goals (functions) or steps (lines of code). We’ll use this feature to handle method refactoring gracefully.&lt;/p&gt;

&lt;h3&gt;
  
  
  Self-Correcting Code in Action
&lt;/h3&gt;

&lt;p&gt;We start by creating an event listener that catches this specific error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Events
- on any error where key="MissingMethod", call FixCode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 1: Collect Available Methods
&lt;/h4&gt;

&lt;p&gt;First create &lt;code&gt;FixCode.goal&lt;/code&gt; and give it the title&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Next, we want to resolve the &lt;code&gt;MissingMethod&lt;/code&gt; error by finding the updated method in the &lt;code&gt;FileModule&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We need to gather all available methods in &lt;code&gt;FileModule&lt;/code&gt;. We can access what module caused the error from the &lt;code&gt;%!step.ModuleType%&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- get all available methods in %!step.ModuleType%, write to %methods%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;ProTip: In Plang, the &lt;code&gt;%!step%&lt;/code&gt; variable always contains the current step running, including its &lt;code&gt;ModuleType&lt;/code&gt;, which points to the &lt;code&gt;FileModule&lt;/code&gt;. If you want to know what properties are in &lt;code&gt;%!step%&lt;/code&gt;, just write it out &lt;code&gt;- write out %!step%&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This will include methods like &lt;code&gt;ReadContentOfTextFile&lt;/code&gt;. Here's an example of what it might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"public async Task&amp;lt;string&amp;gt; ReadContentOfTextFile(string path, string returnValueIfFileNotExisting = '', bool throwErrorOnNotFound = false, bool loadVariables = false, bool emptyVariableIfNotFound = false, string encoding = 'utf-8')"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Read the content from a file. Formerly ReadTextFile"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"public async Task WriteToFile(string path, string content, bool overwrite = false, bool loadVariables = false, bool emptyVariableIfNotFound = false, string encoding = 'utf-8')"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Write content to a file"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 2: Read the Failing Instruction
&lt;/h4&gt;

&lt;p&gt;Next, we read the instruction &lt;code&gt;.pr&lt;/code&gt; file for the step that triggered the error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- read %!step.AbsolutePrPath%, into %instructions%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;AbsolutePrPath&lt;/code&gt; is a property of the &lt;code&gt;%!step%&lt;/code&gt; variable that points to the location of the &lt;code&gt;.pr&lt;/code&gt; file on your hard drive&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3: Call the LLM to Fix the Code
&lt;/h4&gt;

&lt;p&gt;We can now pass the problem to a language model (LLM) to update the method name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- [llm] system: The user is attempting to execute code, but the method was not found, possibly due to renaming.
              These are the instructions to call the C# code: %instructions%
              These are the available methods: %methods%
              Rewrite the instructions
      user: %!error.Message%
      scheme: {instructions:string}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this input, the &lt;a href="https://chatgpt.com/share/c97dde36-ab86-4fba-a406-6d2964a5ad33" rel="noopener noreferrer"&gt;LLM can generate the corrected code&lt;/a&gt; and return it in the &lt;code&gt;%instructions%&lt;/code&gt; variable.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4: Write the Corrected Code
&lt;/h4&gt;

&lt;p&gt;Finally, we overwrite the &lt;code&gt;.pr&lt;/code&gt; file with the corrected code and re-execute the step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- write %instructions% to %!step.AbsolutePrPath%
- retry step
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Final Solution:
&lt;/h3&gt;

&lt;p&gt;The complete self-correcting code looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FixCode
- get all available methods in %!error.ModuleType%, write to %methods%
- read %!step.AbsolutePrPath%, into %instructions%
- [llm] system: The user is attempting to execute code, but the method was not found, possibly due to renaming.
              These are the instructions to call the C# code: %instructions%
              These are the available methods: %methods%
              Rewrite the instructions
      user: %!error.Message%
      scheme: {instructions:string}
- write %instructions% to %!step.AbsolutePrPath%
- retry step
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  In-Theory Article
&lt;/h3&gt;

&lt;p&gt;This is still theoretical—these modules aren't yet available in Plang, and some features like &lt;code&gt;retry step&lt;/code&gt; and &lt;code&gt;get all available methods&lt;/code&gt; aren't implemented. But once the language matures, this will work. &lt;/p&gt;

&lt;p&gt;So why haven’t I implemented this yet? Well, Plang is evolving fast, and there are a thousand things to work on. But I wanted to outline this approach first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Plang's Upgrade Path
&lt;/h3&gt;

&lt;p&gt;This opens up a fascinating upgrade path for Plang. Since Plang is still in its early stages, breaking changes are common. This approach would allow upgrades to happen almost automatically, minimizing the need for manual fixes.&lt;/p&gt;

&lt;p&gt;Of course, there's still a lot of engineering ahead, but the conceptual problem is solved.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extending Plang with Modules
&lt;/h3&gt;

&lt;p&gt;It's easy to extend Plang using modules. For example, to interact with Google Drive, you could install the &lt;a href="https://github.com/PLangHQ/modules/tree/main/Google.Drive" rel="noopener noreferrer"&gt;Google.Drive module&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Start
- get list of all my files in "tAff2u44jU2nZgpJkbY5mSwW3" on Google Drive, %files%
- write out "List of all files: %files%"
- go through %files%, call ProcessFile

ProcessFile
- download file from Google Drive, fileId=%item.id%, save it to file/%item.name%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine the module developer updates the API and renames methods. Thanks to our self-correcting system, your code would still work without any changes on your end.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Word of Caution
&lt;/h3&gt;

&lt;p&gt;As programmers, we’re naturally skeptical about automated fixes happening without confirmation. This is where unit tests come into play. But that’s a topic for another article.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Information
&lt;/h2&gt;

&lt;p&gt;Interested in learning more about Plang? Here are some useful resources to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%202.md" rel="noopener noreferrer"&gt;Basic Concepts and Lessons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/Todo_webservice.md" rel="noopener noreferrer"&gt;Todo Example&lt;/a&gt; to build a simple web service&lt;/li&gt;
&lt;li&gt;Explore the &lt;a href="https://github.com/PLangHQ/" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; for source code&lt;/li&gt;
&lt;li&gt;Join our &lt;a href="https://discord.gg/A8kYUymsDD" rel="noopener noreferrer"&gt;Discord Community&lt;/a&gt; for discussions and support&lt;/li&gt;
&lt;li&gt;Or chat with the &lt;a href="https://chatgpt.com/g/g-Av6oopRtu-plang-help-code-generator" rel="noopener noreferrer"&gt;Plang Assistant&lt;/a&gt; to get help with code generation&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>eventdriven</category>
      <category>ai</category>
      <category>programming</category>
      <category>refactoring</category>
    </item>
    <item>
      <title>Translating with Ease: Automating Translations with Plang</title>
      <dc:creator>Ingi</dc:creator>
      <pubDate>Tue, 03 Sep 2024 15:00:45 +0000</pubDate>
      <link>https://forem.com/ingigauti/translating-with-ease-automating-translations-with-plang-3jbj</link>
      <guid>https://forem.com/ingigauti/translating-with-ease-automating-translations-with-plang-3jbj</guid>
      <description>&lt;p&gt;So, I recently had a client setting up a new website, and everything was written in English. The catch? They needed to translate it all into Icelandic. The developers handed over an Excel file with about 350 keywords to translate. Not a massive task, but still enough to be a bit of a time sink if done manually.&lt;/p&gt;

&lt;p&gt;Here's a peek at how the Excel file looked:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh2nfis39umr5esbji5ua.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh2nfis39umr5esbji5ua.png" alt="Translations" width="800" height="111"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of slogging through it by hand, I figured I'd try out Plang to see if I could streamline the process and save everyone some time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;If you like to try this, then &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/Install.md" rel="noopener noreferrer"&gt;install Plang&lt;/a&gt; and get a &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%202.md" rel="noopener noreferrer"&gt;basic understanding&lt;/a&gt; of how Plang works&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;First off, setting things up is a breeze. Just create a &lt;code&gt;Translate.goal&lt;/code&gt; file and open it in your favorite text editor.&lt;/p&gt;

&lt;p&gt;Kick things off with the line:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reading the Excel File
&lt;/h2&gt;

&lt;p&gt;Next up, we need to read the Excel file. Here’s how you do it in Plang:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- read file translations.xlsx, sheet:translations, into %translations%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells Plang to grab the data from the &lt;code&gt;translations&lt;/code&gt; sheet in &lt;code&gt;translations.xlsx&lt;/code&gt; and load it into the &lt;code&gt;%translations%&lt;/code&gt; variable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Splitting the List
&lt;/h2&gt;

&lt;p&gt;With 350 keywords, sending everything to the language model in one go might be overkill. To avoid confusion (for the model and us), we split the list into chunks of 20 items:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- [code] split %translations% with 20 items in them,
     write to %translationsLists%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, &lt;code&gt;%translationsLists%&lt;/code&gt; contains multiple smaller lists, each with 20 keywords. &lt;/p&gt;

&lt;h2&gt;
  
  
  Processing the List
&lt;/h2&gt;

&lt;p&gt;Next, we loop through each chunk in &lt;code&gt;%translationsLists%&lt;/code&gt; and call &lt;code&gt;TranslateList&lt;/code&gt; for each one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- foreach %translationsLists%, call TranslateList 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step makes sure each group of keywords gets processed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Time to Translate
&lt;/h2&gt;

&lt;p&gt;Here’s where the magic happens. We get the language model to translate the keywords into Icelandic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TranslateList
- [llm] system: Translate the messages to Icelandic, leave key as is
    user: %item%
    scheme:[{key:string, message:string}]
    write to %translated%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this, &lt;code&gt;%translated%&lt;/code&gt; contains the Icelandic translations paired with the original keywords.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saving the Translations
&lt;/h2&gt;

&lt;p&gt;Finally, we save the translations into a CSV file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- append %translated% to csv file 'translate.csv'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that’s it! We’ve got our translations neatly saved in &lt;code&gt;translate.csv&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;In about five minutes, I put together a script that automates translating a list of keywords. Here's the full code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Translate
- read file translations.xlsx, sheet:translations, into %translations%
- [code] split %translations% with 20 items in them,
     write to %translationsLists%
- foreach %translationsLists%, call TranslateList 

TranslateList
- [llm] system: Translate the messages to Icelandic, leave key as is
    user: %item%
    scheme:[{key:string, message:string}]
    write to %translated%
- append %translated% to csv file 'translate.csv'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s important to note that even though the heavy lifting is automated, a human still needs to review the translations. They’ll catch the context-specific nuances that the model might miss.&lt;/p&gt;

&lt;p&gt;Feel free to tweak this approach for your own projects. Let me know how it works for you!&lt;/p&gt;

&lt;h2&gt;
  
  
  More Information
&lt;/h2&gt;

&lt;p&gt;If Plang is interesting to you, you should dig a bit deeper:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%201.md" rel="noopener noreferrer"&gt;Basic concepts and lessons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/Todo_webservice.md" rel="noopener noreferrer"&gt;Simple Todo example&lt;/a&gt; is a good start&lt;/li&gt;
&lt;li&gt;Check out the &lt;a href="https://github.com/PLangHQ/" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://discord.gg/A8kYUymsDD" rel="noopener noreferrer"&gt;Meet up on Discord&lt;/a&gt; or &lt;a href="https://github.com/orgs/PLangHQ/discussions" rel="noopener noreferrer"&gt;GitHub discussions&lt;/a&gt; to get help and for general chat&lt;/li&gt;
&lt;li&gt;And &lt;a href="https://plang.is" rel="noopener noreferrer"&gt;plang.is&lt;/a&gt;, the official Plang website&lt;/li&gt;
&lt;li&gt;Chat with the &lt;a href="https://chatgpt.com/share/78637171-19bd-40d5-9c16-e53bd64c12b1" rel="noopener noreferrer"&gt;current Plang assistant&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>beginners</category>
      <category>automation</category>
    </item>
    <item>
      <title>In Theory: Self-Correcting Software</title>
      <dc:creator>Ingi</dc:creator>
      <pubDate>Sun, 01 Sep 2024 15:27:46 +0000</pubDate>
      <link>https://forem.com/ingigauti/in-theory-self-correcting-software-16bh</link>
      <guid>https://forem.com/ingigauti/in-theory-self-correcting-software-16bh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article explores Plang, an intent-based programming language designed to interpret natural language. For more information, visit &lt;a href="https://plang.is" rel="noopener noreferrer"&gt;plang.is&lt;/a&gt; or &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%201.md" rel="noopener noreferrer"&gt;take your first steps&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Plang, you can bind events to goals(functions) and steps(line of code), a feature that proves incredibly powerful.&lt;/p&gt;

&lt;p&gt;Let's consider a scenario: you want to ensure that a user is logged in before they can call a function in the &lt;code&gt;/admin&lt;/code&gt; route. &lt;/p&gt;

&lt;p&gt;No problem in Plang:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Events
- before any goal in /admin, call AuthenticateUser

AuthenticateUser
- select id as userId from users where %Identity% and role='admin', return 1 row
- if %userId% is empty then
    - show error "You don't have permission"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there you have it—authentication is solved in just 4 lines of code.&lt;/p&gt;

&lt;p&gt;How does this translate to self-correcting software?&lt;/p&gt;

&lt;h2&gt;
  
  
  Self-Correcting Software
&lt;/h2&gt;

&lt;p&gt;Let's say I'm making a POST request to a service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CreateUserAsExample
- post https://example.org/api/createuser
    {name:"%name%", }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's bind an event to all error that happen in step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Events
- on error on any step, call SelfCorrect

SelfCorrect
- [llm] system: fix this plang code...
    user:%!error.Message%
    write to %code%
- write to %!error.Goal.RelativePath%
- build plang code
- retry step
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we've instructed the LLM to fix the Plang code. &lt;/p&gt;

&lt;p&gt;If the &lt;code&gt;/api/createuser&lt;/code&gt; service now requires more than just a name, it will return an error message such as &lt;code&gt;"{error:"You need to provide Email (%email%)"}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Asking the &lt;a href="https://chatgpt.com/share/78637171-19bd-40d5-9c16-e53bd64c12b1" rel="noopener noreferrer"&gt;current Plang assistant&lt;/a&gt; to handle this scenario would give you an updated response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CreateUserAsExample
- post https://example.org/api/createuser
    {name:"%name%", email:%email%}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, plang code can save the new code to its path, build and run the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  But What if the Email is Still Empty?
&lt;/h2&gt;

&lt;p&gt;Yes, the %email% field might still be empty. &lt;/p&gt;

&lt;p&gt;In this case, you need to traverse up the call stack and fix the previous goal. Once one issue is resolved, the same principle applies to the next one. It's just a matter of engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Information
&lt;/h2&gt;

&lt;p&gt;If Plang is interesting to you, you should dig a bit deeper:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%202.md" rel="noopener noreferrer"&gt;Basic concepts and lessons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/Todo_webservice.md" rel="noopener noreferrer"&gt;Simple Todo example&lt;/a&gt; is a good start&lt;/li&gt;
&lt;li&gt;Check out the &lt;a href="https://github.com/PLangHQ/" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://discord.gg/A8kYUymsDD" rel="noopener noreferrer"&gt;Meet up on Discord&lt;/a&gt; to discuss or get help&lt;/li&gt;
&lt;li&gt;Chat with the &lt;a href="https://chatgpt.com/g/g-Av6oopRtu-plang-help-code-generator" rel="noopener noreferrer"&gt;Plang Assistant&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>eventdriven</category>
      <category>programming</category>
      <category>learning</category>
      <category>ai</category>
    </item>
    <item>
      <title>A Beginner's Guide to Implementing Events in Plang</title>
      <dc:creator>Ingi</dc:creator>
      <pubDate>Fri, 30 Aug 2024 15:27:19 +0000</pubDate>
      <link>https://forem.com/ingigauti/a-beginners-guide-to-implementing-events-in-plang-3ici</link>
      <guid>https://forem.com/ingigauti/a-beginners-guide-to-implementing-events-in-plang-3ici</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article explores Plang, an intent-based programming language designed to interpret natural language. For more information, visit &lt;a href="https://plang.is" rel="noopener noreferrer"&gt;plang.is&lt;/a&gt; or &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%201.md" rel="noopener noreferrer"&gt;take your first steps&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Welcome to this step-by-step tutorial on implementing and managing events in your Plang applications. &lt;/p&gt;

&lt;p&gt;Events in Plang allow you to trigger specific actions at various stages in your application’s lifecycle, during the build process, or under certain conditions. This guide covers setting up events, handling errors, managing builder events, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Setting Up Events
&lt;/h2&gt;

&lt;p&gt;To start, you'll need to establish the structure for events in your Plang application:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create an &lt;code&gt;events&lt;/code&gt; Directory&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Begin by creating a folder named &lt;code&gt;events&lt;/code&gt; in your project’s root directory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create the &lt;code&gt;Events.goal&lt;/code&gt; File&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Inside the &lt;code&gt;events&lt;/code&gt; folder, create a file named &lt;code&gt;Events.goal&lt;/code&gt;. This is where you'll define your events.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  2. Application Lifecycle Events
&lt;/h2&gt;

&lt;p&gt;Lifecycle events allow you to execute specific actions when your application starts or ends. Here’s how to set them up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Events
- before app starts, call !AppStarting
- before app ends, call !AppEnding
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create &lt;code&gt;AppStarting.goal&lt;/code&gt; and &lt;code&gt;AppEnding.goal&lt;/code&gt; files in the &lt;code&gt;events&lt;/code&gt; folder:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;AppStarting.goal&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AppStarting
- write out 'App is starting'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;AppEnding.goal&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AppEnding
- write out 'App is ending'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;before app starts&lt;/code&gt;&lt;/strong&gt;: Triggers the &lt;code&gt;AppStarting&lt;/code&gt; action before the application starts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;before app ends&lt;/code&gt;&lt;/strong&gt;: Triggers the &lt;code&gt;AppEnding&lt;/code&gt; action before the application shuts down.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plang is flexible with its syntax. You don’t have to write exactly &lt;code&gt;before app starts&lt;/code&gt;; you can phrase it as &lt;code&gt;when the app starts...&lt;/code&gt;, &lt;code&gt;on app start...&lt;/code&gt;, or any other way that clearly conveys your intent.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Events with Goals and Steps
&lt;/h2&gt;

&lt;p&gt;Plang enables you to trigger events before or after specific goals within a directory or globally after each goal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Events
- before each goal in 'api/*', call !AuthenticateUser
- after each goal, call !Analyze.LogInfoAboutGoal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before each goal in 'api/*'&lt;/strong&gt;: Runs &lt;code&gt;AuthenticateUser&lt;/code&gt; before any goal in the &lt;code&gt;api&lt;/code&gt; directory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;After each goal&lt;/strong&gt;: Runs &lt;code&gt;LogInfoAboutGoal&lt;/code&gt; after every goal in your project.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Error Handling Events
&lt;/h2&gt;

&lt;p&gt;Handling errors effectively is essential. Plang allows you to define events that trigger when errors occur:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Events
- on error in step, call !LoggerStepError
- on error on goal, call !LoggerGoalError
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;on error in step&lt;/code&gt;&lt;/strong&gt;: Calls &lt;code&gt;LoggerStepError&lt;/code&gt; when an error occurs in any step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;on error on goal&lt;/code&gt;&lt;/strong&gt;: Calls &lt;code&gt;LoggerGoalError&lt;/code&gt; when an error occurs in any goal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more detailed error handling, refer to the &lt;a href="//./ErrorHandler.md"&gt;ErrorHandler documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Builder Events
&lt;/h2&gt;

&lt;p&gt;Events related to the Plang builder can be defined in a &lt;code&gt;BuilderEvents.goal&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BuilderEvents
- before each step, call !AnalyzeCode
- after each step, call !AnalyzeCode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plang already uses this build event internally to validate all goals. After your first build, you can find this at &lt;code&gt;/events/external/plang/builder/CheckGoals.goal&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before and after each step&lt;/strong&gt;: &lt;code&gt;AnalyzeCode&lt;/code&gt; is called before and after each step during the build process, ensuring consistent code analysis.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Conditional Events
&lt;/h2&gt;

&lt;p&gt;You may want to trigger events only under certain conditions, such as in debug mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Events
- before each step, call !SendDebug, only when start parameter is '--debug'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To trigger this event, run your application with:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;SendDebug&lt;/code&gt; event is triggered only if the &lt;code&gt;--debug&lt;/code&gt; parameter is passed at startup. Plang’s debugger itself uses this feature, which you can find at &lt;code&gt;/events/external/plang/runtime/SendDebug.goal&lt;/code&gt; after your first debug session.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Using Available Variables
&lt;/h2&gt;

&lt;p&gt;Within your events, you can access information about the current goal, step, or event using predefined variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;%!goal%&lt;/code&gt;&lt;/strong&gt;: Represents the current goal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;%!step%&lt;/code&gt;&lt;/strong&gt;: Represents the current step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;%!event%&lt;/code&gt;&lt;/strong&gt;: Represents the current event.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These variables are useful for passing context-sensitive information to your event handlers.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. External Events
&lt;/h2&gt;

&lt;p&gt;To integrate external events from other sources, place external event files in the following directory structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;events/external/{appName}/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, events related to &lt;code&gt;plang&lt;/code&gt; would be placed in &lt;code&gt;events/external/plang/&lt;/code&gt;, created automatically when you build or run a debugger.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Binding Events to Variables
&lt;/h2&gt;

&lt;p&gt;In Plang, you can bind events to variables to monitor their lifecycle (creation, update, or deletion):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- when %name% is created, call VariableNameIsCreated
- when %email% is changed, call VariableEmailIsChanged
- when %zip% is changed or created, call VariableZipIsChanged
- when %name% is deleted, call VariableNameIsDeleted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup allows dynamic event handling based on how variables change in your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Types of Events in Plang
&lt;/h2&gt;

&lt;p&gt;Plang provides various event types for different scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before and After Events&lt;/strong&gt;: Trigger actions before or after specific goals or steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Events&lt;/strong&gt;: Handle errors by triggering specific actions when an error occurs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conditional Events&lt;/strong&gt;: Execute actions based on specific conditions or parameters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build Events&lt;/strong&gt;: Manage events during the build process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Variable Events&lt;/strong&gt;: Bind actions to changes in variable states.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  11. Source Code Reference
&lt;/h2&gt;

&lt;p&gt;If you're interested in exploring the underlying code for event management in Plang, you can check out the following files in the Plang repository:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/PLangHQ/plang/tree/main/PLang/Events" rel="noopener noreferrer"&gt;EventBuilder.cs&lt;/a&gt;&lt;/strong&gt;: Handles the creation of event files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EventRuntime.cs&lt;/strong&gt;: Manages the runtime execution of events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EventBinding.cs&lt;/strong&gt;: Contains objects used for event management in both the builder and runtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These resources will help you gain a deeper understanding of how events are managed in Plang.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Information
&lt;/h2&gt;

&lt;p&gt;If Plang is interesting to you, you should dig a bit deeper:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%202.md" rel="noopener noreferrer"&gt;Basic concepts and lessons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/Todo_webservice.md" rel="noopener noreferrer"&gt;Simple Todo example&lt;/a&gt; is a good start&lt;/li&gt;
&lt;li&gt;Check out the &lt;a href="https://github.com/PLangHQ/" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://discord.gg/A8kYUymsDD" rel="noopener noreferrer"&gt;Meet up on Discord&lt;/a&gt; to discuss or get help&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>beginners</category>
      <category>eventdriven</category>
      <category>programming</category>
    </item>
    <item>
      <title>Messaging in Plang</title>
      <dc:creator>Ingi</dc:creator>
      <pubDate>Fri, 19 Jul 2024 10:31:06 +0000</pubDate>
      <link>https://forem.com/ingigauti/messaging-in-plang-9mb</link>
      <guid>https://forem.com/ingigauti/messaging-in-plang-9mb</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article explores Plang, an intent-based programming language designed to interpret natural language. For more information, visit &lt;a href="https://plang.is" rel="noopener noreferrer"&gt;plang.is&lt;/a&gt; or &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%201.md" rel="noopener noreferrer"&gt;take your first steps&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Plang has built-in messaging. It uses the &lt;a href="https://nostr.com/" rel="noopener noreferrer"&gt;Nostr protocol&lt;/a&gt; by default to do this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before We Start
&lt;/h2&gt;

&lt;p&gt;Make sure to &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/Install.md" rel="noopener noreferrer"&gt;install Plang&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note that building code in Plang costs money as it uses LLM. If you have an OpenAI key, you can use that. Instructions are available on your first build.&lt;/p&gt;

&lt;p&gt;Plang is a programming language where you write the code in natural language. I call it intent programming because you just need to write your intent and the LLM will figure out what you would like to do.&lt;/p&gt;

&lt;p&gt;To understand it, make sure to go through some of the &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%202.md" rel="noopener noreferrer"&gt;lessons we have&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prepare
&lt;/h2&gt;

&lt;p&gt;There are some Nostr clients out there. I recommend &lt;a href="https://apps.apple.com/us/app/damus/id1628663131" rel="noopener noreferrer"&gt;Damus (iOS)&lt;/a&gt; and &lt;a href="https://play.google.com/store/apps/details?id=com.vitorpamplona.amethyst&amp;amp;hl=en" rel="noopener noreferrer"&gt;Amethyst (Android)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Download either of these clients to your phone. This allows us to communicate with the Plang app we are building in this tutorial.&lt;/p&gt;

&lt;p&gt;After you have set it up, create a new account and find the public address by clicking your profile picture and going into your profile.&lt;/p&gt;

&lt;p&gt;The public address will start with &lt;code&gt;'npub.....'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Copy this address, so you have &lt;code&gt;'npub.....'&lt;/code&gt; in your clipboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set Up Code
&lt;/h2&gt;

&lt;p&gt;Let's get started. You should have &lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/Install.md" rel="noopener noreferrer"&gt;Plang installed&lt;/a&gt; and create a new folder on your computer (you choose the location).&lt;/p&gt;

&lt;p&gt;Let's create the folder &lt;code&gt;MessageTest&lt;/code&gt;. Inside the folder, create a file called &lt;code&gt;Start.goal&lt;/code&gt;. This is the default entry point into your app.&lt;/p&gt;

&lt;p&gt;Now write the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Start
- get the public address for message, write to %publicAddress%
- write out 'Your address is: %publicAddress%'
- listen to message from 'npub...', 
    on new message call ProcessMessage, content of goes into %message%

ProcessMessage
- write out 'Message from phone: %message%'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now build and run it:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;It should now print out the Nostr public address and listen for messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Your address is: npub....
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try sending a message from your phone to the &lt;code&gt;npub&lt;/code&gt; address that was printed out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Send a Message
&lt;/h2&gt;

&lt;p&gt;Now we want to send a message to our phone.&lt;/p&gt;

&lt;p&gt;Create a new file &lt;code&gt;SendMessage.goal&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make sure to put in you npub address from your phone instead of 'npub....'&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SendMessage
- send a message to 'npub....',
    content=%content%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build the code:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;And run the code with some content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;plang SendMessage &lt;span class="nv"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Hello"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your phone should receive a message with the content "Hello."&lt;/p&gt;

&lt;h2&gt;
  
  
  More Information
&lt;/h2&gt;

&lt;p&gt;If Plang is interesting to you, you should dig a bit deeper:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/blogs/Lesson%202.md" rel="noopener noreferrer"&gt;Basic concepts and lessons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/Todo_webservice.md" rel="noopener noreferrer"&gt;Simple Todo example&lt;/a&gt; is a good start&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/PLangHQ/plang/blob/main/Documentation/modules/PLang.Modules.MessageModule.md" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt; on the message module&lt;/li&gt;
&lt;li&gt;Check out the &lt;a href="https://github.com/PLangHQ/" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://discord.gg/A8kYUymsDD" rel="noopener noreferrer"&gt;Meet up on Discord&lt;/a&gt; to discuss or get help&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>beginners</category>
      <category>learning</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
