<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andrey M</title>
    <description>The latest articles on DEV Community by Andrey M (@meamka).</description>
    <link>https://dev.to/meamka</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%2F113078%2Fae527f5e-c127-4cff-b857-b3f00c2f42ec.jpeg</url>
      <title>DEV Community: Andrey M</title>
      <link>https://dev.to/meamka</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/meamka"/>
    <language>en</language>
    <item>
      <title>Attempt to rewrite my note-taking app</title>
      <dc:creator>Andrey M</dc:creator>
      <pubDate>Thu, 10 Jul 2025 16:42:37 +0000</pubDate>
      <link>https://dev.to/meamka/attempt-to-rewrite-my-note-taking-app-2a2h</link>
      <guid>https://dev.to/meamka/attempt-to-rewrite-my-note-taking-app-2a2h</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;For more than a year now, I have been periodically returning to trying to rethink my note-taking application, &lt;a href="https://flathub.org/apps/com.github.tenderowl.norka" rel="noopener noreferrer"&gt;Norka&lt;/a&gt;, to update the interface, add modern features, and finally add synchronization with thae cloud.&lt;/p&gt;

&lt;p&gt;I've had several attempts to use Rust to add speed and reliability to the application. I use C# (&lt;a href="https://gircore.github.io/" rel="noopener noreferrer"&gt;Gir.Core&lt;/a&gt;) for the same reasons and because I love this language. But unfortunately, in the end I returned to Python, because it and &lt;a href="https://pygobject.gnome.org/" rel="noopener noreferrer"&gt;PyGObject&lt;/a&gt; provide the necessary development speed and support a lot of libraries that I need for my work. The Python development ecosystem for GTK looks the most mature and complete.&lt;/p&gt;

&lt;p&gt;So, after a year of experimentation and prototyping, studying analogs and my application requirements, I started another attempt to implement Norka 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration
&lt;/h2&gt;

&lt;p&gt;I have been working with macOS for more than 10 years and I believe that it is for this OS that the most beautiful and user-friendly applications have been created from the point of view of UX. Let's leave beauty out of the box, as it's a matter of taste, and turn to user experience.&lt;/p&gt;

&lt;p&gt;I have tried working with many applications, especially considering those that have received awards for their design - Craft, Ulysses, Bear, Evernote, IA Writer, etc. I also looked at various online services such as Microsoft Loop, Confluence (and why not?) and others . At some point in time, I caught myself thinking that 2 services had become the most convenient for me: craft.do as a desktop application and web service, and Microsoft Loop as a web service. It was decided to assemble the functionality of the new version of Norka from them, namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Workspaces&lt;/li&gt;
&lt;li&gt;A tree structure where each page can have nested pages.&lt;/li&gt;
&lt;li&gt;Customization of the design of pages and spaces: icons and covers help with work and just make work more fun.&lt;/li&gt;
&lt;li&gt;Instead of Markdown, use rich formatting in the document itself, like office software.&lt;/li&gt;
&lt;li&gt;The ability to publish pages, share them with other users, or make them publicly available to everyone.&lt;/li&gt;
&lt;li&gt;Sync with the cloud.&lt;/li&gt;
&lt;li&gt;Encryption of spaces and pages with password access for published pages.&lt;/li&gt;
&lt;li&gt;Integration with LLM both locally and externally (whether &lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; or OpenAI)&lt;/li&gt;
&lt;li&gt;The ability to create tasks, as implemented in Craft.&lt;/li&gt;
&lt;li&gt;Advanced search capabilities, calendar linking, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, this is not the final list, and it will be updated. However, it's a great set to start with :)&lt;/p&gt;

&lt;p&gt;By the way, you can follow the updates on my &lt;a href="https://x.com/meamka" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or on the project's &lt;a href="https://github.com/TenderOwl/NorkaXT" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workspaces
&lt;/h2&gt;

&lt;p&gt;The first thing to do was to sort out the workspaces. The task they are designed to solve is to group pages by topic, project, or otherwise. The user can decide for himself, the main thing is to give him the opportunity. And at the same time, make it possible to add an icon, cover, and control functionality. So we get something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw67etd46k6xuvkohbebf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw67etd46k6xuvkohbebf.png" alt="Workspace creation dialog" width="800" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The user can select an emoji icon and a cover from the preset images. However, in the future I plan to add integration with online services such as &lt;a href="https://www.pexels.com/" rel="noopener noreferrer"&gt;Pexels&lt;/a&gt; or &lt;a href="https://unsplash.com/" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Workspaces contain pages that are deleted when the space is deleted. So be careful 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  Pages
&lt;/h2&gt;

&lt;p&gt;If workspaces are complementary functionality, then creating and editing text is the main one. Therefore, it will require the most work on itself, but let's see what has already been implemented.&lt;/p&gt;

&lt;h3&gt;
  
  
  Editing
&lt;/h3&gt;

&lt;p&gt;Surprisingly, the fact is that pages can already be created and their contents edited. At the same time, syntax highlighting is now being used, which migrated from the first version of Norka - Markdown markup. In addition to this, I started implementing work with formatting tags, without having to use a markup language. My experience suggests that this is a more convenient option, especially if you combine it with Markdown - use markup during typing as shortcuts for tags. For example, if a user types&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# The Awesome Title
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;, then this text will be automatically converted to a title, and the # sign at the beginning of the line will be removed 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;The Awesome Title
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should work for titles, links, images, and other markup elements.&lt;/p&gt;

&lt;p&gt;And if the ability to insert tags was not particularly difficult, then the issue of saving and loading required analysis and study, since the standard functionality of Gtk libraries allows you to save text, but there is no formatting in it. After trying out various data serialization options, I came to the decision not to mix content and formatting, and these two parts of the same whole should be stored separately from each other. This is about how documents are stored &lt;code&gt;.docx&lt;/code&gt; and &lt;code&gt;.odt&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nesting
&lt;/h3&gt;

&lt;p&gt;You can also nest pages inside each other and move them between workspaces. This can be done either by simply dragging the mouse or using the context menu.&lt;/p&gt;

&lt;p&gt;The nesting is not limited, but in the future this parameter may be revised after analyzing the work on large volumes and deep nesting of pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  To be continued
&lt;/h2&gt;

&lt;p&gt;A start has been made, but there is still a lot of work ahead, both in adding new functionality and debugging interfaces and performance. It's too early to talk about release plans, those who suffer can download the source codes and build the application themselves, everything is available on GitHub.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;See you!&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How not to be afraid of your team</title>
      <dc:creator>Andrey M</dc:creator>
      <pubDate>Tue, 08 Aug 2023 06:46:29 +0000</pubDate>
      <link>https://dev.to/meamka/how-not-to-be-afraid-of-your-team-282f</link>
      <guid>https://dev.to/meamka/how-not-to-be-afraid-of-your-team-282f</guid>
      <description>&lt;p&gt;One of my co-workers, who has just become a team leader, is having difficulty arranging meetings with the team due to his fear of communicating with one of the developers. He is afraid to say something wrong and get an adverse reaction, which can lead to a conflict or even a developer leaving the team. Let's look at this situation, identify the problems it causes, and think about how to solve them.&lt;/p&gt;

&lt;p&gt;&lt;a href="/assets/how-not-to-be-afraid-of-your-team/how-not-to-be-afraid-of-your-team.jpg" class="article-body-image-wrapper"&gt;&lt;img src="/assets/how-not-to-be-afraid-of-your-team/how-not-to-be-afraid-of-your-team.jpg" alt="Artificial team meeting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the reasons
&lt;/h2&gt;

&lt;p&gt;One of the basic and, coincidentally, the most challenging aspects of managing a team is the ability to communicate with different people, each of whom may have their own views on development, their own expectations from colleagues, and in general perceive the world differently. Although this is an entirely normal situation for newcomers to management, it is often difficult to cross the line of insecurity and fear of being rejected. In this post, I want to share my experience and tips on how to deal with this problem and improve the quality of meetings with the team.&lt;/p&gt;

&lt;p&gt;First of all, you need to understand the source of your fears about talking with an employee. Perhaps you feel that you do not have sufficient competence or weight to conduct a dialogue with him. Or maybe you heard or saw how he reacts to criticism or suggestions for improving the work and it seems that your words will certainly be taken with hostility. Perhaps you just do not know how to approach him and start a conversation, and this imaginary awkwardness fetters you.&lt;/p&gt;

&lt;p&gt;In any case, it is important to realize that your fear does not help you and your team. If you avoid meetings with the team or keep them formal and superficial, you lose the opportunity to get feedback, identify problems, motivate, and develop your subordinates. Moreover, it is the lack of meetings that increases the risk of losing the trust and respect of the team, which may feel that you are not interested in their opinion and success.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing
&lt;/h2&gt;

&lt;p&gt;What to do? Here are a few steps that can help you overcome your fear and communicate effectively with your team:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prepare for the meeting&lt;/strong&gt;. The key to a good meeting is preparation. It works with any meeting, even with a date ;) So, to simplify a difficult situation as much as possible, you need to think about what you want to talk about and what conclusion to make.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Choose a suitable time and place for the meeting&lt;/strong&gt;. There is no need to hold a meeting at a time when the boss needs you to respond urgently or the developer you are going to talk to is busy fixing a bug in the prod. Offer the developer a convenient time and place to meet, such as a quiet office or coffee shop. I like to have meetings at the beginning or end of the week when everyone is already relaxing before the weekend.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Start the meeting on a positive note&lt;/strong&gt;. Ask your colleague about his mood, Greet the developer, thank him for his work, and share your successes or plans. Show your interest and involvement in the project and the team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Listen carefully&lt;/strong&gt;. As D. Carnegie wrote in his book “How to Win Friends and Influence People” - the ability to listen is the most important skill in a conversation. Let your employee express their emotions, tell their opinion about work and colleagues, and ask questions. Do not interrupt him, do not immediately criticize him, and do not ignore his words. Try to understand his point of view, motives, and problems. Confirm that you hear and understand him using words and gestures. Ask clarifying or open-ended questions to delve deeper into a topic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Express your opinion honestly and tactfully&lt;/strong&gt;. Tell the developer what you think of their work, behavior, or ideas. Use facts, not judgment, no one likes to have their work criticized. Give specific examples from your experience, even if they were unsuccessful, this will show you as a person, and not &lt;em&gt;boss&lt;/em&gt;. Admit your mistakes or shortcomings, if any. Give the developer a chance to respond to your criticisms or suggestions without insisting on their opinion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Seek compromise and cooperation&lt;/strong&gt;. Don't try to win an argument or prove yourself right. Recognize the advantages and disadvantages of different approaches and solutions. Your task as a leader is to develop the team. The ability to make mistakes and learn from your mistakes is one of the most important aspects of learning, but you must warn the team against critical mistakes that will affect the business. Ask the developer what they can do to improve the situation or solve the problem. Offer your help or support if needed, but don't push.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;End the meeting on a positive note&lt;/strong&gt;. Summarize the results of the meeting, and once again list what you talked about and agreed on. Thank the developers for their contribution, it really means a lot to you. Express your respect and trust in him. Invite him to the next meeting or feedback.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;I hope these tips will help you overcome your fear and communicate effectively with your team. Remember that the developer is not your enemy, but your colleague and partner, who is also interested in the success of the project and the team. If you treat him with respect and trust, he will most likely return the same to you.&lt;/p&gt;

