3

I'm switching from Fish Shell to Zsh.

I just went through a long process of converting a bunch of my Fish functions into Zsh, and most things are working, but I just noticed that when I type ls, it not only doesn't work, but actually ends the terminal tab session:

➜  ~  cd code
➜  code  ls

[Process completed]

Super perplexing, as I didn't (I don't think) do anything to mess with that command. Most other basic commands seem to work fine. Any ideas what might be causing this mess? I've put my new Zsh functions and my .zshrc file below.

The functions, which are mostly a bunch of Git/Zeus (a Rails tool) functions to make my life easier:

~/.oh-my-zsh/custom/plugins/functions/functions.plugin.zsh

##############################
######### ZEUS BASED #########
##############################

z () zeus start

rmz () rm .zeus.sock

rr () {
  if [ "$#" -gt 0 ]; then
    r routes | grep "$@" 
  else
    r routes
  fi
}

zeus_on () {
  if ps aux | grep -v grep | grep 'zeus slave: development_environment'; then
    true
  else
    false
  fi
}

mg () r db:migrate "$@"

tprep () {
  if zeus_on; then
    zeus rake db:test:prepare "$@"
  else
    echo "Zeus is not running"
    rake db:test:prepare "$@"
  fi
}

s () { 
  if zeus_on; then
    zeus s
  else
    echo "Zeus is not running"
    rails s
  fi
}

t () {
  if zeus_on; then
    if [ '$#' -gt 0 ]; then
      zeus test "$@"
    else
      zeus test spec
    fi
  else
    echo "Zeus is not running"
    if [ "$#" -gt 0 ]; then
      rspec "$@"
    else
      rspec spec
    fi
  fi
}

tt () zeus rspec --tag $1 spec

r () {
  if zeus_on; then
    zeus rake "$@"
  else
    echo "Zeus is not running"
    rake "$@"
  fi
}

c () {
  if zeus_on; then
    zeus c "$@"
  else
    echo "Zeus is not running"
    rails c "$@"
  fi
}

jt () {
  if zeus_on; then
    if [ "$#" -gt 0 ]; then
      zeus tr spec:javascript SPEC="$@"
    else
      zeus tr spec:javascript
    fi
  else
    echo "Zeus is not running"
    if [ "$#" -gt 0 ]; then
      rake spec:javascript RAILS_ENV=test SPEC="$@"
    else
      rake spec:javascript RAILS_ENV=test
    fi
  fi
}

# ##############################
# ############ GIT #############
# ##############################

gcurrent () git rev-parse --abbrev-ref HEAD

gclean! () git clean -f -d

gd () git diff "$@"

gds () git diff --staged "$@"

gdh () git diff HEAD^

gr () git rebase "$@"

gri () gr -i "$@"

grc () gr --continue

gback () git reset HEAD^

gh () hub browse

gac () {
  ga
  gc "$@"
}

gacm () gac -m "$@"

ga () {
  if [ "$#" -gt 0 ]; then
    git add "$@"
  else
    git add .
  fi
}

gp () git pull "$@"

gs () git status "$@"

gsp () git stash pop

gss () git stash save

gl () git log --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit "$@"

gco () git checkout "$@"

gcom () git checkout master

gpush () git push "$@"

gb () git branch "$@"

gbd () git branch -d "$@"

gc () git commit "$@"

gca () gc --amend

grb () git rebase "$@"

g () git "$@"

gcpick () git cherry-pick "$@"

grh () git reset --hard "$@"

gbdelete () git push origin --delete "$@"


# ###############################
# ######## CD SHORTCUTS #########
# ###############################

fish_dir () cd ~/.config/fish/

# Define code_directory in .zshrc
code () cd /$code_directory/"$@"

f () code "$@"

# ##############################
# ########### OTHER ############
# ##############################


tasks () ps aux | grep $@

b () bundle $@

ll () ls -lh $@

fs () foreman start $@

hcon () heroku run rails console

dtest () tail -f diagnostic.txt

sb () {
  if [ "$#" -gt 0 ]; then
    sublime "$@"
  else
    sublime .
  fi
}

fish_edit () {
  sb ~/.config/fish/config.fish
}

Probably unrelated, but also confusing to me. I get this warning when I open a new shell tab in relation to the uses of grep in that file. This didn't happen before with Fish:

usage: grep [-abcDEFGHhIiJLlmnOoqRSsUVvwxZ] [-A num] [-B num] [-C[num]]
  [-e pattern] [-f file] [--binary-files=value] [--color=when]
  [--context[=num]] [--directories=action] [--label] [--line-buffered]
  [--null] [pattern] [file ...]

Finally, the .zshrc file that imports these plugins. This answer (despite the different behavior) suggests that it might be a PATH definition issue, but I think I'm including all necessary paths in my PATH:

# Path to your oh-my-zsh installation.
export ZSH=$HOME/.oh-my-zsh

