• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mattwparas / steel / 17772690385

16 Sep 2025 04:36PM UTC coverage: 43.331% (+0.04%) from 43.289%
17772690385

Pull #519

github

web-flow
Merge 98d4fd22c into 3c10433b9
Pull Request #519: fix a bunch more clippy lints

56 of 123 new or added lines in 30 files covered. (45.53%)

8 existing lines in 3 files now uncovered.

12416 of 28654 relevant lines covered (43.33%)

2985398.75 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

33.33
/crates/steel-core/src/primitives/fs.rs
1
use crate::rvals::{
2
    self, AsRefMutSteelVal, AsRefSteelVal, Custom, IntoSteelVal, RestArgsIter, Result, SteelString,
3
    SteelVal,
4
};
5
use crate::steel_vm::builtin::BuiltInModule;
6
use crate::{steelerr, throw};
7
use std::env::{current_dir, set_current_dir};
8
use std::path::{Path, PathBuf};
9

10
use std::fs::{self, DirEntry, Metadata, ReadDir};
11
use std::io;
12

13
fn get_extension_from_filename(filename: &str) -> Option<&str> {
×
14
    Path::new(filename)
×
15
        .extension()
16
        .and_then(std::ffi::OsStr::to_str)
×
17
}
18

19
/// Copy files from source to destination recursively.
20
/// from https://nick.groenen.me/notes/recursively-copy-files-in-rust/
21
pub fn copy_recursively(source: impl AsRef<Path>, destination: impl AsRef<Path>) -> io::Result<()> {
×
22
    fs::create_dir_all(&destination)?;
×
23
    for entry in fs::read_dir(source)? {
×
24
        let entry = entry?;
×
25
        let filetype = entry.file_type()?;
×
26
        if filetype.is_dir() {
×
27
            copy_recursively(entry.path(), destination.as_ref().join(entry.file_name()))?;
×
28
        } else {
29
            fs::copy(entry.path(), destination.as_ref().join(entry.file_name()))?;
×
30
        }
31
    }
32
    Ok(())
×
33
}
34

35
impl Custom for PathBuf {
36
    fn fmt(&self) -> Option<std::result::Result<String, std::fmt::Error>> {
×
37
        Some(Ok(format!("#<Path:{:?}>", self)))
×
38
    }
39
}
40

41
impl Custom for glob::MatchOptions {}
42
impl Custom for glob::PatternError {}
43
impl Custom for glob::Paths {}
44

45
#[steel_derive::function(name = "glob")]
46
pub fn glob(pattern: SteelString, mut rest: RestArgsIter<'_, &SteelVal>) -> Result<SteelVal> {
×
47
    use crate::rvals::FromSteelVal;
48

49
    let options = rest
×
50
        .next()
NEW
51
        .map(|x| glob::MatchOptions::from_steelval(x.unwrap()))
×
52
        .unwrap_or_else(|| Ok(glob::MatchOptions::default()))?;
×
53

54
    if rest.next().is_some() {
55
        crate::stop!(ArityMismatch => "glob expects no more than 2 arguments");
×
56
    }
57

58
    glob::glob_with(pattern.as_str(), options)
59
        .map_err(|x| throw!(Generic => "glob pattern: {:?}", x)())?
×
60
        .into_steelval()
61
}
62

63
#[steel_derive::function(name = "glob-iter-next!")]
64
pub fn glob_paths_next(paths: &SteelVal) -> Result<SteelVal> {
×
65
    let mut paths = glob::Paths::as_mut_ref(paths)?;
×
66
    match paths.next() {
67
        Some(Ok(v)) => v.into_steelval(),
×
68
        Some(Err(e)) => crate::stop!(Generic => "glob-iter-next!: {:?}", e),
×
69
        None => Ok(SteelVal::BoolV(false)),
×
70
    }
71
}
72

73
#[steel_derive::function(name = "path->string")]
74
pub fn path_to_string(path: &SteelVal) -> Result<SteelVal> {
×
NEW
75
    <PathBuf as rvals::AsRefSteelVal>::as_ref(path)?
×
76
        .to_str()
77
        .map(|x| SteelVal::StringV(x.to_string().into()))
×
78
        .into_steelval()
79
}
80

