HN user

okdana

235 karma
Posts0
Comments42
View on HN
No posts found.

If by '99% coverage' you mean it can complete the command's options, and know which of them take arguments, and maybe even know about sub-commands, yes. zsh's _arguments, and its _gnu_generic wrapper, can do that — just compdef whatever command to _gnu_generic and it'll pull the options and descriptions out of the --help output for you. fish does something similar, and maybe bash-completion has it too, idk.

But, even with relatively simple commands, that type of completion is very limited compared to the contextual functionality that proper zsh completion functions provide. These functions know...

* Which arguments are meaningful to complete more than once — there's no reason to complete `-a` again after you've already entered `ls -a`, but an option like `-v` might be cumulative

* Which arguments are meaningful to complete in the presence of other arguments — there's no reason to complete `-A` if you've already entered `ls -a`, since those two options are exclusive

* Whether the command supports permutation — GNU tools usually do (`ls mydir/ -al`), BSD ones usually don't (`ls -al mydir/`)

* Whether options can be stacked — some commands require `-a -b -c` instead of `-abc`

* How options can be joined to their optargs — GNU supports both `--foo bar` and `--foo=bar`, curl supports only `--foo bar`, grep supports both `-m 3` and `-m3`, tree supports only `-L 3`

* How the current argument might be affected by a previous one — if you've entered `make -C mydir` it's useful to complete targets from mydir/Makefile

* How to complete multi-part arguments — if you press tab after `ssh foo@` you probably want to complete a host name or IP

* The descriptions of arguments — zsh can explain what the difference between `always` and `auto` is, and even when an argument is arbitrary, it can explain what format it takes, what the default is, what the min/max are, &c.

* Probably most importantly, the values of optargs and operands — just blindly offering file names or presenting a metavar parsed from --help (like WHEN or TYPE) is not very nice; a useful completion function will offer package names, man-page names, compression levels, PIDs, NIC addresses, or whatever else is appropriate

I know it's technically possible to do some of this with bash completion functions, but most don't, probably because the infrastructure isn't there. fish is nicer, but even it doesn't (can't?) usually go that far with it.

This level of richness (along with related UI stuff like menu selection) is why a lot of people switch to zsh even if they don't really care about its scripting features and modules and stuff. It's probably why i started using it originally.

A way to specify completion behaviour declaratively would be really cool, but if it's just going to be dumbed down to bash-like functionality, i'm not sure it's going to gain much more traction with zsh users than _gnu_generic and bashcompinit (zsh's bash-completion compatibility shim) have.

What do you mean 'rewrite unlink'? As far as i know, none of the standard POSIX/C file-manipulation functions, including unlink(2), have ever supported NUL bytes embedded in file names. Path arguments to those functions are all NUL-terminated strings, as are exec*() process arguments, so it would be impossible to manipulate or reference those files using any of the standard APIs or command-line tools.

I can't think of how macOS could have previously supported NUL bytes in file names without those files existing in a separate universe that can only be interacted with by software that uses some proprietary Apple API. And if that's really how it worked, i feel like that was the real mistake all along...?

As the other person said, if your scripts are executables with an sh or bash 'shebang' at the top, they will continue to use the same shell they always did.

But if you did want to run them with zsh, most simple scripts that just set environment variables, string together commands, or redirect to files should work without any changes. The most obvious difference for basic scripts like that is that zsh doesn't split parameter-expansions on white space by default (so if you did something like `opts='-a -b -c'; mycmd $opts` it wouldn't work without additional, minor, modifications)

I agree that zsh's default configuration sucks (and the new-user wizard is overwhelming). I would like the project to provide a more opinionated set of defaults to OS vendors; i think we are probably just nervous about breaking 30 years' worth of expectations, and so far nobody has really pushed for it.

But i do think the misunderstanding i mentioned is very common, as illustrated by the fact that the GP seems to think that OMZ itself provides zsh's completion functionality. It's also a frequent point of confusion with people seeking assistance on zsh's IRC channel.

zsh doesn't require any 'plugins' for its tab-completion, everything you need is distributed with the shell. A lot of people who use zsh just don't understand how it works and think that OMZ/Prezto/whatever are doing something special for them that they couldn't achieve themselves with one line in their .zshrc (or that may even be enabled by default in their OS's global zshrc, as is the case on Ubuntu for example)

