Rust终端尺寸获取库termsize的使用,轻松获取和控制终端窗口大小

Rust终端尺寸获取库termsize的使用,轻松获取和控制终端窗口大小

因为终端尺寸很重要

Termsize是一个Rust crate,提供了一个多平台接口,用于解析终端的当前行数和列数大小。在大多数Unix系统上,这类似于调用stty(1)程序,请求终端大小。

安装

在终端中运行cargo add termsize,或者将以下内容添加到您的Cargo.toml文件中

[dependencies]
termsize = "0.1"

使用

Termize提供了一个函数get,它返回一个termsize::Size结构体,暴露两个字段:rowscols,表示终端标准输出支持的行数和列数。

pub fn main() {
  termsize::get().map(|{ rows, cols }| {
    println!("rows {} cols {}", size.rows, size.cols)
  });
}

Doug Tangren (softprops) 2015-2024

完整示例代码

// 引入termsize库
use termsize;

fn main() {
    // 获取终端尺寸
    match termsize::get() {
        // 如果成功获取到尺寸信息
        Some(size) => {
            // 打印终端行数和列数
            println!("终端行数: {}", size.rows);
            println!("终端列数: {}", size.cols);
            
            // 可以根据终端尺寸进行相应的布局控制
            if size.cols < 80 {
                println!("警告: 终端宽度较小,建议调整窗口大小以获得更好的显示效果");
            }
            
            // 示例:根据终端尺寸动态调整输出格式
            let message = "欢迎使用termsize库!";
            if message.len() > size.cols as usize {
                println!("消息过长,需要换行显示");
            } else {
                println!("{}", message);
            }
        },
        // 如果无法获取终端尺寸(例如在非终端环境中)
        None => {
            eprintln!("无法获取终端尺寸信息");
        }
    }
}

要使用此代码,请确保在您的Cargo.toml中添加了termsize依赖:

[dependencies]
termsize = "0.1"

完整示例demo

// 引入termsize库
use termsize;

fn main() {
    // 获取终端尺寸
    match termsize::get() {
        // 如果成功获取到尺寸信息
        Some(size) => {
            // 打印终端行数和列数
            println!("终端行数: {}", size.rows);
            println!("终端列数: {}", size.cols);
            
            // 可以根据终端尺寸进行相应的布局控制
            if size.cols < 80 {
                println!("警告: 终端宽度较小,建议调整窗口大小以获得更好的显示效果");
            }
            
            // 示例:根据终端尺寸动态调整输出格式
            let message = "欢迎使用termsize库!";
            if message.len() > size.cols as usize {
                println!("消息过长,需要换行显示");
            } else {
                println!("{}", message);
            }
        },
        // 如果无法获取终端尺寸(例如在非终端环境中)
        None => {
            eprintln!("无法获取终端尺寸信息");
        }
    }
}

1 回复

Rust终端尺寸获取库termsize的使用指南

介绍

termsize是一个轻量级的Rust库,专门用于获取和控制终端窗口的尺寸信息。它提供了跨平台的解决方案,可以轻松获取终端的行数和列数,帮助开发者创建响应式的命令行应用程序。

安装方法

在Cargo.toml中添加依赖:

[dependencies]
termsize = "0.1"

基本使用方法

获取终端尺寸

use termsize::Size;

fn main() {
    match termsize::get() {
        Some(size) => {
            println!("终端尺寸: {} x {}", size.cols, size.rows);
            println!("宽度: {} 字符", size.cols);
            println!("高度: {} 行", size.rows);
        }
        None => println!("无法获取终端尺寸"),
    }
}

实时监控终端尺寸变化

use termsize::{Size, watch};

fn main() {
    // 设置尺寸变化回调
    if let Err(e) = watch(|size: Size| {
        println!("终端尺寸已改变: {} x {}", size.cols, size.rows);
    }) {
        eprintln!("无法监控终端尺寸: {}", e);
    }
    
    // 保持程序运行以接收回调
    std::thread::sleep(std::time::Duration::from_secs(10));
}

响应式布局示例

use termsize::Size;

fn format_output(text: &str) -> String {
    if let Some(size) = termsize::get() {
        let max_width = size.cols as usize;
        if text.len() > max_width {
            format!("{}...", &text[..max_width - 3])
        } else {
            text.to_string()
        }
    } else {
        text.to_string()
    }
}

fn main() {
    let long_text = "这是一个非常非常非常非常非常非常非常非常长的文本字符串";
    println!("{}", format_output(long_text));
}

跨平台兼容性处理

use termsize::Size;

fn get_terminal_size() -> Option<(u16, u16)> {
    termsize::get().map(|size| (size.cols, size.rows))
}

fn main() {
    match get_terminal_size() {
        Some((cols, rows)) => {
            println!("当前终端: {}x{}", cols, rows);
            
            // 根据终端尺寸调整界面
            if cols < 80 {
                println!("小终端模式");
            } else {
                println!("标准终端模式");
            }
        }
        None => {
            println!("使用默认尺寸: 80x24");
        }
    }
}