</description>
      <category>management</category>
      <category>howto</category>
      <category>career</category>
    </item>
    <item>
      <title>Make a weather app with Dart</title>
      <dc:creator>Andrey M</dc:creator>
      <pubDate>Sat, 29 Jul 2023 20:12:12 +0000</pubDate>
      <link>https://dev.to/meamka/make-a-weather-app-with-dart-faj</link>
      <guid>https://dev.to/meamka/make-a-weather-app-with-dart-faj</guid>
      <description>&lt;p&gt;Today we're going to build a console application that can fetch and show weather for the given location. Under the hood, it uses  &lt;a href="https://open-meteo.com/"&gt;Open-Meteo&lt;/a&gt; as a weather data source. In addition to the Dart language, we will use several libraries to implement the application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/packages/args"&gt;args&lt;/a&gt; to parse command-line arguments&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/packages/http"&gt;http&lt;/a&gt; to fetch the data via API&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/packages/console"&gt;console&lt;/a&gt; to make output of the app more fancy ✨&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Concept
&lt;/h2&gt;

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

&lt;p&gt;To start developing, we need to design how our application should work: how to get input from the user, how to determine what coordinates the place is located and how to fetch weather conditions and forecasts for this location. While it seems like a small application we never know do we want to grow it into something bigger or not, and as good developers do, we have to think about architecture before we start. Let's split these tasks into 3 steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  User's input
&lt;/h3&gt;

&lt;p&gt;Command-line or console applications usually work straightforwardly from start to end. Users can pass the data to process in the beginning by entering values as arguments to the application.&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;dart compile exe -o myApp bin/myApp.dart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a lot, I know, but let's see what is presented here.&lt;br&gt;
&lt;code&gt;dart&lt;/code&gt; - is the application itself. Next goes a bunch of arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;compile&lt;/code&gt;, &lt;code&gt;exe&lt;/code&gt; - command and subcommand to the &lt;code&gt;dart&lt;/code&gt; program, it describes the main command to execute.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-o myApp&lt;/code&gt; - argument, which tells what the name of the output file should be.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bin/myApp.dart&lt;/code&gt; - the last argument pointing to the filename to be compiled.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There could be more or less arguments, all of them passed and parsed when application starts. But, how to do that?&lt;/p&gt;
&lt;h2&gt;
  
  
  Parsing arguments
&lt;/h2&gt;

&lt;p&gt;Dart has a package to work with arguments, it helps to design a command-line interface, parse the arguments and show usage examples if needed. It is called &lt;a href="https://pub.dev/packages/args"&gt;args&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To start, we need to instantiate the object of the &lt;a href="https://pub.dev/documentation/args/latest/args/ArgParser-class.html"&gt;ArgParser&lt;/a&gt; class and then add options, arguments, and flags to let the parser know what we are expecting for input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:args/args.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Initialize the ArgParser object&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;argParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ArgParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;// Add a boolean flag.&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addFlag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'debug'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;help:&lt;/span&gt; &lt;span class="s"&gt;'enable debug mode'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addFlag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'select'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;abbr:&lt;/span&gt; &lt;span class="s"&gt;'s'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;help:&lt;/span&gt; &lt;span class="s"&gt;'select from found locations, otherwise first found will be used'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Then add options that can modify app behavior&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addOption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'temp_unit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;abbr:&lt;/span&gt; &lt;span class="s"&gt;'t'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;defaultsTo:&lt;/span&gt; &lt;span class="s"&gt;'celsius'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;allowed:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'celsius'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'fahrenheit'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="nl"&gt;help:&lt;/span&gt; &lt;span class="s"&gt;'temperature units'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addOption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'wind_unit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;abbr:&lt;/span&gt; &lt;span class="s"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;defaultsTo:&lt;/span&gt; &lt;span class="s"&gt;'kmh'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;allowed:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'kmh'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'ms'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'mph'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'kn'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="nl"&gt;help:&lt;/span&gt; &lt;span class="s"&gt;'wind speed units'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addOption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'prec_unit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;abbr:&lt;/span&gt; &lt;span class="s"&gt;'p'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;defaultsTo:&lt;/span&gt; &lt;span class="s"&gt;'mm'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;allowed:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'mm'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'inch'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="nl"&gt;help:&lt;/span&gt; &lt;span class="s"&gt;'precipitation units'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, flags are kind of indicators, they can be &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. On the other hand, options can take any values but they can be limited to &lt;code&gt;allowed&lt;/code&gt; values only. There is a much more feature available, like commands or rest values such as in the example above, and you can read about them in the &lt;a href="https://pub.dev/packages/args"&gt;package documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding the location
&lt;/h2&gt;

&lt;p&gt;When user input is collected and parsed, our application logic comes first. It starts with the need to find the coordinates of a given location because the Open-Meteo API requires coordinates to provide us with a forecast. To do this, we can use reverse geocoding, and for these purposes Open-Meteo offers us the API method &lt;a href="https://open-meteo.com/ru/docs/geocoding-api"&gt;https://open-meteo.com/ru/docs/geocoding-api&lt;/a&gt; , to which we must pass the name of the place, and in response we will receive a list from suitable locations. Each location contains a lot of geographic information, but we will only be interested in the name and coordinates. &lt;/p&gt;

&lt;p&gt;Let's start with an API request. We need a function that takes a location name and returns a list of locations from the API response. Something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getCoordinates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;locationName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Send request and parse response&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to make a request we need to build a &lt;code&gt;Uri&lt;/code&gt; object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Uri&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;https&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;'geocoding-api.open-meteo.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;'/v1/search'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'name'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;locationName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'count'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can send an HTTP request and process results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Send request and await for response.&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// Check response HTTP Code.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;HttpStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Try to parse JSON body into a list of `Location` objects&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;jsonBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jsonDecode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jsonBody&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'results'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;jsonBody&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'results'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;((&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;TimeoutException&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Operation timed out'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Error occured while getting location coordinates: &lt;/span&gt;&lt;span class="si"&gt;$e&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;Location&lt;/code&gt; model will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Location&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;countryCode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;country&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;countryCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;factory&lt;/span&gt; &lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="nl"&gt;latitude:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'latitude'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toDouble&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nl"&gt;longitude:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'longitude'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toDouble&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nl"&gt;country:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'country'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="nl"&gt;countryCode:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'country_code'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;Location: &lt;/span&gt;&lt;span class="si"&gt;$name&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;$country&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cool! Now we have a list with &lt;code&gt;Location&lt;/code&gt;-s and thus we can go to the next part - get the current weather conditions!&lt;/p&gt;

&lt;h2&gt;
  
  
  Current weather condition
&lt;/h2&gt;

&lt;p&gt;Let's start with defining &lt;code&gt;CurrentWeather&lt;/code&gt; model. As you may see in the Open-Meteo API condition can contain a lot of data such as temperature, precipation, UV-level and more. To make our code compact we will care only about few of them: temperature, weather code and wind speed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CurrentWeather&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;windSpeed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;weatherCode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;CurrentWeather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;windSpeed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;weatherCode&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;factory&lt;/span&gt; &lt;span class="n"&gt;CurrentWeather&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;CurrentWeather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;weatherCode:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"weathercode"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nl"&gt;temperature:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"temperature"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toDouble&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nl"&gt;windSpeed:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"windspeed"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toDouble&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All that remains for us is to form a request to the server and process the response in the same way as we did in the getCoordinates function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create a Uri object&lt;/li&gt;
&lt;li&gt;using the http library we send a request to the API and wait for a response&lt;/li&gt;
&lt;li&gt;check that the response contains no errors and try to parse JSON into a CurrentWeather object.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CurrentWeather&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getCurrentWeather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt; &lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Uri&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;https&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;'api.open-meteo.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;'/v1/forecast'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;'latitude'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;latitude&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="s"&gt;'longitude'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;longitude&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="s"&gt;'current_weather'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;HttpStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;jsonData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="s"&gt;'current_weather'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;CurrentWeather&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jsonData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;TimeoutException&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Operation timed out'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Error occured while getting location coordinates: &lt;/span&gt;&lt;span class="si"&gt;$e&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Finishing steps
&lt;/h2&gt;

&lt;p&gt;In order to make the users of our application a little more satisfied, I added a function for a beautiful output of the received data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;printWeather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CurrentWeather&lt;/span&gt; &lt;span class="n"&gt;weather&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weather&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;temperature&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
      &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'{color.gold}&lt;/span&gt;&lt;span class="si"&gt;${weather.temperature}&lt;/span&gt;&lt;span class="s"&gt;{color.end}'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'{color.blue}&lt;/span&gt;&lt;span class="si"&gt;${weather.temperature}&lt;/span&gt;&lt;span class="s"&gt;{color.end}'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'🌚'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weather&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;weatherCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;//    Clear sky&lt;/span&gt;
      &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'☀️'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;// Mainly clear&lt;/span&gt;
      &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'🌤'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;// Partly cloudy&lt;/span&gt;
      &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'⛅️'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;//    Overcast&lt;/span&gt;
      &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'☁️'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;${location.name}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;${location.country}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;$condition&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;$temp&lt;/span&gt;&lt;span class="s"&gt;°C'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thank you for being with me, like, share, and subscribe are always appreciated ❤️ ! You can find full code of this article on GitHub &lt;a href="https://github.com/amka/spotty"&gt;https://github.com/amka/spotty&lt;/a&gt;. See you in the next chapters!&lt;/p&gt;

</description>
      <category>dart</category>
      <category>tutorial</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Reading CSV in Dart</title>
      <dc:creator>Andrey M</dc:creator>
      <pubDate>Fri, 04 Nov 2022 14:43:07 +0000</pubDate>
      <link>https://dev.to/meamka/reading-csv-in-dart-2pfe</link>
      <guid>https://dev.to/meamka/reading-csv-in-dart-2pfe</guid>
      <description>&lt;h2&gt;
  
  
  What is a CSV files
