(ctx *snap.Context)
| 2812 | } |
| 2813 | |
| 2814 | func readConfirmationChoice(ctx *snap.Context) (byte, error) { |
| 2815 | if file, ok := ctx.Stdin().(*os.File); ok { |
| 2816 | stateCmd := exec.Command("stty", "-g") |
| 2817 | stateCmd.Stdin = file |
| 2818 | stateCmd.Stdout = nil |
| 2819 | stateCmd.Stderr = nil |
| 2820 | if oldStateBytes, err := stateCmd.Output(); err == nil { |
| 2821 | oldState := strings.TrimSpace(string(oldStateBytes)) |
| 2822 | if oldState != "" { |
| 2823 | rawCmd := exec.Command("stty", "raw", "-echo") |
| 2824 | rawCmd.Stdin = file |
| 2825 | rawCmd.Stdout = nil |
| 2826 | rawCmd.Stderr = nil |
| 2827 | if err := rawCmd.Run(); err == nil { |
| 2828 | defer func() { |
| 2829 | restoreCmd := exec.Command("stty", oldState) |
| 2830 | restoreCmd.Stdin = file |
| 2831 | restoreCmd.Stdout = nil |
| 2832 | restoreCmd.Stderr = nil |
| 2833 | _ = restoreCmd.Run() |
| 2834 | }() |
| 2835 | |
| 2836 | var buf [1]byte |
| 2837 | for { |
| 2838 | n, err := file.Read(buf[:]) |
| 2839 | if err != nil { |
| 2840 | return 0, err |
| 2841 | } |
| 2842 | if n == 0 { |
| 2843 | continue |
| 2844 | } |
| 2845 | b := buf[0] |
| 2846 | if b == '\r' || b == '\n' { |
| 2847 | continue |
| 2848 | } |
| 2849 | fmt.Fprintln(ctx.Stdout()) |
| 2850 | return b, nil |
| 2851 | } |
| 2852 | } |
| 2853 | } |
| 2854 | } |
| 2855 | } |
| 2856 | |
| 2857 | reader := bufio.NewReader(ctx.Stdin()) |
| 2858 | for { |
| 2859 | b, err := reader.ReadByte() |
| 2860 | if err != nil { |
| 2861 | return 0, err |
| 2862 | } |
| 2863 | if b == '\r' || b == '\n' { |
| 2864 | continue |
| 2865 | } |
| 2866 | return b, nil |
| 2867 | } |
| 2868 | } |
| 2869 | |
| 2870 | // resolveOpenAIKey attempts to find an OpenAI key quickly without extra config. |
| 2871 | // resolveOpenAIKey reads the key from OPENAI_API_KEY and caches it for reuse. |
no outgoing calls
no test coverage detected