Skip to content

Commit

Permalink
refactor: redesigned input arg handler to be more extensible
Browse files Browse the repository at this point in the history
  • Loading branch information
ptdewey committed Oct 13, 2024
1 parent f9ecc9e commit c5adcd4
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 64 deletions.
11 changes: 6 additions & 5 deletions lua/pendulum/remote.lua
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,15 @@ local function setup_pendulum_commands()
return
end

local range = args.args or "all"
local time_range = args.args or "all"

local command_args = {
options.log_file,
"" .. options.timer_len,
"" .. options.top_n,
"" .. range,
log_file = options.log_file,
timer_len = options.timer_len,
top_n = options.top_n,
time_range = time_range,
}

local success, result =
pcall(vim.fn.rpcrequest, chan, "pendulum", command_args)
if not success then
Expand Down
51 changes: 29 additions & 22 deletions remote/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,53 +9,60 @@ import (
"github.com/neovim/go-client/nvim"
)

// RpcEventHandler handles RPC events and creates a metrics report popup.
//
// Parameters:
// - v: A pointer to the Neovim instance.
// - args: A slice of strings where args[0] is expected to be the pendulum
// log file path, args[1] is the timeout length (active -> inactive),
// and args[2] is the number of top entries to show for each metric.
//
// Returns:
// - An error if there are not enough arguments, if the buffer cannot be created,
// or if the popup window cannot be created.
func RpcEventHandler(v *nvim.Nvim, args []string) error {
if len(args) < 4 {
return errors.New("Not enough arguments")
// RpcEventHandler handles the RPC call from Lua and creates a buffer with pendulum data.
func RpcEventHandler(v *nvim.Nvim, args map[string]interface{}) error {
// Extract and validate arguments from input table
pendulumArgs, err := pkg.ParsePendlumArgs(args)
if err != nil {
return err
}

// create and populate metrics report buffer
buf, err := pkg.CreateBuffer(v, args)
// Call CreateBuffer with the struct
buf, err := pkg.CreateBuffer(v, *pendulumArgs)
if err != nil {
return err
}

// open popup window
// Open popup window
if err := pkg.CreatePopupWindow(v, buf); err != nil {
return err
}

return err
return nil
}

func main() {
log.SetFlags(0)

// only use stdout for stderr
// Redirect stdout to stderr
stdout := os.Stdout
os.Stdout = os.Stderr

// Connect to Neovim
v, err := nvim.New(os.Stdin, stdout, stdout, log.Printf)
if err != nil {
log.Fatal(err)
}

v.RegisterHandler("pendulum", RpcEventHandler)
// Register the "pendulum" RPC handler, which receives Lua tables
v.RegisterHandler("pendulum", func(v *nvim.Nvim, args ...interface{}) error {
// Expecting the first argument to be a map (Lua table)
if len(args) < 1 {
return errors.New("not enough arguments")
}

// Parse the first argument as a map
argMap, ok := args[0].(map[string]interface{})
if !ok {
return errors.New("expected a map as the first argument")
}

// Call the actual handler with the parsed map
return RpcEventHandler(v, argMap)
})

// run rpc message loop
// Run the RPC message loop
if err := v.Serve(); err != nil {
log.Fatal(err)
return
}
}
53 changes: 16 additions & 37 deletions remote/pkg/buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,45 @@ package pkg

import (
"pendulum-nvim/internal"
"strconv"
"strings"

"github.com/neovim/go-client/nvim"
)

// CreateBuffer creates a new Neovim buffer and populates it with data.
//
// Parameters:
// - v: A pointer to the Neovim instance.
// - args: A slice of strings where:
// - args[0] is the path to the pendulum log file.
// - args[1] is the timeout length as a string.
// - args[2] is the number of data points to aggregate.
// - args[3] is the time range to aggregate data from
//
// Returns:
// - The created buffer.
// - An error if any step in the buffer creation or data population fails.
func CreateBuffer(v *nvim.Nvim, args []string) (nvim.Buffer, error) {
func CreateBuffer(v *nvim.Nvim, args PendulumArgs) (nvim.Buffer, error) {
// create a new buffer
buf, err := v.CreateBuffer(false, true)
if err != nil {
return buf, err
}

// set buffer filetype to add some highlighting
// TODO: a custom hl group could be considerably nicer looking
if err := v.SetBufferOption(buf, "filetype", "markdown"); err != nil {
return buf, err
}

// read pendulum data file
data, err := internal.ReadPendulumLogFile(args[0])
if err != nil {
return buf, err
}

timeout_len, err := strconv.ParseFloat(args[1], 64)
if err != nil {
return buf, err
}

n, err := strconv.Atoi(args[2])
data, err := internal.ReadPendulumLogFile(args.LogFile)
if err != nil {
return buf, err
}

// get prettified buffer text
buf_text := getBufText(data, timeout_len, n, args[3])
bufText := getBufText(data, args.Timeout, args.TopN, args.TimeRange)

// set contents of new buffer
if err := v.SetBufferLines(buf, 0, -1, false, buf_text); err != nil {
if err := v.SetBufferLines(buf, 0, -1, false, bufText); err != nil {
return buf, err
}

// set buffer close keymap
kopts := make(map[string]bool)
kopts["silent"] = true
v.SetBufferKeyMap(buf, "n", "q", "<cmd>close!<CR>", kopts)
kopts := map[string]bool{
"silent": true,
}
if err := v.SetBufferKeyMap(buf, "n", "q", "<cmd>close!<CR>", kopts); err != nil {
return buf, err
}

return buf, nil
}
Expand All @@ -70,24 +49,24 @@ func CreateBuffer(v *nvim.Nvim, args []string) (nvim.Buffer, error) {
//
// Parameters:
// - data: A 2D slice of strings representing the pendulum data.
// - timeout_len: A float64 representing the timeout length.
// - timeoutLen: A float64 representing the timeout length.
// - n: An integer representing the number of data points to aggregate.
// - rangeType: A string representing the time window to aggregate data for ("all" is recommended)
//
// Returns:
// - A 2D slice of bytes representing the text to be set in the buffer.
func getBufText(data [][]string, timeout_len float64, n int, rangeType string) [][]byte {
out := internal.AggregatePendulumMetrics(data, timeout_len, rangeType)
func getBufText(data [][]string, timeoutLen float64, n int, rangeType string) [][]byte {
out := internal.AggregatePendulumMetrics(data, timeoutLen, rangeType)

lines := internal.PrettifyMetrics(out, n)

var buf_text [][]byte
var bufText [][]byte
for _, l := range lines {
splitLines := strings.Split(l, "\n")
for _, line := range splitLines {
buf_text = append(buf_text, []byte(line))
bufText = append(bufText, []byte(line))
}
}

return buf_text
return bufText
}
51 changes: 51 additions & 0 deletions remote/pkg/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package pkg

import (
"errors"
"fmt"
)

// NOTE: add new fields here and to following function to extend functionalities
// - The fields in this struct should mirror the "command_args" table in `lua/pendulum/remote.lua`
type PendulumArgs struct {
LogFile string
Timeout float64
TopN int
TimeRange string
}

// Parse input arguments from lua table args
func ParsePendlumArgs(args map[string]interface{}) (*PendulumArgs, error) {
logFile, ok := args["log_file"].(string)
if !ok {
return nil, errors.New("log_file missing or not a string. " +
fmt.Sprintf("Type: %T\n", args["log_file"]))
}

topN, ok := args["top_n"].(int64)
if !ok {
return nil, errors.New("top_n missing or not a number. " +
fmt.Sprintf("Type: %T\n", args["top_n"]))
}

timerLen, ok := args["timer_len"].(int64)
if !ok {
return nil, errors.New("timer_len missing or not a number. " +
fmt.Sprintf("Type: %T\n", args["timer_len"]))
}

timeRange, ok := args["time_range"].(string)
if !ok {
return nil, errors.New("timeRange missing or not a string. " +
fmt.Sprintf("Type: %T\n", args["time_range"]))
}

out := PendulumArgs{
LogFile: logFile,
Timeout: float64(timerLen),
TopN: int(topN),
TimeRange: timeRange,
}

return &out, nil
}

0 comments on commit c5adcd4

Please sign in to comment.