zsh isn't a perfect super-set of bash (there are some differences in syntax, provided built-ins, &c.), but it does have equivalents for most of bash's functionality. Off the top of my head i can't think of anything useful that it's missing. People may have subjective preferences for e.g. readarray over parameter expansion, but the functionality is all there. I suppose it doesn't (and probably never will) fully conform to POSIX, if that's important to you

Bash 5.0 released 8 years ago

You probably don't need to update /etc/shells unless you really want to. chsh just won't let you switch to a shell that's not listed there without using sudo, which isn't a problem for most (generally single-user) Mac systems. You can also change your shell from the Users & Groups system preferences (in the advanced settings).

Bash 5.0 released 8 years ago

bash's EPOCHREALTIME was inspired by mksh, which was in turn inspired by zsh. And in zsh, EPOCHREALTIME was named after the system real-time clock (specifically the CLOCK_REALTIME clock ID passed to clock_gettime()). And i imagine that was named by analogy with hardware real-time clocks, since they both track human ('real') time. But i don't know much about electronics or the history of POSIX clock sources.

Fish shell 3.0 8 years ago

Yeah, you're right of course. I think i was conflating job control with sub-shells, sorry.

Terminals Are Sexy 8 years ago

The problem with most of these lists and how-tos is that they're the CLI equivalent of 'I Fucking Love Science'. The people suggesting things like zsh frame-works rarely seem able to properly justify their use — they don't know what they actually do, nor what the alternative is, nor even whether you could accomplish the exact same thing in a less featureful shell like bash. It's just a cargo cult of people who don't really understand what they're doing writing Medium posts or whatever to evangelise unnecessary, badly written software to other people who don't really understand what they're doing.

