github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/shell/history/history.go (about)

     1  package history
     2  
     3  import (
     4  	"bufio"
     5  	"encoding/json"
     6  	"errors"
     7  	"os"
     8  	"strings"
     9  	"time"
    10  )
    11  
    12  // History exports common functions needed for shell history
    13  type History struct {
    14  	filename string
    15  	list     []Item
    16  }
    17  
    18  // Item is the structure of an individual item in the History.list slice
    19  type Item struct {
    20  	Index    int
    21  	DateTime time.Time
    22  	Block    string
    23  }
    24  
    25  // New creates a History object
    26  func New(filename string) (h *History, err error) {
    27  	h = new(History)
    28  	h.filename = filename
    29  	h.list, _ = openHist(filename)
    30  
    31  	return h, nil //err
    32  }
    33  
    34  func openHist(filename string) (list []Item, err error) {
    35  	file, err := os.Open(filename)
    36  	if err != nil {
    37  		return list, err
    38  	}
    39  
    40  	scanner := bufio.NewScanner(file)
    41  	for scanner.Scan() {
    42  		var item Item
    43  		err := json.Unmarshal(scanner.Bytes(), &item)
    44  		if err != nil || len(item.Block) == 0 {
    45  			continue
    46  		}
    47  		item.Index = len(list)
    48  		list = append(list, item)
    49  	}
    50  
    51  	file.Close()
    52  	return list, nil
    53  }
    54  
    55  // Write item to history file. eg ~/.murex_history
    56  func (h *History) Write(s string) (int, error) {
    57  	block := strings.TrimSpace(s)
    58  
    59  	item := Item{
    60  		DateTime: time.Now(),
    61  		Block:    block,
    62  		Index:    len(h.list),
    63  	}
    64  
    65  	if len(h.list) == 0 || h.list[len(h.list)-1].Block != block {
    66  		h.list = append(h.list, item)
    67  	}
    68  
    69  	line := struct {
    70  		DateTime time.Time `json:"datetime"`
    71  		Block    string    `json:"block"`
    72  	}{
    73  		Block:    block,
    74  		DateTime: item.DateTime,
    75  	}
    76  
    77  	b, err := json.Marshal(line)
    78  	if err != nil {
    79  		return h.Len(), err
    80  	}
    81  
    82  	f, err := os.OpenFile(h.filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
    83  	if err != nil {
    84  		return 0, err
    85  	}
    86  
    87  	_, err = f.Write(append(b, '\n'))
    88  	f.Close()
    89  	return h.Len(), err
    90  }
    91  
    92  // GetLine returns a specific line from the history file
    93  func (h *History) GetLine(i int) (string, error) {
    94  	if i < 0 {
    95  		return "", errors.New("cannot use a negative index when requesting historic commands")
    96  	}
    97  	if i < len(h.list) {
    98  		return h.list[i].Block, nil
    99  	}
   100  	return "", errors.New("index requested greater than number of items in history")
   101  }
   102  
   103  // Len returns the number of items in the history file
   104  func (h *History) Len() int {
   105  	return len(h.list)
   106  }
   107  
   108  // Dump returns the entire history file
   109  func (h *History) Dump() interface{} {
   110  	return h.list
   111  }