Tutorial: How to Write a Simple V Application Step by Step

Building a simple utility to display the top V repositories based on the number of stars

When I decided to write a training article on V, I initially had no specific idea in mind. After some consideration, I decided to combine the article with the V community itself by developing a utility that displays the top repositories on V based on the number of stars they have on GitHub. This will help identify the most popular repositories and contributors within the V community.

Of course, the V language and projects by the V organization will be included in the leaderboards, but I still wonder who was able to accumulate more stars outside the language organization.

Installing V

If you haven’t installed V yet, then follow the instructions from the Installation article from documentation.

Creating a project

Let us create a new project, V provides the handy v new command for this:

v new stars

The command will ask you to provide additional information about the project, which you can skip by pressing Enter.

As a result, the command will create a new folder stars and add several files to it:

cd stars
tree .

# .
# ├── src
# │   └── main.v
# └── v.mod
#
# 2 directories, 2 files

Let us check that everything is fine by running our project:

v run .

# Hello, World!

Fetching

I have already prepared the URL from which we can fetch the data. You can open it in your browser and view the JSON output: https://api.github.com/search/repositories?sort=stars&order=desc&q=language:v

GitHub returns JSON with the total number of repositories, and the items field contains an array of repositories that we need. It’s already pre-sorted by stars in descending order because we specified that in the part sort=stars&order=desc of request in the URL.

Now, our task is simply to fetch the data from this URL and output it to the terminal. Open the file src/main.v in your favorite editor or IDE. You can see the available plugins for your editor in documentation.

In this article, we will use the JetBrains IDE with the IntelliJ V plugin, as this bundle provides the best V development experience.

Screenshot showing the IDE with boilerplate code generated by V

In order to fetch the list of repositories, we need the net.http module. To make a simple GET request, we can use the get() method, which takes a request URL as a parameter.

Let us import this module. You can read more about imports in documentation.

import net.http

Next, add a constant with GitHub URL:

const github_repositories_url = 'https://api.github.com/search/repositories?sort=stars&order=desc&q=language:v'

Remove the current code from the main() function and add a http.get() call to fetch the data from the URL, and output the response body.

fn main() {
	response := http.get(github_repositories_url)!

	println(response.body)
}

Since http.get() returns the Result, we must either handle the error case or propagate it up.

If you propagate an error in the main() function, the program will panic because it is not possible to propagate the error further up the call stack.

As a result, we will get the following code:

module main

import net.http

const github_repositories_url = 'https://api.github.com/search/repositories?sort=stars&order=desc&q=language:v'

fn main() {
	response := http.get(github_repositories_url)!

	println(response.body)
}

Try to execute it using the v run . and look at the result.

JSON magic

From the GitHub response, we need only two fields, total_count and items. From items we need not all fields, only full_name, description, stargazers_count, and html_url.

The json module does not require describing all fields, we can specify only the necessary fields, and the rest will be ignored.

The json.decode() method accepts a structure that will be built during the parsing process and a string with JSON; in our case, it is the response.body.

So let us describe this structure. As we decided earlier, we only need total_count and items:

struct GitHubRepositoriesSearchAPI {
pub:
	total_count int
	items       []GitHubRepositoriesItem
}

items — is an array of structures, so we also need to provide a structure for it:

struct GitHubRepositoriesItem {
pub:
	full_name        string
	description      string
	stargazers_count int
	html_url         string
}

These are all the structures we need to describe the JSON response from GitHub. We only need to parse the response into a structure.

Add the following code after response := http.get(github_repositories_url)!:

repositories_result := json.decode(GitHubRepositoriesSearchAPI, response.body) or {
	panic('An error occurred during JSON parsing: ${err}')
}

In the code above, you may notice the variable err, which no one has declared before. This is a special variable that is defined in the or block, which contains the error that was returned from the function. The or block and the err variable are syntax sugar for unwrapping the Result or the Option type, you can read more about it in documentation.

Once we have the structure, we can work with the data the way we are used to in V. For example, to output the total number of repositories in V, we can add the following code:

println('The total repository count is ${repositories_result.total_count}')

V supports string interpolation, which allows us to include variables or expressions directly in strings. This feature makes it easy to format strings.

Make sure you have written everything correctly and run the code using the v run . command.

Screenshot showing the IDE with code and output with the total number of V repositories.

Let us display the list of repositories.

Display everything beautifully

All we need to do is iterate over the items array and output information about the repositories. V provides a for loop for this, which makes it easy to iterate through all the elements of the array.

for index, repository in repositories_result.items {
	// ...
}

If we do not need an index, we can simply omit it.

Now we need to display everything beautifully. But we will do it beautifully in the truest sense of the word. Let us not complicate this article by searching for a suitable module. I chose everything in advance. For color text output in the terminal, we will use the Mewzax.chalk module.

The standard library already contains the term module, which allows you to display colored text in the terminal, but I thought it would be more interesting to show how to use a third-party module.

Let us use the built-in package manager V to install it:

v install Mewzax.chalk

You can find the module README here.

Now import it:

import mewzax.chalk

And write the formatted output of repositories inside the body of the for loop:

for index, repository in repositories_result.items {
	colored_description := chalk.fg(repository.description, 'cyan')
	colored_star_count := chalk.fg(repository.stargazers_count.str(), 'green')

	println('#${index + 1} ${repository.full_name}')
	println('  URL: ${repository.html_url}')

	if repository.description != '' {
		println('  Description: ${colored_description}')
	}

	println('  Star count: ${colored_star_count}')
}

The if repository.description != '' condition was added in case there is no description in the repository, so we don’t output an empty string.

Run the code and look at the result.

Screenshot showing the IDE with code and output of the final version utility

Conclusion

From the obtained results, we can conclude that the top 3 projects on V by stars are now:

  1. cotowali/cotowali – A statically typed scripting language that transpiles into POSIX sh.
  2. nedpals/vex – Easy-to-use, modular web framework built for V.
  3. elliotchance/vsql – Single-file or PostgreSQL-server compatible transactional SQL database written in pure V.

Homework

  1. Try using search filters or the GitHub code to exclude V organization repositories so that you can only see community projects.
  2. Create a separate function for fetching data from the GitHub API, where the sorting type and order can be passed as arguments.

You can ask questions or share the results of your work in the comments below, or in Discord.

Source code: https://github.com/vlang-association/v-tutorial-stars