(In zsh's case, i think that's partly the project's own fault; it has very underwhelming defaults and a very overwhelming set-up process for new users.)

Right, it was just a random example that popped into my head. You would probably also want to think twice about using -R (at least with GNU grep), about hard-coding the search directory, &c.

All of PHP's process-execution methods (except one, which is unusable on many systems) go through the shell, so by virtue of that it also searches the PATH.

Simple trick behind this technique is that when using shell wildcards, especially asterisk (...), Unix shell will interpret files beginning with hyphen (-) character as command line arguments to executed command/program.

To be clear, the shell isn't really 'interpreting' anything here — it knows absolutely nothing about the argument conventions of whatever program you're running[0]. All it's doing is passing a list of arguments to an executable; how the executable deals with that is up to it.

And this isn't only a shell problem — it's an issue when you pass arbitrary arguments to ANY external utility in ANY language. For example, maybe you have some kind of tool that calls grep:

    # Perl
    exec '/usr/bin/grep', '-R', $input, 'mydir';

    # PHP (with Symfony Process)
    (new Process(['/usr/bin/grep', '-R', $input, 'mydir']))->run();

    # Python
    subprocess.run(['/usr/bin/grep', '-R', input, 'mydir'])

    # C
    execv("/usr/bin/grep", (char *[]) {"grep", "-R", input, "mydir", NULL});
All of these are safe in the sense that there's no risk of shell command injection (in fact, only the PHP one even calls the shell), but NONE of them are safe against this problem, where the input value might begin with a hyphen. In this grep scenario it's probably not a security issue, but it can produce confusing results for the user if nothing else.

As others mentioned, you must ALWAYS use '--' to mark the end of option processing when you do something like this.

[0] Technically the shell knows about the conventions of its built-ins, but even those mostly handle arguments in a similar fashion to external utilities, where an arbitrary argv is fed to a function and then parsed using some getopts-like method.

How are you going to white-list network-interface names? On Linux at least you can name them almost anything you want:

  % sudo ip link set eth3 down
  % sudo ip link set eth3 name "'deal-with-it'"
  % sudo ip link show "'deal-with-it'"
  5: 'deal-with-it': <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN mode DEFAULT group default qlen 10000
      link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
The only interface-name restrictions iproute2 sets is that they can't contain NUL, slash, or white space, and they can't be longer than 15 characters.

Also, if unions are not a direct, full frontal attack on capital and hierarchy, why are they facing constant attack from organs of ruling class consciousness, like, say, the WSJ, the Financial Times, or even other less explicit papers like the New York Times?

The fact that the capitalist class doesn't appreciate tactics that complicate or reduce the effectiveness of their preferred business practices doesn't mean that those tactics represent an attack on capitalism itself. Corporations violently oppose taxes and regulations, too, but neither threatens capitalism or its fundamental class structure.

Unions started as an instrument of class struggle and remain precisely that, the fact that that is even slightly controversial is more representative of the ideological climate of today and specifically this website.

It's hardly peculiar to the 'climate of today'. Karl Marx, 1865:

At the same time, and quite apart from the general servitude involved in the wages system, the working class ought not to exaggerate to themselves the ultimate working of these everyday struggles. They ought not to forget that they are fighting with effects, but not with the causes of those effects; that they are retarding the downward movement, but not changing its direction; that they are applying palliatives, not curing the malady. They ought, therefore, not to be exclusively absorbed in these unavoidable guerilla fights incessantly springing up from the never ceasing encroachments of capital or changes of the market. They ought to understand that, with all the miseries it imposes upon them, the present system simultaneously engenders the material conditions and the social forms necessary for an economical reconstruction of society. Instead of the conservative motto: “A fair day's wage for a fair day's work!” they ought to inscribe on their banner the revolutionary watchword: “Abolition of the wages system!”

And in regards to unions specifically:

Trades Unions work well as centers of resistance against the encroachments of capital. They fail partially from an injudicious use of their power. They fail generally from limiting themselves to a guerilla war against the effects of the existing system, instead of simultaneously trying to change it, instead of using their organized forces as a lever for the final emancipation of the working class that is to say the ultimate abolition of the wages system.

Shells like zsh and fish will never get mainstream adoption because they are not compatible with bash.

zsh and fish don't really belong in the same comparison IMO.

zsh is, like bash, a ksh-like shell with a Bourne-style grammar. Obviously it depends on the exact use case, but in practice, for basic scripting purposes, it is almost a super-set of bash, and it provides several emulation options (like sh_word_split) specifically designed to increase compatibility with POSIX and with bash in particular. It even provides shims to support bash completion functions. (It is fair to point out that, even with all the emulation stuff enabled, it's still not completely bash-compatible, nor POSIX-compliant. It's close enough that the changes required are usually extremely trivial, though.)

fish on the other hand has its own completely different grammar and makes no attempt to provide POSIX/ksh/bash compatibility at all.

GREP_OPTIONS is deprecated in GNU grep since i think 2.20. It will be removed in a future version, and until then it's going to print an irritating warning message every time you use it.

(I don't think there's any such plan for the various BSD greps, so if you use those exclusively you're probably fine.)

He has some videos that are commentated by voice, but for some reason he finds doing the recordings very stressful, so most of his content is unfortunately on his 'uncommentated' channel. I agree it would be nice to have the voice-overs

There are good reasons to use Zsh beyond its autocomplete system...

zsh also performs much better in practice than bash. Not only does it run the same code faster, it subsumes a great deal of functionality that normally requires external utility calls (which are very slow) into the shell itself.

For example:

* zsh has native floating-point arithmetic, so no need for `awk` or whatever. It can even format (digit-group) the numbers

* Regular-expression matching with =~ can be replaced by extended globs (which offer similar functionality but are significantly faster in most cases)

* `basename`, `dirname`, `readlink -m`, and `readlink -f` can be replaced by parameter-expansion modifiers

* `sort` can be replaced by parameter-expansion flags

* `grep` can be replaced by parameter-expansion flags and extended globs

* `find` (including its `-type` and `-exec` features) can be replaced by globs

* `date` can be replaced by prompt expansion or the `zsh/datetime` module

* `cp`, `mkdir`, `rm`, and so on can be replaced by the `zsh/files` module

* `stat` can be replaced by the `zsh/stat` module

* `column` can be replaced by `print -c` or `print -C`

there are massive swaths of the program, entire subsystems, that are more or less completely undocumented

Like what? I'm not sure i'd noticed that myself. Sometimes the documentation is vague, maybe hard to find (e.g., the completion system's documentation is a bit overwhelming), but it's always been there when i went looking for it.

Also, the ad-hoc "plugin" ecosystem is in a strange and fragmented state.

The plug-in ecosystem (i assume you mean OMZ, zplug, and stuff like that) is entirely unofficial and most of the zsh developers don't seem to care for any of it because it tends to be slow, error-prone, and often just unnecessary. It's also a major support burden for the people on IRC and in the mailing list, which doesn't endear them to it. Might be cool to have something official though.

It's a shame that more people don't write actual modules in C (yes, Zsh has a native module system), but then again, is the API even documented?

I don't think it is, there's just an example module you can build. bash also supports loadable modules and it's the same way AFAIK.

One more thing about Zsh: it has emacs syndrome. Do your really need an FTP client and calendar built into your shell?

Most of the weird stuff like the FTP client and calendar and Tetris game are optional modules or even just regular shell scripts. None of them are enabled by default and packagers can omit them (and they often do, especially with static builds).

I use heredocs for 'commenting out' code in shell scripts a lot. For example:

    : <<- 'NOOP'
    some
    code
    here
    NOOP
In some languages there is a very slight performance impact to doing this, however. Especially in the shell, because it actually has to juggle file descriptors whenever a heredoc or herestring is involved — even if you're directing it into a built-in like `:`. (It only costs a few-dozen microseconds though.)

Also, heredocs are irritating because they usually can't deal with indentation properly. bash and zsh support the `<<-` operator which allows you to indent the closing delimiter, but only if you use tabs. Most other languages require the delimiter to be the first thing on the line, which is tedious and confusing.

Python's triple-quotes seem to solve all of these problems, and they're one of the best things about Python's grammar IMO. I wish every language had that, combined with the ability to treat expressions as statements. It'd be a little ugly in C-like languages, but certainly usable:

    '''
    my comment
    ''';

I think the Swift language is great, but the tool chain (specifically `/usr/bin/swift` and `/usr/bin/swiftc`) is absolute garbage. The documentation is almost non-existent, its preferred method of 'handling' errors is to just segfault, when it does give you an actual error message it's completely nonsensical, and as mentioned it's very very slow.

I think i'm a version or two behind the latest, so maybe it's better now, but that's been my experience so far.

Anyway, in spite of the above i still prefer it to ObjC.

The question i have is why do users configure their terminals to use colours that are unreadable to them?

If your blue doesn't look right on your dark background, why are you using that blue?

If your yellow doesn't look right on your light background, why are you using that yellow?

I mean i get how this can be a problem with hard-coded arbitrary values — you can't ever guarantee that e.g. #ff6600 will go with anyone's particular colour scheme. But these 8 or 16 standard colours are not hard-coded, they're configurable in every terminal i've ever used, including Windows's shitty command prompt. They can and should be set to a value that's appropriate for your background and text colours.

Maybe this is more a fault of the terminal/theme developers for providing unusable defaults. idk.

That doesn't seem like an especially compelling argument. There are components of every ready-made operating system that you 'don't need or want'. I don't need or want an IPv6 stack, or debugfs, or half of the other features that come with most distributions' Linux kernels, and i don't need or want legacy bull shit like (d)ash and cpio and Python 2. But there they always are anyway, and i don't lose much sleep over that fact.

You can use syslog in conjunction with the systemd journal. Some distributions come set up that way by default, and for the others you can just `apt-get install rsyslog` or whatever. When you have a syslog daemon installed, `tail -f` and everything else you're used to works exactly the same as before, you can pretend the journal doesn't even exist if you want. And if you don't have a syslog daemon installed... well, i don't know if that's really journalctl's fault, is it?

Regex Puzzle 9 years ago

I don't know of any that require it. But it's common to see punctuation characters escaped like that because Perl (and PCRE and its various cousins/descendants) allows you to escape any non-meta-character and have it treated as a literal.

I suppose the two main benefits are

(a) neither the writer nor the reader has to remember which punctuation characters are meta-characters (you just have to remember that it's always a literal if it's escaped), and

(b) in implementations like PHP's which try to replicate the Perl-style 'delimited' syntax (e.g., /foo/), it prevents characters in the pattern from conflicting with the delimiters.

Maybe there's some other advantage but i can't think of what.

They mean like this, where `-` is tab and `.` is space:

    --def myfunc(
    ---foobar = 1,
    ---...baz = 2
    --)
(silly example, idk, you get what i mean)

No matter what size tab stops you use, the `=` will always line up vertically, because the tabs are only used for the indentation (nesting level), not the visual alignment.

By that definition there isn't a main-stream political party in the entire Western world that isn't leftist, because they all support 'forced income redistribution' to some degree. In the United States it's Medicare, Medicaid, and Social Security, all three of which are enshrined in both parties' official platforms.