81
/// Filesystem functions, mostly just thin wrappers around the `std::fs` functions in
82
/// the Rust std library.
83
#[steel_derive::define_module(name = "steel/filesystem")]
84
pub fn fs_module() -> BuiltInModule {
4✔
85
    let mut module = BuiltInModule::new("steel/filesystem");
8✔
86
    module
144✔
87
        .register_native_fn_definition(DELETE_DIRECTORY_DEFINITION)
140✔
88
        .register_native_fn_definition(CREATE_DIRECTORY_DEFINITION)
136✔
89
        .register_native_fn_definition(COPY_DIRECTORY_RECURSIVELY_DEFINITION)
132✔
90
        .register_native_fn_definition(IS_DIR_DEFINITION)
128✔
91
        .register_native_fn_definition(IS_FILE_DEFINITION)
124✔
92
        .register_native_fn_definition(READ_DIR_DEFINITION)
120✔
93
        .register_native_fn_definition(PATH_EXISTS_DEFINITION)
116✔
94
        .register_native_fn_definition(FILE_NAME_DEFINITION)
112✔
95
        .register_native_fn_definition(PARENT_NAME_DEFINITION)
108✔
96
        .register_native_fn_definition(CANONICALIZE_PATH_DEFINITION)
104✔
97
        .register_native_fn_definition(CURRENT_DIRECTORY_DEFINITION)
100✔
98
        .register_native_fn_definition(CHANGE_CURRENT_DIRECTORY_DEFINITION)
96✔
99
        .register_native_fn_definition(GET_EXTENSION_DEFINITION)
92✔
100
        .register_native_fn_definition(DELETE_FILE_DEFINITION)
88✔
101
        .register_native_fn_definition(READ_DIR_ITER_DEFINITION)
84✔
102
        .register_native_fn_definition(READ_DIR_ITER_NEXT_DEFINITION)
80✔
103
        .register_native_fn_definition(READ_DIR_ENTRY_IS_DIR_DEFINITION)
76✔
104
        .register_native_fn_definition(READ_DIR_ENTRY_IS_FILE_DEFINITION)
72✔
105
        .register_native_fn_definition(READ_DIR_ENTRY_IS_SYMLINK_DEFINITION)
68✔
106
        .register_native_fn_definition(READ_DIR_ENTRY_PATH_DEFINITION)
64✔
107
        .register_native_fn_definition(READ_DIR_ENTRY_FILE_NAME_DEFINITION)
60✔
108
        .register_native_fn_definition(READ_DIR_ENTRY_METADATA_DEFINITION)
56✔
109
        .register_native_fn_definition(FS_METADATA_MODIFIED_DEFINITION)
52✔
110
        .register_native_fn_definition(FS_METADATA_ACCESSED_DEFINITION)
48✔
111
        .register_native_fn_definition(FS_METADATA_CREATED_DEFINITION)
44✔
112
        .register_native_fn_definition(FS_METADATA_IS_FILE_DEFINITION)
40✔
113
        .register_native_fn_definition(FS_METADATA_IS_DIR_DEFINITION)
36✔
114
        .register_native_fn_definition(FS_METADATA_IS_SYMLINK_DEFINITION)
32✔
115
        .register_native_fn_definition(FS_METADATA_LEN_DEFINITION)
28✔
116
        .register_native_fn_definition(FILE_METADATA_DEFINITION)
24✔
117
        .register_native_fn_definition(IS_FS_METADATA_DEFINITION)
20✔
118
        .register_native_fn_definition(IS_READ_DIR_DEFINITION)
16✔
119
        .register_native_fn_definition(IS_READ_DIR_ITER_ENTRY_DEFINITION)
12✔
120
        .register_native_fn_definition(GLOB_DEFINITION)
8✔
121
        .register_native_fn_definition(GLOB_PATHS_NEXT_DEFINITION)
4✔
122
        .register_native_fn_definition(PATH_TO_STRING_DEFINITION);
8✔
123
    module
4✔
124
}
125