&lt;/h2&gt;

&lt;p&gt;CSV is a common format for transferring tabular data between different programs. Its history goes back centuries, to a time when computers were big and trees were green. In the general case, it represents data separated by commas and collected in lines so that each line defines a specific record. However, variations occur: for example, some programs separate values ​​with tabs rather than commas, while also using the &lt;code&gt;.csv&lt;/code&gt; extension, which can cause applications to crash.&lt;/p&gt;

&lt;p&gt;Let's see an example of such data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;id, title, type, count
1, "Citroen C3", Car, 2
2, "KTM 890 ADVENTURE R", Motorcycle, 4
3, "Jeep Avenger", Car, 1
4, "Polestar P1", Car, 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, it looks like we have presented the table as text: each row is a file row, and the first row is a header with column names. You may also notice that double quotes sometimes surround strings, this is done in case the columns contain control characters or other characters that can break formatting, such as commas. Actually, there is an RFC describing CSV format: &lt;a href="https://datatracker.ietf.org/doc/html/rfc4180"&gt;RFC4180&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Today we will focus on how to read such files, how to do it efficiently, and even try to determine the data types inside the strings. So let's get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read CSV file synchronously
&lt;/h2&gt;

&lt;p&gt;Let's start by defining the API we want to get. For our program, the following is enough:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;get the file name when running from the command line&lt;/li&gt;
&lt;li&gt;check that the name is passed, otherwise, we print out the problem to the console and exit&lt;/li&gt;
&lt;li&gt;if the path is specified, read the file and output all lines sequentially to the console and exit
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:io'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:csv_reading/csv_reading.dart'&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;csv_reading&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Usage: csv_reading path/to.csv&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv_reading&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readCsvSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we've defined the interface, we need to write the &lt;code&gt;readCsvSync&lt;/code&gt; method. It must take a string pointing to a file on the user's computer, check for its existence, and after reading the entire file, return all the strings as a list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:io'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;readCsvSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Create `File` object&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Check if file is ready to be read :)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Read lines sync and return them.&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readAsLinesSync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On this, our minimal program is ready, you can run it from the command line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart run bin/csv_reader.dart path/to/data.csv
&lt;span class="nb"&gt;id&lt;/span&gt;, title, &lt;span class="nb"&gt;type&lt;/span&gt;, count
1, &lt;span class="s2"&gt;"Citroen C3"&lt;/span&gt;, Car, 2
2, &lt;span class="s2"&gt;"KTM 890 ADVENTURE R"&lt;/span&gt;, Motorcycle, 4
3, &lt;span class="s2"&gt;"Jeep Avenger"&lt;/span&gt;, Car, 1
4, &lt;span class="s2"&gt;"Polestar P1"&lt;/span&gt;, Car, 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Async reading
&lt;/h2&gt;

&lt;p&gt;Working in synchronous mode is simple and straightforward, but from a program performance point of view, it is not always the best option, since it completely blocks the program from executing until the end of reading. What can we do about it? For example, we can use asynchronous reading! I will not go into the very concept of asynchronous work and how it is implemented in the Dart language, if you are not already familiar, then this will be your &lt;a href="https://dart.dev/guides/language/language-tour#asynchrony-%20support"&gt;homework&lt;/a&gt;. Let's move on to solving our problem.&lt;/p&gt;

&lt;p&gt;So, first, we need to change the interface of our program and method calls from synchronous to asynchronous. To do this, just add the &lt;code&gt;await&lt;/code&gt; keyword before calling the method. But how can we call an async method inside a synchronous &lt;code&gt;main()&lt;/code&gt;? I'm afraid not, but Dart gives us the ability to make the &lt;code&gt;main()&lt;/code&gt; method asynchronous!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Usage: csv_reading path/to.csv&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;csv_reading&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readCsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our &lt;code&gt;main()&lt;/code&gt; method will look like this. As you can see, not much has changed.&lt;/p&gt;

&lt;p&gt;Now we need to implement the &lt;code&gt;readCsv(String)&lt;/code&gt; method. First, we can no longer return a list of strings, asynchronous methods must return a &lt;code&gt;Future&lt;/code&gt; object, which, in turn, will contain the necessary data. Also, we must mark our method as asynchronous, as we did with the &lt;code&gt;main()&lt;/code&gt; method before, by adding the keyword &lt;code&gt;async&lt;/code&gt; to its description. After that, we can use asynchronous file methods such as &lt;code&gt;exists()&lt;/code&gt; and &lt;code&gt;readAsLines()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Wrap response in a `Future` object and mark function as `async`&lt;/span&gt;
&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;readCsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Create `File` object&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Check if file is ready to be read :)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Read lines sync and return them.&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readAsLines&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Still easy enough, right? Let's move on!&lt;/p&gt;

&lt;h2&gt;
  
  
  Async reading with Streams
&lt;/h2&gt;

&lt;p&gt;One of the disadvantages of our program in its current form is that it reads the entire file, after which we can work with it. Yes, despite being asynchronous, we're still loading the entire file into memory, we're just doing it asynchronously. And although this will not be a problem for small files, if our program must process files of tens and hundreds of megabytes, this can become a problem: not every computer may have enough memory.&lt;/p&gt;

&lt;p&gt;Dart has special classes that allow us to work with a stream of data by processing it on the fly, thereby saving memory and time. One such class is &lt;a href="https://api.dart.dev/stable/2.18.4/dart-async/Stream-class.html"&gt;Stream&lt;/a&gt;. You can always read more about it in the official documentation and &lt;a href="https://dart.dev/articles/libraries/creating-streams"&gt;articles&lt;/a&gt;. For our program, 2 points are important:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how to create a &lt;code&gt;Stream&lt;/code&gt; to read a file&lt;/li&gt;
&lt;li&gt;how to return a &lt;code&gt;Stream&lt;/code&gt; with a stream of strings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To achieve this, we need to make a few changes to our program. First, we need to change the description of our method so that Dart knows that it returns a &lt;code&gt;Stream&lt;/code&gt; instead of a list of strings, to do this, we need to convert our method to a generator. This is easy to do with the &lt;code&gt;async*&lt;/code&gt; keyword and changing the return type to &lt;code&gt;Stream&amp;lt;String&amp;gt;&lt;/code&gt; along the way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;streamCsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, instead of reading the whole file, we need to open the stream for reading, like this: &lt;code&gt;file.openRead()&lt;/code&gt;. But here's the catch: when reading this stream, it will return a stream of bytes to us, not lines; we don't want to work with bytes: it's the lines in the file that are important to us. What do we do? How to transform the stream in the way we need? For this, Dart has special classes &lt;a href="https://api.dart.dev/stable/2.18.4/dart-async/StreamTransformer-class.html"&gt;StreamTransformer&lt;/a&gt;, they will help us perform transformations, namely: get characters from a set of bytes; split one endless stream of characters into lines, detecting the end of the line by the control characters &lt;code&gt;\n&lt;/code&gt; and &lt;a href="https://api.dart.dev/stable/2.18.4/dart-convert/LineSplitter-class.html"&gt;other&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Don't forget to import `dart:convert` package&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:convert'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;openRead&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;// Convert bytes to string&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utf8&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decoder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Split string into a lines&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LineSplitter&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have a stream of lines from a file, all we need to do is return them to the caller, but without blocking the program, as a stream, using &lt;code&gt;await for&lt;/code&gt; and &lt;code&gt;yield&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Iterate over the stream&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// return generated value from the our generator.&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Excellent! All that remains for us is to learn how to listen to the stream and print the received data to the console. I think you yourself already know how to achieve this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;csv_reading&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;streamCsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Type detection
&lt;/h2&gt;

&lt;p&gt;Awesome! Now we have a list of values, it remains only to determine their types! Let's proceed as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;first, trim all spaces at the beginning and end of our value&lt;/li&gt;
&lt;li&gt;try to convert the value to an integer using &lt;code&gt;int.tryParse(value)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;if the received value is equal to &lt;code&gt;null&lt;/code&gt;, then this is not a number :)&lt;/li&gt;
&lt;li&gt;go ahead and try to convert to fractional &lt;code&gt;double.tryParse(value)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;if the received value is equal to &lt;code&gt;null&lt;/code&gt;, then this is not a fractional number :)&lt;/li&gt;
&lt;li&gt;check if our value is framed in &lt;code&gt;quotechar&lt;/code&gt; and if so, cut them off, leaving only the value.&lt;/li&gt;
&lt;li&gt;we collect values ​​in the list and we return from the generator.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The algorithm is ready, let's write the code!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delimeter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Iterate over each element in the items list&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 1 trim spaces&lt;/span&gt;
        &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// 2. Check if the value is int&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ival&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tryParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// 3. Parsed successfully?&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ival&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ival&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// 4. Try to parse into double value&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;dval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tryParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// 5. Parsed successfully?&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dval&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dval&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// 6. Check if the string is quoted&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;quotechar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;endsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;quotechar&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// 7. Return final list&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can check the return types and make sure it's not just strings anymore!&lt;/p&gt;

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

&lt;p&gt;Great, the full source code for these examples can be found in the &lt;a href="https://github.com/amka/csv_reading_article"&gt;https://github.com/amka/csv_reading_article&lt;/a&gt; repository.&lt;/p&gt;

</description>
      <category>dart</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Server-side Dart</title>
      <dc:creator>Andrey M</dc:creator>
      <pubDate>Mon, 03 Oct 2022 21:51:48 +0000</pubDate>
      <link>https://dev.to/meamka/server-side-dart-15ml</link>
      <guid>https://dev.to/meamka/server-side-dart-15ml</guid>
      <description>&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;Laska is under active development and is not supposed to be used in production. API may change dramatically in future versions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;It's not a secret that Dart's popularity comes from the Flutter framework and its acceptance by the community. I love Flutter as well, but what I miss is server-side. How cool it could be to be a full-stack developer by using only Dart language?&lt;/p&gt;

&lt;p&gt;There was a time, I want to start a new project and have to choose what technologies to use for the frontend and backend parts as well. Research gets me to &lt;a href="https://aqueduct.io/" rel="noopener noreferrer"&gt;Aqueduct&lt;/a&gt; and &lt;a href="https://pub.dev/packages/shelf" rel="noopener noreferrer"&gt;Shelf&lt;/a&gt;, both of them weren't looking actively developing and supported and that leads me to the idea to make my own small micro-framework like &lt;a href="https://echo.labstack.com/" rel="noopener noreferrer"&gt;Echo&lt;/a&gt; for Golang or &lt;a href="https://bottlepy.org/" rel="noopener noreferrer"&gt;Bottle&lt;/a&gt; for Python. And it was easy to decide: I've had time and motivation :)&lt;/p&gt;

