Part of Learn Lua with NeoVim

Learn Lua in Neovim: Hello World with print() & :!lua % | Episode 1

Sandy LaneSandy Lane

Video: Learn Lua in Neovim: Hello World with print() & :!lua % | Episode 1 by Taught by Celeste AI - AI Coding Coach

Take the quiz on the full lesson page
Test what you've read · interactive walkthrough

Hello World in Lua: print() and Running Code in Neovim

Your first Lua program. print() for output, :!lua % to run the current file from inside Neovim. The whole runtime in three lines.

Lua is the language behind Neovim plugins, Roblox, World of Warcraft addons, and a lot of game-engine scripting. This series teaches Lua from scratch while coding inside Neovim — two skills at once.

The first program is the canonical one: print "Hello, World!" and watch it appear.

Create the file

Inside Neovim:

:e hello.lua

:e (edit) opens a buffer; if the file doesn't exist, Neovim creates it on the next :w. The .lua extension tells Lua's interpreter (and Neovim) what kind of file this is.

The first line

print("Hello, World!")

print(...) is Lua's built-in output function. It takes any number of arguments, converts each to a string, and writes them to stdout separated by tabs, ending with a newline.

The string "Hello, World!" uses double quotes. Single quotes work too — 'Hello, World!' produces the same result. Pick whichever doesn't conflict with content ("It's me" vs 'She said "hi"').

Run the file

Save with :w, then run with:

:!lua %

Three pieces:

  • :! — run an external shell command from Neovim.
  • lua — the Lua interpreter installed on your system.
  • % — Neovim shorthand for "the current buffer's filename."

So :!lua % is "run the lua interpreter on this file." Output appears at the bottom of Neovim.

Add more lines

print("Hello, World!")

print("My name is Lua")

print("Welcome to")
print("Learn Lua in Neovim!")
print("Time to start coding!")

Each print() produces one line of output. Lua executes top to bottom; there's no main(), no compilation step, no boilerplate.

To open a new line below the cursor in Neovim, press o in normal mode. It opens the line and drops you into insert mode in one keystroke — much faster than : o or arrow + return.

Why no semicolons?

Lua treats newlines as statement separators by default. You can put semicolons (print("a"); print("b")) when stacking statements on one line, but they're optional and most code skips them.

What print actually does

print("a", 42, true)

Outputs a 42 true — three values, tab-separated, ending with newline. Internally:

  1. Each argument goes through tostring() to become a string.
  2. The result is written to standard output.

For more control over formatting, use io.write() (no automatic separators or newline) or string.format() (printf-style).

Common stumbles

:!lua % says command not found. Lua isn't installed. On macOS: brew install lua. On Ubuntu/Debian: sudo apt install lua5.4. On Windows: download from lua.org or use scoop install lua.

The output flashes and disappears. Neovim buffers :! output briefly. Press <Enter> to dismiss the prompt and return to your buffer; the output remains in the message history (:messages).

Forgot to save before running. :!lua % runs the file on disk, not the unsaved buffer. Always :w first. Or chain it: :w | !lua %.

Mixing tabs and spaces. Lua doesn't care about indentation (it's whitespace-insensitive), but mixed tabs/spaces look wrong in diffs and other tools. Pick one. Two-space indent is the community norm.

What's next

Episode 2: variables and types. local, the four basic types (string, number, boolean, nil), and the type() function for inspection.

Recap

print("text") writes a line to the screen. :!lua % runs the current file from inside Neovim. Lua runs top-to-bottom — no main() entry point. Save with :w before running. Press o in normal mode to add a new line below.

Next episode: variables and types.

Ready? Take the quiz on the full lesson page →
Test what you've learned. Watch the lesson and try the interactive quiz on the same page.