126
#[steel_derive::define_module(name = "steel/filesystem")]
127
pub fn fs_module_sandbox() -> BuiltInModule {
4✔
128
    BuiltInModule::new("steel/filesystem")
4✔
129
}
130

131
impl Custom for ReadDir {}
132
impl Custom for DirEntry {}
133
impl Custom for Metadata {}
134

135
/// Creates an iterator over the contents of the given directory.
136
/// The given path must be a directory.
137
///
138
/// (read-dir-iter dir) -> #<ReadDir>
139
///
140
/// * dir : (is-dir?) - the directory to iterate over
141
///
142
/// # Examples
143
/// ```scheme
144
/// (define my-iter (read-dir-iter "src"))
145
/// (read-dir-iter-next! my-iter) ;; => #<DirEntry> src/lib.rs
146
/// (read-dir-iter-next! my-iter) ;; => #<DirEntry> src/main.rs
147
/// (read-dir-iter-next! my-iter) ;; => #false
148
/// ```
149
#[steel_derive::function(name = "read-dir-iter")]
150
pub fn read_dir_iter(directory: &SteelString) -> Result<SteelVal> {
23✔
151
    let p = Path::new(directory.as_ref());
69✔
152
    p.read_dir()?.into_steelval()
69✔
153
}
154

155
/// Reads one entry from the iterator. Reads a `ReadDir` struct.
156
///
157
/// (read-dir-iter-next! read-dir-iter) -> #<DirEntry>
158
///
159
/// * dir : (read-dir-iter?) - the directory to iterate over
160
///
161
/// # Examples
162
/// ```scheme
163
/// (define my-iter (read-dir-iter "src"))
164
/// (define nex-entry (read-dir-iter-next! my-iter)) ;; => #<DirEntry> src/lib.rs
165
/// (read-dir-entry-is-dir? next-entry) ;; => #false
166
/// (read-dir-entry-is-file? next-entry) ;; => #true
167
/// (read-dir-entry-file-name) ;; => "lib.rs"
168
/// ```
169
#[steel_derive::function(name = "read-dir-iter-next!")]
170
pub fn read_dir_iter_next(iter: &SteelVal) -> Result<SteelVal> {
98✔
171
    ReadDir::as_mut_ref(iter)?
196✔
172
        .next()
173
        .transpose()
174
        .map(|x| x.map(|entry| entry.into_steelval().unwrap()))?
421✔
175
        .into_steelval()
176
}
177

178
/// Checks whether the given value is a #<ReadDir>
179
///
180
/// (read-dir-iter? value) -> bool?
181
///
182
/// # Examples
183
/// ```scheme
184
/// (define my-iter (read-dir-iter "src"))
185
/// (read-dir-iter? my-iter) ;; => #true
186
/// (read-dir-iter "not an iter") ;; => #false
187
/// ```
188
#[steel_derive::function(name = "read-dir-iter?")]
189
pub fn is_read_dir(value: &SteelVal) -> Result<SteelVal> {
×
190
    ReadDir::as_ref(value).is_ok().into_steelval()
×
191
}
192

193
/// Checks whether the given value is a #<DirEntry>
194
///
195
/// (read-dir-iter-entry? value) -> bool?
196
///
197
/// # Examples
198
/// ```scheme
199
/// (define my-iter (read-dir-iter "src"))
200
/// (define next (read-dir-iter-next! my-iter))
201
/// (read-dir-iter-entry? next) ;; => #true
202
/// ```
203
#[steel_derive::function(name = "read-dir-iter-entry?")]
204
pub fn is_read_dir_iter_entry(value: &SteelVal) -> Result<SteelVal> {
×
205
    DirEntry::as_ref(value).is_ok().into_steelval()
×
206
}
207