&lt;p&gt;And before we get started, I'd like to answer some questions that will definitely come up: why do we need one more framework, and what's the problem your framework resolves? The first one is easy: ask JavaScript developers! But OK, the real answer is competition: the more frameworks we have, the more we learn from each other and, eventually, we build better apps. The second answer: it was designed and built for micro-services and small applications. Sure, there is a way to extend it with middleware and extensions that come later, but as I said I treat it as a Dart alternative to Bottle or Echo. And when I say built I mean will be built :) &lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;Laska - that's how the project is named - is a micro-framework, it's not aimed to be a full-featured app like Django. Therefore the architecture is quite simple: every request is processed by the same process while performance is based on leveraging the async nature of Dart.&lt;/p&gt;

&lt;p&gt;Let's briefly review how it works.&lt;/p&gt;

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

&lt;p&gt;As we can see on the diagram, asynchronous server processing works like a charm :) &lt;/p&gt;

&lt;p&gt;I did experiment with Isolates and multiprocessing, but finally, I decided it would require the developers to work with additional limitations. It is not the way I want to use any kind of software, so why does anyone should do it? Programming should be easy and fun therefore there is no kind of parallelism in Laska.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's build something
&lt;/h2&gt;

&lt;p&gt;There is a trivial way to present programming languages and frameworks called 'Hello world'. Let's be trivial!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:laska/laska.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;laska&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Laska&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="n"&gt;laska&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/hello/:name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello &lt;/span&gt;&lt;span class="si"&gt;${context.param('name')}&lt;/span&gt;&lt;span class="s"&gt;!"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;laska&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's easy to understand what's going on here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;initialize a Laska object&lt;/li&gt;
&lt;li&gt;add a handler for GET requests at the route '/hello/:name', where &lt;code&gt;name&lt;/code&gt; is a placeholder for context parameters&lt;/li&gt;
&lt;li&gt;code a handler that returns a string with a parameter given in the path&lt;/li&gt;
&lt;li&gt;and run the server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it, an asynchronous server is up and running on &lt;a href="http://localhost:3789" rel="noopener noreferrer"&gt;http://localhost:3789&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  More realistic example
&lt;/h2&gt;

&lt;p&gt;Surely, 'Hello world' is not a kind of real-world application someone will deploy to production. The more realistic would be to build a server that logs user requests to the stdout and has routes that require authorization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:laska/laska.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Custom middleware that checks user access.&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Acl&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="n"&gt;Middleware&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;allowedRoles&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;Acl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;allowedRoles&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Function&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// In this case it's simple check:&lt;/span&gt;
      &lt;span class="c1"&gt;// Does the request contains `role` header with `admin` value.&lt;/span&gt;
      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'role'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// If the header's `role` is not in `allowedRoles`, reject the request.&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;allowedRoles&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Role &lt;/span&gt;&lt;span class="si"&gt;$role&lt;/span&gt;&lt;span class="s"&gt; is not allowed.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Role &lt;/span&gt;&lt;span class="si"&gt;$role&lt;/span&gt;&lt;span class="s"&gt; is allowed.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Don't forget to call the handler.&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Custom middleware that prints request path and given prefix.&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="n"&gt;Middleware&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Function&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;$prefix&lt;/span&gt;&lt;span class="s"&gt;: Path: &lt;/span&gt;&lt;span class="si"&gt;${context.path}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Don't forget to call the handler.&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;laska&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Laska&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;acl_middleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Acl&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="c1"&gt;// Add global middleware&lt;/span&gt;
  &lt;span class="n"&gt;laska&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'global'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="c1"&gt;// Create handler with per-route middlewares: logger and acl&lt;/span&gt;
  &lt;span class="n"&gt;laska&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/secret'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secretHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;middlewares:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'route'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;acl_middleware&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Add route handler, only global middleware will apply&lt;/span&gt;
  &lt;span class="n"&gt;laska&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Add route with acl middleware, but only for the POST method.&lt;/span&gt;
  &lt;span class="n"&gt;laska&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;middlewares:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;acl_middleware&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;laska&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;secretHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'You have access to secret path!'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'id'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'name'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'Make something useful'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'status'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'id'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'name'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'Make new website'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'status'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope this code is self-explanatory but you can ask me  any questions  in comments :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Roadmap
&lt;/h2&gt;

&lt;p&gt;🅿️ - P is for planned.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Dynamic routing with placeholders&lt;/li&gt;
&lt;li&gt;✅ Middlewares&lt;/li&gt;
&lt;li&gt;✅ JSON handling&lt;/li&gt;
&lt;li&gt;✅ Form handling&lt;/li&gt;
&lt;li&gt;✅ Null-Safety&lt;/li&gt;
&lt;li&gt;🅿️ Logging&lt;/li&gt;
&lt;li&gt;🅿️ Serve static files&lt;/li&gt;
&lt;li&gt;🅿️ Template rendering?&lt;/li&gt;
&lt;li&gt;🅿️ Extensions&lt;/li&gt;
&lt;li&gt;🅿️ Health checks&lt;/li&gt;
&lt;li&gt;❓ What's more?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The end
&lt;/h2&gt;

&lt;p&gt;I'd love to see more server-side Dart projects and hope you do too. If you think so it would be very encouraging if you star the project on &lt;a href="https://github.com/TenderOwl/laska" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and like it on Dev.to.&lt;/p&gt;

</description>
      <category>dart</category>
      <category>microframework</category>
      <category>serverside</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to hire people</title>
      <dc:creator>Andrey M</dc:creator>
      <pubDate>Tue, 14 Jun 2022 07:58:41 +0000</pubDate>
      <link>https://dev.to/meamka/how-to-hire-people-40ne</link>
      <guid>https://dev.to/meamka/how-to-hire-people-40ne</guid>
      <description>&lt;p&gt;Over the past 6 years, my job has been a lot to find the right people for my team, and in that time I've developed a set of questions and markers that help me quite easily determine whether a candidate is a good fit or not. Conventionally, these markers can be divided into several points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Teamwork&lt;/strong&gt;: I don't build solo teams, I assemble effective teams that can get the job done. Each member of the team should be able to communicate and at the same time not go into conflict, disagreements happen to everyone, but they need to be resolved peacefully;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The ability to convey your thoughts&lt;/strong&gt;: working in a team on one project involves a lot of communication and the ability to explain your ideas, ask the right questions is critical;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The ability get things done&lt;/strong&gt;: any task is of value only when completed, read “available to users”;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Involvement, interest&lt;/strong&gt;: I do not want to educate everyone, I need people in the team who are interested in what they do, they themselves study the language / framework / database / other related technologies to make their projects the best on the market;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Teamwork
&lt;/h3&gt;

&lt;p&gt;Communication is a mandatory skill when working in a team, as a good team resolves issues within itself and at the same time, discussions do not turn into conflict. But what makes a good team different from a great one? At a minimum, it is open to discussion not only internally, but also with external customers/executors. It doesn’t matter whether it’s a new product feature that seems overcomplicated and needs to be explained to the customer, or the API that the backend team implemented seems primitive to you and does not take into account the needs of your mobile team. (Teams are fiction, %username%). All members of such a team are open to discussions, they know how to discuss and will tell other members about what they think is important.&lt;/p&gt;

&lt;p&gt;To find out about this quality, try asking the candidate about what was his role in the team? Who gave him tasks? Did he participate in the assessment of tasks, did he have to explain to customers or contractors what and why should be done, or vice versa, what should not be done?&lt;/p&gt;

&lt;h3&gt;
  
  
  The ability to convey your thoughts
&lt;/h3&gt;

&lt;p&gt;Here it is important to understand how the candidate can convey his ideas to the interlocutor, whether he works with feedback, whether he is convinced that his interlocutor understood the idea as closely as possible. For example, an employee has a task to solve which he needs to assign a task to another developer. He describes it in JIRA, appoints the performer and ... that's it. Thinks the job is done. He may even try to explain it in a chat or by phone, but he forgets the key point: to make sure that the task is really understood as it stands? Or, understanding is far from the original goal.&lt;/p&gt;

&lt;p&gt;How can you find out about this in an interview? Ask about whether the candidates assigned tasks to other developers? Were all the tasks done correctly the first time, or did you need a lot of clarifications in the process? What would he do next time? If we are talking about entry-level developers, then they, as a rule, do not set tasks, but are the final performers, however, even they must convey their thoughts to colleagues and team leaders. Can you ask them about what they did if the tasks were not clear? Have the requirements been successfully clarified?&lt;/p&gt;

&lt;h3&gt;
  
  
  Ability to get things done
&lt;/h3&gt;

&lt;p&gt;Many at the beginning of their professional career quite often change jobs, projects, periodically declaring that they have reached their ceiling and they have nowhere else to develop. At the same time, the projects they were working on at the time of their departure may be far from complete, and they themselves, as part of their work in the company, have already changed more than one project, because they were bored with them.&lt;/p&gt;

&lt;p&gt;I don't see it as a problem, it's normal when we're young and full of energy. There is so much energy that we cannot concentrate on one task for a long time, having launched the first prototype, we are already in a hurry to declare that the work is done and quickly switch to the next one.&lt;/p&gt;

&lt;p&gt;However, as a rule, when searching, companies need programmers of “middle” and higher levels, which means that I expect people to be able to solve problems on their own and certainly not leave them halfway.&lt;/p&gt;

&lt;p&gt;How to find out about this in an interview? Ask questions related to any completed tasks. Find out if a person has their own pet projects? Perhaps he developed some kind of internal project in the company where he worked? Maybe a friend's project where he helped with some part? This does not have to be software development, because here you are not interested in the qualities of a programmer, but in purposefulness.&lt;/p&gt;

&lt;h3&gt;
  
  
  Involvement, interest
&lt;/h3&gt;

&lt;p&gt;When recruiting people to a team, we always aim to make this team stronger and more efficient in the long term. Of course, technical competencies play a key role, but let's just assume that they are absolutely suitable for us and leave this issue outside the scope of this article. So, how can you strengthen the team by hiring a new person? This may be the strongest technical specialist, maybe he has excellent analytical skills, maybe he studies everything related to his area of ​​​​expertise and tries to bring new things to work, or maybe all at once and something else from above. One thing is clear, he is interested in his work and he is trying to make it even better by developing from one side or another. If so, feel free to hire!&lt;/p&gt;

