3

In shell I do conditional stuff depending on distro like this:

eval "$(source /etc/os-release && typeset -p ID)"
if [[ $ID =~ ^(rhel|fedora.*|amzn|ol|rocky|almalinux)$ ]]; then
  ...
fi

How could I do that in vimscript?

6
  • Using source that way seems like it could open you to attacks. But in Vim you could read the lines of the file (readfile()) and find the one with ID (filter ()), then grab everything after the = (matchstr?)
    – D. Ben Knoble
    Oct 22, 2023 at 12:41
  • 1
    Why do you need that? Oct 22, 2023 at 18:32
  • @ChristianBrabandt I've started using different terminal colours on different machines/servers to help me know where I am and wanted to change the vim colourschemes to match. I can't think of a better way to differentiate as they all use the same dotfiles. I could use hostnames, but this would not need updating.
    – paradroid
    Oct 23, 2023 at 5:53
  • @paradroid ah okay that makes sense. I would in that case use as on the suggested answer readfile() or system() or systemlist() to get the distribuation. But note, checking this on startup, may slow down your startup time (obviously) Oct 23, 2023 at 9:15
  • From your answer, what you need isn't determining the distro but the term (or some of its available capabilities.) What I mean is that within the same distro the results may differ according to the installed packages and account settings.
    – gildux
    Oct 25, 2023 at 18:45

5 Answers 5

3

As I pointed out in my comment, I suspect it's an XY problem. I wouldn't read any files in /etc in Vim at all. Although I have to say I'm delighted to have read some great answers.

A comment on the question says the same dotfiles are used on all machines and I think that's where things start to go wrong. Those are configuration files, they are meant to be configured. So allow for some system-specific tweaking.

I would propose a distro-agnostic approach of reading from an optional, machine-specific configuration file like this:

" set defaults that make sense
" ...
if filereadable(expand('~/.vim/overrides/distro.vim'))
    source ~/.vim/overrides/distro.vim
endif

You can put the config file next to your Vim configuration like in my example or specify another path. See :help filereadable() and :help expand() for usage information.

There are two more points to consider which largely depend on how the machines are set up and dotfiles are deployed. There's nothing about it in the question so I'll have to guess a little.

You can write distro.vim e.g. from a shell script much like that in the question or a makefile when you set up a new machine and install your dotfiles. A less favorable option would be to write it from a shell profile whenever you log in.

Also, the configuration should be ignored in whatever tool is used to setup the dotfiles, e.g. add it to .gitignore if Git is what you use.

Main advantages of this approach:

  • easy to adapt to allow for other distinguishing features other than Linux distro.
  • equally easy to expand or make exceptions. You can script something or just edit that file.
  • uses both shell script and Vim for what they're good at.
  • comes with the minimal performance penalty of sourceing another file and re-setting some options. You should not be able to notice.
4
  • Good idea. It would be much more flexible to write the file as a heredoc.
    – paradroid
    Oct 24, 2023 at 6:45
  • 1
    you can even use $ENV variables to make it more flexible. And heredocs could also be used if you really want to Oct 24, 2023 at 9:41
  • I'd use whatever integrates nicest with the deployment strategy. There's nothing of it in the question so we can only guess.
    – Friedrich
    Oct 24, 2023 at 9:51
  • 1
    I like this answer much. I tend to split also my dotfiles in a generic one plus a specific (per host currently but that's not always the right way to go) Final organisation depends the deployment tools
    – gildux
    Oct 25, 2023 at 18:51
2

Here's my version:

:echo readfile('/etc/os-release')->filter({k,v -> v =~# '^ID='})[0]->slice(3)

This errors if !filereadable('/etc/os-release') and assumes the line of interest is exactly ID=<value>. If the file must be interpreted by a shell to be correct, something like Vivian's answer using source in systemlist() is probably more appropriate.

2
  • This is nice, but it errors in nvim, which I also use. E117: Unknown function: slice
    – paradroid
    Oct 24, 2023 at 1:47
  • Must be new. You can technically accomplish something similar with [3:] or similar syntax @paradroid
    – D. Ben Knoble
    Oct 24, 2023 at 2:53
2

I would do:

let distrib = system('source /etc/os-release && typeset -p ID')
if distrib =~ '(rhel|fedora.*|amzn|ol|rocky|almalinux)'
  " ...
endif
2
  • Thanks a lot, but it doesn't seem to work for me. Have you tested it?
    – paradroid
    Oct 23, 2023 at 5:54
  • I tested it on WSL Ubuntu. I could provide a more robust version but the idea is to use system to get the output of source Oct 23, 2023 at 6:30
1

Will this work ?

function! GetLinuxDistro()
    let os_release_path = '/etc/os-release'
    
    if filereadable(os_release_path)
        let os_info = readfile(os_release_path)
        for line in os_info
            if line =~ 'PRETTY_NAME'
                return substitute(line, 'PRETTY_NAME="\(.*\)"', '\1', '')
            endif
        endfor
    endif
    
    return 'Unknown Linux Distribution'
endfunction

echo GetLinuxDistro()

2
  • 1
    Welcome to Vi and Vim SE and thank you for writing an answer. Most great answers explain how and why they solve a problem. You could edit your answer and tell us what your function does.
    – Friedrich
    Oct 23, 2023 at 17:50
  • 1
    yes, should work Oct 23, 2023 at 18:12
0

I've started using different terminal colours on different machines/servers to help me know where I am and wanted to change the vim colourschemes to match. I can't think of a better way to differentiate as they all use the same dotfiles. I could use hostnames, but this would not need updating.

Or you could:

  • make sure all your shells expose an appropriate $TERM, like xterm-16color,
  • and use a 16color-ready colorscheme in Vim, like default and any of the other built-in ones or this one or that one.

That way, Vim doesn't need to be aware of where it is running; it always shows the expected colors.

5
  • I have ssh forwarding $TERM fine and all shells local and remote are either xterm-256 or tmux-256color with 16m Truecolor and everything displaying as it should (with this fix ix.io/4JPR). In tmux things aren't quite perfect, but only if I look very closely. Not sure what you mean, as I basically want different colours on remote servers compared to local machines, as it helps workflow, remembering where I am in the terminal.) It's $LS_COLORS and vim colorschemes that I am conditionally changing, I should have been clearer.)
    – paradroid
    Oct 24, 2023 at 13:26
  • I suspect what paradroid is saying is that they want each machine to use different colors. Not my thing, but it could be an interesting way to quickly distinguish things if working on multiple machines regularly.
    – D. Ben Knoble
    Oct 25, 2023 at 1:25
  • Misunderstanding on my part: I thought the whole terminal palette was different from one machine to another, which would have made adding that logic to Vim superfluous. If all OP did was change their $LS_COLORS then my answer is irrelevant. FWIW, a colleague of mine used a similar technique a few years ago: one profile/theme per host, with a different background for each, all set at the terminal emulator level. It seemed to work well for him.
    – romainl
    Oct 25, 2023 at 7:45
  • Ever notice when a ~100 rep user writes an answer that's slightly besides the point, they get 3 downvotes and death threats in the comments. Do the same at 38k rep and OP apologizes for having asked the wrong question :D
    – Friedrich
    Oct 25, 2023 at 8:27
  • 1
    That's why we rake those internet points in. They give us insane POWERS and shield us from scrutiny and responsibility.
    – romainl
    Oct 25, 2023 at 8:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.