1use serde::Deserialize;
2use std::collections::HashMap;
3
4const DEFAULT_CTAGS_TIMEOUT_MS: u64 = 500;
5
6#[derive(Clone, Debug, Deserialize, Default)]
7pub struct PicklsConfig {
8 #[serde(default)]
9 pub languages: HashMap<String, PicklsLanguageConfig>,
10 pub symbols: Option<PicklsSymbolsConfig>,
11 #[serde(default)]
12 pub ai: PicklsAIConfig,
13}
14
15fn default_ctags_timeout_ms() -> u64 {
16 DEFAULT_CTAGS_TIMEOUT_MS
17}
18
19#[derive(Eq, PartialEq, Clone, Debug, Deserialize)]
20pub struct PicklsSymbolsConfig {
21 pub source: PicklsSymbolsSource,
22
23 #[serde(default = "default_ctags_timeout_ms")]
25 pub ctags_timeout_ms: u64,
26}
27
28#[derive(Eq, PartialEq, Clone, Debug, Deserialize)]
29pub enum PicklsSymbolsSource {
30 #[serde(rename = "universal-ctags")]
31 UniversalCtags,
32}
33
34#[derive(Clone, Debug, Default, Deserialize)]
35pub struct PicklsLanguageConfig {
36 #[serde(default)]
42 pub root_markers: Vec<String>,
43
44 #[serde(default)]
47 pub linters: Vec<PicklsLinterConfig>,
48
49 #[serde(default)]
54 pub formatters: Vec<PicklsFormatterConfig>,
55}
56
57#[derive(Clone, Debug, Deserialize)]
58pub struct PicklsLinterConfig {
59 pub program: String,
61 #[serde(default = "Vec::new")]
65 pub args: Vec<String>,
66 pub use_stdin: bool,
69 pub pattern: String,
72 pub filename_match: Option<usize>,
74 pub line_match: usize,
76 pub start_col_match: Option<usize>,
78 pub end_col_match: Option<usize>,
80 pub severity_match: Option<usize>,
83 pub description_match: Option<isize>,
86 #[serde(default = "default_false")]
89 pub use_stderr: bool,
90}
91
92fn default_false() -> bool {
93 false
94}
95
96fn default_true() -> bool {
97 true
98}
99
100#[derive(Clone, Debug, Deserialize)]
101pub struct PicklsFormatterConfig {
102 pub program: String,
104 pub args: Vec<String>,
106 #[serde(default = "default_true")]
109 pub use_stdin: bool,
110 #[serde(default = "default_false")]
113 pub stderr_indicates_error: bool,
114}
115
116#[derive(Clone, Debug, Deserialize, Default)]
117pub struct PicklsAIConfig {
118 #[serde(default = "default_inline_assist_system_prompt")]
119 pub system_prompt: String,
120 pub inline_assist_provider: PicklsAIProvider,
121 #[serde(default = "default_inline_assist_prompt_template")]
122 pub inline_assist_prompt_template: String,
123 pub openai: Option<OpenAIConfig>,
124 pub ollama: Option<OllamaConfig>,
125}
126
127#[derive(Clone, Debug, Deserialize, Default)]
137pub struct OllamaConfig {
138 pub model: String,
139 pub api_address: String,
141}
142
143#[derive(Clone, Debug, Deserialize, Default)]
144#[serde(rename_all = "lowercase")]
145pub enum PicklsAIProvider {
146 #[default]
147 OpenAI,
148 Ollama,
149}
150
151#[derive(Clone, Debug, Deserialize)]
152pub struct OpenAIConfig {
153 pub model: String,
155 #[serde(default = "default_openai_api_key_cmd")]
157 pub api_key_cmd: Vec<String>,
158}
159
160impl Default for OpenAIConfig {
161 fn default() -> Self {
162 OpenAIConfig {
163 model: "gpt-4o".to_string(),
164 api_key_cmd: default_openai_api_key_cmd(),
165 }
166 }
167}
168
169fn default_openai_api_key_cmd() -> Vec<String> {
170 ["sh", "-c", "echo $OPENAI_API_KEY"]
171 .into_iter()
172 .map(|s| s.to_string())
173 .collect()
174}
175
176fn default_inline_assist_prompt_template() -> String {
177 "I'm working within the {{language_id}} language. If I show you code below, then please \
178 rewrite it to make improvements as you see fit. If I show you a question or directive, \
179 write code to satisfy the question or directive. Never use markdown to format your response. \
180 For example, do not use triple backticks (```). Always include type annotations where possible.\n\n\
181 {{text}}\n"
182 .to_string()
183}
184
185fn default_inline_assist_system_prompt() -> String {
186 "You are an inline assistant for a code editor. Your response to user prompts will be used \
187 to replace code in the editor."
188 .to_string()
189}