&lt;p&gt;How to know about it? Ask about what the candidate has learned during the six months/year; why did he study it? How does he find out about the latest in his field? Ask him what he changed in the work of his previous company, within his job or department?&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions
&lt;/h2&gt;

&lt;p&gt;These are just examples of questions, you can adjust them to suit your team.&lt;/p&gt;

&lt;h3&gt;
  
  
  Teamwork
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;What was your role on the team?&lt;/li&gt;
&lt;li&gt;Have you ever had to explain why a task would take longer?&lt;/li&gt;
&lt;li&gt;Have you assigned tasks to other people in the company?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The ability to convey your thoughts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Were there moments that you did not like? How did you try to solve them?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ability to get things done
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Do you have open projects on GitHub/Gitlab? What problems do they solve?&lt;/li&gt;
&lt;li&gt;What products have you created or would like to create? It can be anything: an application, a book, a blog, music, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Involvement, interest
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;What recent have you studied or read?&lt;/li&gt;
&lt;li&gt;How do you find out about new technologies?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to use it
&lt;/h2&gt;

&lt;p&gt;Well, you have two options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can evaluate your current employees on these points - I mean those who you hired in the past.&lt;/li&gt;
&lt;li&gt;If you are actively hiring employees, you can try evaluating them using this technique.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>management</category>
      <category>hiring</category>
      <category>interview</category>
    </item>
    <item>
      <title>From Python to Dart - Day 2, Meet the dart CLI</title>
      <dc:creator>Andrey M</dc:creator>
      <pubDate>Mon, 07 Mar 2022 15:37:39 +0000</pubDate>
      <link>https://dev.to/meamka/from-python-to-dart-day-2-meet-the-dart-cli-3e18</link>
      <guid>https://dev.to/meamka/from-python-to-dart-day-2-meet-the-dart-cli-3e18</guid>
      <description>&lt;p&gt;The Dart language is unimaginable without the command-line utility (CLI) of the same name. This is a full-fledged tool that greatly simplifies the life of a developer in terms of its capabilities, far exceeding the built-in capabilities of the Python interpreter.&lt;/p&gt;

&lt;p&gt;Among the &lt;code&gt;dart&lt;/code&gt; features available are project creation, source code analyzing and formatting, and even publishing packages to &lt;a href="https://pub.dev"&gt;pub.dev&lt;/a&gt; and more.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Bear in mind that the goal of this cycle is not a complete immersion in Dart from scratch, but a quick acquaintance for those who already know how to develop, in particular, in the Python language.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Projects creation
&lt;/h2&gt;

&lt;p&gt;Python does not have built-in capabilities for automated project creation, everything has to be done manually: create a folder structure, describe dependencies in &lt;code&gt;requirements.txt&lt;/code&gt;. Of course, there are third-party applications that make this process easier, such as  &lt;a href="https://python-poetry"&gt;poetry&lt;/a&gt; or &lt;a href="https://cookiecutter.readthedocs.io/"&gt;Cookiecutter&lt;/a&gt;. However, they are third-party and require installation in a system or virtual environment. Dart has this feature built-in.&lt;/p&gt;

&lt;h3&gt;
  
  
  dart create
&lt;/h3&gt;

&lt;p&gt;So, &lt;code&gt;dart create&lt;/code&gt; is a CLI utility that can help you to create a project from the specified template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart create project_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, this is a simple console application like &lt;a href="https://sass-lang.com/dart-sass"&gt;dart-sass&lt;/a&gt;. However, this is not all. Using the &lt;code&gt;-t&lt;/code&gt; option, you can specify which template to use for creation, it can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;console-simple&lt;/code&gt;: A simple console application (basic template).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;console-full&lt;/code&gt;: Console application with tests.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;package-simple&lt;/code&gt;: A starting point for Dart libraries or apps.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;server-shelf&lt;/code&gt;: Server based on &lt;a href="https://pub.dev/packages/shelf"&gt;shelf&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;web-simple&lt;/code&gt;: Web application with core libraries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When run, &lt;code&gt;dart create&lt;/code&gt; will first create the project structure and then try to load all required libraries from &lt;a href="https://pub.dev"&gt;pub.dev&lt;/a&gt;. This behavior can be changed by specifying the &lt;code&gt;--no-pub&lt;/code&gt; flag when invoking the command.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Analogue from the world of Python: &lt;code&gt;poetry new project_name&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Analyzing and formatting
&lt;/h2&gt;

&lt;p&gt;When working with several people on one project, it is very often necessary to use a single style of code design, writing comments, using variable names, etc. In the Python world, we use linters &lt;a href="https://flake8.pycqa.org/"&gt;flake8&lt;/a&gt;, various formatters (&lt;a href="https://black.readthedocs.io/"&gt;black&lt;/a&gt;, &lt;a href="https://github.com/google/yapf"&gt;yapf&lt;/a&gt;, &lt;a href="https://pypi.org/project/autopep8%20/"&gt;autopep8&lt;/a&gt;) and &lt;a href="http://www.mypy-lang.org/"&gt;mypy&lt;/a&gt; for type checking. How can Dart help meet these challenges?&lt;/p&gt;

&lt;h3&gt;
  
  
  dart analyze
&lt;/h3&gt;

&lt;p&gt;The utility allows you to perform &lt;a href="https://dart.dev/guides/language/analysis-options"&gt;static analysis&lt;/a&gt; of the source code and point out errors and shortcomings.&lt;/p&gt;

&lt;p&gt;By default, the call will run a check and indicate errors and warnings, indicating the need to respond to the &lt;code&gt;info&lt;/code&gt; level with the &lt;code&gt;--fatal-infos&lt;/code&gt; flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart analyze &lt;span class="o"&gt;[&lt;/span&gt;&amp;lt;DIRECTORY&amp;gt; | &amp;lt;DART_FILE&amp;gt;]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The behavior of the analyzer can be adjusted using the configuration file or comments in the code. &lt;/p&gt;

&lt;h3&gt;
  
  
  dart format
&lt;/h3&gt;

&lt;p&gt;Using the command, we can style our source code according to the &lt;a href="https://dart.dev/guides/language/effective-dart/style#formatting"&gt;Dart guide&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart format
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will overwrite the files, formatting them "properly".&lt;/p&gt;

&lt;h3&gt;
  
  
  dart fix
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart fix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Applies automatic fixes to source code files, fixing two types of errors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;‎Analysis of issues related to automatic fixes (sometimes ‎‎called &lt;em&gt;quick-fixes&lt;/em&gt; or &lt;em&gt;code actions&lt;/em&gt;))&lt;/li&gt;
&lt;li&gt;‎Issues related to package API transfer information‎&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To see the changes, specify the &lt;code&gt;--dry-run&lt;/code&gt; flag; to apply &lt;code&gt;--apply&lt;/code&gt;; there is no &lt;em&gt;default&lt;/em&gt; behavior for this command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building / Compilation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  dart run
&lt;/h3&gt;

&lt;p&gt;Launching a Dart application is extremely simple, just run the following command in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart run bin/myapp.dart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are inside a package and in the &lt;code&gt;bin&lt;/code&gt; directory there is a dart file with the same name as the package name, then the application can be done without specifying the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$dart&lt;/span&gt; run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is also possible to run applications from the packages specified in the dependencies to the current. For example, if your application has a dependency on the package &lt;code&gt;foo&lt;/code&gt;, to run a program in this package, just call the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart run foo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or specify a different program inside the &lt;code&gt;foo&lt;/code&gt; package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart run foo:bar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Arguments and flags
&lt;/h4&gt;

&lt;p&gt;Often when developing, you need to pass arguments to the &lt;code&gt;main()&lt;/code&gt; function, for this you need to pass them at startup after specifying the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart run bin/myapp.dart arg1 arg2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also specify additional flags, for example, to debug the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart run &lt;span class="nt"&gt;--enable-asserts&lt;/span&gt; bin/myapp.dart arg1 arg2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  dart compile
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;dart compile&lt;/code&gt; command allows you to compile a Dart program for the target platform. The output you specify with a subcommand can either include the Dart runtime or be a module (also known as a snapshot).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart compile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;exe&lt;/code&gt; - executable - A standalone, architecture-specific executable containing source code compiled to native code and a small Dart runtime.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;aot-snapshot&lt;/code&gt; - AOT module - An architecture-specific file containing source code compiled to native code, but &lt;strong&gt;does not contain&lt;/strong&gt; the Dart runtime.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jit-snapshot&lt;/code&gt; - JIT Module - An architecture-specific file with an intermediate representation of the entire source code, as well as an optimized representation of the source code that was running during the training run of the program. JIT code may have higher peak performance than AOT code, but it depends on the training run.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kernel&lt;/code&gt; - kernel module - A portable intermediate representation of the source code. &lt;a href="https://dart.dev/tools/dart-compile#kernel"&gt;More&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;js&lt;/code&gt;: JavaScript -  JavaScript file with application. &lt;a href="https://dart.dev/tools/dart-compile#js"&gt;More&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  dart test
&lt;/h3&gt;

&lt;p&gt;Every program needs testing, this will reduce the number of errors during development and improve the quality of the application. For Python, there is an excellent framework that simplifies the work with tests, writing, and executing them - &lt;a href="https://docs.pytest.org/"&gt;Pytest&lt;/a&gt;. Running tests with it is extremely simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of the command is quite detailed and makes it easy to understand where and what went wrong when running the tests. Here's what it looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UizHpGQx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mvoaafpi86u7x4oir16a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UizHpGQx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mvoaafpi86u7x4oir16a.png" alt="Pytest example" width="800" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Testing in Dart is done with the &lt;code&gt;dart test&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Several flags such as &lt;code&gt;--name&lt;/code&gt; (&lt;code&gt;-n&lt;/code&gt;), &lt;code&gt;--tags&lt;/code&gt; (&lt;code&gt;-t&lt;/code&gt;), or &lt;code&gt;--exclude-tags&lt;/code&gt; (&lt;code&gt;-x&lt;/code&gt;) allow you to control which tests will be run. If several flags are specified, then tests that satisfy all conditions at once will be executed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZgRzw3Tz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fjo69t4d06peyrujo04u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZgRzw3Tz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fjo69t4d06peyrujo04u.png" alt="dart test example" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Package management
&lt;/h2&gt;

&lt;h3&gt;
  
  
  dart pub
&lt;/h3&gt;

&lt;p&gt;Python has a built-in &lt;code&gt;pip&lt;/code&gt; utility that allows you to easily manage packages, install, upgrade, and remove them. For more control, there are also third-party tools like poetry. Dart also has a tool that makes it easier to work with external dependencies - this is &lt;code&gt;dart doc&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The possibilities of &lt;code&gt;dart pub&lt;/code&gt; are much wider than installing and removing packages. With it, you can manage the local package cache, publish packages to &lt;a href="https://pub.dev"&gt;pub.dev&lt;/a&gt;, etc.&lt;/p&gt;