export code_directory=$HOME/code/

ZSH_THEME="robbyrussell"

plugins=(functions github)

# User configuration

export PATH="/Users/sasha/.rvm/gems/ruby-2.2.0/bin:/Users/sasha/.rvm/gems/ruby-2.2.0@global/bin:/Users/sasha/.rvm/rubies/ruby-2.2.0/bin:/Users/sasha/.rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/git/bin"
# export MANPATH="/usr/local/man:$MANPATH"

source $ZSH/oh-my-zsh.sh

In response to the below question:

➜  .oh-my-zsh git:(master) ✗ which ls
ls: aliased to ls -G
➜  .oh-my-zsh git:(master) ✗ typeset -f ls
ls () {
    ls -G -lh $@
}
➜  .oh-my-zsh git:(master) ✗ type ls
ls is an alias for ls -G

UPDATE

I've figured out what is causing it, but not why. It's this line:

ll () ls -lh $@

in my functions file. I figured that would run ls -lh whatever-arguments-follow when I typed ll. Any ideas why that woul raise an error when I ran ls?

Community
  • 1
  • 1
Sasha
  • 6,224
  • 10
  • 55
  • 102
  • 1
    What does `which ls` or `typeset -f ls` or `type ls` say? – Jens Jan 28 '15 at 21:44
  • Answered above -- looks like it's aliased somewhere? I'll look around for that, but I don't understand why `ls -G` would break the terminal tab anyway. – Sasha Jan 28 '15 at 21:47
  • 1
    Could this be caused by a recursive (infinite) definition of `ls`? What happens if you alias `ls` to `/bin/ls -G`? – bdesham Jan 28 '15 at 21:50
  • I added `alias ls=/bin/ls -G` to my functions file, opened a new tab, and tried it, and it killed the tab again, unfortunately. – Sasha Jan 28 '15 at 21:51
  • Found what was causing it, but not why. Update above. – Sasha Jan 28 '15 at 21:58
  • 1
    Try typing `ls` in a subshell, i.e., run `zsh` and then type `ls` at the `zsh` prompt. If `zsh` is printing an error message as it dies, that should let you see it before the tab closes (and take you back to the parent shell). – Keith Thompson Jan 28 '15 at 22:00
  • Your `ll` function definition should't cause the problem you're seeing, since you're typing the `ls` command, not `ll`. (Unless `ll` is being invoked indirectly.) – Keith Thompson Jan 28 '15 at 22:03
  • Yeah. Not typing `ll` at all, but it IS definitely the culprit somehow. If I comment it out, the error stops. And this is what I see when I run it in a subshell: `[1] 11628 segmentation fault zsh` – Sasha Jan 28 '15 at 22:03

1 Answers1

3

Okay, so ls is both an alias and a function. That's not gonna work because they'll recurse. On my terminal, with ls being an alias and a function, when I run

ls

it thinks for two seconds, then I get

ls:1: maximum nested function level reached

Use either a function, or an alias, but not both.

Edit Oh, it looks like that could work, but the problem is that the ls function is recursive. It should read

ls () {
    command ls -G -lh $@
}

The command builtin makes sure you execute the actual command, neither an alias nor a function.

Jens
  • 69,818
  • 15
  • 125
  • 179
  • I don't see where I'm making it either an alias or a function. I've defined an `ll` function. Is that implicitly aliasing `ls` or something? – Sasha Jan 28 '15 at 22:02
  • 1
    Someone else did that. Maybe your zsh is configured to source `/etc/profile` or `/etc/zsh` or `/etc/zshrc` or ... Do you have the `ENV` variable set to something? – Jens Jan 28 '15 at 22:04
  • Super weird. I don't have an `ls` function at all. Just `ll`, which should call `ls` directly. But when I added `command` it both a) worked, and b) replaced both `ll` and `ls` with the same function (essentially what I created `ll` to be). Again. I don't redefine `ls` anywhere, but it looks like `ll` is somehow redefining it recursively!?! (My only code is in the question above). Any ideas why that would be? – Sasha Jan 28 '15 at 22:16
  • Literally just renaming my `ll` method to `lol` fixed it entirely. (So that both `ls` and `ll` work in their correct, separate ways). WEIRD. I poked around a bit more, and it looks like there's an `ll` function already defined somewhere, and redefining it caused the problems. – Sasha Jan 28 '15 at 22:17
  • 1
    @Sasha If you want to know, in gory detail, what zsh does when it starts up as a login shell, run `zsh -l -x`. This should finally provide a clue where the aliases and functions come from. – Jens Jan 29 '15 at 07:55
  • 1
    Note that with `type ll` you can see, which ll is being used (for example, an alias to something, or a shell function), and `whence -f ll` shows its definition. This might give you some clue on where it is defined. – user1934428 Jan 29 '15 at 13:24