208
/// Checks whether the read dir entry is a directory.
209
///
210
/// (read-dir-entry-is-dir? value) -> bool?
211
///
212
/// * value : read-dir-iter-entry?
213
///
214
/// # Examples
215
/// ```scheme
216
/// (define my-iter (read-dir-iter "src"))
217
/// (define next (read-dir-iter-next! my-iter))
218
///
219
/// (read-dir-entry-path) ;; => "src/lib.rs"
220
/// (read-dir-entry-is-dir? next) ;; #false - because this is a file
221
///
222
/// ```
223
#[steel_derive::function(name = "read-dir-entry-is-dir?")]
224
pub fn read_dir_entry_is_dir(value: &SteelVal) -> Result<SteelVal> {
75✔
225
    Ok(SteelVal::BoolV(
226
        DirEntry::as_ref(value)?.file_type()?.is_dir(),
300✔
227
    ))
228
}
229

230
/// Checks whether the read dir entry is a file.
231
///
232
/// (read-dir-entry-is-dir? value) -> bool?
233
///
234
/// * value : read-dir-iter-entry?
235
///
236
/// # Examples
237
/// ```scheme
238
/// (define my-iter (read-dir-iter "src"))
239
/// (define next (read-dir-iter-next! my-iter))
240
///
241
/// (read-dir-entry-path) ;; => "src/lib.rs"
242
/// (read-dir-entry-is-dir? next) ;; #true - because this is a file
243
///
244
/// ```
245
#[steel_derive::function(name = "read-dir-entry-is-file?")]
246
pub fn read_dir_entry_is_file(value: &SteelVal) -> Result<SteelVal> {
×
247
    Ok(SteelVal::BoolV(
248
        DirEntry::as_ref(value)?.file_type()?.is_file(),
×
249
    ))
250
}
251

252
/// Checks whether the read dir entry is a symlink.
253
#[steel_derive::function(name = "read-dir-entry-is-symlink?")]
254
pub fn read_dir_entry_is_symlink(value: &SteelVal) -> Result<SteelVal> {
×
255
    Ok(SteelVal::BoolV(
256
        DirEntry::as_ref(value)?.file_type()?.is_symlink(),
×
257
    ))
258
}
259

260
/// Returns the path from a given read-dir-entry.
261
#[steel_derive::function(name = "read-dir-entry-path")]
262
pub fn read_dir_entry_path(value: &SteelVal) -> Result<SteelVal> {
75✔
263
    match DirEntry::as_ref(value)?.path().to_str() {
225✔
264
        Some(p) => Ok(SteelVal::StringV(p.into())),
150✔
265
        None => Ok(SteelVal::BoolV(false)),
×
266
    }
267
}
268

269
/// Returns the file name from a given read-dir-entry.
270
#[steel_derive::function(name = "read-dir-entry-file-name")]
271
pub fn read_dir_entry_file_name(value: &SteelVal) -> Result<SteelVal> {
×
272
    match DirEntry::as_ref(value)?.file_name().to_str() {
×
273
        Some(p) => Ok(SteelVal::StringV(p.into())),
×
274
        None => Ok(SteelVal::BoolV(false)),
×
275
    }
276
}
277

278
/// Checks if this value is a #<Metadata>
279
#[steel_derive::function(name = "fs-metadata?")]
280
pub fn is_fs_metadata(value: &SteelVal) -> Result<SteelVal> {
×
281
    Metadata::as_ref(value).is_ok().into_steelval()
×
282
}
283

284
/// Extract the file metadata from the #<DirEntry>
285
#[steel_derive::function(name = "read-dir-entry-metadata")]
286
pub fn read_dir_entry_metadata(value: &SteelVal) -> Result<SteelVal> {
×
287
    let entry = DirEntry::as_ref(value)?;
×
288
    entry.metadata()?.into_steelval()
×
289
}
290

291
/// Get the last modified time from the file metadata
292
#[steel_derive::function(name = "fs-metadata-modified")]
293
pub fn fs_metadata_modified(value: &SteelVal) -> Result<SteelVal> {
×
294
    Metadata::as_ref(value)?.modified()?.into_steelval()
×
295
}
296