&lt;p&gt;For example, consider installing a package in Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install &lt;/span&gt;django
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will install the up-to-date version of the Django package, however, it will not write it as a dependency, which means that on a new installation, you need to learn about this dependency somehow.&lt;/p&gt;

&lt;p&gt;The same can be done in Dart 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;&lt;span class="nv"&gt;$ &lt;/span&gt;dart pub add shelf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, the package &lt;a href="https://pub.dev/packages/shelf"&gt;shelf&lt;/a&gt; will be added to the project, specified as a dependency in &lt;a href="https://dart.dev/tools/pub/pubspec"&gt;pubspec.yml&lt;/a&gt; and loaded into the cache.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Analogs in Python: &lt;a href="https://pip.pypa.io/en/stable/"&gt;pip&lt;/a&gt;, &lt;a href="https://python-poetry.org/"&gt;poetry&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  dart doc
&lt;/h3&gt;

&lt;p&gt;An important part of the development of applications and libraries is the documentation of functionality and source code. And for this, Dart has a special utility, which is extremely easy to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart doc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1yTWylGy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bbdoiqw0tpoylnui7nje.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1yTWylGy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bbdoiqw0tpoylnui7nje.png" alt="Sample generated by the dart doc documentation" width="800" height="697"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dart allows you to use comments and markup in your code to describe classes, functions, modules, and other structures. We'll look at these in more detail in a separate article, but for now, we'll mention that Dart handles special document comments. You can read about how to make documentation as effective as possible in the article &lt;a href="https://dart.dev/guides/language/effective-dart/documentation"&gt;Effective Dart&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Analogues in Python can be the generator &lt;a href="https://www.sphinx-doc.org/"&gt;Sphinx&lt;/a&gt; or &lt;a href="https://pdoc3.github.io/pdoc/"&gt;pdoc&lt;/a&gt;, their capabilities are far beyond the capabilities of &lt;code&gt;dart doc&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;We have reviewed some of the commands available using the &lt;code&gt;dart&lt;/code&gt; utility, some of them require a deeper understanding. However, even this cursory glance gives an idea of ​​its capabilities and convenience available "out of the box" for the developer.&lt;/p&gt;

&lt;p&gt;Next, we'll start diving into the Dart language and compare it to Python.&lt;/p&gt;

</description>
      <category>python</category>
      <category>dart</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>From Python to Dart - Day 1, Hello Dart</title>
      <dc:creator>Andrey M</dc:creator>
      <pubDate>Wed, 02 Mar 2022 08:14:55 +0000</pubDate>
      <link>https://dev.to/meamka/from-python-to-dart-344b</link>
      <guid>https://dev.to/meamka/from-python-to-dart-344b</guid>
      <description>&lt;p&gt;Many developers during their work develop in a certain area and do not always consider technologies that are on the periphery of their professional tasks. However, over time, the horizons begin to expand, developers of server applications begin to look towards client applications and vice versa; those who use interpreted languages ​​look towards compiled ones; others are looking at completely different areas showing interest in the field of DevOps and others. To tame the interest of some of them, we'll talk about how the &lt;a href="https://dart.dev"&gt;Dart&lt;/a&gt; language can help Python developers and why they need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  About Dart
&lt;/h2&gt;

&lt;p&gt;Dart is a compiled language born somewhere in Google more than 10 years ago. At some point in time, it was positioned as an alternative to JavaScript for developing client applications, later changing its direction towards a universal language for both client applications using &lt;a href="https://flutter.dev/"&gt;Flutter&lt;/a&gt; and server applications.&lt;/p&gt;

&lt;p&gt;Dart is an object-oriented, class-based language with a garbage collector that is inspired by C, C#, JavaScript, and many more. Dart applications can be compiled into binary code for both desktop x86 systems and mobile ARM processors; can be run in a virtual machine, thereby providing hot-reloading and, as a result, fast development; and even web apps can be implemented with Dart and Flutter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Dart
&lt;/h2&gt;

&lt;p&gt;Many OS users do not need any steps to use Python, it comes pre-installed on macOS, most if not all Linux and *BSD based distributions, and only Windows users will need to download and run the installer. Things are different with Dart.&lt;/p&gt;

&lt;p&gt;The easiest way to try Dart is to use &lt;a href="https://dartpad.dev"&gt;DartPad&lt;/a&gt;, an editor available online that allows you to write small applications.&lt;/p&gt;

&lt;p&gt;To install Dart on a local computer, go to the site &lt;a href="https://dart.dev/get-dart"&gt;https://dart.dev/get-dart&lt;/a&gt; and follow one of the paths according to your operating system. So, for macOS users using &lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt; just use the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;dart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An alternative option would be to &lt;a href="https://docs.flutter.dev/get-started/install/"&gt;install&lt;/a&gt; Flutter, Dart will be installed as a part of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dart CLI utility
&lt;/h2&gt;

&lt;p&gt;After installation, the &lt;code&gt;dart&lt;/code&gt; console utility will become available to you, with which you can perform many actions that help in development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create new projects with &lt;code&gt;dart create&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;run them in a virtual machine with &lt;code&gt;dart run&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;compile to native code (&lt;a href="https://dart.dev/tools/dart-compile#exe"&gt;ahead-of-time&lt;/a&gt;) using &lt;code&gt;dart compile&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;format source code with &lt;code&gt;dart format&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;generate documentation with &lt;code&gt;dart doc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;and much more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When using Python, we are used to installing dependencies using pip or poetry packages, but can Dart offer something similar? The answer is yes, Dart comes with a &lt;code&gt;dart pub&lt;/code&gt; utility that makes it easy to install, update, publish packages, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hello Dart
&lt;/h2&gt;

&lt;p&gt;Getting to know Dart would not be complete if we did not try to write the simplest application in this language. Let's correct this omission.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Define a function&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sayHi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Hello, &lt;/span&gt;&lt;span class="si"&gt;$name&lt;/span&gt;&lt;span class="s"&gt;.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Prints a message to the console.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// With this function, the application starts its work.&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'Pythonista'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Define and initialize the variable.&lt;/span&gt;
   &lt;span class="n"&gt;sayHi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Call the function.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, a Dart program starts its execution from the &lt;code&gt;main&lt;/code&gt; function. In it we declare a variable &lt;code&gt;name&lt;/code&gt;, its type will be automatically deduced based on the assigned value. After that, we call the function, passing the variable into it. Unlike Python, Dart does not rely on indentation and uses curly braces to separate blocks of code, as well as semicolons to indicate the end of executable statements. In the following chapters, we will look at the language in detail in light of how it compares to Python.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BLfqKISl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/68zgi3ildlnkacmpk8mg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BLfqKISl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/68zgi3ildlnkacmpk8mg.png" alt="Image description" width="800" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;We will learn how to create projects using the &lt;code&gt;dart&lt;/code&gt; utility and consider its capabilities in detail.&lt;/p&gt;

</description>
      <category>python</category>
      <category>dart</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>What's new in Norka 1.0</title>
      <dc:creator>Andrey M</dc:creator>
      <pubDate>Tue, 22 Feb 2022 13:16:28 +0000</pubDate>
      <link>https://dev.to/meamka/whats-new-in-norka-10-2i6m</link>
      <guid>https://dev.to/meamka/whats-new-in-norka-10-2i6m</guid>
      <description>&lt;p&gt;Nearly two years ago, Norka was born, a note-taking application made specifically for elementary OS and also distributed via Flathub. This version was far from version 1.0, its functionality was limited only to essential things: editing, searching, autosaving. Later, it introduced document search, export to various formats, spell checking, convenient keyboard shortcuts for editing, the ability to preview documents in HTML and statistics, etc. This was enough to start, but there was room for improvement. One possibility might be the ability to group notes in a folder and structure the user’s resources in a certain way. So what’s new comes in version 1.0?&lt;/p&gt;

&lt;h2&gt;
  
  
  Folders
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8X_HZPVV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ullk5epq6ail37txipv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8X_HZPVV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ullk5epq6ail37txipv.png" alt="Folders and documents" width="800" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main and most important innovation is the ability to structure documents using folders. Folders can be created by clicking on a button in the header bar or by dragging documents onto each other. In this case, you will see a window displaying a suggestion for a folder name.&lt;/p&gt;

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

&lt;p&gt;Folders can be moved from one to another. The level is not limited, but there is a limit on a path length, which, by the way, are found under the title of the window in the title. Also, some characters cannot be used in the names, we plan to fix this in the next releases.&lt;/p&gt;

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

&lt;p&gt;The backup function also includes the structure of the library and exports documents by putting them in the right folders. This way you will get a complete copy of the library on disk.&lt;/p&gt;

&lt;h2&gt;
  
  
  New fonts and updated theme
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1Bsq8hSd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tf3t88sh8rr70olhsepv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1Bsq8hSd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tf3t88sh8rr70olhsepv.png" alt="New fonts and updated theme" width="800" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We continue to work on using Norka not only in terms of functionality but also in terms of UI. Starting with version 1.0 Norka will use the iA Writer Duospace font. Thank you for sharing them with the community. The color scheme of the editor has also been updated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Actions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--naa07b_E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z5nqvjxnh93gulndye0j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--naa07b_E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z5nqvjxnh93gulndye0j.png" alt="quick note shortcut" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In many desktop environments, it is possible to set up global hotkeys to trigger specific actions in applications. For example, take a screenshot or share a file. Now you can use the command to quickly take notes with Norka.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flatpak run com.github.tenderowl.norka --new="Quick Note"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This action can also be implemented as a command to call from hot corners in GNOME or elementary OS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Specifying the language for spell checking
&lt;/h2&gt;

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

&lt;p&gt;In one of the latest releases, we switched from GtkSpell to use GSpell, but at the same time, Norka lost the ability to specify which language to use for this check. And while this isn’t a problem if you’re writing in English, it creates problems for writers in other languages. This setting can now be changed in the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Import and formatting fixes
&lt;/h2&gt;

&lt;p&gt;As with spell checking, one might not have noticed that for non-Latin languages, hotkeys are used to format text, leading to unexpected results. For example, when inserting a title, some of the text could be erased. Now we have fixed this problem, Norka correctly inserts formatting without text loss.&lt;/p&gt;

&lt;p&gt;We also fixed auto-completion of lists: when pressing Enter, Norka will check if an item text has been entered, and if not, then inserting the list formatting ends.&lt;/p&gt;

