Monday, 20 July 2026

Cursor Movement and Screen Control

  

Terminals are not limited to printing text line by line. Using ANSI escape sequences, applications can control where text appears on the screen and dynamically update content.

 

This capability is the foundation for building interactive terminal applications, dashboards, and progress indicators.

 

By controlling the cursor position and clearing parts of the screen, programs can update information in place instead of continuously printing new lines.

 

Libraries such as Jansi make it easy to send these control sequences from Java applications.

 

1. Moving the Cursor

One of the most useful ANSI capabilities is moving the cursor to a specific position on the terminal screen.

 

The escape sequence for cursor positioning is: ESC[row;columnH

 

Here:

·      row vertical position (top to bottom)

·      column horizontal position (left to right)

 

Example

ESC[10;5H

Above statement move the cursor to row 10, column 5. When the program prints text after this command, it will appear at that exact location.

 

Example With Java

System.out.print("\u001B[10;5HHello");

   

This technique allows programs to build structured terminal layouts, such as tables, dashboards, and menus.

 

Experiment with following application to understand the cursor movement.

 

CursorPositionPrinter.java

 

package com.sample.app;

import org.fusesource.jansi.AnsiConsole;

import java.util.Scanner;

public class CursorPositionPrinter {

    private static final String EXIT_COMMAND = "exit";

    public static void main(String[] args) {

        AnsiConsole.systemInstall();
        Scanner scanner = new Scanner(System.in);

        System.out.println("====================================");
        System.out.println(" Cursor Position Printer");
        System.out.println("====================================");
        System.out.println("Enter row, column, and message.");
        System.out.println("Type 'exit' anytime to quit.\n");

        while (true) {

            System.out.print("Row (or 'exit'): ");
            String rowInput = scanner.nextLine();

            if (isExit(rowInput)) break;

            System.out.print("Column (or 'exit'): ");
            String colInput = scanner.nextLine();

            if (isExit(colInput)) break;

            System.out.print("Message (or 'exit'): ");
            String message = scanner.nextLine();

            if (isExit(message)) break;

            try {

                int row = Integer.parseInt(rowInput);
                int col = Integer.parseInt(colInput);

                // Clear the screen
                System.out.print("\u001B[2J");

                // Move cursor
                String cursorMove = "\u001B[" + row + ";" + col + "H";

                System.out.print(cursorMove + message);
                System.out.flush();

                // Move cursor below output for next input
                System.out.print("\u001B[" + (row + 2) + ";1H");

            } catch (NumberFormatException e) {
                System.out.println("Invalid row/column value. Please enter numbers only.");
            }
        }

        System.out.println("\nExiting program...");
        scanner.close();
        AnsiConsole.systemUninstall();
    }

    private static boolean isExit(String input) {
        return EXIT_COMMAND.equalsIgnoreCase(input.trim());
    }
}

   

2. Clearing Lines

When building dynamic terminal interfaces, programs often need to remove previously printed text before displaying updated information. ANSI escape codes provide commands that allow applications to clear either individual lines or the entire screen.

 

This prevents the terminal from filling up with repeated messages and enables applications to create clean, continuously updating output.

 

Typical use cases include:

 

·      progress indicators

·      download status updates

·      live counters

·      interactive terminal dashboards

 

2.1 Clearing the Current Line

The most common command used to clear a line is: ESC[2K

 

It clear the entire current line where the cursor is located.

 

In code, the escape character is often written as: \u001B[2K

 

FileDownloadDemo.java

package com.sample.app;

import org.fusesource.jansi.AnsiConsole;

public class FileDownloadDemo {

    public static void main(String[] args) throws Exception {

        AnsiConsole.systemInstall();

        System.out.println("Downloading file: report-data.zip\n");

        for (int progress = 0; progress <= 100; progress++) {

            // Move cursor to beginning of line
            System.out.print("\r");

            // Clear the entire line
            System.out.print("\u001B[2K");

            // Print updated progress
            System.out.print("Downloading... " + progress + "%");

            System.out.flush();

            Thread.sleep(100);
        }

        // Clear line one last time
        System.out.print("\r\u001B[2K");
        System.out.println("Download complete ✓");

        AnsiConsole.systemUninstall();
    }
}

2.2 Clearing the Entire Screen

Another related command is: ESC[2J, it is used to clear the entire screen. However, this command does not automatically reposition the cursor. After clearing the screen, programs typically move the cursor back to the top-left corner using ESC[H.

 

So a common sequence for clearing and resetting the screen is: ESC[2J ESC[H.

 

This sequence:

 

·      Clears the screen

·      Moves the cursor to the home position (row 1, column 1)

 

SystemMonitorDemo.java

 

package com.sample.app;

import org.fusesource.jansi.AnsiConsole;

import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.util.Random;

public class SystemMonitorDemo {

    public static void main(String[] args) throws Exception {

        AnsiConsole.systemInstall();

        OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
        Runtime runtime = Runtime.getRuntime();
        Random random = new Random();

        while (true) {

            // Clear entire screen
            System.out.print("\u001B[2J");

            // Move cursor to home position
            System.out.print("\u001B[H");

            System.out.println("=====================================");
            System.out.println("      TERMINAL SYSTEM DASHBOARD      ");
            System.out.println("=====================================\n");

            // CPU usage (simulated or load average)
            double cpuLoad = osBean.getSystemLoadAverage();
            System.out.println("CPU Load Average : " + cpuLoad);

            // Memory usage
            long totalMemory = runtime.totalMemory() / (1024 * 1024);
            long freeMemory = runtime.freeMemory() / (1024 * 1024);
            long usedMemory = totalMemory - freeMemory;

            System.out.println("Total Memory     : " + totalMemory + " MB");
            System.out.println("Used Memory      : " + usedMemory + " MB");
            System.out.println("Free Memory      : " + freeMemory + " MB");

            // Simulated Disk usage
            int diskUsage = random.nextInt(100);
            System.out.println("Disk Usage       : " + diskUsage + "%");

            System.out.println("\n-------------------------------------");
            System.out.println("Refreshing every 2 seconds...");
            System.out.println("Press Ctrl+C to exit");

            System.out.flush();

            Thread.sleep(2000);
        }
    }
}

Following table summarizes the escape codes.

 

Escape Code

Action

ESC[2K

Clear the current line            

ESC[K

Clear from cursor to end of line  

ESC[1K

Clear from start of line to cursor

ESC[2J

Clear the entire screen           

ESC[H

Move cursor to home position      

 

3. Updating Specific Screen Regions

By combining cursor movement and line clearing, applications can update only specific parts of the screen.

 

For example:

 

·      Move cursor to a location

·      Clear the line

·      Print new data

 

Example:

 

System.out.print("\u001B[5;1H");  // Move cursor
System.out.print("\u001B[2K");    // Clear line
System.out.println("CPU Usage: 72%");

   

This technique allows programs to create live dashboards that update in place.

 

Each line can be updated independently without redrawing the whole screen. Many terminal monitoring tools use this approach to refresh information several times per second.

 

4. Cursor Hiding and Showing

When building dynamic terminal interfaces, the blinking cursor can become distracting. ANSI escape sequences allow applications to hide and show the cursor.

 

Hide cursor: ESC[?25l

Show cursor again: ESC[?25h

 

CursorHideDemo.java

 

package com.sample.app;

import org.fusesource.jansi.AnsiConsole;

public class CursorHideDemo {

    public static void main(String[] args) throws Exception {

        AnsiConsole.systemInstall();

        // Hide cursor
        System.out.print("\u001B[?25l");

        String[] spinner = {"|", "/", "-", "\\"};

        System.out.println("Processing data...");

        for (int i = 0; i < 40; i++) {

            // Move cursor to beginning of line
            System.out.print("\r");

            // Display animated spinner
            System.out.print("Working " + spinner[i % spinner.length]);

            System.out.flush();

            Thread.sleep(150);
        }

        // Move to new line
        System.out.print("\r");
        System.out.println("Task completed successfully ✓");

        // Show cursor again
        System.out.print("\u001B[?25h");

        AnsiConsole.systemUninstall();
    }
}

5. How Dynamic Terminal Interfaces Work?

Modern terminal applications rely heavily on these techniques:

 

·      cursor movement

·      line clearing

·      selective screen updates

·      cursor visibility control

 

Together, these capabilities allow developers to build rich text-based user interfaces directly in the terminal. Tools like htop, btop use the same techniques to display live system statistics and interactive dashboards.

  

Previous                                                    Next                                                    Home

No comments:

Post a Comment