高级功能

自定义错误处理

use termsize::{Size, Error};

fn get_size_with_fallback() -> Result<Size, Error> {
    termsize::get().ok_or(Error::UnableToGetSize)
}

fn main() {
    match get_size_with_fallback() {
        Ok(size) => {
            // 使用获取到的尺寸
            println!("成功获取尺寸: {}x{}", size.cols, size.rows);
        }
        Err(e) => {
            eprintln!("错误: {:?}", e);
            // 使用默认值
            println!("使用默认尺寸: 80x24");
        }
    }
}

完整示例demo

use termsize::{Size, watch, Error};
use std::thread;
use std::time::Duration;

// 获取终端尺寸的基本示例
fn get_terminal_size() {
    println!("=== 获取终端尺寸示例 ===");
    match termsize::get() {
        Some(size) => {
            println!("终端尺寸: {} x {}", size.cols, size.rows);
            println!("宽度: {} 字符", size.cols);
            println!("高度: {} 行", size.rows);
        }
        None => println!("无法获取终端尺寸"),
    }
    println!();
}

// 响应式文本格式化示例
fn responsive_text_formatting() {
    println!("=== 响应式文本格式化示例 ===");
    let long_text = "这是一个非常非常非常非常非常非常非常非常长的文本字符串,用于演示响应式截断功能";
    
    let formatted = if let Some(size) = termsize::get() {
        let max_width = size.cols as usize;
        if long_text.len() > max_width {
            format!("{}...", &long_text[..max_width - 3])
        } else {
            long_text.to_string()
        }
    } else {
        long_text.to_string()
    };
    
    println!("格式化后的文本: {}", formatted);
    println!();
}

// 自适应界面布局示例
fn adaptive_layout() {
    println!("=== 自适应界面布局示例 ===");
    match termsize::get().map(|size| (size.cols, size.rows)) {
        Some((cols, rows)) => {
            println!("当前终端尺寸: {}x{}", cols, rows);
            
            if cols < 60 {
                println!("超小终端模式 - 使用简化界面");
            } else if cols < 80 {
                println!("小终端模式 - 使用紧凑布局");
            } else if cols < 120 {
                println!("标准终端模式 - 使用常规布局");
            } else {
                println!("大终端模式 - 使用扩展布局");
            }
            
            if rows < 20 {
                println!("终端高度较小,建议减少输出内容");
            }
        }
        None => {
            println!("无法获取终端尺寸,使用默认布局");
            println!("标准终端模式 - 使用常规布局");
        }
    }
    println!();
}

// 监控终端尺寸变化示例
fn monitor_terminal_resize() {
    println!("=== 监控终端尺寸变化示例 ===");
    println!("请尝试调整终端窗口大小,观察输出变化(10秒后结束)");
    
    if let Err(e) = watch(|size: Size| {
        println!("终端尺寸已改变: {} x {}", size.cols, size.rows);
    }) {
        eprintln!("无法监控终端尺寸: {}", e);
    }
    
    // 保持程序运行以接收回调
    thread::sleep(Duration::from_secs(10));
    println!();
}

// 带错误处理的完整示例
fn advanced_example_with_error_handling() {
    println!("=== 高级错误处理示例 ===");
    
    fn get_size_with_retry() -> Result<Size, Error> {
        termsize::get().ok_or(Error::UnableToGetSize)
    }
    
    match get_size_with_retry() {
        Ok(size) => {
            println!("成功获取终端尺寸: {}x{}", size.cols, size.rows);
            
            // 基于尺寸的业务逻辑
            if size.cols >= 100 && size.rows >= 30 {
                println!("终端尺寸充足,可以显示丰富内容");
            } else {
                println!("终端尺寸有限,使用精简模式");
            }
        }
        Err(e) => {
            eprintln!("获取终端尺寸失败: {:?}", e);
            println!("使用默认尺寸 80x24 进行后续操作");
            
            // 使用默认值的业务逻辑
            println!("默认模式运行中...");
        }
    }
    println!();
}

fn main() {
    // 运行所有示例
    get_terminal_size();
    responsive_text_formatting();
    adaptive_layout();
    monitor_terminal_resize();
    advanced_example_with_error_handling();
    
    println!("所有示例执行完成!");
}

注意事项

  1. 在非终端环境(如重定向到文件)中可能无法获取尺寸
  2. 某些旧终端可能不支持尺寸查询
  3. 建议始终提供尺寸获取失败的备选方案
  4. 实时监控功能在某些平台上可能有限制
  5. 在多线程环境中使用时需要注意线程安全性

这个库非常适合需要创建响应式命令行界面或需要根据终端尺寸动态调整输出的应用程序。

回到顶部