297
/// Get the last accessed time from the file metadata
298
#[steel_derive::function(name = "fs-metadata-accessed")]
299
pub fn fs_metadata_accessed(value: &SteelVal) -> Result<SteelVal> {
×
300
    Metadata::as_ref(value)?.accessed()?.into_steelval()
×
301
}
302

303
/// Get the created time from the file metadata
304
#[steel_derive::function(name = "fs-metadata-created")]
305
pub fn fs_metadata_created(value: &SteelVal) -> Result<SteelVal> {
×
306
    Metadata::as_ref(value)?.created()?.into_steelval()
×
307
}
308

309
/// Check if this metadata is from a file
310
#[steel_derive::function(name = "fs-metadata-is-file?")]
311
pub fn fs_metadata_is_file(value: &SteelVal) -> Result<SteelVal> {
×
312
    Metadata::as_ref(value)?.is_file().into_steelval()
×
313
}
314

315
/// Check if this metadata is from a directory
316
#[steel_derive::function(name = "fs-metadata-is-dir?")]
317
pub fn fs_metadata_is_dir(value: &SteelVal) -> Result<SteelVal> {
×
318
    Metadata::as_ref(value)?.is_dir().into_steelval()
×
319
}
320

321
/// Check if this metadata is from a symlink
322
#[steel_derive::function(name = "fs-metadata-is-symlink?")]
323
pub fn fs_metadata_is_symlink(value: &SteelVal) -> Result<SteelVal> {
×
324
    Metadata::as_ref(value)?.is_symlink().into_steelval()
×
325
}
326

327
/// Get the length of the file in bytes
328
#[steel_derive::function(name = "fs-metadata-len")]
329
pub fn fs_metadata_len(value: &SteelVal) -> Result<SteelVal> {
×
330
    Metadata::as_ref(value)?.len().into_steelval()
×
331
}
332

333
/// Access the file metadata for a given path
334
#[steel_derive::function(name = "file-metadata")]
335
pub fn file_metadata(path: &SteelString) -> Result<SteelVal> {
×
336
    std::fs::metadata(path.as_str())?.into_steelval()
×
337
}
338

339
/// Deletes the directory
340
///
341
/// (delete-directory! dir) -> void?
342
///
343
/// * dir : (string?) - The directory name to delete.
344
///
345
/// # Examples
346
/// ```scheme
347
/// > (delete-directory! "logs") ;;
348
/// ```
349
#[steel_derive::function(name = "delete-directory!")]
350
pub fn delete_directory(directory: &SteelString) -> Result<SteelVal> {
×
351
    std::fs::remove_dir_all(directory.as_str())?;
×
352
    Ok(SteelVal::Void)
×
353
}
354

355
/// Creates the directory
356
///
357
/// (create-directory! dir) -> void?
358
///
359
/// * dir : (string?) - The directory name to create.
360
///
361
/// # Examples
362
/// ```scheme
363
/// > (create-directory! "logs") ;;
364
/// ```
365
#[steel_derive::function(name = "create-directory!")]
366
pub fn create_directory(directory: &SteelString) -> Result<SteelVal> {
×
367
    std::fs::create_dir_all(directory.as_str())?;
×
368

369
    Ok(SteelVal::Void)
×
370
}
371

372
/// Recursively copies the contents of the source directory to the destination
373
///
374
/// (copy-directory-recursively! source destination) -> void?
375
///
376
/// * source : (string?) - The directory to copy.
377
/// * destination : (string?) - The destination directory into which to copy.
378
///
379
/// # Examples
380
/// ```scheme
381
/// > (copy-directory-recursively! "logs" "backup") ;;
382
/// ```
383
#[steel_derive::function(name = "copy-directory-recursively!")]
384
pub fn copy_directory_recursively(
×
385
    source: &SteelString,
386
    destination: &SteelString,
387
) -> Result<SteelVal> {
388
    copy_recursively(source.as_str(), destination.as_str())?;
×
389

390
    Ok(SteelVal::Void)
×
391
}
392

