github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/cmds/exp/page/main.go (about)

     1  // Copyright 2012-2020 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Synopsis:
     6  //
     7  //	page [file]
     8  //
     9  // Description:
    10  // page prints a page at a time to stdout from either stdin or a named file.
    11  // It stops every x rows, where x is the number of rows determined from gtty.
    12  // Single character commands tell it what to do next. Currently the only ones
    13  // are return and q.
    14  //
    15  // Options:
    16  package main
    17  
    18  import (
    19  	"bufio"
    20  	"fmt"
    21  	"io"
    22  	"log"
    23  	"os"
    24  
    25  	"github.com/mvdan/u-root-coreutils/pkg/termios"
    26  )
    27  
    28  func page(t *termios.TTYIO, r io.Reader, w io.Writer) error {
    29  	rows := int64(24)
    30  	if w, err := t.GetWinSize(); err != nil {
    31  		log.Printf("Could not get win size: %v; continuing assuming %d rows", err, rows)
    32  	} else {
    33  		rows = int64(w.Row)
    34  	}
    35  
    36  	l := int64(1)
    37  	scanner := bufio.NewScanner(r)
    38  	for {
    39  		cur := l
    40  		for {
    41  			if !scanner.Scan() {
    42  				return scanner.Err()
    43  			}
    44  			line := scanner.Text()
    45  			if _, err := fmt.Fprintf(w, "%s\r\n", string(line)); err != nil {
    46  				return err
    47  			}
    48  			cur++
    49  			if cur > l+rows {
    50  				break
    51  			}
    52  		}
    53  		if cur == l {
    54  			break
    55  		}
    56  		l = cur
    57  		if _, err := fmt.Fprintf(t, ":"); err != nil {
    58  			return err
    59  		}
    60  		var cmd [1]byte
    61  		if _, err := t.Read(cmd[:]); err != nil {
    62  			return err
    63  		}
    64  		switch cmd[0] {
    65  		default:
    66  			fmt.Printf("%q:unknown\n", cmd[0])
    67  		case '\n', ' ':
    68  		case 'q':
    69  			return nil
    70  		}
    71  		fmt.Fprintf(w, "\r")
    72  	}
    73  
    74  	return nil
    75  }
    76  
    77  func main() {
    78  	t, err := termios.New()
    79  	if err != nil {
    80  		log.Fatal(err)
    81  	}
    82  	in := os.Stdin
    83  
    84  	switch len(os.Args) {
    85  	case 1:
    86  	case 2:
    87  		f, err := os.Open(os.Args[1])
    88  		if err != nil {
    89  			log.Fatal(err)
    90  		}
    91  		in = f
    92  	default:
    93  		log.Fatal("Usage: page [file]")
    94  	}
    95  	c, err := t.Raw()
    96  	if err != nil {
    97  		log.Fatal(err)
    98  	}
    99  	defer func() {
   100  		if err := t.Set(c); err != nil {
   101  			log.Printf("Restoring modes failed; sorry (%v)", err)
   102  		}
   103  	}()
   104  	if err := page(t, in, os.Stdout); err != nil {
   105  		log.Fatal(err)
   106  	}
   107  }