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 }