393
/// Checks if a path exists
394
///
395
/// (path-exists? path) -> bool?
396
///
397
/// * path : (string?) - The path to check
398
///
399
/// # Examples
400
/// ```scheme
401
/// > (path-exists? "logs") ;; => #true
402
/// > (path-exists? "backup/logs") ;; => #false
403
/// ```
404
#[steel_derive::function(name = "path-exists?")]
405
pub fn path_exists(path: &SteelString) -> Result<SteelVal> {
6✔
406
    Ok(SteelVal::BoolV(Path::new(path.as_ref()).exists()))
12✔
407
}
408

409
/// Checks if a path is a file
410
///
411
/// (is-file? path) -> bool?
412
///
413
/// * path : (string?) - The path to check
414
///
415
/// # Examples
416
/// ```scheme
417
/// > (is-file? "logs") ;; => #false
418
/// > (is-file? "logs/today.json") ;; => #true
419
/// ```
420
#[steel_derive::function(name = "is-file?")]
421
pub fn is_file(path: &SteelString) -> Result<SteelVal> {
×
422
    Ok(SteelVal::BoolV(Path::new(path.as_ref()).is_file()))
×
423
}
424

425
/// Checks if a path is a directory
426
///
427
/// (is-dir? path) -> bool?
428
///
429
/// * path : (string?) - The path to check
430
///
431
/// # Examples
432
/// ```scheme
433
/// > (is-dir? "logs") ;; => #true
434
/// > (is-dir? "logs/today.json") ;; => #false
435
/// ```
436
#[steel_derive::function(name = "is-dir?")]
437
pub fn is_dir(path: &SteelString) -> Result<SteelVal> {
×
438
    Ok(SteelVal::BoolV(Path::new(path.as_ref()).is_dir()))
×
439
}
440

441
/// Gets the extension from a path
442
///
443
/// (path->extension path) -> (or/c string? void?)
444
///
445
/// * path : (string?) - The path to check
446
///
447
/// # Examples
448
/// ```scheme
449
/// > (path->extension "logs") ;; => void
450
/// > (path->extension "logs/today.json") ;; => ".json"
451
/// ```
452
#[steel_derive::function(name = "path->extension")]
453
pub fn get_extension(path: &SteelString) -> Result<SteelVal> {
×
454
    if let Some(ext) = get_extension_from_filename(path) {
×
455
        Ok(SteelVal::StringV(ext.into()))
456
    } else {
457
        Ok(SteelVal::Void)
×
458
    }
459
}
460

461
/// Gets the filename for a given path
462
///
463
/// (file-name path) -> string?
464
///
465
/// * path : (string?) - The path to check
466
///
467
/// # Examples
468
/// ```scheme
469
/// > (file-name "logs") ;; => "logs"
470
/// > (file-name "logs/today.json") ;; => "today.json"
471
/// ```
472
#[steel_derive::function(name = "file-name")]
473
pub fn file_name(path: &SteelString) -> Result<SteelVal> {
×
474
    Ok(SteelVal::StringV(
475
        Path::new(path.as_str())
×
476
            .file_name()
×
477
            .and_then(|x| x.to_str())
×
478
            .unwrap_or("")
×
479
            .into(),
×
480
    ))
481
}
482

483
/// Gets the parent directory name for a given path
484
///
485
/// (parent-name path) -> string?
486
///
487
/// * path : (string?) - The path to check
488
///
489
/// # Examples
490
/// ```scheme
491
/// > (parent-name "logs") ;; => ""
492
/// > (parent-name "logs/today.json") ;; => "logs"
493
/// ```
494
#[steel_derive::function(name = "parent-name")]
495
pub fn parent_name(path: &SteelString) -> Result<SteelVal> {
×
496
    Ok(SteelVal::StringV(
497
        Path::new(path.as_str())
×
498
            .parent()
×
499
            .and_then(|x| x.to_str())
×
500
            .unwrap_or("")
×
501
            .into(),
×
502
    ))
503
}
504

