首页 > 其他分享 >Go每日一库之164:uiprogress(终端进度条)

Go每日一库之164:uiprogress(终端进度条)

时间:2023-10-01 09:04:04浏览次数:52  
标签:wg AddBar bar uiprogress 进度条 time 164

今天给大家推荐的是在终端(terminal)下能够显示进度条的工具:uiprogress。先看下使用该包的效果图:

相信大家在linux或mac终端上都下载过东西,然后会出现下载的进度条。今天我们就给大家分析下实现原理并演示其效果。

安装

$ go get -v github.com/gosuri/uiprogress

实现原理分析

实现原理其实也很简单,本质上是通过计算机的换码符来实现的。这里使用的就是“清除当前行,将鼠标移动到行首,再重新输出进度”的原理。“清除当前行,将鼠标移动到行首”的换码符是:ESC[1AESC[2K。ESC[1A是代表将鼠标移动到第1行;ESC[2K是代表清除终端上的整行内容。二者组合就能实现上述效果。如下是一个简单的输出百分比的代码:

const ESC = 27

var clear = fmt.Sprintf("%c[%dA%c[2K", ESC, 1, ESC)

var Out = io.Writer(os.Stdout)

func main() {
    for i:= 0; i <=100; i++ {
        _, _ = fmt.Fprint(io.Writer(os.Stdout), clear)
        fmt.Fprintf(Out, "Downloading.. (%d/%d)GB\n", i, 100)
        time.Sleep(time.Millisecond * 500)
    }
}

在该包中,为了计算进度条还获取了当前终端的宽度(即一行能显示多列)的如下代码:


type windowSize struct {
    rows    uint16
    cols    uint16
}

var sz windowSize

func getTermSize() (int, int) {
    if runtime.GOOS == "openbsd" {
        out, err = os.OpenFile("/dev/tty", os.O_RDWR, 0)
        if err != nil {
            return 0, 0
        }
        
    } else {
        out, err = os.OpenFile("/dev/tty", os.O_WRONLY, 0)
        if err != nil {
            return 0, 0
        }
    }
    _, _, _ = syscall.Syscall(syscall.SYS_IOCTL,
                              out.Fd(), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&sz)))
    return int(sz.cols), int(sz.rows)
}

该包的特点

  • 同时渲染多个进度条:uiprogress能够同时并行处理多个进度条
  • 动态添加进度条:可以随时添加进度条
  • 前置函数和后置函数处理:通过前置和后置函数,可以在进度条的前、后添加已消耗的时间和当前的进度占比。
  • 自定义进度条样式函数:通过Bar的辅助函数还可以自定义进度条样式。

包的基本使用

通过uiprogress.Start()函数就能开启对进度条的监听,然后使用uiprogress.AddBar(total int)函数可以添加一个进度条。通过bar.Incr() 或 bar.Set(n int)可以设置进度条的进度值。如下:


uiprogress.Start()            // start rendering
bar := uiprogress.AddBar(100) // Add a new bar

// optionally, append and prepend completion and elapsed time
bar.AppendCompleted()
bar.PrependElapsed()

for bar.Incr() {
  time.Sleep(time.Millisecond * 20)
}

代码效果:

自定义进度条样式

除了使用bar.AppendCompleted()函数(在进度条最后增加百分比进度)和bar.PrependElapsed()函数(在进度条最前面添加耗时)可以装饰进度条外,还可以通过自定义的装饰函数给进度条。下面代码就是演示了一个自定义的部署进度的样式,如下:


uiprogress.Start()
var steps = []string{"downloading source", "installing deps", "compiling", "packaging", "seeding database", "deploying", "staring servers"}
bar := uiprogress.AddBar(len(steps))

// prepend the current step to the bar
bar.PrependFunc(func(b *uiprogress.Bar) string {
    return "app: " + steps[b.Current()-1]
})

for bar.Incr() {
    time.Sleep(time.Millisecond * 1000)
}

多个进度条

通过调用uiprogress.AddBar(n)函数多次来添加多个进度条。下面代码演示了并发更新多个进度条以及在程序运行中新添加一个进度条(符合随时添加进度条的特点)的示例。

waitTime := time.Millisecond * 100
uiprogress.Start()

// start the progress bars in go routines
var wg sync.WaitGroup

bar1 := uiprogress.AddBar(20).AppendCompleted().PrependElapsed()
wg.Add(1)
go func() {
    defer wg.Done()
    for bar1.Incr() {
        time.Sleep(waitTime)
    }
}()

bar2 := uiprogress.AddBar(40).AppendCompleted().PrependElapsed()
wg.Add(1)
go func() {
    defer wg.Done()
    for bar2.Incr() {
        time.Sleep(waitTime)
    }
}()

time.Sleep(time.Second)
bar3 := uiprogress.AddBar(20).PrependElapsed().AppendCompleted()
wg.Add(1)
go func() {
    defer wg.Done()
    for i := 1; i <= bar3.Total; i++ {
        bar3.Set(i)
        time.Sleep(waitTime)
    }
}()

// wait for all the go routines to finish
wg.Wait()

效果图如下:

更多项目详情请查看如下链接。

开源项目地址:https://github.com/gosuri/uiprogress

开源项目作者:Greg Osuri

标签:wg,AddBar,bar,uiprogress,进度条,time,164
From: https://www.cnblogs.com/arena/p/17738580.html

相关文章

  • 《看了受制了》第三十一天,7道题,合计164道题
    2023年9月30日Acwing5266队列题目大意问你,n加在三个数上,看最后三个数能不能相等。题目理解先把三个数都变成最大的,然后最后的n如果是3的倍数且大于等于0即可代码实现voidsolve(){lln,a,b,c;cin>>a>>b>>c>>n;llk=max(a,max(b,c));......
  • python进度条的实现(time)
    最近有小伙伴留言说想使用python实现进度条的功能,其实python中使用sleep每秒钟输出一部分就很容易的实现了这一类功能。案例一:importtimeforiinrange(20):print("□",end="")time.sleep(1)运行结果:案例二:(实现.........)importtimeforiinrange(20):p......
  • 亚马逊筋膜枪UL1647测试报告申请
    筋膜枪,又称深层肌筋膜冲击仪,是一种通过高频冲击放松身体的软组织的软组织康复工具。[1]筋膜枪可理解为DMS(电动深层肌肉刺激器)的民用版本。使用时振动频率会发生变化,其基本功能与DMS相似。[2]筋膜枪的使用必须注意方法和方法。同时,筋膜枪的首次使用需要在专业人士的指导下使用。最好......
  • 成品直播源码推荐,Flutter波浪进度条WaveProgressBar
    成品直播源码推荐,Flutter波浪进度条WaveProgressBar第一步:添加以下代码到你的pubspec.yaml文件 dependencies: waveprogressbar_flutter:"^0.1.1"​第二步:导包,添加以下代码到你要使用的文件下 import'package:waveprogressbar_flutter/waveprogressbar_flutter.dart'......
  • 如何实现图片预加载和加载进度条
    很久没有发文了今天水一篇文章,图片预加载且展示加载的进度条,在现代的Web开发中,优化用户体验至关重要。一种常见的方法是在页面加载时预加载图片,并展示一个加载进度条,让用户了解加载进度。在本文中,我们将深入探讨如何实现这两个关键功能,以提高网站性能和用户满意度,首先谈一下我的思......
  • 基于php+webuploader的大文件分片上传,支持断点续传,带进度条
    基于php+webuploader的大文件分片上传,带进度条,支持断点续传(刷新、关闭页面、重新上传、网络中断等情况)。文件上传前先检测该文件是否已上传,如果已上传提示“文件已存在”,如果未上传则直接上传。视频上传时会根据设定的参数(分片大小、分片数量)进行上传,上传过程中会在目标文件夹......
  • ABAP进度条
    *进度条例子1:DATA:perctypei,cntTYPEi.DATA:stxtTYPEstring.DATA:sperc(3)TYPEc.perc=0.cnt=1000.DOcntTIMES.stxt=''.perc=sy-index*100/cnt.sperc=perc.CONCATENATE'已经完成:'sperc'%......
  • 如何在gradio使用多进程,并且使用进度条显示多进程
    直接上代码:defmethod_a(progress=gr.Progress(track_tqdm=True)):pool=multiprocessing.Pool(multiprocessing.cpu_count())param_v=range(10)pbar=tqdm(total=len(param_v))resy=[]forpinparam_v:pool.apply_async(task_deal......
  • Progress 圆形进度条 实现
    效果图实现过程分析简要说明本文主要以TypeScript+React为例进行讲解,demo中使用到了sass,但用法相对简单,不影响理解HTMLDOM元素说明<divclassName="g-progress-wrap"><divclassName="g-progress"></div><divclassName="g-circle">......
  • [CF1641D] Two Arrays
    题目描述Samchangedhisschoolandonthefirstbiologylessonhegotaveryinterestingtaskaboutgenes.Youaregiven$n$arrays,the$i$-thofthemcontains$m$differentintegers—$a_{i,1},a_{i,2},\ldots,a_{i,m}$.Alsoyouaregivenanarra......