summaryrefslogtreecommitdiffstats
path: root/nsis
AgeCommit message (Expand)Author
2024-04-25patch 9.1.0370: MS-Windows: patch number is zero in installerv9.1.0370RestorerZ
2024-04-09NSIS: Fix a few issues with gvim.nsiRestorerZ
2024-04-05NSIS: Correctly distribute libsodium with the installer (#14422)Christian Brabandt
2024-03-29NSIS: fix path of uganda.nsis.txt in german.nsi file (#14331)Restorer
2024-03-28NSIS: Possibility to include translated license and README.txt files (#14311)Restorer
2024-03-25NSIS: Redesigning the appearance of the vimrc settings page (#14292)Restorer
2024-03-24NSIS: Update nsis installer and nsis docs (#14256)Restorer
2024-03-20patch 9.1.0191: Installer does not remove all filesv9.1.0191RestorerZ
2024-03-06translation(gr): add translation of the installer (#14148)Christos Longros
2024-03-05translation(sr): Update Serbian messages (#14143)Ivan Pešić
2024-03-03translation(ru): Updated Russian installer translation (#14134)Restorer
2024-02-13runtime(vim): include Vim Syntax generatorh-east
2024-01-16patch 9.1.0032: MS-Windows installer misses keymapsv9.1.0032Ken Takata
2024-01-04patch 9.1.0008: NSIS installer includes syntax testdirv9.1.0008Christian Brabandt
2024-01-02patch 9.1.0000: Vim 9.1 releasev9.1.0000v9.1.0Christian Brabandt
2023-05-14Update runtime filesBram Moolenaar
2023-02-17patch 9.0.1316: MS-Windows: vimfiles dir created with admin groupv9.0.1316Christopher Plewright
2023-01-04patch 9.0.1146: MS-Windows: various special keys/modifiers are not mappablev9.0.1146Christopher Plewright
2022-10-08patch 9.0.0698: VisVim is outdated, does not work with current Visual Studiov9.0.0698Martin Tournoij
2022-08-24patch 9.0.0258: MS-Windows installer skips syntax/sharedv9.0.0258K.Takata
2022-06-28release version 9.0v9.0.0000Bram Moolenaar
2022-05-06patch 8.2.4893: distributed import files are not installedv8.2.4893Bram Moolenaar
2022-03-11patch 8.2.4545: MS-Windows: the installed icon is low resolutionv8.2.4545Christian Brabandt
2022-02-13patch 8.2.4370: MS-Windows: libsodium.dll not included with the installerv8.2.4370Christian Brabandt
2021-10-24patch 8.2.3562: cannot add color namesv8.2.3562Drew Vogel
2021-08-29Update runtime filesBram Moolenaar
2021-07-24patch 8.2.3214: MS-Windows: passing /D does not set the install locationv8.2.3214Christian Brabandt
2021-06-27Update runtime filesBram Moolenaar
2021-05-02Update runtime filesBram Moolenaar
2021-05-02patch 8.2.2823: MS-Windows: launching Vim from installer doesn't open READMEv8.2.2823Bram Moolenaar
2021-05-01patch 8.2.2822: MS-Windows: unnessarily loading libraries when unregisteringv8.2.2822Bram Moolenaar
2021-02-26patch 8.2.2551: MS-Windows: colors test file is not installedv8.2.2551Bram Moolenaar
2020-09-21patch 8.2.1721: MS-Windows installer doesn't workv8.2.1721Bram Moolenaar
2020-09-20patch 8.2.1717v8.2.1717Bram Moolenaar
2020-09-19Update runtime files.Bram Moolenaar
2020-07-14patch 8.2.1214: MS-Windows: default _vimrc not correct in silent install modev8.2.1214Bram Moolenaar
2020-02-12patch 8.2.0247: misleading comment in NSIS installer scriptv8.2.0247Bram Moolenaar
2020-01-18patch 8.2.0129: MS-Windows installer doesn't use Turkish translationsv8.2.0129Bram Moolenaar
2020-01-14Update runtime files.Bram Moolenaar
2019-12-12Vim 8.2 releasev8.2.0000v8.2.0Bram Moolenaar
2019-11-10Update runtime filesBram Moolenaar
2019-10-16Update runtime files.Bram Moolenaar
2019-09-27patch 8.1.2086: missing a few changes for the renamed filesv8.1.2086Bram Moolenaar
2019-09-27patch 8.1.2082: some files have a weird name to fit in 8.3 charactersv8.1.2082Bram Moolenaar
2019-09-11Update runtime filesBram Moolenaar
2019-06-10Update runtime filesBram Moolenaar
2019-05-26patch 8.1.1404: cannot change the patch level when building with NSISv8.1.1404Bram Moolenaar
2019-05-17patch 8.1.1339: installer needs to product name et al.v8.1.1339Bram Moolenaar
2019-04-28patch 8.1.1230: a lot of code is shared between vim.exe and gvim.exev8.1.1230Bram Moolenaar
2019-04-12patch 8.1.1159: MS-Windows: with a silent (un)install $VIM/_vimrc is removedv8.1.1159Bram Moolenaar
id='n468' href='#n468'>468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
use dir::Dir;
use file::File;
use column::Column;
use column::Column::*;
use output::{Grid, Details};
use term::dimensions;

use std::ascii::AsciiExt;
use std::cmp::Ordering;
use std::fmt;

use getopts;
use natord;

use self::Misfire::*;

/// The *Options* struct represents a parsed version of the user's
/// command-line options.
#[derive(PartialEq, Debug, Copy)]
pub struct Options {
    pub dir_action: DirAction,
    pub filter: FileFilter,
    pub view: View,
}

#[derive(PartialEq, Debug, Copy)]
pub struct FileFilter {
    reverse: bool,
    show_invisibles: bool,
    sort_field: SortField,
}

#[derive(PartialEq, Copy, Debug)]
pub enum View {
    Details(Details),
    Lines,
    Grid(Grid),
}

impl Options {

    /// Call getopts on the given slice of command-line strings.
    pub fn getopts(args: &[String]) -> Result<(Options, Vec<String>), Misfire> {
        let mut opts = getopts::Options::new();
        opts.optflag("1", "oneline",   "display one entry per line");
        opts.optflag("a", "all",       "show dot-files");
        opts.optflag("b", "binary",    "use binary prefixes in file sizes");
        opts.optflag("B", "bytes",     "list file sizes in bytes, without prefixes");
        opts.optflag("d", "list-dirs", "list directories as regular files");
        opts.optflag("g", "group",     "show group as well as user");
        opts.optflag("h", "header",    "show a header row at the top");
        opts.optflag("H", "links",     "show number of hard links");
        opts.optflag("i", "inode",     "show each file's inode number");
        opts.optflag("l", "long",      "display extended details and attributes");
        opts.optflag("r", "reverse",   "reverse order of files");
        opts.optflag("R", "recurse",   "recurse into directories");
        opts.optopt ("s", "sort",      "field to sort by", "WORD");
        opts.optflag("S", "blocks",    "show number of file system blocks");
        opts.optopt ("t", "time",      "which timestamp to show for a file", "WORD");
        opts.optflag("T", "tree",      "recurse into subdirectories in a tree view");
        opts.optflag("x", "across",    "sort multi-column view entries across");
        opts.optflag("?", "help",      "show list of command-line options");

        let matches = match opts.parse(args) {
            Ok(m) => m,
            Err(e) => return Err(Misfire::InvalidOptions(e)),
        };

        if matches.opt_present("help") {
            return Err(Misfire::Help(opts.usage("Usage:\n  exa [options] [files...]")));
        }

        let sort_field = match matches.opt_str("sort") {
            Some(word) => try!(SortField::from_word(word)),
            None => SortField::Name,
        };

        let filter = FileFilter {
            reverse:         matches.opt_present("reverse"),
            show_invisibles: matches.opt_present("all"),
            sort_field:      sort_field,
        };

        let path_strs = if matches.free.is_empty() {
            vec![ ".".to_string() ]
        }
        else {
            matches.free.clone()
        };

        Ok((Options {
            dir_action: try!(DirAction::deduce(&matches)),
            view:       try!(View::deduce(&matches, filter)),
            filter:     filter,
        }, path_strs))
    }

    pub fn transform_files<'a>(&self, files: &mut Vec<File<'a>>) {
        self.filter.transform_files(files)
    }
}

impl FileFilter {
    /// Transform the files (sorting, reversing, filtering) before listing them.
    pub fn transform_files<'a>(&self, files: &mut Vec<File<'a>>) {

        if !self.show_invisibles {
            files.retain(|f| !f.is_dotfile());
        }

        match self.sort_field {
            SortField::Unsorted => {},
            SortField::Name => files.sort_by(|a, b| natord::compare(&*a.name, &*b.name)),
            SortField::Size => files.sort_by(|a, b| a.stat.size.cmp(&b.stat.size)),
            SortField::FileInode => files.sort_by(|a, b| a.stat.unstable.inode.cmp(&b.stat.unstable.inode)),
            SortField::Extension => files.sort_by(|a, b| {
                if a.ext.cmp(&b.ext) == Ordering::Equal {
                    Ordering::Equal
                }
                else {
                    a.name.to_ascii_lowercase().cmp(&b.name.to_ascii_lowercase())
                }
            }),
        }

        if self.reverse {
            files.reverse();
        }
    }
}

/// User-supplied field to sort by.
#[derive(PartialEq, Debug, Copy)]
pub enum SortField {
    Unsorted, Name, Extension, Size, FileInode
}

impl SortField {

    /// Find which field to use based on a user-supplied word.
    fn from_word(word: String) -> Result<SortField, Misfire> {
        match word.as_slice() {
            "name"  => Ok(SortField::Name),
            "size"  => Ok(SortField::Size),
            "ext"   => Ok(SortField::Extension),
            "none"  => Ok(SortField::Unsorted),
            "inode" => Ok(SortField::FileInode),
            field   => Err(SortField::none(field))
        }
    }

    /// How to display an error when the word didn't match with anything.
    fn none(field: &str) -> Misfire {
        Misfire::InvalidOptions(getopts::Fail::UnrecognizedOption(format!("--sort {}", field)))
    }
}

/// One of these things could happen instead of listing files.
#[derive(PartialEq, Debug)]
pub enum Misfire {

    /// The getopts crate didn't like these arguments.
    InvalidOptions(getopts::Fail),

    /// The user asked for help. This isn't strictly an error, which is why
    /// this enum isn't named Error!
    Help(String),

    /// Two options were given that conflict with one another
    Conflict(&'static str, &'static str),

    /// An option was given that does nothing when another one either is or
    /// isn't present.
    Useless(&'static str, bool, &'static str),
}

impl Misfire {
    /// The OS return code this misfire should signify.
    pub fn error_code(&self) -> i32 {
        if let Help(_) = *self { 2 }
                          else { 3 }
    }
}

impl fmt::Display for Misfire {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InvalidOptions(ref e) => write!(f, "{}", e),
            Help(ref text)        => write!(f, "{}", text),
            Conflict(a, b)        => write!(f, "Option --{} conflicts with option {}.", a, b),
            Useless(a, false, b)  => write!(f, "Option --{} is useless without option --{}.", a, b),
            Useless(a, true, b)   => write!(f, "Option --{} is useless given option --{}.", a, b),
        }
    }
}

impl View {
    pub fn deduce(matches: &getopts::Matches, filter: FileFilter) -> Result