diff --git a/.gitmodules b/.gitmodules index f4a339bc3c..dbf0310f3a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,14 +1,14 @@ [submodule "libs/rbenv"] - path = libs/rbenv + path = vendor/rbenv url = git://github.com/sstephenson/rbenv.git [submodule "libs/git-extras"] - path = libs/git-extras + path = vendor/git-extras url = git://github.com/visionmedia/git-extras.git [submodule "libs/z"] - path = libs/z + path = vendor/z url = git://github.com/rupa/z.git [submodule "libs/nave"] - path = libs/nave + path = vendor/nave url = git://github.com/isaacs/nave.git [submodule "link/.rbenv/plugins/rbenv-vars"] path = link/.rbenv/plugins/rbenv-vars diff --git a/README.md b/README.md index 1bea1c61bb..609f37d48b 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ Any file in the `link` subdirectory gets symbolically linked with `ln -s` into ` To keep things easy, the `~/.bashrc` and `~/.bash_profile` files are extremely simple, and should never need to be modified. Instead, add your aliases, functions, settings, etc into one of the files in the `source` subdirectory, or add a new file. They're all automatically sourced when a new shell is opened. Take a look, I have [a lot of aliases and functions](https://github.com/cowboy/dotfiles/tree/master/source). I even have a [fancy prompt](source/50_prompt.sh) that shows the current directory, time and current git/svn repo status. ## Scripts -In addition to the aforementioned [dotfiles][dotfiles] script, there are a few other [bash scripts][bin]. This includes [ack](https://github.com/petdance/ack), which is a [git submodule](https://github.com/cowboy/dotfiles/tree/master/libs). +In addition to the aforementioned [dotfiles][dotfiles] script, there are a few other [bash scripts][bin]. This includes [nave](https://github.com/isaacs/nave), which is a [git submodule](https://github.com/cowboy/dotfiles/tree/master/vendor). * [dotfiles][dotfiles] - (re)initialize dotfiles. It might ask for your password (for `sudo`). * [src](link/.bashrc#L6-15) - (re)source all files in `source` directory diff --git a/bin/nave b/bin/nave index 4d93755ab4..aef43641aa 120000 --- a/bin/nave +++ b/bin/nave @@ -1 +1 @@ -../libs/nave/nave.sh \ No newline at end of file +../vendor/nave/nave.sh \ No newline at end of file diff --git a/bin/rename b/bin/rename deleted file mode 120000 index eb7795a62d..0000000000 --- a/bin/rename +++ /dev/null @@ -1 +0,0 @@ -../libs/rename/rename \ No newline at end of file diff --git a/bin/rename b/bin/rename new file mode 100755 index 0000000000..eb115b6a71 --- /dev/null +++ b/bin/rename @@ -0,0 +1,310 @@ +#!/usr/bin/perl +use strict; +use warnings; + +=head1 NAME + +rename - renames multiple files + +=head1 SYNOPSIS + +F +S> + +F +S> + +F +S> +S> +S> +S> +S> +S> +S> +S> +S> +S> +S> + +=head1 DESCRIPTION + +C renames the filenames supplied according to the rules specified. If a given filename is not modified, it will not be renamed. If no filenames are given on the command line, filenames will be read via standard input. + +For example, to rename all files matching C<*.bak> to strip the extension, you might say + + rename 's/\.bak$//' *.bak + +If are confident that none of the filenames has C<.bak> anywhere else than at the end, you can also use the much easier typed + + rename -s .bak '' *.bak + +You can always do multiple changes in one ago: + + rename -s .tgz .tar.gz -s .tbz2 .tar.bz2 *.tar.* + +Note however that expressive options are order sensitive. The following would probably surprise you: + + rename -s foo bar -s bar baz * + +Since operations are cumulative, this would end up substituting (some of) the F matches in filenames with F! So pay attention to order. You may want to request a verbose dry run with C<-nv> for the first stab at a complex rename operation. + + rename -nv -s bar baz -s foo bar * + +You can combine the various expressive options to suit your needs. F.ex files from Microsoft(tm) Windows systems often have blanks and (sometimes nothing but) capital letters in their names. Let's say you have a bunch of such files to clean up, and you also want to move them to subdirectories based on extension. The following command should help, provided all directories already exist: + + rename -cz -e '$_ = "$1/$_" if /(\..*)\z/' * + +Again you need to pay attention to order sensitivity for expressive options. If you placed the C<-c> after the C<-e> in the above example, files with F<.zip> and F<.ZIP> extensions would be (attempted to be) moved to different directories because the directory name prefix would be added before the filenames were normalized. Once again, use verbose dry run requested using C<-nv> to get an idea of what exactly a complex rename operation is going to do. + +=head1 ARGUMENTS + +=over 4 + +=item B<-h>, B<--help> + +See a synopsis. + +=item B<--man> + +Browse the manpage. + +=back + +=head1 OPTIONS + +=over 4 + +=item B<-0>, B<--null> + +When reading file names from C, split on NUL bytes instead of newlines. This is useful in combination with GNU find's C<-print0> option, GNU grep's C<-Z> option, and GNU sort's C<-z> option, to name just a few. B + +=item B<-c>, B<--lower-case> + +Converts file names to all lower case. + +=item B<-C>, B<--upper-case> + +Converts file names to all upper case. + +=item B<-e>, B<--expr> + +The C argument to this option should be a Perl expression that assumes the filename in the C<$_> variable and modifies it for the filenames to be renamed. When no other C<-c>, C<-C>, C<-e>, C<-s>, or C<-z> options are given, you can omit the C<-e> from infront of the code. + +=item B<-g>, B<--glob> + +Glob filename arguments. This is useful if you're using a braindead shell such as F which won't expand wildcards on behalf of the user. + +=item B<-f>, B<--force> + +Rename even when a file with the destination name already exists. + +=item B<-i>, B<--interactive> + +Ask the user to confirm every action before it is taken. + +=item B<-k>, B<--backwards>, B<--reverse-order> + +Process the list of files in reverse order, last file first. This prevents conflicts when renaming files to names which are currently taken but would be freed later during the process of renaming. + +=item B<-l>, B<--symlink> + +Create symlinks from the new names to the existing ones, instead of renaming the files. B.> + +=item B<-L>, B<--hardlink> + +Create hard links from the new names to the existing ones, instead of renaming the files. B.> + +=item B<-n>, B<--dry-run>, B<--just-print> + +Show how the files would be renamed, but don't actually do anything. + +=item B<-s>, B<--subst>, B<--simple> + +Perform a simple textual substitution of C to C. The C and C parameters must immediately follow the argument. + +Quoting issues aside, this is equivalent to supplying a C<-e 's/\Qfrom/to/'>. + +=item B<-v>, B<--verbose> + +Print additional information about the operations (not) executed. + +=item B<-z>, B<--sanitize> + +Replaces consecutive blanks, shell meta characters, and control characters in filenames with underscores. + +=back + +=head1 SEE ALSO + +mv(1), perl(1), find(1), grep(1), sort(1) + +=head1 BUGS + +None currently known. + +=head1 AUTHORS + +Aristotle Pagaltzis + +Idea, inspiration and original code from Larry Wall and Robin Barker. + +=head1 COPYRIGHT + +This script is free software; you can redistribute it and/or modify it under the same terms as Perl itself. + +=cut + +use Pod::Usage; +use Getopt::Long 2.24, qw(:config bundling no_ignore_case no_auto_abbrev); + +use constant ERROR => do { bless \(my $l = 0), 'LOGLEVEL' }; +use constant INFO => do { bless \(my $l = 1), 'LOGLEVEL' }; +use constant DEBUG => do { bless \(my $l = 2), 'LOGLEVEL' }; +use constant VERB_FOR => { + link => { + inf => 'link', + pastp => 'linked', + exec => sub { link shift, shift or die }, + }, + symlink => { + inf => 'symlink', + pastp => 'symlinked', + exec => sub { symlink shift, shift or die }, + }, + rename => { + inf => 'rename', + pastp => 'renamed', + exec => sub { rename shift, shift or die }, + }, +}; + +sub argv_to_subst_expr { + my $modifier = shift || ''; + pod2usage( -verbose => 1 ) if @ARGV < 2; + my ($from, $to) = map quotemeta, splice @ARGV, 0, 2; + # the ugly \${\""} construct is necessary because unknown backslash escapes are + # not treated the same in pattern- vs doublequote-quoting context; only the + # latter lets us do the right thing with problematic input like + # ']{ool(haracter$' or maybe '>>' + sprintf 's/\Q${\"%s"}/%s/%s', $from, $to, $modifier; +} + +my @EXPR; + +GetOptions( + 'h|help' => sub { pod2usage( -verbose => 1 ) }, + 'man' => sub { pod2usage( -verbose => 2 ) }, + '0|null' => \my $opt_null, + 'c|lower-case' => sub { push @EXPR, 's/([[:upper:]]+)/\L$1/g' }, + 'C|upper-case' => sub { push @EXPR, 's/([[:lower:]]+)/\U$1/g' }, + 'e|expr=s' => \@EXPR, + 'f|force' => \my $opt_force, + 'g|glob' => \my $opt_glob, + 'i|interactive' => \my $opt_interactive, + 'k|backwards|reverse-order' => \my $opt_backwards, + 'l|symlink' => \my $opt_symlink, + 'L|hardlink' => \my $opt_hardlink, + 'n|just-print|dry-run' => \my $opt_dryrun, + 'p|mkpath|make-dirs' => \my $opt_mkpath, + 'v|verbose+' => \(my $opt_verbose = 0), + 'z|sanitize' => sub { push @EXPR, 's/[!"\$&()=?`*\';<>|_[:cntrl:][:blank:]]+/_/g' }, + 's|subst|simple' => sub { push @EXPR, argv_to_subst_expr }, + 'S|subst-global' => sub { push @EXPR, argv_to_subst_expr('g') }, +) or pod2usage( -verbose => 1 ); + +die "TODO" if $opt_mkpath; + +if(not @EXPR) { + pod2usage( -verbose => 1 ) if not @ARGV or -e $ARGV[0]; + push @EXPR, shift; +} + +pod2usage( -verbose => 1 ) + if ($opt_hardlink and $opt_symlink) + or ($opt_null and @ARGV); + +++$opt_verbose if $opt_dryrun; + +BEGIN { + *CORE::GLOBAL::warn = sub { + if(ref $_[0] eq 'LOGLEVEL') { + my $msglevel = ${(shift)}; + print "@_\n" if $opt_verbose >= $msglevel; + return; + } + warn @_; + }; +} + +my $code = do { + my $cat = "sub { ".join('; ', @EXPR)." }"; + warn DEBUG, "Using expression: $cat"; + + my $evaled = eval $cat; + die $@ if $@; + die "Evaluation to subref failed. Check expression using -vn\n" + unless 'CODE' eq ref $evaled; + + $evaled; +}; + +my $verb = VERB_FOR->{ + $opt_hardlink ? 'link' : + $opt_symlink ? 'symlink' : + do { 'rename' } +}; + +if (!@ARGV) { + warn INFO, "Reading filenames from STDIN"; + @ARGV = do { + if($opt_null) { + warn INFO, "Splitting on NUL bytes"; + local $/ = "\0"; + } + ; + }; + chomp @ARGV; +} + +@ARGV = map glob, @ARGV if $opt_glob; + +@ARGV = reverse @ARGV if $opt_backwards; + +for (@ARGV) { + my $old = $_; + + $code->(); + + if($old eq $_) { + warn DEBUG, "'$old' unchanged"; + next; + } + + if(!$opt_force and -e) { + warn ERROR, "'$old' not $verb->{pastp}: '$_' already exists"; + next; + } + + if($opt_dryrun) { + warn INFO, "'$old' would be $verb->{pastp} to '$_'"; + next; + } + + if($opt_interactive) { + print "\u$verb->{inf} '$old' to '$_'? [n] "; + if( !~ /^y(?:es)?$/i) { + warn DEBUG, "Skipping '$old'."; + next; + } + } + + eval { $verb->{exec}($old, $_) }; + + if($@) { + warn ERROR, "Can't $verb->{inf} '$old' to '$_': $!"; + next; + } + + warn INFO, "'$old' $verb->{pastp} to '$_'"; +} diff --git a/init/10_ubuntu.sh b/init/10_ubuntu.sh index b731b25a5b..8b40249d9a 100644 --- a/init/10_ubuntu.sh +++ b/init/10_ubuntu.sh @@ -63,7 +63,7 @@ fi if [[ ! "$(type -P git-extras)" ]]; then e_header "Installing Git Extras" ( - cd ~/.dotfiles/libs/git-extras && + cd ~/.dotfiles/vendor/git-extras && sudo make install ) fi diff --git a/source/50_file.sh b/source/50_file.sh index ef60efa056..991487cb74 100644 --- a/source/50_file.sh +++ b/source/50_file.sh @@ -43,4 +43,4 @@ function md() { # Fast directory switching _Z_NO_PROMPT_COMMAND=1 _Z_DATA=~/.dotfiles/caches/.z -. ~/.dotfiles/libs/z/z.sh +. ~/.dotfiles/vendor/z/z.sh diff --git a/source/50_ruby.sh b/source/50_ruby.sh index f62c6043c8..bf9c65c900 100644 --- a/source/50_ruby.sh +++ b/source/50_ruby.sh @@ -1,7 +1,7 @@ export PATH # rbenv init. -PATH=$(path_remove ~/.dotfiles/libs/rbenv/bin):~/.dotfiles/libs/rbenv/bin +PATH=$(path_remove ~/.dotfiles/vendor/rbenv/bin):~/.dotfiles/vendor/rbenv/bin if [[ "$(type -P rbenv)" && ! "$(type -t _rbenv)" ]]; then eval "$(rbenv init -)" diff --git a/libs/git-extras b/vendor/git-extras similarity index 100% rename from libs/git-extras rename to vendor/git-extras diff --git a/libs/nave b/vendor/nave similarity index 100% rename from libs/nave rename to vendor/nave diff --git a/libs/rbenv b/vendor/rbenv similarity index 100% rename from libs/rbenv rename to vendor/rbenv diff --git a/libs/rename/README.txt b/vendor/rename/README.txt similarity index 100% rename from libs/rename/README.txt rename to vendor/rename/README.txt diff --git a/libs/rename/rename b/vendor/rename/rename similarity index 100% rename from libs/rename/rename rename to vendor/rename/rename diff --git a/libs/z b/vendor/z similarity index 100% rename from libs/z rename to vendor/z