github.com/hugelgupf/u-root@v0.0.0-20191023214958-4807c632154c/cmds/core/less/main.go (about)

     1  // Copyright 2018 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  // less pages through a file
     6  //
     7  // Synopsis:
     8  //     less [OPTIONS] FILE
     9  //
    10  // Options:
    11  //     -profile FILE: Save profile in this file
    12  //     -tabstop NUMBER: Number of spaces per tab
    13  //
    14  // Keybindings:
    15  //     Control:
    16  //
    17  //     * q: Quit
    18  //
    19  //     Scrolling:
    20  //
    21  //     * j: Scroll down
    22  //     * k: Scroll up
    23  //     * g: Scroll to top
    24  //     * G: Scroll to bottom
    25  //     * Pgdn: Scroll down one screen full
    26  //     * Pgup: Scroll up one screen full
    27  //     * ^D: Scroll down one half screen full
    28  //     * ^U: Scroll up one half screen full
    29  //
    30  //     Searching:
    31  //
    32  //     * /: Enter search regex (re2 syntax). Press enter to search.
    33  //     * n: Jump down to next search result
    34  //     * N: Jump up to previous search result
    35  //
    36  // Author:
    37  //     Michael Pratt (github.com/prattmic) whom we are forever grateful for
    38  //     writing https://github.com/prattmic/lesser.
    39  package main
    40  
    41  import (
    42  	"bytes"
    43  	"fmt"
    44  	"log"
    45  	"os"
    46  	"runtime/pprof"
    47  	"syscall"
    48  
    49  	"github.com/nsf/termbox-go"
    50  	flag "github.com/spf13/pflag"
    51  	"github.com/u-root/u-root/pkg/less"
    52  )
    53  
    54  var profile = flag.String("profile", "", "Save profile in this file")
    55  var tabStop = flag.Int("tabstop", 8, "Number of spaces per tab")
    56  
    57  func mmapFile(f *os.File) ([]byte, error) {
    58  	stat, err := f.Stat()
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  
    63  	return syscall.Mmap(int(f.Fd()), 0, int(stat.Size()), syscall.PROT_READ, syscall.MAP_PRIVATE)
    64  }
    65  
    66  func main() {
    67  	flag.Usage = func() {
    68  		fmt.Fprintf(os.Stderr, "Usage of %s: %s filename\n", os.Args[0], os.Args[0])
    69  		flag.PrintDefaults()
    70  	}
    71  	flag.Parse()
    72  
    73  	if len(flag.Args()) != 1 {
    74  		flag.Usage()
    75  		os.Exit(1)
    76  	}
    77  
    78  	name := flag.Arg(0)
    79  	f, err := os.Open(name)
    80  	if err != nil {
    81  		log.Fatalf("failed to open %s: %v", name, err)
    82  	}
    83  
    84  	m, err := mmapFile(f)
    85  	if err != nil {
    86  		log.Fatalf("failed to mmap file: %v", err)
    87  	}
    88  	defer syscall.Munmap(m)
    89  
    90  	err = termbox.Init()
    91  	if err != nil {
    92  		log.Fatalf("Failed to init: %v", err)
    93  	}
    94  	defer termbox.Close()
    95  
    96  	if *profile != "" {
    97  		p, err := os.Create(*profile)
    98  		if err != nil {
    99  			log.Fatalf("Failed to create profile: %v", err)
   100  		}
   101  		defer p.Close()
   102  		pprof.StartCPUProfile(p)
   103  		defer pprof.StopCPUProfile()
   104  	}
   105  
   106  	l := less.NewLess(bytes.NewReader(m), *tabStop)
   107  	l.Run()
   108  }