&lt;p&gt;For those who use drag-n-drop to import, the problem turned into the fact that when importing several files in sequence, the documents / those that were used the first time that time were re-imported instead of the last ones. We have fixed this issue, there is no more reason to worry about erroneous imports and prevent the deletion of redundant copies.&lt;/p&gt;

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

&lt;p&gt;As always Norka available on the elementary &lt;a href="https://appcenter.elementary.io/com.github.tenderowl.norka/"&gt;AppCenter&lt;/a&gt; and &lt;a href="https://flathub.org/apps/details/com.github.tenderowl.norka"&gt;Flathub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We keep improving Norka even further. We aimed to become the best writing app and note editor for Linux in the future, and possibly not only a Linux.&lt;/p&gt;

&lt;p&gt;Thanks to everyone who uses Norka!&lt;/p&gt;

</description>
      <category>norka</category>
      <category>markdown</category>
      <category>editor</category>
      <category>elementaryos</category>
    </item>
    <item>
      <title>How to use elementary OS Contractor to simplify your daily routines.</title>
      <dc:creator>Andrey M</dc:creator>
      <pubDate>Sat, 23 Oct 2021 21:09:58 +0000</pubDate>
      <link>https://dev.to/meamka/how-to-use-elementary-os-contractor-to-simplify-your-daily-routines-mc4</link>
      <guid>https://dev.to/meamka/how-to-use-elementary-os-contractor-to-simplify-your-daily-routines-mc4</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Almost two years ago I lost my iMac and it brought me an idea to see what's changed in the Linux world for 10 years. Starting from Ubuntu and Fedora I finally came to the elementary OS project's website. And it was quite astonishing. In comparison to the other distributions elementary had its view on how the operating system should view, how to make apps, its own design language and &lt;a href="https://docs.elementary.io/develop/"&gt;developers documentation&lt;/a&gt;. Thereby the decision to move to this OS was easy.&lt;/p&gt;

&lt;p&gt;For now, it is almost two years since I moved from macOS to elementary OS as my daily driver. And, as I said earlier, I'm a developer. After looking for a native text editor I made myself think to make &lt;a href="https://tenderowl.com/work/norka/"&gt;Norka&lt;/a&gt;. But, this article is about the distinct application. Actually, I'm not the author of it, the app is already a part of elementary itself - &lt;a href="https://github.com/elementary/contractor"&gt;Contractor&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contractor
&lt;/h2&gt;

&lt;p&gt;The idea is very simple: users can write a contract - a file which instructs the Contractor how to call the command - and it comes available in any supported apps: Files, Photos, etc. &lt;/p&gt;

&lt;h2&gt;
  
  
  Action
&lt;/h2&gt;

&lt;p&gt;I suppose you're already got the idea of how the Contractor can help you in your daily work, but let's make a contract that... well.. help you share any file via Telegram. What do we need for it?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;install Telegram&lt;/li&gt;
&lt;li&gt;get the command&lt;/li&gt;
&lt;li&gt;create a contract&lt;/li&gt;
&lt;li&gt;test it!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because it differences in one case of installation on another I will write for the &lt;a href="https://flathub.org/apps/details/org.telegram.desktop"&gt;Flathub version&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Let's dive in!&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Telegram
&lt;/h3&gt;

&lt;p&gt;As of &lt;a href="https://elementary.io"&gt;elementary OS&lt;/a&gt; user, I can simply go to flathub.org and press the "Install" button. Sideload app do the job. But what about other distros? Well, the right way is completely covered on the Flathub site so we don't wanna go through all steps :)&lt;/p&gt;

&lt;h3&gt;
  
  
  Get the right command
&lt;/h3&gt;

&lt;p&gt;To write a good contract we need to find out what command does the job we need. In some cases, it could be easily extracted from &lt;code&gt;--help&lt;/code&gt; info or &lt;code&gt;man&lt;/code&gt; pages. Luckily Telegram command-line switches are fully described in the GitHub Wiki: &lt;a href="https://github.com/telegramdesktop/tdesktop/wiki/Command-Line-Switches"&gt;https://github.com/telegramdesktop/tdesktop/wiki/Command-Line-Switches&lt;/a&gt;. &lt;code&gt;-sendpath &amp;lt;file&amp;gt;&lt;/code&gt; - the desired switch.&lt;/p&gt;

&lt;p&gt;One part is done, let's figure out the second one. To run the application with a command-line switch installed via Flatpak we have to call &lt;code&gt;flatpak run&lt;/code&gt; command. Thus our command will look 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;flatpak run org.telegram.desktop &lt;span class="nt"&gt;-sendpath&lt;/span&gt; %f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is already enough to make a contract!&lt;/p&gt;

&lt;h3&gt;
  
  
  Contract
&lt;/h3&gt;

&lt;p&gt;Every contract should be placed inside &lt;code&gt;~/.local/share/contractor&lt;/code&gt; if we talking about a specific user or inside &lt;code&gt;/usr/share/contractor&lt;/code&gt; for the system-wide availability.&lt;/p&gt;

&lt;p&gt;Simple &lt;code&gt;.contract&lt;/code&gt; file example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Contractor Entry]&lt;/span&gt;
&lt;span class="py"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Mount&lt;/span&gt;
&lt;span class="py"&gt;MimeType&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;application/x-cd-image;application/x-raw-disk-image&lt;/span&gt;
&lt;span class="py"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;gnome-disk-image-mounter %f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example shows how to make a command that will mount disk images to the filesystem. We need something different.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;telegram-share.contract&lt;/code&gt; file and open it in &lt;a href="https://github.com/elementary/code"&gt;Code&lt;/a&gt; or your text editor of choice.&lt;br&gt;
Change &lt;code&gt;Name&lt;/code&gt; to &lt;code&gt;Share via Telegram&lt;/code&gt; and &lt;code&gt;Exec&lt;/code&gt; field to a command we discovered earlier. If English is not your primary language you can add localized &lt;code&gt;Name&lt;/code&gt; by adding &lt;code&gt;Name[language code]&lt;/code&gt; option. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="err"&gt;Name&lt;/span&gt;&lt;span class="nn"&gt;[ru]&lt;/span&gt;&lt;span class="err"&gt;=Поделиться&lt;/span&gt; &lt;span class="err"&gt;в&lt;/span&gt; &lt;span class="err"&gt;Telegram&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Last but not least we have to set what mime-types has to activate the Share command. Of course, it doesn't mean to be only disk images &lt;br&gt;
and here is the special type - &lt;code&gt;!inode&lt;/code&gt; - which means any file you select no matter archive it or pdf.&lt;/p&gt;

&lt;p&gt;Let's see what we've got!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Contractor Entry]&lt;/span&gt;
&lt;span class="py"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Share via Telegram&lt;/span&gt;
&lt;span class="err"&gt;Name&lt;/span&gt;&lt;span class="nn"&gt;[ru]&lt;/span&gt;&lt;span class="err"&gt;=Поделиться&lt;/span&gt; &lt;span class="err"&gt;в&lt;/span&gt; &lt;span class="err"&gt;Telegram&lt;/span&gt;
&lt;span class="py"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;telegram&lt;/span&gt;
&lt;span class="py"&gt;MimeType&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;!inode;&lt;/span&gt;
&lt;span class="py"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;flatpak run org.telegram.desktop -sendpath %f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now save your contract and test it by clicking on any file in Files and pressing the "Share via Telegram" option.&lt;/p&gt;

&lt;p&gt;More examples listed in the &lt;a href="https://github.com/elementary/contractor#examples"&gt;Contractor repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Notification
&lt;/h3&gt;

&lt;p&gt;Sometimes you wanna indicate to yourself when the contract will be completed. To make it happen it's not enough to call just one command, you need to send a notification somehow. Again, elementary already has an application for it named &lt;code&gt;notify-send&lt;/code&gt;, and all we need is to combine all the commands into one with help of &lt;code&gt;sh&lt;/code&gt;. As you may see in the Tips section it is easy enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;sh -c "flatpak run org.telegram.desktop -sendpath %f &amp;amp;&amp;amp; notify-send 'File sent' '%f successfully sent via Telegram'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Final version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Contractor Entry]&lt;/span&gt;
&lt;span class="py"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Share via Telegram&lt;/span&gt;
&lt;span class="err"&gt;Name&lt;/span&gt;&lt;span class="nn"&gt;[ru]&lt;/span&gt;&lt;span class="err"&gt;=Поделиться&lt;/span&gt; &lt;span class="err"&gt;в&lt;/span&gt; &lt;span class="err"&gt;Telegram&lt;/span&gt;
&lt;span class="py"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;telegram&lt;/span&gt;
&lt;span class="py"&gt;MimeType&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;!inode;&lt;/span&gt;
&lt;span class="py"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;sh -c "flatpak run org.telegram.desktop -sendpath %f &amp;amp;&amp;amp; notify-send 'File sent' '%f successfully sent via Telegram'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install .deb packages
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Contractor Entry]&lt;/span&gt;
&lt;span class="py"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Install app&lt;/span&gt;
&lt;span class="err"&gt;Name&lt;/span&gt;&lt;span class="nn"&gt;[ru]&lt;/span&gt;&lt;span class="err"&gt;=Установить&lt;/span&gt; &lt;span class="err"&gt;приложение&lt;/span&gt;
&lt;span class="py"&gt;MimeType&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;application/vnd.debian.binary-package&lt;/span&gt;
&lt;span class="py"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Quickly install .deb package&lt;/span&gt;
&lt;span class="py"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;sh -c "pkexec apt install %u &amp;amp;&amp;amp; notify-send 'the App installed' -a Apt"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tips:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use pkexec to ask for root permissions. Example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;  &lt;span class="py"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;pkexec chmod +x %U&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;To call multiple commands at once try to use sh:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;  &lt;span class="py"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;sh -c "echo 'step 1' &amp;amp;&amp;amp; notify-send 'Done' &amp;amp;&amp;amp; echo 'step 2'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>elementary</category>
      <category>linux</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to use WebSockets with Python and Gtk+</title>
      <dc:creator>Andrey M</dc:creator>
      <pubDate>Mon, 05 Oct 2020 23:26:31 +0000</pubDate>
      <link>https://dev.to/meamka/python-gtk-and-websocket-kjm</link>
      <guid>https://dev.to/meamka/python-gtk-and-websocket-kjm</guid>
      <description>&lt;p&gt;Hey there! I'm here to present you an amazing trip to the native apps with WebSockets! In this current case we will be using these technologies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;GTK+&lt;/li&gt;
