package main import ( "bufio" "encoding/json" "fmt" "io/ioutil" "net/http" "net/url" "os" "os/exec" ) type Output struct { Message string `json:"message,omitempty"` // Sets rofi message, hides it if empty or null Overlay string `json:"overlay,omitempty"` // Shows overlay with text, hides it if empty or null Prompt string `json:"prompt,omitempty"` // sets prompt text Input string `json:"input,omitempty"` // sets input text, to clear use empty string InputAction string `json:"input action,omitempty"` // "send" or "filter" EventFormat string `json:"event format,omitempty"` // event format used to send to input Lines []Line `json:"lines"` // a list of sting or json object to set rofi list content } type Line struct { Text string `json:"text,required"` Urgent bool `json:"urgent,omitempty"` Highlight bool `json:"highlight,omitempty"` Markup bool `json:"markup,omitempty"` Icon string `json:"icon,omitempty"` } type Input struct { Name string `json:"name"` Value string `json:"value"` } func handleSelect(input Input) { param := url.Values{} param.Add("q", input.Value) exec.Command("xdg-open", "https://duckduckgo.com/?"+param.Encode()).Start() os.Exit(0) } func getSuggestions(query string) []string { param := url.Values{} param.Add("q", query) param.Add("type", "list") param.Add("kl", "en-US") resp, _ := http.Get("https://ac.duckduckgo.com/ac?" + param.Encode()) body, _ := ioutil.ReadAll(resp.Body) resp.Body.Close() var result []interface{} json.Unmarshal(body, &result) if len(result) < 2 { return []string{} } rtn := make([]string, len(result[1].([]interface{}))) for i, v := range result[1].([]interface{}) { rtn[i] = v.(string) } return rtn } func convertStringsToLine(strings []string) []Line { lines := make([]Line, len(strings)) for i, v := range strings { lines[i] = Line{v, false, false, false, ""} } return lines } func handleInput(input Input) { switch input.Name { case "input change": output := newOutput() output.Lines = convertStringsToLine(getSuggestions(input.Value)) sendOutput(output) case "custom key": case "active entry": case "select entry": handleSelect(input) case "delete entry": case "exec custom input": } } func sendOutput(output Output) { res, _ := json.Marshal(output) fmt.Printf("%s\n", res) } func simpleLines(lines []string) []Line { outputLines := make([]Line, len(lines)) for i := 0; i < len(lines); i++ { outputLines[i] = Line{lines[i], false, false, false, ""} } return outputLines } func newOutput() Output { return Output{"", "", "", "", "", "", []Line{}} } func main() { // Setup rofi initialOutput := newOutput() initialOutput.Prompt = "Search" initialOutput.InputAction = "send" sendOutput(initialOutput) // Input loop scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { var input Input bytes := scanner.Bytes() json.Unmarshal(bytes, &input) handleInput(input) } }