Indenting Fortran code in Vim

10,363

Solution 1

I've gone through a very similar process of trying to get Fortran indenting to work in vim. I still don't have it great, but I've made some progress. The script that arutaku posted (http://www.vim.org/scripts/script.php?script_id=2299) is where I started, but you need to make sure that filetype plugin indent on is in your vimrc.

I also needed a script for determining if I was using fixed-form or free-form syntax, since in my environment I use both. This is recommended in the documentation (http://vimdoc.sourceforge.net/htmldoc/syntax.html#ft-fortran-syntax). As it specifies, I put this script in ~/.vim/ftplugin/fortran.vim:

let s:extfname = expand("%:e")
if s:extfname ==? "f90"
  let fortran_free_source=1
  unlet! fortran_fixed_source
else
  let fortran_fixed_source=1
  unlet! fortran_free_source
endif

I also use a script so that I can press F7 to automatically complete certain constructs: http://www.vim.org/scripts/script.php?script_id=2487. I also put that in ~/.vim/ftplugin/.

I also have these in my vimrc to try to improve things further:

let fortran_do_enddo=1
let fortran_more_precise=1
let fortran_have_tabs=1

I believe those are supposed to interact with the first script to control its behavior, but I'm not convinced that they all work for me. I know the first is supposed to properly indent do/enddo blocks. The issue there is that since old-style Fortran allows a do without a matching enddo, the script can't indent them properly unless you can guarantee that you won't use unmatched 'do' statements. The let fortran_do_enddo=1 is supposed to be that guarantee, but it doesn't seem to work for me. The last one is supposed to allow usage of the tab character, which old Fortran considered bad, so it prevents them from being marked as errors. That one appears to work for me. And to be honest, I don't remember what the middle one is supposed to do nor if it works for me.

Edit:

I discovered that there was an older version of the the first script in my vim installation directory (/usr/share/vim/vim70/indent/ in my case) to which I do not have access rights. You might have those rights, and if it's causing you problems, overwrite or delete it. If, like me, you can't edit it, you can get the version in your $HOME to overwrite the functions from the first. I did this by doing two things. First I had to remove the checks to see if the functions already exist (the statements like if exists("*FortranGetFixedIndent")) and then I had to change all the function declarations to force overwriting by using the ! character, i.e. function! SebuFortranGetFreeIndent(). As far as I can tell, everything now works roughly as I would expect!

Solution 2

Does gg=G work?

gg: go to top
=: indent...
G: ... until the end

Solution 3

Try: https://sourceforge.net/projects/findent/files/

From the README:

findent: indents/beautifies/converts Fortran sources

  • findent supports Fortran-2008

  • findent can convert from fixed form to free form

  • binaries for Unix and Windows (findent and findent.exe respectively)

  • wrapper for processing one or more files in one call available for Unix and Windows (wfindent and wfindent.bat respectively)

  • (g)vim users: findent can act as a plug-in to format your edit file with the '=' command

  • gui frontent available in a separate package: jfindent

Solution 4

You can use auto-indentation writing <x>== (in command mode) where x is the number of lines to be indented.

If vim does not have fortran indentation you can load the following plugin and try the == combination: http://www.vim.org/scripts/script.php?script_id=2299

Share:
10,363
armando
Author by

armando

Updated on June 05, 2022

Comments

  • armando
    armando almost 2 years

    I have a fortran code which looks like this:

       open(2,file=filenm(i),status='unknown')
             do j=1,num_lines
                do k=1,dime
                         read(2,*) z(k)
                enddo
                   if( j .ge. 1000 ) then
                         do k=1,dime
                                  sumz(k)=sumz(k)+z(k)
                         enddo
                         nsteps=nsteps+1.0
                   endif
             enddo
       close(2)
    

    as you can see the indentation is not even, I would like to have something like this:

       open(2,file=filenm(i),status='unknown')
              do j=1,num_lines
                     do k=1,dime
                            read(2,*) z(k)
                     enddo
                     if( j .ge. 1000 ) then
                            do k=1,dime
                                   sumz(k)=sumz(k)+z(k)
                            enddo
                            nsteps=nsteps+1.0
                     endif
              enddo
       close(2)
    

    I can go line by line fixing the indentation but the code is kind of big. I appreciate any comment.

  • armando
    armando about 11 years
    it doesn't work properly. The "close(2)" for instance stays at the beginning of the line and all the other lines go one tab from the beginning of the line
  • armando
    armando about 11 years
    I put the script in the $HOME/.vim/after/indent/ directory. The results were similar to these with gg=G. I think the issue could be due to the fact that I don't have the Ajit J. Thakkar's Vim scripts for Fortran. I downloaded that script for fortran indent but I don't know where to put it, I mean the path. Do you have any idea?
  • happy coder
    happy coder about 11 years
    @armando, the Vim webpage tells you: install details Place the fortran.vim file in the $HOME/.vim/after/indent/ directory. In order to use this script, you must use Ajit J. Thakkar's Vim scripts for Fortran. Those should already be part of your Vim installation (in the $VIMRUNTIME directory). If not, you may find them at unb.ca/fredericton/science/chem/ajit/f_vim.htm CHEERS!
  • TomCho
    TomCho over 6 years
    just for the record this answer is particularly good because it doesn't rely on any other tool (like vim and its files). In my opinion this is the best answer here by far!
  • Roel
    Roel about 6 years
    For anyone finding this in 2018: I fixed my main problem with formatting Fortran by setting "let fortran_do_enddo=1" as indicated above, on a stock Vim install - no external script needed. It might well be that the script fixes additional things or does things better, just saying that if you're a casual Fortran programmer like me and want to just fix the loop indenting behavior, this setting might be all you need.
  • knia
    knia over 2 years
    it seems findent was written by Willem Vermin. This answer should mention that.