Struct hyper_scripter::config::Config
source · pub struct Config {
pub recent: Option<u32>,
pub main_tag_selector: TagSelector,
pub editor: Vec<String>,
pub tag_selectors: Vec<NamedTagSelector>,
pub alias: HashMap<String, Alias>,
pub types: HashMap<ScriptType, ScriptTypeConfig>,
pub env: HashMap<String, String>,
/* private fields */
}Fields§
§recent: Option<u32>§main_tag_selector: TagSelector§editor: Vec<String>§tag_selectors: Vec<NamedTagSelector>§alias: HashMap<String, Alias>§types: HashMap<ScriptType, ScriptTypeConfig>§env: HashMap<String, String>Implementations§
source§impl Config
impl Config
sourcepub fn load(p: &Path) -> Result<Self>
pub fn load(p: &Path) -> Result<Self>
Examples found in repository?
More examples
src/util/completion_util.rs (line 114)
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
pub async fn handle_completion(comp: Completion, repo: &mut Option<ScriptRepo>) -> Result {
match comp {
Completion::LS { name, args } => {
let mut new_root = match Root::try_parse_from(args) {
Ok(Root {
subcmd: Some(Subs::Tags(_) | Subs::Types(_)),
..
}) => {
// TODO: 在補全腳本中處理,而不要在這邊
return Err(Error::Completion);
}
Ok(t) => t,
Err(e) => {
log::warn!("補全時出錯 {}", e);
// NOTE: -V 或 --help 也會走到這裡
return Err(Error::Completion);
}
};
log::info!("補完模式,參數為 {:?}", new_root);
new_root.set_home_unless_from_alias(false)?;
new_root.sanitize_flags();
*repo = Some(init_repo(new_root.root_args, false).await?);
let iter = repo.as_mut().unwrap().iter_mut(Visibility::Normal);
let scripts = if let Some(name) = name {
fuzz_arr(&name, iter).await?
} else {
let mut t: Vec<_> = iter.collect();
sort(&mut t);
t
};
print_iter(scripts.iter().map(|s| s.name.key()), " ");
}
Completion::NoSubcommand { args } => {
if let Ok(root) = parse_alias_root(&args) {
if root.subcmd.is_some() {
log::debug!("子命令 = {:?}", root.subcmd);
return Err(Error::Completion);
}
} // else: 解析錯誤當然不可能有子命令啦
}
Completion::Alias { args } => {
let root = parse_alias_root(&args)?;
if root.root_args.no_alias {
log::info!("無別名模式");
return Err(Error::Completion);
}
let home = path::compute_home_path_optional(root.root_args.hs_home.as_ref(), false)?;
let conf = Config::load(&home)?;
if let Some(new_args) = root.expand_alias(&args, &conf) {
print_iter(new_args, " ");
} else {
log::info!("並非別名");
return Err(Error::Completion);
};
}
Completion::Home { args } => {
let root = parse_alias_root(&args)?;
let home = root.root_args.hs_home.ok_or_else(|| Error::Completion)?;
print!("{}", home);
}
Completion::ParseRun { args } => {
let mut root = Root::try_parse_from(args).map_err(|e| {
log::warn!("補全時出錯 {}", e);
Error::Completion
})?;
root.sanitize()?;
match root.subcmd {
Some(Subs::Run {
script_query, args, ..
}) => {
let iter = std::iter::once(script_query.to_string())
.chain(args.into_iter().map(|s| to_display_args(s)));
print_iter(iter, " ");
}
res @ _ => {
log::warn!("非執行指令 {:?}", res);
return Err(Error::Completion);
}
}
}
}
Ok(())
}pub fn store(&self) -> Result
pub fn is_from_dafault(&self) -> bool
pub fn set_prompt_level(l: Option<PromptLevel>)
sourcepub fn get_prompt_level() -> PromptLevel
pub fn get_prompt_level() -> PromptLevel
Examples found in repository?
src/query/util.rs (line 106)
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
pub async fn do_script_query<'b>(
script_query: &ScriptQuery,
script_repo: &'b mut ScriptRepo,
finding_filtered: bool,
forbid_prompt: bool,
) -> Result<Option<RepoEntry<'b>>> {
log::debug!("開始尋找 `{:?}`", script_query);
let mut visibility = compute_vis(script_query.bang);
if finding_filtered {
visibility = visibility.invert();
}
match &script_query.inner {
ScriptQueryInner::Prev(prev) => {
assert!(!finding_filtered); // XXX 很難看的作法,應設法靜態檢查
let latest = script_repo.latest_mut(prev.get(), visibility);
log::trace!("找最新腳本");
return if latest.is_some() {
Ok(latest)
} else {
Err(Error::Empty)
};
}
ScriptQueryInner::Exact(name) => Ok(script_repo.get_mut(name, visibility)),
ScriptQueryInner::Fuzz(name) => {
let level = if forbid_prompt {
PromptLevel::Never
} else {
Config::get_prompt_level()
};
let iter = script_repo.iter_mut(visibility);
let fuzz_res = fuzzy::fuzz(name, iter, SEP).await?;
let mut is_low = false;
let mut is_multi_fuzz = false;
let entry = match fuzz_res {
Some(fuzzy::High(entry)) => entry,
Some(fuzzy::Low(entry)) => {
is_low = true;
entry
}
#[cfg(feature = "benching")]
Some(fuzzy::Multi { ans, .. }) => {
is_multi_fuzz = true;
ans
}
#[cfg(not(feature = "benching"))]
Some(fuzzy::Multi { ans, others, .. }) => {
is_multi_fuzz = true;
the_multifuzz_algo(ans, others)
}
None => return Ok(None),
};
let need_prompt = {
match level {
PromptLevel::Always => true,
PromptLevel::Never => false,
PromptLevel::Smart => is_low || is_multi_fuzz,
PromptLevel::OnMultiFuzz => is_multi_fuzz,
}
};
if need_prompt {
prompt_fuzz_acceptable(&*entry)?;
}
Ok(Some(entry))
}
}
}sourcepub fn get() -> &'static Config
pub fn get() -> &'static Config
Examples found in repository?
More examples
src/util/mod.rs (line 74)
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
pub fn open_editor(path: &Path) -> Result {
let conf = Config::get();
let cmd = create_concat_cmd(&conf.editor, &[&path]);
let stat = run_cmd(cmd)?;
if !stat.success() {
let code = stat.code().unwrap_or_default();
return Err(Error::EditorError(code, conf.editor.clone()));
}
Ok(())
}
pub fn create_concat_cmd<'a, 'b, I1, S1, I2, S2>(arg1: I1, arg2: I2) -> Command
where
I1: IntoIterator<Item = &'a S1>,
I2: IntoIterator<Item = &'b S2>,
S1: AsRef<OsStr> + 'a,
S2: AsRef<OsStr> + 'b,
{
let mut arg1 = arg1.into_iter();
let cmd = arg1.next().unwrap();
let remaining = arg1
.map(|s| s.as_ref())
.chain(arg2.into_iter().map(|s| s.as_ref()));
create_cmd(cmd, remaining)
}
pub fn file_modify_time(path: &Path) -> Result<DateTime<Utc>> {
let meta = handle_fs_res(&[path], std::fs::metadata(path))?;
let modified = handle_fs_res(&[path], meta.modified())?;
Ok(modified.into())
}
pub fn read_file(path: &Path) -> Result<String> {
let mut file = handle_fs_res(&[path], File::open(path)).context("唯讀開啟檔案失敗")?;
let mut content = String::new();
handle_fs_res(&[path], file.read_to_string(&mut content)).context("讀取檔案失敗")?;
Ok(content)
}
pub fn write_file(path: &Path, content: &str) -> Result<()> {
let mut file = handle_fs_res(&[path], File::create(path))?;
handle_fs_res(&[path], file.write_all(content.as_bytes()))
}
pub fn remove(script_path: &Path) -> Result<()> {
handle_fs_res(&[&script_path], remove_file(&script_path))
}
pub fn mv(origin: &Path, new: &Path) -> Result<()> {
log::info!("修改 {:?} 為 {:?}", origin, new);
// NOTE: 創建資料夾和檔案
if let Some(parent) = new.parent() {
handle_fs_res(&[&new], create_dir_all(parent))?;
}
handle_fs_res(&[&new, &origin], rename(&origin, &new))
}
pub fn cp(origin: &Path, new: &Path) -> Result<()> {
// NOTE: 創建資料夾和檔案
if let Some(parent) = new.parent() {
handle_fs_res(&[parent], create_dir_all(parent))?;
}
let _copied = handle_fs_res(&[&origin, &new], std::fs::copy(&origin, &new))?;
Ok(())
}
pub fn handle_fs_err<P: AsRef<Path>>(path: &[P], err: std::io::Error) -> Error {
use std::sync::Arc;
let mut p = path.iter().map(|p| p.as_ref().to_owned()).collect();
log::warn!("檔案系統錯誤:{:?}, {:?}", p, err);
match err.kind() {
std::io::ErrorKind::PermissionDenied => Error::PermissionDenied(p),
std::io::ErrorKind::NotFound => Error::PathNotFound(p),
std::io::ErrorKind::AlreadyExists => Error::PathExist(p.remove(0)),
_ => Error::GeneralFS(p, Arc::new(err)),
}
}
pub fn handle_fs_res<T, P: AsRef<Path>>(path: &[P], res: std::io::Result<T>) -> Result<T> {
match res {
Ok(t) => Ok(t),
Err(e) => Err(handle_fs_err(path, e)),
}
}
/// check_subtype 是為避免太容易生出子模版
pub fn get_or_create_template_path<T: AsScriptFullTypeRef>(
ty: &T,
force: bool,
check_subtype: bool,
) -> Result<(PathBuf, Option<&'static str>)> {
if !force {
Config::get().get_script_conf(ty.get_ty())?; // 確認類型存在與否
}
let tmpl_path = path::get_template_path(ty)?;
if !tmpl_path.exists() {
if check_subtype && ty.get_sub().is_some() {
return Err(Error::UnknownType(ty.display().to_string()));
}
let default_tmpl = get_default_template(ty);
return write_file(&tmpl_path, default_tmpl).map(|_| (tmpl_path, Some(default_tmpl)));
}
Ok((tmpl_path, None))
}
pub fn get_or_create_template<T: AsScriptFullTypeRef>(
ty: &T,
force: bool,
check_subtype: bool,
) -> Result<String> {
let (tmpl_path, default_tmpl) = get_or_create_template_path(ty, force, check_subtype)?;
if let Some(default_tmpl) = default_tmpl {
return Ok(default_tmpl.to_owned());
}
read_file(&tmpl_path)
}
/// copied from `shell_escape` crate
pub fn to_display_args(arg: String) -> String {
fn non_whitelisted(ch: char) -> bool {
match ch {
'a'..='z' | 'A'..='Z' | '0'..='9' | '-' | '_' | '=' | '/' | ',' | '.' | '+' => false,
_ => true,
}
}
if !arg.is_empty() && !arg.contains(non_whitelisted) {
return arg;
}
let mut es = String::with_capacity(arg.len() + 2);
es.push('\'');
for ch in arg.chars() {
match ch {
'\'' | '!' => {
es.push_str("'\\");
es.push(ch);
es.push('\'');
}
_ => es.push(ch),
}
}
es.push('\'');
es
}
fn relative_to_home(p: &Path) -> Option<&Path> {
const CUR_DIR: &str = ".";
let home = dirs::home_dir()?;
if p == home {
return Some(CUR_DIR.as_ref());
}
p.strip_prefix(&home).ok()
}
fn get_birthplace() -> Result<PathBuf> {
// NOTE: 用 $PWD 可以取到 symlink 還沒解開前的路徑
// 若用 std::env::current_dir,該路徑已為真實路徑
let here = std::env::var("PWD")?;
Ok(here.into())
}
#[derive(Debug)]
pub struct PrepareRespond {
pub is_new: bool,
pub time: DateTime<Utc>,
}
pub fn prepare_script<T: AsRef<str>>(
path: &Path,
script: &ScriptInfo,
sub_type: Option<&ScriptType>,
no_template: bool,
content: &[T],
) -> Result<PrepareRespond> {
log::info!("開始準備 {} 腳本內容……", script.name);
let has_content = !content.is_empty();
let is_new = !path.exists();
if is_new {
let birthplace = get_birthplace()?;
let birthplace_rel = relative_to_home(&birthplace);
let mut file = handle_fs_res(&[path], File::create(&path))?;
let content = content.iter().map(|s| s.as_ref().split('\n')).flatten();
if !no_template {
let content: Vec<_> = content.collect();
let info = json!({
"birthplace_in_home": birthplace_rel.is_some(),
"birthplace_rel": birthplace_rel,
"birthplace": birthplace,
"name": script.name.key().to_owned(),
"content": content,
});
log::debug!("編輯模版資訊:{:?}", info);
// NOTE: 計算 `path` 時早已檢查過腳本類型,這裡直接不檢查了
let template = get_or_create_template(&(&script.ty, sub_type), true, true)?;
handle_fs_res(&[path], write_prepare_script(file, &template, &info))?;
} else {
let mut first = true;
for line in content {
if !first {
writeln!(file, "")?;
}
first = false;
write!(file, "{}", line)?;
}
}
} else {
if has_content {
log::debug!("腳本已存在,往後接上給定的訊息");
let mut file = handle_fs_res(
&[path],
std::fs::OpenOptions::new()
.append(true)
.write(true)
.open(path),
)?;
for content in content.iter() {
handle_fs_res(&[path], writeln!(&mut file, "{}", content.as_ref()))?;
}
}
}
Ok(PrepareRespond {
is_new,
time: file_modify_time(path)?,
})
}
fn write_prepare_script<W: Write>(
w: W,
template: &str,
info: &serde_json::Value,
) -> std::io::Result<()> {
use handlebars::{Handlebars, TemplateRenderError};
let reg = Handlebars::new();
reg.render_template_to_write(&template, &info, w)
.map_err(|err| match err {
TemplateRenderError::IOError(err, ..) => err,
e => panic!("解析模版錯誤:{}", e),
})
}
/// 可用來表示「未知類別」的概念 TODO: 測試之
pub struct DisplayType<'a> {
ty: &'a ScriptType,
color: Option<Color>,
}
impl<'a> DisplayType<'a> {
pub fn is_unknown(&self) -> bool {
self.color.is_none()
}
pub fn color(&self) -> Color {
self.color.unwrap_or(Color::BrightBlack)
}
pub fn display(&self) -> Cow<'a, str> {
if self.is_unknown() {
Cow::Owned(format!("{}, unknown", self.ty))
} else {
Cow::Borrowed(self.ty.as_ref())
}
}
}
pub fn get_display_type(ty: &ScriptType) -> DisplayType {
let conf = Config::get();
match conf.get_color(ty) {
Err(e) => {
log::warn!("取腳本顏色時出錯:{},視為未知類別", e);
DisplayType { ty, color: None }
}
Ok(c) => DisplayType { ty, color: Some(c) },
}
}src/script.rs (line 158)
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
fn add_ext(
name: &mut String,
ty: &ScriptType,
fallback: bool,
err: &mut Option<Error>,
) -> Result {
let ext = match Config::get().get_script_conf(ty) {
Err(e) => {
if !fallback {
return Err(e);
}
log::warn!(
"取腳本路徑時找不到類別設定:{},直接把類別名當擴展名試試",
e,
);
*err = Some(e);
Some(ty.as_ref())
}
Ok(c) => c.ext.as_ref().map(|s| s.as_ref()),
};
if let Some(ext) = ext {
write!(name, ".{}", ext).unwrap();
}
Ok(())
}src/args/mod.rs (line 398)
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
fn handle_alias_args(args: Vec<String>) -> Result<Root> {
if args.iter().any(|s| s == "--no-alias") {
log::debug!("不使用別名!"); // NOTE: --no-alias 的判斷存在於 clap 之外!
let root = Root::parse_from(args);
return Ok(root);
}
match AliasRoot::try_parse_from(&args) {
Ok(alias_root) => {
log::info!("別名命令行物件 {:?}", alias_root);
set_home(&alias_root.root_args.hs_home, true)?;
let mut root = match alias_root.expand_alias(&args, Config::get()) {
Some(new_args) => Root::parse_from(new_args),
None => Root::parse_from(&args),
};
root.is_from_alias = true;
Ok(root)
}
Err(e) => {
log::warn!("解析別名參數出錯:{}", e); // NOTE: 不要讓這個錯誤傳上去,而是讓它掉入 Root::parse_from 中再來報錯
Root::parse_from(args);
unreachable!()
}
}
}src/util/init_repo.rs (line 35)
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
pub async fn init_repo(args: RootArgs, need_journal: bool) -> Result<ScriptRepo> {
let RootArgs {
no_trace,
humble,
archaeology,
select,
toggle,
recent,
timeless,
..
} = args;
let conf = Config::get();
let recent = if timeless {
None
} else {
recent.or(conf.recent).map(|recent| RecentFilter {
recent,
archaeology,
})
};
// TODO: 測試 toggle 功能,以及名字不存在的錯誤
let tag_group = {
let mut toggle: HashSet<_> = toggle.into_iter().collect();
let mut tag_group = conf.get_tag_selector_group(&mut toggle);
if let Some(name) = toggle.into_iter().next() {
return Err(Error::TagSelectorNotFound(name));
}
for select in select.into_iter() {
tag_group.push(select);
}
tag_group
};
let (env, init) = init_env(need_journal).await?;
let mut repo = ScriptRepo::new(recent, env, &tag_group)
.await
.context("載入腳本倉庫失敗")?;
if no_trace {
repo.no_trace();
} else if humble {
repo.humble();
}
if init {
log::info!("初次使用,載入好用工具和預執行腳本");
main_util::load_utils(&mut repo).await?;
main_util::prepare_pre_run(None)?;
main_util::load_templates()?;
}
Ok(repo)
}src/util/main_util.rs (line 150)
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
fn run(
script_path: &Path,
info: &ScriptInfo,
remaining: &[String],
hs_tmpl_val: &serde_json::Value,
remaining_envs: &[EnvPair],
) -> Result<()> {
let conf = Config::get();
let ty = &info.ty;
let script_conf = conf.get_script_conf(ty)?;
let cmd_str = if let Some(cmd) = &script_conf.cmd {
cmd
} else {
return Err(Error::PermissionDenied(vec![script_path.to_path_buf()]));
};
let env = conf.gen_env(&hs_tmpl_val)?;
let ty_env = script_conf.gen_env(&hs_tmpl_val)?;
let pre_run_script = prepare_pre_run(None)?;
let (cmd, shebang) = super::shebang_handle::handle(&pre_run_script)?;
let args = shebang
.iter()
.map(|s| s.as_ref())
.chain(std::iter::once(pre_run_script.as_os_str()))
.chain(remaining.iter().map(|s| s.as_ref()));
let set_cmd_envs = |cmd: &mut Command| {
cmd.envs(ty_env.iter().map(|(a, b)| (a, b)));
cmd.envs(env.iter().map(|(a, b)| (a, b)));
cmd.envs(remaining_envs.iter().map(|p| (&p.key, &p.val)));
};
let mut cmd = super::create_cmd(cmd, args);
set_cmd_envs(&mut cmd);
let stat = super::run_cmd(cmd)?;
log::info!("預腳本執行結果:{:?}", stat);
if !stat.success() {
// TODO: 根據返回值做不同表現
let code = stat.code().unwrap_or_default();
return Err(Error::PreRunError(code));
}
let args = script_conf.args(&hs_tmpl_val)?;
let full_args = args
.iter()
.map(|s| s.as_str())
.chain(remaining.iter().map(|s| s.as_str()));
let mut cmd = super::create_cmd(&cmd_str, full_args);
set_cmd_envs(&mut cmd);
let stat = super::run_cmd(cmd)?;
log::info!("程式執行結果:{:?}", stat);
if !stat.success() {
let code = stat.code().unwrap_or_default();
Err(Error::ScriptError(code))
} else {
Ok(())
}
}sourcepub fn gen_env(&self, info: &Value) -> Result<Vec<(String, String)>>
pub fn gen_env(&self, info: &Value) -> Result<Vec<(String, String)>>
Examples found in repository?
src/util/main_util.rs (line 160)
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
fn run(
script_path: &Path,
info: &ScriptInfo,
remaining: &[String],
hs_tmpl_val: &serde_json::Value,
remaining_envs: &[EnvPair],
) -> Result<()> {
let conf = Config::get();
let ty = &info.ty;
let script_conf = conf.get_script_conf(ty)?;
let cmd_str = if let Some(cmd) = &script_conf.cmd {
cmd
} else {
return Err(Error::PermissionDenied(vec![script_path.to_path_buf()]));
};
let env = conf.gen_env(&hs_tmpl_val)?;
let ty_env = script_conf.gen_env(&hs_tmpl_val)?;
let pre_run_script = prepare_pre_run(None)?;
let (cmd, shebang) = super::shebang_handle::handle(&pre_run_script)?;
let args = shebang
.iter()
.map(|s| s.as_ref())
.chain(std::iter::once(pre_run_script.as_os_str()))
.chain(remaining.iter().map(|s| s.as_ref()));
let set_cmd_envs = |cmd: &mut Command| {
cmd.envs(ty_env.iter().map(|(a, b)| (a, b)));
cmd.envs(env.iter().map(|(a, b)| (a, b)));
cmd.envs(remaining_envs.iter().map(|p| (&p.key, &p.val)));
};
let mut cmd = super::create_cmd(cmd, args);
set_cmd_envs(&mut cmd);
let stat = super::run_cmd(cmd)?;
log::info!("預腳本執行結果:{:?}", stat);
if !stat.success() {
// TODO: 根據返回值做不同表現
let code = stat.code().unwrap_or_default();
return Err(Error::PreRunError(code));
}
let args = script_conf.args(&hs_tmpl_val)?;
let full_args = args
.iter()
.map(|s| s.as_str())
.chain(remaining.iter().map(|s| s.as_str()));
let mut cmd = super::create_cmd(&cmd_str, full_args);
set_cmd_envs(&mut cmd);
let stat = super::run_cmd(cmd)?;
log::info!("程式執行結果:{:?}", stat);
if !stat.success() {
let code = stat.code().unwrap_or_default();
Err(Error::ScriptError(code))
} else {
Ok(())
}
}sourcepub fn get_color(&self, ty: &ScriptType) -> Result<Color>
pub fn get_color(&self, ty: &ScriptType) -> Result<Color>
sourcepub fn get_script_conf(&self, ty: &ScriptType) -> Result<&ScriptTypeConfig>
pub fn get_script_conf(&self, ty: &ScriptType) -> Result<&ScriptTypeConfig>
Examples found in repository?
More examples
src/util/mod.rs (line 161)
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
pub fn get_or_create_template_path<T: AsScriptFullTypeRef>(
ty: &T,
force: bool,
check_subtype: bool,
) -> Result<(PathBuf, Option<&'static str>)> {
if !force {
Config::get().get_script_conf(ty.get_ty())?; // 確認類型存在與否
}
let tmpl_path = path::get_template_path(ty)?;
if !tmpl_path.exists() {
if check_subtype && ty.get_sub().is_some() {
return Err(Error::UnknownType(ty.display().to_string()));
}
let default_tmpl = get_default_template(ty);
return write_file(&tmpl_path, default_tmpl).map(|_| (tmpl_path, Some(default_tmpl)));
}
Ok((tmpl_path, None))
}src/script.rs (line 158)
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
fn add_ext(
name: &mut String,
ty: &ScriptType,
fallback: bool,
err: &mut Option<Error>,
) -> Result {
let ext = match Config::get().get_script_conf(ty) {
Err(e) => {
if !fallback {
return Err(e);
}
log::warn!(
"取腳本路徑時找不到類別設定:{},直接把類別名當擴展名試試",
e,
);
*err = Some(e);
Some(ty.as_ref())
}
Ok(c) => c.ext.as_ref().map(|s| s.as_ref()),
};
if let Some(ext) = ext {
write!(name, ".{}", ext).unwrap();
}
Ok(())
}src/util/main_util.rs (line 153)
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
fn run(
script_path: &Path,
info: &ScriptInfo,
remaining: &[String],
hs_tmpl_val: &serde_json::Value,
remaining_envs: &[EnvPair],
) -> Result<()> {
let conf = Config::get();
let ty = &info.ty;
let script_conf = conf.get_script_conf(ty)?;
let cmd_str = if let Some(cmd) = &script_conf.cmd {
cmd
} else {
return Err(Error::PermissionDenied(vec![script_path.to_path_buf()]));
};
let env = conf.gen_env(&hs_tmpl_val)?;
let ty_env = script_conf.gen_env(&hs_tmpl_val)?;
let pre_run_script = prepare_pre_run(None)?;
let (cmd, shebang) = super::shebang_handle::handle(&pre_run_script)?;
let args = shebang
.iter()
.map(|s| s.as_ref())
.chain(std::iter::once(pre_run_script.as_os_str()))
.chain(remaining.iter().map(|s| s.as_ref()));
let set_cmd_envs = |cmd: &mut Command| {
cmd.envs(ty_env.iter().map(|(a, b)| (a, b)));
cmd.envs(env.iter().map(|(a, b)| (a, b)));
cmd.envs(remaining_envs.iter().map(|p| (&p.key, &p.val)));
};
let mut cmd = super::create_cmd(cmd, args);
set_cmd_envs(&mut cmd);
let stat = super::run_cmd(cmd)?;
log::info!("預腳本執行結果:{:?}", stat);
if !stat.success() {
// TODO: 根據返回值做不同表現
let code = stat.code().unwrap_or_default();
return Err(Error::PreRunError(code));
}
let args = script_conf.args(&hs_tmpl_val)?;
let full_args = args
.iter()
.map(|s| s.as_str())
.chain(remaining.iter().map(|s| s.as_str()));
let mut cmd = super::create_cmd(&cmd_str, full_args);
set_cmd_envs(&mut cmd);
let stat = super::run_cmd(cmd)?;
log::info!("程式執行結果:{:?}", stat);
if !stat.success() {
let code = stat.code().unwrap_or_default();
Err(Error::ScriptError(code))
} else {
Ok(())
}
}sourcepub fn get_tag_selector_group(
&self,
toggle: &mut HashSet<String>
) -> TagSelectorGroup
pub fn get_tag_selector_group(
&self,
toggle: &mut HashSet<String>
) -> TagSelectorGroup
Examples found in repository?
src/util/init_repo.rs (line 49)
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
pub async fn init_repo(args: RootArgs, need_journal: bool) -> Result<ScriptRepo> {
let RootArgs {
no_trace,
humble,
archaeology,
select,
toggle,
recent,
timeless,
..
} = args;
let conf = Config::get();
let recent = if timeless {
None
} else {
recent.or(conf.recent).map(|recent| RecentFilter {
recent,
archaeology,
})
};
// TODO: 測試 toggle 功能,以及名字不存在的錯誤
let tag_group = {
let mut toggle: HashSet<_> = toggle.into_iter().collect();
let mut tag_group = conf.get_tag_selector_group(&mut toggle);
if let Some(name) = toggle.into_iter().next() {
return Err(Error::TagSelectorNotFound(name));
}
for select in select.into_iter() {
tag_group.push(select);
}
tag_group
};
let (env, init) = init_env(need_journal).await?;
let mut repo = ScriptRepo::new(recent, env, &tag_group)
.await
.context("載入腳本倉庫失敗")?;
if no_trace {
repo.no_trace();
} else if humble {
repo.humble();
}
if init {
log::info!("初次使用,載入好用工具和預執行腳本");
main_util::load_utils(&mut repo).await?;
main_util::prepare_pre_run(None)?;
main_util::load_templates()?;
}
Ok(repo)
}Trait Implementations§
source§impl<'de> Deserialize<'de> for Config
impl<'de> Deserialize<'de> for Config
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read more
source§impl PartialEq<Config> for Config
impl PartialEq<Config> for Config
impl Eq for Config
impl StructuralEq for Config
impl StructuralPartialEq for Config
Auto Trait Implementations§
impl RefUnwindSafe for Config
impl Send for Config
impl Sync for Config
impl Unpin for Config
impl UnwindSafe for Config
Blanket Implementations§
source§impl<Q, K> Equivalent<K> for Qwhere
Q: Eq + ?Sized,
K: Borrow<Q> + ?Sized,
impl<Q, K> Equivalent<K> for Qwhere
Q: Eq + ?Sized,
K: Borrow<Q> + ?Sized,
source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
Compare self to
key and return true if they are equal.