Ambiente & argumentos de linha de comando
O módulo stdlib::env é a janela do Glide para o ambiente por processo: os argumentos de linha de comando com que o programa foi iniciado, as variáveis de ambiente que ele herdou, e a capacidade de lê-las, mutá-las, enumerá-las e expandi-las — além de um exit imediato do processo. Informações estáticas do host (nome do SO, arquitetura, caminho do executável, separadores de caminho) residem em stdlib::os.
Importação
import stdlib::env::*;
Superfície pública resumida
| Item | Tipo | Assinatura |
|---|---|---|
env_args_count |
fn | fn env_args_count() -> i32 |
env_args_at |
fn | fn env_args_at(i: i32) -> string |
env_args |
fn | fn env_args() -> *Vector<string> |
env_get |
fn | fn env_get(name: string) -> string |
env_has |
fn | fn env_has(name: string) -> bool |
env_set |
fn | fn env_set(name: string, value: string) -> ! |
env_unset |
fn | fn env_unset(name: string) -> ! |
env_all |
fn | fn env_all() -> *Vector<EnvKV> |
env_expand |
fn | fn env_expand(s: string) -> string |
env_exit |
fn | fn env_exit(code: i32) |
EnvKV |
struct | pub struct EnvKV { pub key: string, pub value: string } |
Toda função pública e o único tipo público estão documentados a seguir.
Argumentos de linha de comando
A indexação de argumentos espelha a convenção de argc/argv do C: o índice 0 é o caminho do programa e os argumentos fornecidos pelo usuário começam em 1.
| Função | Assinatura | Descrição |
|---|---|---|
env_args_count |
fn env_args_count() -> i32 |
Número total de argumentos de linha de comando, incluindo o caminho do programa no índice 0. |
env_args_at |
fn env_args_at(i: i32) -> string |
Argumento no índice i. Retorna "" para índices fora do intervalo. |
env_args |
fn env_args() -> *Vector<string> |
Todos os argumentos do usuário como um vector, pulando o caminho do programa no índice 0. |
env_args_count / env_args_at
env_args_at é totalmente segura: qualquer índice fora do intervalo (negativo, ou >= env_args_count()) produz "" em vez de causar uma falha.
import stdlib::env::*;
fn main() -> i32 {
let n: i32 = env_args_count();
println!("argc =", n);
let prog: string = env_args_at(0); // caminho do programa
let first: string = env_args_at(1); // primeiro argumento do usuário, "" se ausente
println!("prog =", prog);
println!("first =", first);
return 0;
}
Invocado como ./app build --release:
argc = 3
prog = ./app
first = build
env_args
env_args retorna um *Vector<string> recém-alocado contendo apenas os argumentos do usuário (a partir do índice 1), que é geralmente o que um parser de argumentos precisa.
import stdlib::env::*;
fn main() -> i32 {
let args: *Vector<string> = env_args();
for let i: i32 = 0; i < args.len(); i++ {
println!("arg", i, args.get(i));
}
return 0;
}
Fundamentos de parsing de argumentos
env deliberadamente não inclui um parser de flags — ele entrega o vector de argumentos bruto e você decide a convenção. O padrão abaixo lida com flags simples (-v / --verbose) e pares --chave=valor dividindo em =:
import stdlib::env::*;
fn main() -> i32 {
let args: *Vector<string> = env_args();
let mut verbose: bool = false;
let mut out: string = "a.out";
for let i: i32 = 0; i < args.len(); i++ {
let a: string = args.get(i);
if a.eq("-v") || a.eq("--verbose") {
verbose = true;
} else if a.contains("=") {
let parts: *Vector<string> = a.split("=");
if parts.len() == 2 && parts.get(0).eq("--out") {
out = parts.get(1);
}
}
}
println!("verbose =", verbose);
println!("out =", out);
return 0;
}
Lendo variáveis de ambiente
| Função | Assinatura | Descrição |
|---|---|---|
env_get |
fn env_get(name: string) -> string |
Valor de name, ou "" quando não definida. |
env_has |
fn env_has(name: string) -> bool |
true somente se name está definida com um valor não vazio. |
env_get
Retorna "" para uma variável não definida. Como um valor vazio e uma variável não definida são ambos lidos como "", use env_has quando precisar distingui-los.
import stdlib::env::*;
fn main() -> i32 {
let path: string = env_get("PATH");
println!("PATH len =", path.len());
return 0;
}
env_has
import stdlib::env::*;
fn main() -> i32 {
if env_has("DEBUG") {
println!("debug on");
} else {
println!("debug off");
}
return 0;
}
Lendo configurações com valores padrão
Um idioma comum é "ler uma variável, analisá-la e recorrer a um padrão." Como string.try_parse_int() retorna !i32, é possível definir um padrão para toda a expressão com ??. Encapsule a consulta de modo que não definida e não analisável ambas se apresentem como um err, então reduza-as ao valor padrão em um único lugar:
import stdlib::env::*;
fn port_from_env() -> !i32 {
let raw: string = env_get("PORT");
if raw.eq("") { return err("PORT unset"); }
return raw.try_parse_int(); // err em texto não numérico
}
fn main() -> i32 {
// Padrão quando não definida OU não analisável, em uma única expressão.
let port: i32 = port_from_env() ?? 8080;
let host: string = env_get("HOST");
if host.eq("") { host = "127.0.0.1"; } // padrão para string
println!("listening on", host, port);
return 0;
}
Mutando variáveis de ambiente
Ambos os mutadores retornam o tipo resultado sem payload !. Erros são raros e têm origem no SO — tipicamente um nome inválido (p. ex., um que contenha =) ou um limite do sistema. Propague com ? em uma função !T, ou inspecione .ok / .err.
| Função | Assinatura | Descrição |
|---|---|---|
env_set |
fn env_set(name: string, value: string) -> ! |
Define name como value, sobrescrevendo qualquer valor existente. Err se o SO rejeitar a chamada. |
env_unset |
fn env_unset(name: string) -> ! |
Remove name. Idempotente — remover uma variável inexistente não é um erro. |
env_set é multiplataforma: no Windows usa _putenv_s, que atualiza tanto o bloco de ambiente Win32 quanto a tabela CRT, para que um env_get posterior enxergue o novo valor; no POSIX usa setenv(name, value, 1). env_unset remove a variável de ambos os repositórios.
env_set / env_unset
import stdlib::env::*;
fn main() -> !i32 {
env_set("LANG", "en_US.UTF-8")?;
let v: string = env_get("LANG");
println!("LANG =", v);
env_unset("LANG")?;
if env_has("LANG") {
println!("still set");
} else {
println!("unset ok");
}
return ok(0);
}
Para tratar o erro sem propagá-lo, vincule o resultado e leia seus campos. eprintln (de stdlib::io) escreve na stderr:
import stdlib::env::*;
import stdlib::io::*; // eprintln
fn main() -> i32 {
let r: ! = env_set("GLIDE_DOC_DEMO", "1");
if !r.ok {
eprintln(r.err);
return 1;
}
println!("set:", env_get("GLIDE_DOC_DEMO")); // "1"
println!("has:", env_has("GLIDE_DOC_DEMO")); // true
let u: ! = env_unset("GLIDE_DOC_DEMO");
if !u.ok { eprintln(u.err); return 1; }
println!("has after unset:", env_has("GLIDE_DOC_DEMO")); // false
return 0;
}
Enumerando o ambiente
struct EnvKV
Uma entrada de ambiente decomposta, conforme retornada por env_all().
pub struct EnvKV {
pub key: string,
pub value: string,
}
| Campo | Tipo | Descrição |
|---|---|---|
key |
string |
Nome da variável (texto à esquerda do primeiro =). |
value |
string |
Valor da variável (texto à direita do primeiro =). |
env_all
| Função | Assinatura | Descrição |
|---|---|---|
env_all |
fn env_all() -> *Vector<EnvKV> |
Instantâneo de todo o ambiente do processo, dividido em pares EnvKV. |
O vector retornado é uma cópia tirada no momento da chamada. Entradas brutas malformadas (aquelas sem =, ou com chave vazia) são ignoradas. Chamar env_set / env_unset depois não atualiza um vector já retornado — chame env_all() novamente para um instantâneo atualizado.
import stdlib::env::*;
fn main() -> i32 {
let all: *Vector<EnvKV> = env_all();
println!("env count =", all.len());
for let i: i32 = 0; i < all.len(); i++ {
let kv: EnvKV = all.get(i);
println!(kv.key, "=", kv.value);
}
return 0;
}
Como env_has/env_get não conseguem distinguir FOO= (vazio) de um FOO não definido, env_all é a ferramenta para uma verificação exata de presença. Retornar ?string permite ao chamador ramificar em some/none:
import stdlib::env::*;
fn lookup(key: string) -> ?string {
let all: *Vector<EnvKV> = env_all();
for let i: i32 = 0; i < all.len(); i++ {
let kv: EnvKV = all.get(i);
if kv.key.eq(key) { return some(kv.value); }
}
return none();
}
fn main() -> i32 {
let r: ?string = lookup("PATH");
match r {
some(v) => println!("PATH value length", v.len()),
none() => println!("PATH absent"),
}
return 0;
}
Expansão de variáveis
env_expand
| Função | Assinatura | Descrição |
|---|---|---|
env_expand |
fn env_expand(s: string) -> string |
Expande referências $VAR, ${VAR} e %VAR% em s para seus valores atuais no ambiente. |
Regras de expansão:
$VAR— forma POSIX simples. O nome começa no primeiro caractere de início de${VAR}— chaves POSIX, encerradas pelo}correspondente.%VAR%— forma Windows, encerrada pelo próximo%.- Variáveis desconhecidas são expandidas para a string vazia.
- Um
$seguido de um caractere que não seja de nome, ou um%sem%
nome (A-Z, a-z, _) e se estende pelos caracteres de continuação de nome seguintes (esses mais 0-9).
fechador, é mantido intacto (preservado literalmente).
import stdlib::env::*;
fn main() -> !i32 {
env_set("DEMO_DIR", "/srv")?;
// $VAR e %VAR% podem ser escritos inline.
println!(env_expand("posix: $DEMO_DIR/logs"));
println!(env_expand("win: %DEMO_DIR%\\logs"));
// ${VAR} colidiria com a interpolação de strings do próprio Glide, então
// construa o literal por concatenação em vez de escrever as chaves inline.
let tmpl: string = "braced: ".concat("$").concat("{").concat("DEMO_DIR").concat("}/x");
println!(env_expand(tmpl));
// Variável desconhecida -> vazio; $ isolado antes de caractere não-nome é preservado.
println!(env_expand("missing=[$NOPE_VAR] price=$5"));
return ok(0);
}
posix: /srv/logs
win: /srv\logs
braced: /srv/x
missing=[] price=$5
Encerramento do processo
env_exit
| Função | Assinatura | Descrição |
|---|---|---|
env_exit |
fn env_exit(code: i32) |
Encerra o processo imediatamente com code. |
env_exit chama diretamente o exit do C: ignora a limpeza do lado Glide, portanto blocos defer e auto-drops (let v* = ...) nos stack frames envolventes não serão executados. Use-a para encerramento forçado de alto nível após reportar um erro; prefira retornar um i32 não nulo de main quando quiser o desempilhamento normal.
import stdlib::env::*;
import stdlib::io::*; // eprintln
fn main() -> i32 {
let mode: string = env_get("MODE");
if mode.eq("") {
eprintln("MODE is required");
env_exit(2); // ignora limpeza por defer/auto-drop
}
println!("mode =", mode);
return 0;
}
Veja também
os— informações estáticas do host: nome do SO, arquitetura, caminho doio—eprintlne o restante da I/O de stdin/stdout/stderr usada noscli— parsing de argumentos de nível mais alto construído sobreenv_args*.
executável e os separadores de caminho/lista que você combina com env_get("PATH").
caminhos de erro acima.