505
/// Returns canonical path with all components normalized
506
///
507
/// (canonicalize-path path) -> string?
508
///
509
/// * path : (string?) - The path to canonicalize
510
///
511
/// # Examples
512
/// ```scheme
513
/// > (canonicalize-path "logs") ;; => "/Users/me/Desktop/programming/logs"
514
/// > (canonicalize-path "logs/today.json") ;; => "/Users/me/Desktop/programming/logs/today.json"
515
/// ```
516
#[steel_derive::function(name = "canonicalize-path")]
517
pub fn canonicalize_path(path: &SteelString) -> Result<SteelVal> {
×
518
    let path = path.as_str();
×
519
    let canonicalized = if path.len() > 0 && path.starts_with('~') {
×
520
        if path.len() > 1 && !path.starts_with("~/") {
×
521
            steelerr!(Generic => "references to other users home directories are not supported")?
×
522
        } else {
523
            let mut expanded = env_home::env_home_dir()
×
524
                .ok_or_else(throw!(Generic => "could not determine user home directory"))?;
×
525
            if path.len() > 2 {
×
526
                expanded.push(&path[2..]);
×
527
            }
528
            fs::canonicalize(expanded)?
×
529
        }
530
    } else {
531
        fs::canonicalize(path)?
×
532
    };
533
    Ok(SteelVal::StringV(
534
        canonicalized
535
            .to_str()
536
            .ok_or_else(throw!(Generic => "path contains non-unicode characters"))?
×
537
            .into(),
×
538
    ))
539
}
540

541
/// Returns the contents of the directory as a list
542
///
543
/// (read-dir path) -> list?
544
///
545
/// * path : (string?) - The path to check
546
///
547
/// # Examples
548
/// ```scheme
549
/// > (read-dir "logs") ;; => '("logs/today.json" "logs/yesterday.json")
550
/// > (read-dir "empty_dir") ;; => '()
551
/// ```
552
#[steel_derive::function(name = "read-dir")]
553
pub fn read_dir(path: &SteelString) -> Result<SteelVal> {
×
554
    let p = Path::new(path.as_ref());
×
555
    let iter = p.read_dir()?;
×
556
    Ok(SteelVal::ListV(
557
        iter.into_iter()
558
            .map(|x| match x?.path().to_str() {
×
559
                Some(s) => Ok(SteelVal::StringV(s.into())),
×
560
                None => Ok(SteelVal::BoolV(false)),
×
561
            })
562
            .collect::<Result<_>>()?,
×
563
    ))
564
}
565

566
/// Outputs the current working directory as a string
567
///
568
/// (current-directory) -> string?
569
///
570
/// # Examples
571
/// ```scheme
572
/// > (current-directory) ;; => "/Users/me/Desktop/programming"
573
/// ```
574
#[steel_derive::function(name = "current-directory")]
575
pub fn current_directory() -> Result<SteelVal> {
×
576
    let path = current_dir()?;
×
577
    Ok(SteelVal::StringV(path.to_str().unwrap_or("").into()))
578
}
579

580
/// Change the current working directory
581
///
582
/// (change-current-directory! path) -> void?
583
///
584
/// * path : (string?) - The directory to switch to
585
///
586
/// # Examples
587
/// ```scheme
588
/// > (change-current-directory! "logs") ;;
589
/// > (change-current-directory! "..") ;;
590
/// ```
591
#[steel_derive::function(name = "change-current-directory!")]
592
pub fn change_current_directory(path: &SteelString) -> Result<SteelVal> {
×
593
    let path = Path::new(path.as_ref());
×
594

595
    set_current_dir(path)?;
×
596
    Ok(SteelVal::Void)
×
597
}
598

599
/// Deletes the file
600
///
601
/// (delete-file! path) -> void?
602
///
603
/// * path : (string?) - The file to delete
604
///
605
/// # Examples
606
/// ```scheme
607
/// > (delete-file! "logs/today.json") ;;
608
/// ```
609
#[steel_derive::function(name = "delete-file!")]
610
pub fn delete_file(file: &SteelString) -> Result<SteelVal> {
6✔
611
    std::fs::remove_file(file.as_str())?;
12✔
612
    Ok(SteelVal::Void)
6✔
613
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc