Commit 7e1c3801 authored by mtabriz's avatar mtabriz

first commit

parents
Pipeline #67855 passed with stage
in 30 seconds
image: gitlab-registry.mpcdf.mpg.de/mpcdf/module-image
stages:
- build
build:
stage: build
script:
- cd bin
- make
Willem Vermin wvermin@gmail.com
Copyright: 2015-2020 Willem Vermin wvermin@gmail.com
2020 Meisam Farzalipour Tabriz
License: BSD-3-Clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
findent: Indents/beautifies/converts Fortran sources.
Prints dependencies based on:
- definitions and uses of modules and submodules
- include, #include and ??include statements
Findent can emit a script that uses findent to
create a dependencies file for use in an Makefile.
- findent supports Fortran-66 up to Fortran-2018
- findent can convert from fixed form to free form and vice-versa
- findent honours cpp and coco preprocess statements
- findent is validated against all constructs in
'Modern Fortran explained, Incorporating Fortran 2018, Metcalf e.a.'
- findent honours OpenMP conditionals
- findent runs in Unix and Windows
- high speed: 50K - 100K lines per second
- wrapper for processing one or more files in one call available
for Unix and Windows (wfindent and wfindent.bat respectively)
- vim, gedit, emacs: findent optionally emits configuration files
for these editors to use findent as a plugin.
- gui frontent available in a separate package: jfindent
Unix-Linux users for whom above recipe does not work:
prerequisites: a Bourne shell (sh, bash), C++ compiler
make findent:
download findent-x.y.tgz
$ tar xf findent-x.y.z.tgz
$ cd findent-x.y
edit simplemake.sh to fill in the correct values of
the name of the C++ compiler, default: g++
the compile flags, default: -O2
the name of the program to create, default: findent
$ sh simplemake.sh
copy the generated program to the desired location
( e.g. $HOME/bin).
All systems:
Usage: $ findent -h
Examples: $ findent < in.f90 > out.f90
$ findent -i4 -Rr < in.f > out.f90
$ wfindent -i4 -Rr *.f
(g)vim users:
Install findent, the following command shows instructions
how to use findent in (g)vim:
findent --vim_help
Documentation:
in (g)vim:
:help equalprg
:help indentexpr
vim/README
and the comments in the files vim/findent.vim and vim/fortran.vim
gedit users:
Install findent, the following command shows instructions
how to use findent in gedit:
findent --gedit_help
emacs users:
Install findent, the following command shows instructions
how to use findent in emacs:
findent --emacs_help
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
SRC=../src/
CPP=g++
CPPFLAGS=-O2 -I$(SRC)
LEX=flex
YACC=bison
EXE=findentm
DEP=$(SRC)parser.cpp $(SRC)lexer.cpp
SRC_FILE = $(DEP) $(wildcard $(SRC)*.cpp)
OBJ_FILE = $(notdir $(SRC_FILE:.cpp=.o))
LDFLAGS =
all: $(OBJ_FILE) $(EXE)
$(OBJ_FILE): %.o:$(SRC)%.cpp
$(CPP) $(CPPFLAGS) -c $< -o $@
$(EXE):
$(CPP) $(OBJ_FILE) -o $(EXE) $(LDFLAGS)
$(SRC)parser.cpp:
$(YACC) -o $(SRC)parser.cpp -d $(SRC)parser.y
$(SRC)lexer.cpp:
$(LEX) -i -o $(SRC)lexer.cpp $(SRC)lexer.l
.PHONY: clean
clean:
rm -f $(OBJ_FILE) $(DEP) $(EXE)
SRC=../src/
CPP=g++
CPPFLAGS=-O2 -I$(SRC)
LEX=flex
YACC=bison
EXE=findentm
DEP=$(SRC)parser.cpp $(SRC)lexer.cpp
SRC_FILE = $(DEP) $(wildcard $(SRC)*.cpp)
OBJ_FILE = $(notdir $(SRC_FILE:.cpp=.o))
LDFLAGS =
all: $(OBJ_FILE) $(EXE)
$(OBJ_FILE): %.o:$(SRC)%.cpp
$(CPP) $(CPPFLAGS) -c $< -o $@
$(EXE):
$(CPP) $(OBJ_FILE) -o $(EXE) $(LDFLAGS)
$(SRC)parser.cpp:
$(YACC) -o $(SRC)y.tab.c -o $(SRC)parser.cpp -d $(SRC)parser.y
$(SRC)lexer.cpp:
$(LEX) -i -o $(SRC)lexer.cpp $(SRC)lexer.l
.PHONY: clean
clean:
rm -f $(OBJ_FILE) $(DEP) $(EXE)
File added
File added
EXTRA_DIST = findent.el README
This diff is collapsed.
Usage of findent in emacs
After following one of these two methods, the buffer is indented with Ctrl-Alt-q
Method 1:
- Put the output of
findent --emacs_findent
to the directory where you store your emacs scripts, for example:
mkdir -p ~/.emacs.d/lisp && findent --emacs_findent > ~/.emacs.d/lisp/findent.el
- Edit .emacs or .emacs.el or .emacs.d/init.el :
- If not already done, add the following two lines to extend load-path :
(add-to-list 'load-path (concat user-emacs-directory
(convert-standard-filename "lisp/")))
- Add a command to load findent.el :
(load "findent")
Method 2:
- Add the output of
findent --emacs_findent
to ~/.emacs ~/.emacs.el or ~/.emacs.d/init.el
;;;; this file contains an interface to use findent within emacs.
;;;; the C-M-q command ("indent function") is redefined to
;;;; indent the whole buffer.
; how to call findent for a fixed format Fortran source:
(defvar fortran-findent-command
"findent -ifixed -Ia"
"findent command for fixed format fortran source")
;
; how to call findent for a free format Fortran source:
(defvar f90-findent-command
"findent -ifree -Ia"
"findent command for free format fortran source")
;
;;;; define function findent-indent-buffer: it calls the program
;;;; findent with the whole buffer as input and output
(defun findent-indent-buffer()
"
Function that uses findent to indent the whole buffer.
The call to findent must be provided in the string findent-command,
for example (setq findent-command \"findent -ifixed -Ia\")
Findent supports Fortran-2008, free and fixed format;
indents correctly DO statements that share a common label;
is in general not confused by #if, #ifdef or #else preprocessor
statements.
"
(interactive)
(let (
(lines (count-lines (point-min) (point-max)))
(lpos (line-number-at-pos))
(first-window-line)
(offset)
(linelength)
(pos (point))
)
; this function tries to restore cursor and window
; position after indenting, hence the extra code.
; If somebody knows something better ...
(beginning-of-line)
(end-of-line)
(skip-chars-backward "[:blank:]")
(setq offset (- (point) pos))
(if (< offset 0) (setq offset 0))
(move-to-window-line 0)
(setq first-window-line (line-number-at-pos))
(message "indenting buffer ..." )
(shell-command-on-region (point-min) (point-max) findent-command 1 1 )
(goto-line lpos)
(redisplay)
(move-to-window-line 0)
(scroll-down (- (line-number-at-pos) first-window-line))
(goto-line lpos)
(setq pos (point))
(end-of-line)
(setq linelength (- (point) pos))
(if (< offset linelength)
(backward-char offset)
(beginning-of-line))
(message "indenting buffer ... %d lines indented" lines)
)
)
;
(add-hook 'fortran-mode-hook (lambda() (setq findent-command fortran-findent-command)))
(add-hook 'f90-mode-hook (lambda() (setq findent-command f90-findent-command)))
(add-hook 'fortran-mode-hook (lambda() (local-set-key "\C-\M-q" 'findent-indent-buffer)))
(add-hook 'f90-mode-hook (lambda() (local-set-key "\C-\M-q" 'findent-indent-buffer)))
EXTRA_DIST = findent-gedit findent.plugin findent.py README
This diff is collapsed.
Usage of findent in gedit
1) as an external tool:
Enter the following commands:
#################################################
mkdir -p $HOME/bin
findent --gedit_external > $HOME/bin/findent-gedit
chmod +x $HOME/bin/findent-gedit
#################################################
Make sure the $HOME/bin is in the PATH environment variable.
Open gedit:
-----------------------
(Edit ->) Preferences -> plugins : enable "External Tools"
Close gedit and start it again.
Tools -> Manage External Tools -> Add
- rename "New Tool" into findent
- put
findent-gedit
in the tool
Shortcut Key: <Alt>F11 (or something more to your liking)
Save: Nothing
Input: Current document
Output: Replace current document
Applicability: All documents Fortran 95
-----------------------
Alternatively, if all is well, it would be sufficient to place
the command
findent -Ia -i3
in the tool, but the script findent-gedit does some sanity checks
to prevent "oops" experiences.
2) as plugin:
Find the location of the directory where gedit expects the configuration
files, we assume here $HOME/.local/share/gedit/plugins
Enter the following commands:
##################################################
geditroot=$HOME/.local/share/gedit/plugins
mkdir -p $geditroot
findent --gedit_plugin > $geditroot/findent.plugin
findent --gedit_plugin_py > $geditroot/findent.py
##################################################
in gedit:
(Edit ->) Preferences -> plugins -> check: findent
findent is available in popup menu (right-click) and
shortcut <Ctrl><Alt>f . You can change that in
findent.py, look for the definition of 'shortcut'.
Advantage of plugin over external tool: gedit scrolls
back to point where you called findent.
Flags for findent:
both the external command as the plugin pass the environment
variable GEDIT_FINDENT_FLAGS to findent. Example: if you
want general indentation set to 2 but indentation of do-loops
set to 4, specify:
export GEDIT_FINDENT_FLAGS="-i2 -d4"
Use
findent -h
for a list of flags.
#!/bin/sh
# to be used in gedit to indent fortran source
# in gedit:
# Edit -> preferences -> enable "External Tools"
# Tools -> Manage External Tools -> Add
# - rename "New Tool" into findent
# - put this file in the tool, or place a command
# in the tool that starts this script
# Shortcut Key: <Alt>F1 (or something more to your liking)
# Save: Nothing
# Input: Current document
# Output: Replace current document
# Applicability: All documents Fortran 95
#
flags="-Ia -i3" # flags for findent
fin=`mktemp`
fout=`mktemp`
trap "rm $fin $fout" 0 # remove temps on exit
restore()
{
cat $fin
if [ "$lineadded" = "yes" ] ; then
echo "empty line added" >&2
else
echo "nothing changed" >&2
fi
exit
}
cat > $fin # copy input to $fin
# gedit version 2 has some troubles keeping stdout and
# stderr separate when stdout does not end with newline.
# add newline if input file does not end with newline:
lastchar="$(tail -c1 $fin | od -a -An | tr -d ' ')"
if [ "$lastchar" != "nl" ] ; then
echo >> $fin
lineadded=yes
else
lineadded=no
fi
if [ "$GEDIT_CURRENT_DOCUMENT_TYPE" != "text/x-fortran" ]; then
echo "not a fortran file" >&2
restore
fi
FINDENT=`which /bin/ls 2>/dev/null`
FINDENT=`which findent 2>/dev/null`
if [ -z "$FINDENT" ] ; then
echo "cannot find findent" 1>&2
restore
fi
fname="$GEDIT_CURRENT_DOCUMENT_NAME" # get the file name
# get suffix in lowercase:
suffix=`echo "${fname##*.}" | tr '[:upper:]' '[:lower:]'`
# determine input type (fflag) from suffix:
case "$suffix" in
f|for|fpp|ftn|fortran|f77)
fflag="-ifixed"
;;
f90|f95|f03|f08)
fflag="-ifree"
;;
*)
# let findent find out:
fflag=""
;;
esac
findentflags="$flags $fflag"
# run findent:
$FINDENT $findentflags < $fin > $fout 2>/dev/null
if [ $? -ne 0 ] ; then
echo "findent reports error" >&2
echo "using \"$FINDENT $findentflags\"" >&2
restore
fi
# check if output has same number of lines as input:
win=`wc -l < $fin`
wout=`wc -l < $fout`
if [ "$win" != "$wout" ] ; then
echo "findent does not function properly" >&2
restore
fi
# produce the result
echo $wout lines indented 1>&2
if [ "$lineadded" = "yes" ] ; then
echo "empty line added" >&2
fi
cat $fout
[Plugin]
Loader=python3
Module=findent
IAge=3
Name=findent
Description=Indent Fortran source
Authors=Willem Vermin
Copyright=Copyright @ 2017 Willem Vermin
Website=http://www.gedit.org
Version=0.1
# -*- coding: utf-8 -*-
# Findent plugin
# This file is part of gedit
#
# Copyright (C) 2017 Willem Vermin
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
from gi.repository import GObject, Gio, Gtk, Gedit
import gettext
import os.path
from subprocess import Popen,PIPE
try:
gettext.bindtextdomain(GETTEXT_PACKAGE, GP_LOCALEDIR)
_ = lambda s: gettext.dgettext(GETTEXT_PACKAGE, s)
except:
_ = lambda s: s
class FindentAppActivatable(GObject.Object, Gedit.AppActivatable):
app = GObject.Property(type=Gedit.App)
def __init__(self):
GObject.Object.__init__(self)
global shortcut
shortcut = "<Ctrl><Alt>f"
def do_activate(self):
self.app.add_accelerator(shortcut, "win.findent", None)
def do_deactivate(self):
self.app.remove_accelerator("win.findent", None)
class FindentWindowActivatable(GObject.Object, Gedit.WindowActivatable):
window = GObject.Property(type=Gedit.Window)
def __init__(self):
GObject.Object.__init__(self)
self.bottom_bar = Gtk.Box()
def do_activate(self):
action = Gio.SimpleAction(name="findent")
action.connect('activate', lambda a, p: self.do_findent())
self.window.add_action(action)
self._insert_bottom_panel()
def do_deactivate(self):
self.window.remove_action("findent")
self._remove_bottom_panel()
def do_update_state(self):
view = self.window.get_active_view()
enable = view is not None and view.get_editable()
self.window.lookup_action("findent").set_enabled(enable)
return
def do_findent(self):
view = self.window.get_active_view()
if view and hasattr(view, "findent_view_activatable"):
view.findent_view_activatable.do_findent()
def _insert_bottom_panel(self):
# Add elements to panel.
self.findent_label = Gtk.Label()
self.findent_textbuffer = Gtk.TextBuffer()
global mesg
mesg = self.findent_textbuffer
self.findent_textview = Gtk.TextView()
self.findent_textview.set_buffer(self.findent_textbuffer)
self.bottom_bar.add(self.findent_textview)
# Get bottom bar (A Gtk.Stack) and add our bar.
panel = self.window.get_bottom_panel()
panel.add_titled(self.bottom_bar, 'findent_panel', "Findent output")
# Make sure everything shows up.
panel.show()
self.bottom_bar.show_all()
panel.set_visible_child(self.bottom_bar)
def _remove_bottom_panel(self):
panel = self.window.get_bottom_panel()
panel.remove(self.bottom_bar)
def settext(self,text):
self.findent_textbuffer.set_text(text)
class FindentViewActivatable(GObject.Object, Gedit.ViewActivatable):
view = GObject.Property(type=Gedit.View)
def __init__(self):
GObject.Object.__init__(self)
self.default_flags = "-Ia -i3"
self.executable = "findent"
self.userflags = os.getenv("GEDIT_FINDENT_FLAGS")
if self.userflags == None:
self.userflags = ""
def do_activate(self):
self.view.findent_view_activatable = self
self.view.connect('populate-popup', self.populate_popup)
mesg.set_text("Findent ready for use."+ \
" Shortcut: "+shortcut+ \
" and in popup menu." + \
" Default flags: '" + self.default_flags + "'" + \
"\nflags from environment variable GEDIT_FINDENT_FLAGS: '" +
self.userflags+"'")
def do_deactivate(self):
delattr(self.view, "findent_view_activatable")
def populate_popup(self, view, popup):
if not isinstance(popup, Gtk.MenuShell):
return
item = Gtk.SeparatorMenuItem()
item.show()
popup.append(item)
item = Gtk.MenuItem.new_with_mnemonic(_('_Findent'))
item.set_sensitive(self.view.get_editable())
item.show()
item.connect('activate', lambda i: self.do_findent())
popup.append(item)
def do_findent(self):
doc = self.view.get_buffer()
if doc is None:
return
ctype = doc.get_content_type()
if ctype != "text/x-fortran":
mesg.set_text("Content type is '"+ctype+"'" + \
". Findent handles only 'text/x-fortran'")
return
# run a simple test to see if findent is doing what we expect