&lt;li&gt;Libsoup&lt;/li&gt;
&lt;li&gt;Websocket messaging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're wondering how to build a native GTK+ chat app, let's dive with me!&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/WebSocket"&gt;WebSockets&lt;/a&gt; is a protocol designed to provide a consistent connection between the client and a server where both can send data to each other. It's like a wire over the Internet or a tube, distinct of regular HTTP, where the client only can send data to the server and it gets a response immediately.&lt;/p&gt;

&lt;p&gt;Benefits of this approach are quite obvious: the server can push the data to the client when it comes to server from another client or generated somewhere on the backend. And the client doesn't need to refresh the page or do something to fetch new data, it just comes to the client by itself.&lt;/p&gt;

&lt;p&gt;More information about WebSockets you can find on the &lt;a href="http://websocket.org/aboutwebsocket.html"&gt;websocket.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What I want to show you in this article it is how to connect to a WebSocket server and send or receive data from it in a native GTK+ application.&lt;/p&gt;

&lt;p&gt;I will code my app in elementary OS using &lt;a href="https://wiki.gnome.org/Apps/Builder"&gt;GNOME Builder&lt;/a&gt;, but the same logic should work anywhere where &lt;a href="https://gtk.org"&gt;GTK+&lt;/a&gt; and &lt;a href="https://libsoup.org"&gt;libsoup&lt;/a&gt; are available and all code could be easily adapted even for macOS.&lt;/p&gt;

&lt;h2&gt;
  
  
  UI
&lt;/h2&gt;

&lt;p&gt;The app logic is quite simple yet representative. The UI will consist of two screens (&lt;code&gt;Gtk.Grid&lt;/code&gt;) placed in &lt;code&gt;Gtk.Stack&lt;/code&gt;. The first screen contains widgets required to connect to the server such as &lt;code&gt;Gtk.Entry&lt;/code&gt; for server address, button to initiate a connection and a spinner to show the state.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zOA4TnVC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/6peeanzovpi8tbpp38rn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zOA4TnVC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/6peeanzovpi8tbpp38rn.png" alt="First page" width="758" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second screen is more complex. Purpose of this is to enter the message, send it to the server and show the server's response in &lt;code&gt;Gtk.TextView&lt;/code&gt;. Thus we need &lt;code&gt;Gtk.Grid&lt;/code&gt; to place widgets. &lt;code&gt;Gtk.Entry&lt;/code&gt; and &lt;code&gt;Gtk.Button&lt;/code&gt; the same way we did it on the first page. And to display log we need &lt;code&gt;Gtk.TextView&lt;/code&gt; placed within &lt;code&gt;Gtk.ScrolledWindow&lt;/code&gt; in case there will be much more logs than the window can contain and the scrolling will be as much useful feature as it could :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gd2a6R9O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/b9we4xc3cwi202qr5c86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gd2a6R9O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/b9we4xc3cwi202qr5c86.png" alt="Second page" width="758" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Connection page
&lt;/h3&gt;

&lt;p&gt;Let's start building! Create a new project in Builder, as the language, we will use Python 3.6+.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M7Hv6zcE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/6s87by1ljgku3jsp9h5p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M7Hv6zcE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/6s87by1ljgku3jsp9h5p.png" alt="New project" width="800" height="684"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;IDE will generate a base app structure with all we need, and all we need is just two files: &lt;code&gt;window.ui&lt;/code&gt; and &lt;code&gt;window.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Firstly, we need a correct UI for our app, so open &lt;code&gt;window.ui&lt;/code&gt;. file and replace the "hello world" &lt;code&gt;Label&lt;/code&gt; with &lt;code&gt;Gtk.Stack&lt;/code&gt;. We will need two pages. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YrJBqQDr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/h289zyc16lxbjwx4o840.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YrJBqQDr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/h289zyc16lxbjwx4o840.png" alt="Stack properties" width="476" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Name the first screen "connection", and place onto it &lt;code&gt;Gtk.Grid&lt;/code&gt; with 3 rows and columns. In the central cell place &lt;code&gt;Gtk.Box&lt;/code&gt; with 4 rows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Gtk.Label&lt;/code&gt; with text "Connection"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Gtk.Entry&lt;/code&gt;. Set its id to "host_entry"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Gtk.Button&lt;/code&gt; with id "connect_btn"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Gtk.Spinner&lt;/code&gt;. Call it whatever you like, mine is just a "spinner" :)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's enough for the "Connection" page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chat page
&lt;/h3&gt;

&lt;p&gt;Moving further. The second screen is a bit more complex. Again, we need &lt;code&gt;Gtk.Grid&lt;/code&gt; to put all the widgets we need. But for now, it will be a grid with just 2 rows and 2 columns.&lt;/p&gt;

&lt;p&gt;First row with two widgets in its own cells:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Gtk.Entry&lt;/code&gt; with id "message_entry"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Gtk.Button&lt;/code&gt; with id "send_btn"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the second row place &lt;code&gt;Gtk.ScrolledWindow&lt;/code&gt;, no id required because we don't need to call its method. Inside this ScrolledWindow put a new &lt;code&gt;Gtk.TextView&lt;/code&gt; widget. Set its id to "log_view".&lt;/p&gt;

&lt;p&gt;To make it looks more convenient, set &lt;em&gt;width&lt;/em&gt; = 2 in the container's props inside attribute editor for ScrolledWindow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AcU-LIAf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/oiu7wgjgguqg4g0dn4ue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AcU-LIAf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/oiu7wgjgguqg4g0dn4ue.png" alt="ScrolledWindow packing" width="370" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Logic
&lt;/h2&gt;

&lt;p&gt;Ok, out UI is ready enough to build some logic for it, finally :)&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;window.py&lt;/code&gt; and add class vars to connect with widgets from the &lt;code&gt;.ui&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Stack with pages
&lt;/span&gt;&lt;span class="n"&gt;screens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Gtk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Child&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Connection page widgets
&lt;/span&gt;&lt;span class="n"&gt;host_entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Gtk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Child&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;connect_btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Gtk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Child&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;disconnect_btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Gtk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Child&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;spinner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Gtk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Child&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Chat page widgets
&lt;/span&gt;&lt;span class="n"&gt;send_btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Gtk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Child&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;message_entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Gtk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Child&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;log_view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Gtk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Child&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Declare some class-vars
&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, now we are able to call methods of these widgets. But also, we have to handle its signals. Let's connect "connect_btn":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Some app logic
&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect_btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'clicked'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on_connect_clicked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_connect_clicked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Check if there is a text inside the host_entry
&lt;/span&gt;    &lt;span class="c1"&gt;# and grab focus if its empty
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host_entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host_entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grab_focus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="c1"&gt;# Show user we are trying to connect
&lt;/span&gt;    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spinner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Init libsoup Session, create message and start connection
&lt;/span&gt;    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host_entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;websocket_connect_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on_connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above is quite straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get the server address&lt;/li&gt;
&lt;li&gt;Create new &lt;a href="https://lazka.github.io/pgi-docs/#Soup-2.4/classes/Session.html"&gt;&lt;code&gt;Session&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Init the connection with &lt;a href="https://lazka.github.io/pgi-docs/#Soup-2.4/classes/Session.html#Soup.Session.websocket_connect_async"&gt;&lt;code&gt;websocket_connect_async&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a callback for connection function, we put &lt;code&gt;on_connection&lt;/code&gt; method, which takes the result of this operation and finish the process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Finish connection process
&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;websocket_connect_finish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# If we here, the connection went correctly
&lt;/span&gt;        &lt;span class="c1"&gt;# Connect `message` handler to the connection
&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Show to user all is OK and switch to the Chat page
&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_visible_child_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'chat'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;disconnect_btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_visible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# In case something goes wrong just print an exception
&lt;/span&gt;        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Don't forget to show a user that process is finished.
&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spinner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are almost done! All we need to do more is to handle click event from the "send_btn" and display messages in the "log_view".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;'&amp;lt;b&amp;gt;RECEIVED:&amp;lt;/b&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_data&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert_markup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_start_iter&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                              &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                              &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Could it be more simple than that? 😉 Just to display a message in a more readable way we add some Pango markup and use &lt;a href="https://lazka.github.io/pgi-docs/#Gtk-3.0/classes/TextBuffer.html#Gtk.TextBuffer.insert_markup"&gt;&lt;code&gt;insert_markup&lt;/code&gt;&lt;/a&gt; method of &lt;code&gt;Gtk.TextBuffer&lt;/code&gt; to... insert markup!&lt;/p&gt;

&lt;p&gt;Last, but not least required thing is a handler for "send_btn" signal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_send_clicked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Get the message from the Entry
&lt;/span&gt;    &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message_entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# If there is no message - grab focus.
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message_entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grab_focus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="c1"&gt;# Send a text to the server.
&lt;/span&gt;    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our simple case, all we need is just the &lt;a href="https://lazka.github.io/pgi-docs/#Soup-2.4/classes/WebsocketConnection.html#Soup.WebsocketConnection.send_text"&gt;&lt;code&gt;send_text&lt;/code&gt;&lt;/a&gt; method. But libsoup could do a lot of different stuff, such as &lt;a href="https://lazka.github.io/pgi-docs/#Soup-2.4/classes/WebsocketConnection.html#Soup.WebsocketConnection.send_binary"&gt;&lt;code&gt;send_binary&lt;/code&gt;&lt;/a&gt; or emit a signal if something &lt;a href="https://lazka.github.io/pgi-docs/#Soup-2.4/classes/WebsocketConnection.html#Soup.WebsocketConnection.signals.error"&gt;goes wrong&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gAPo8Si---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/6th5fr8cow67bmb8nh3z.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gAPo8Si---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/6th5fr8cow67bmb8nh3z.gif" alt="Spacebeam" width="648" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Simple yet descriptive example of how to start building your GTK+ app with WebSockets inside. Maybe you will create a new chat app? &lt;/p&gt;

&lt;p&gt;Stay tuned if you want to read more! Or go to the docs from the Links section. &lt;/p&gt;

&lt;p&gt;Anyway, good luck!&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;Source code:&lt;br&gt;
 &lt;a href="https://github.com/amka/pygobject-gtk-websocket-app"&gt;https://github.com/amka/pygobject-gtk-websocket-app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Docs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://websocket.org/"&gt;https://websocket.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lazka.github.io/pgi-docs/#Gtk-3.0"&gt;https://lazka.github.io/pgi-docs/#Gtk-3.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lazka.github.io/pgi-docs/#Soup-2.4"&gt;https://lazka.github.io/pgi-docs/#Soup-2.4&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>gtk</category>
      <category>websocket</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
