merge trunk
This commit is contained in:
commit
b3253cd4b4
325 changed files with 11987 additions and 8304 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
|||
2010-09-26 Lars Magne Ingebrigtsen <larsi@gnus.org>
|
||||
|
||||
* configure.in (HAVE_GNUTLS): Don't break if we don't have the
|
||||
gnutls libraries.
|
||||
|
||||
2010-09-26 Teodor Zlatanov <tzz@lifelogs.com>
|
||||
|
||||
* configure.in: Set up GnuTLS.
|
||||
|
||||
2010-09-22 Chong Yidong <cyd@stupidchicken.com>
|
||||
|
||||
* configure.in: Announce whether libxml2 is linked to.
|
||||
|
||||
2010-09-20 Dan Nicolaescu <dann@ics.uci.edu>
|
||||
|
||||
* configure.in (LINKER): Rename to LD_FIRSTFLAG, do not include $(CC).
|
||||
|
|
119
configure
vendored
119
configure
vendored
|
@ -681,6 +681,8 @@ FONTCONFIG_LIBS
|
|||
FONTCONFIG_CFLAGS
|
||||
LIBXMU
|
||||
LIBXTR6
|
||||
LIBGNUTLS_LIBS
|
||||
LIBGNUTLS_CFLAGS
|
||||
LIBSELINUX_LIBS
|
||||
GCONF_LIBS
|
||||
GCONF_CFLAGS
|
||||
|
@ -822,6 +824,7 @@ with_gpm
|
|||
with_dbus
|
||||
with_gconf
|
||||
with_selinux
|
||||
with_gnutls
|
||||
with_makeinfo
|
||||
with_compress_info
|
||||
with_pkg_config_prog
|
||||
|
@ -1532,6 +1535,7 @@ Optional Packages:
|
|||
--without-dbus don't compile with D-Bus support
|
||||
--without-gconf don't compile with GConf support
|
||||
--without-selinux don't compile with SELinux support
|
||||
--without-gnutls don't use -lgnutls for SSL/TLS support
|
||||
--without-makeinfo don't require makeinfo for building manuals
|
||||
--without-compress-info don't compress the installed Info pages
|
||||
--with-pkg-config-prog=PATH
|
||||
|
@ -2843,6 +2847,14 @@ else
|
|||
fi
|
||||
|
||||
|
||||
# Check whether --with-gnutls was given.
|
||||
if test "${with_gnutls+set}" = set; then :
|
||||
withval=$with_gnutls;
|
||||
else
|
||||
with_gnutls=yes
|
||||
fi
|
||||
|
||||
|
||||
## For the times when you want to build Emacs but don't have
|
||||
## a suitable makeinfo, and can live without the manuals.
|
||||
|
||||
|
@ -9398,6 +9410,110 @@ $as_echo "#define HAVE_LIBSELINUX 1" >>confdefs.h
|
|||
fi
|
||||
|
||||
|
||||
HAVE_GNUTLS=no
|
||||
if test "${with_gnutls}" = "yes" ; then
|
||||
|
||||
succeeded=no
|
||||
|
||||
# Extract the first word of "pkg-config", so it can be a program name with args.
|
||||
set dummy pkg-config; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if test "${ac_cv_path_PKG_CONFIG+set}" = set; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
case $PKG_CONFIG in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
|
||||
;;
|
||||
*)
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
PKG_CONFIG=$ac_cv_path_PKG_CONFIG
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
|
||||
$as_echo "$PKG_CONFIG" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test "$PKG_CONFIG" = "no" ; then
|
||||
HAVE_GNUTLS=no
|
||||
else
|
||||
PKG_CONFIG_MIN_VERSION=0.9.0
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gnutls >= 2.2.4" >&5
|
||||
$as_echo_n "checking for gnutls >= 2.2.4... " >&6; }
|
||||
|
||||
if $PKG_CONFIG --exists "gnutls >= 2.2.4" 2>&5; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
succeeded=yes
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking LIBGNUTLS_CFLAGS" >&5
|
||||
$as_echo_n "checking LIBGNUTLS_CFLAGS... " >&6; }
|
||||
LIBGNUTLS_CFLAGS=`$PKG_CONFIG --cflags "gnutls >= 2.2.4"|sed -e 's,///*,/,g'`
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBGNUTLS_CFLAGS" >&5
|
||||
$as_echo "$LIBGNUTLS_CFLAGS" >&6; }
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking LIBGNUTLS_LIBS" >&5
|
||||
$as_echo_n "checking LIBGNUTLS_LIBS... " >&6; }
|
||||
LIBGNUTLS_LIBS=`$PKG_CONFIG --libs "gnutls >= 2.2.4"|sed -e 's,///*,/,g'`
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBGNUTLS_LIBS" >&5
|
||||
$as_echo "$LIBGNUTLS_LIBS" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
LIBGNUTLS_CFLAGS=""
|
||||
LIBGNUTLS_LIBS=""
|
||||
## If we have a custom action on failure, don't print errors, but
|
||||
## do set a variable so people can do so.
|
||||
LIBGNUTLS_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "gnutls >= 2.2.4"`
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
else
|
||||
echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
|
||||
echo "*** See http://www.freedesktop.org/software/pkgconfig"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $succeeded = yes; then
|
||||
HAVE_GNUTLS=yes
|
||||
else
|
||||
HAVE_GNUTLS=no
|
||||
fi
|
||||
|
||||
if test "${HAVE_GNUTLS}" = "yes"; then
|
||||
$as_echo "#define HAVE_GNUTLS 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
HAVE_XAW3D=no
|
||||
LUCID_LIBW=
|
||||
if test x"${USE_X_TOOLKIT}" = xmaybe || test x"${USE_X_TOOLKIT}" = xLUCID; then
|
||||
|
@ -14849,10 +14965,13 @@ echo " Does Emacs use a gif library? ${HAVE_GIF} $LIB
|
|||
echo " Does Emacs use -lpng? ${HAVE_PNG}"
|
||||
echo " Does Emacs use -lrsvg-2? ${HAVE_RSVG}"
|
||||
echo " Does Emacs use imagemagick? ${HAVE_IMAGEMAGICK}"
|
||||
|
||||
echo " Does Emacs use -lgpm? ${HAVE_GPM}"
|
||||
echo " Does Emacs use -ldbus? ${HAVE_DBUS}"
|
||||
echo " Does Emacs use -lgconf? ${HAVE_GCONF}"
|
||||
echo " Does Emacs use -lselinux? ${HAVE_LIBSELINUX}"
|
||||
echo " Does Emacs use -lgnutls (BROKEN)? ${HAVE_GNUTLS}"
|
||||
echo " Does Emacs use -lxml2? ${HAVE_LIBXML2}"
|
||||
|
||||
echo " Does Emacs use -lfreetype? ${HAVE_FREETYPE}"
|
||||
echo " Does Emacs use -lm17n-flt? ${HAVE_M17N_FLT}"
|
||||
|
|
14
configure.in
14
configure.in
|
@ -171,6 +171,7 @@ OPTION_DEFAULT_ON([gpm],[don't use -lgpm for mouse support on a GNU/Linux consol
|
|||
OPTION_DEFAULT_ON([dbus],[don't compile with D-Bus support])
|
||||
OPTION_DEFAULT_ON([gconf],[don't compile with GConf support])
|
||||
OPTION_DEFAULT_ON([selinux],[don't compile with SELinux support])
|
||||
OPTION_DEFAULT_ON([gnutls],[don't use -lgnutls for SSL/TLS support])
|
||||
|
||||
## For the times when you want to build Emacs but don't have
|
||||
## a suitable makeinfo, and can live without the manuals.
|
||||
|
@ -1999,6 +2000,16 @@ if test "${with_selinux}" = "yes"; then
|
|||
fi
|
||||
AC_SUBST(LIBSELINUX_LIBS)
|
||||
|
||||
HAVE_GNUTLS=no
|
||||
if test "${with_gnutls}" = "yes" ; then
|
||||
PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 2.2.4], HAVE_GNUTLS=yes, HAVE_GNUTLS=no)
|
||||
if test "${HAVE_GNUTLS}" = "yes"; then
|
||||
AC_DEFINE(HAVE_GNUTLS)
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(LIBGNUTLS_LIBS)
|
||||
AC_SUBST(LIBGNUTLS_CFLAGS)
|
||||
|
||||
dnl Do not put whitespace before the #include statements below.
|
||||
dnl Older compilers (eg sunos4 cc) choke on it.
|
||||
HAVE_XAW3D=no
|
||||
|
@ -3696,10 +3707,13 @@ echo " Does Emacs use a gif library? ${HAVE_GIF} $LIB
|
|||
echo " Does Emacs use -lpng? ${HAVE_PNG}"
|
||||
echo " Does Emacs use -lrsvg-2? ${HAVE_RSVG}"
|
||||
echo " Does Emacs use imagemagick? ${HAVE_IMAGEMAGICK}"
|
||||
|
||||
echo " Does Emacs use -lgpm? ${HAVE_GPM}"
|
||||
echo " Does Emacs use -ldbus? ${HAVE_DBUS}"
|
||||
echo " Does Emacs use -lgconf? ${HAVE_GCONF}"
|
||||
echo " Does Emacs use -lselinux? ${HAVE_LIBSELINUX}"
|
||||
echo " Does Emacs use -lgnutls (BROKEN)? ${HAVE_GNUTLS}"
|
||||
echo " Does Emacs use -lxml2? ${HAVE_LIBXML2}"
|
||||
|
||||
echo " Does Emacs use -lfreetype? ${HAVE_FREETYPE}"
|
||||
echo " Does Emacs use -lm17n-flt? ${HAVE_M17N_FLT}"
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2010-09-21 Glenn Morris <rgm@gnu.org>
|
||||
|
||||
* cons-1.eps, cons-2.eps, cons-2a.eps, cons-3.eps, cons-4.eps:
|
||||
* cons-5.eps, lambda-1.eps, lambda-2.eps, lambda-3.eps:
|
||||
Add first line EPSF magic comment. (Bug#7064)
|
||||
|
||||
2010-06-23 Glenn Morris <rgm@gnu.org>
|
||||
|
||||
* emacs-lisp-intro.texi: Untabify.
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
%!
|
||||
%!PS-Adobe-3.0 EPSF-3.0
|
||||
%%BoundingBox: 35 711 289 757
|
||||
%%Title: cons-cell-diagram1
|
||||
%%CreationDate: Wed Mar 8 14:26:58 1995
|
||||
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
|
||||
%
|
||||
% Due to bugs in Transcript, the 'PS-Adobe-' stuff is omitted from line 1
|
||||
%
|
||||
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
% Free Software Foundation, Inc.
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
% 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
%
|
||||
% This file is part of GNU Emacs.
|
||||
%
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
%!
|
||||
%!PS-Adobe-3.0 EPSF-3.0
|
||||
%%BoundingBox: 15 712 321 775
|
||||
%%Title: cons-cell-diagram2
|
||||
%%CreationDate: Wed Mar 8 14:26:39 1995
|
||||
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
|
||||
%
|
||||
% Due to bugs in Transcript, the 'PS-Adobe-' stuff is omitted from line 1
|
||||
%
|
||||
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
% Free Software Foundation, Inc.
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
% 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
%
|
||||
% This file is part of GNU Emacs.
|
||||
%
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
%!
|
||||
%!PS-Adobe-3.0 EPSF-3.0
|
||||
%%BoundingBox: 15 702 300 767
|
||||
%%Title: cons-cell-diagram2a
|
||||
%%CreationDate: Tue Mar 14 15:09:30 1995
|
||||
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
|
||||
%
|
||||
% Due to bugs in Transcript, the 'PS-Adobe-' stuff is omitted from line 1
|
||||
%
|
||||
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
% Free Software Foundation, Inc.
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
% 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
%
|
||||
% This file is part of GNU Emacs.
|
||||
%
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
%!
|
||||
%!PS-Adobe-3.0 EPSF-3.0
|
||||
%%BoundingBox: -1 691 324 757
|
||||
%%Title: cons-cell-diagram3
|
||||
%%CreationDate: Wed Mar 8 14:25:41 1995
|
||||
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
|
||||
%
|
||||
% Due to bugs in Transcript, the 'PS-Adobe-' stuff is omitted from line 1
|
||||
%
|
||||
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
% Free Software Foundation, Inc.
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
% 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
%
|
||||
% This file is part of GNU Emacs.
|
||||
%
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
%!
|
||||
%!PS-Adobe-3.0 EPSF-3.0
|
||||
%%BoundingBox: 6 681 355 758
|
||||
%%Title: cons-cell-diagram4
|
||||
%%CreationDate: Wed Mar 8 14:25:06 1995
|
||||
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
|
||||
%
|
||||
% Due to bugs in Transcript, the 'PS-Adobe-' stuff is omitted from line 1
|
||||
%
|
||||
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
% Free Software Foundation, Inc.
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
% 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
%
|
||||
% This file is part of GNU Emacs.
|
||||
%
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
%!
|
||||
%!PS-Adobe-3.0 EPSF-3.0
|
||||
%%BoundingBox: 15 680 305 764
|
||||
%%Title: cons-cell-diagram5
|
||||
%%CreationDate: Wed Mar 8 14:27:28 1995
|
||||
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
|
||||
%
|
||||
% Due to bugs in Transcript, the 'PS-Adobe-' stuff is omitted from line 1
|
||||
%
|
||||
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
% Free Software Foundation, Inc.
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
% 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
%
|
||||
% This file is part of GNU Emacs.
|
||||
%
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
%!
|
||||
%!PS-Adobe-3.0 EPSF-3.0
|
||||
%%BoundingBox: 33 710 173 759
|
||||
%%Title: lambda-diagram1
|
||||
%%CreationDate: Wed Mar 8 14:31:53 1995
|
||||
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
|
||||
%
|
||||
% Due to bugs in Transcript, the 'PS-Adobe-' stuff is omitted from line 1
|
||||
%
|
||||
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
% Free Software Foundation, Inc.
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
% 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
%
|
||||
% This file is part of GNU Emacs.
|
||||
%
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
%!
|
||||
%!PS-Adobe-3.0 EPSF-3.0
|
||||
%%BoundingBox: 33 730 240 777
|
||||
%%Title: lambda-diagram2
|
||||
%%CreationDate: Wed Mar 8 14:33:09 1995
|
||||
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
|
||||
%
|
||||
% Due to bugs in Transcript, the 'PS-Adobe-' stuff is omitted from line 1
|
||||
%
|
||||
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
% Free Software Foundation, Inc.
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
% 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
%
|
||||
% This file is part of GNU Emacs.
|
||||
%
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
%!
|
||||
%!PS-Adobe-3.0 EPSF-3.0
|
||||
%%BoundingBox: 33 728 211 777
|
||||
%%Title: lambda-diagram3
|
||||
%%CreationDate: Wed Mar 8 14:33:49 1995
|
||||
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
|
||||
%
|
||||
% Due to bugs in Transcript, the 'PS-Adobe-' stuff is omitted from line 1
|
||||
%
|
||||
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
% Free Software Foundation, Inc.
|
||||
% Copyright (C) 1995, 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
% 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
%
|
||||
% This file is part of GNU Emacs.
|
||||
%
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2010-09-25 Ulrich Mueller <ulm@gentoo.org>
|
||||
|
||||
* etags.1: xz compression is now supported.
|
||||
|
||||
2010-08-26 Sven Joachim <svenjoac@gmx.de>
|
||||
|
||||
* emacs.1: Mention "maximized" value for the "fullscreen" X resource.
|
||||
|
|
|
@ -62,7 +62,7 @@ Files specified with absolute file names will be recorded
|
|||
with absolute file names. Files generated from a source file\-\-like
|
||||
a C file generated from a source Cweb file\-\-will be recorded with
|
||||
the name of the source file.
|
||||
Compressed files are supported using gzip and bzip2.
|
||||
Compressed files are supported using gzip, bzip2, and xz.
|
||||
The programs recognize the language used in an input file based on its
|
||||
file name and contents. The \fB\-\-language\fP switch can be used to force
|
||||
parsing of the file names following the switch according to the given
|
||||
|
|
|
@ -1,3 +1,60 @@
|
|||
2010-09-26 Lars Magne Ingebrigtsen <larsi@gnus.org>
|
||||
|
||||
* gnus-news.texi: Mention nnimap-inbox.
|
||||
|
||||
* gnus.texi (Picons): Document gnus-picon-inhibit-top-level-domains.
|
||||
|
||||
2010-09-26 Julien Danjou <julien@danjou.info>
|
||||
|
||||
* gnus.texi (Oort Gnus): Remove mention of ssl.el
|
||||
|
||||
2010-09-26 Lars Magne Ingebrigtsen <larsi@gnus.org>
|
||||
|
||||
* gnus.texi (Security): Remove gpg.el mention.
|
||||
|
||||
2010-09-26 Andreas Seltenreich <seltenreich@gmx.de>
|
||||
|
||||
* gnus.texi (Browse Foreign Server): New variable
|
||||
gnus-browse-subscribe-newsgroup-method.
|
||||
|
||||
* gnus-news.texi: Mention it.
|
||||
|
||||
2010-09-26 Lars Magne Ingebrigtsen <larsi@gnus.org>
|
||||
|
||||
* gnus.texi (NoCeM): Removed.
|
||||
(Startup Variables): No jingle.
|
||||
|
||||
2010-09-25 Ulrich Mueller <ulm@gentoo.org>
|
||||
|
||||
* woman.texi (Interface Options): xz compression is now supported.
|
||||
|
||||
2010-09-25 Lars Magne Ingebrigtsen <larsi@gnus.org>
|
||||
|
||||
* gnus.texi (Article Commands): Document gnus-fetch-partial-articles.
|
||||
(Unavailable Servers): Document gnus-server-copy-server.
|
||||
(Using IMAP): Document the new nnimap.
|
||||
|
||||
2010-09-25 Julien Danjou <julien@danjou.info>
|
||||
|
||||
* gnus.texi (Customizing Articles): Remove gnus-treat-translate
|
||||
|
||||
2010-09-24 Glenn Morris <rgm@gnu.org>
|
||||
|
||||
* url.texi (Disk Caching): Tweak previous change.
|
||||
|
||||
2010-09-24 Julien Danjou <julien@danjou.info>
|
||||
|
||||
* url.texi (Disk Caching): Mention url-cache-expire-time,
|
||||
url-cache-expired, and url-fetch-from-cache.
|
||||
|
||||
2010-09-24 Julien Danjou <julien@danjou.info>
|
||||
|
||||
* gnus.texi: Add Gravatars.
|
||||
|
||||
2010-09-23 Lars Magne Ingebrigtsen <larsi@gnus.org>
|
||||
|
||||
* gnus.texi (Startup Variables): Mention gnus-use-backend-marks.
|
||||
|
||||
2010-09-21 Lars Magne Ingebrigtsen <larsi@gnus.org>
|
||||
|
||||
* gnus.texi (Expunging mailboxes): Update name of the expunging
|
||||
|
|
|
@ -68,8 +68,10 @@ remove-installed-shadows}.
|
|||
|
||||
@item New version of @code{nnimap}
|
||||
|
||||
@code{nnimap} has been reimplemented in a mostly-compatible way.
|
||||
@c Mention any incompatibilities.
|
||||
@code{nnimap} has been reimplemented in a mostly-compatible way. See
|
||||
the Gnus manual for a description of the new interface. In
|
||||
particular, @code{nnimap-inbox} and the client side split method has
|
||||
changed.
|
||||
|
||||
@item Gnus includes the Emacs Lisp @acronym{SASL} library.
|
||||
|
||||
|
@ -103,6 +105,12 @@ EasyPG is included in Emacs 23 and available separately as well.
|
|||
@c ************************
|
||||
|
||||
@itemize @bullet
|
||||
|
||||
@item
|
||||
Symbols like @code{gcc-self} now has the same presedence rules in
|
||||
@code{gnus-parameters} as other ``real'' variables: The last match
|
||||
wins instead of the first match.
|
||||
|
||||
@item
|
||||
Old intermediate incoming mail files (@file{Incoming*}) are deleted
|
||||
after a couple of days, not immediately. @xref{Mail Source
|
||||
|
@ -246,6 +254,16 @@ of the "Whomever writes:" line. You need to set
|
|||
@code{message-insert-formatted-citation-line} as well.
|
||||
@end itemize
|
||||
|
||||
@item Changes in Browse Server mode
|
||||
|
||||
@itemize @bullet
|
||||
@item Gnus' sophisticated subscription methods are now available in
|
||||
Browse Server buffers as well using the variable
|
||||
@code{gnus-browse-subscribe-newsgroup-method}.
|
||||
|
||||
@end itemize
|
||||
|
||||
|
||||
@item Changes in back ends
|
||||
|
||||
@itemize @bullet
|
||||
|
@ -336,6 +354,8 @@ be unchanged except that the marks will be removed when copying or
|
|||
moving articles to a group that has not turned auto-expire on.
|
||||
@xref{Expiring Mail}.
|
||||
|
||||
@item NoCeM support has been removed.
|
||||
|
||||
@end itemize
|
||||
|
||||
@end itemize
|
||||
|
|
1234
doc/misc/gnus.texi
1234
doc/misc/gnus.texi
File diff suppressed because it is too large
Load diff
|
@ -1090,11 +1090,11 @@ the passphrase prompt.
|
|||
@subsection Using PGP/MIME
|
||||
|
||||
@acronym{PGP/MIME} requires an external OpenPGP implementation, such
|
||||
as @uref{http://www.gnupg.org/, GNU Privacy Guard}. Pre-OpenPGP
|
||||
implementations such as PGP 2.x and PGP 5.x are also supported. One
|
||||
as @uref{http://www.gnupg.org/, GNU Privacy Guard}. Pre-OpenPGP
|
||||
implementations such as PGP 2.x and PGP 5.x are also supported. One
|
||||
Emacs interface to the PGP implementations, PGG (@pxref{Top, ,PGG,
|
||||
pgg, PGG Manual}), is included, but Mailcrypt and Florian Weimer's
|
||||
@code{gpg.el} are also supported. @xref{PGP Compatibility}.
|
||||
pgg, PGG Manual}), is included, but Mailcrypt is also supported.
|
||||
@xref{PGP Compatibility}.
|
||||
|
||||
@cindex gpg-agent
|
||||
Message internally calls GnuPG (the @command{gpg} command) to perform
|
||||
|
|
|
@ -731,14 +731,6 @@ directory to store the cache files. It defaults to sub-directory
|
|||
@file{cache} of @code{url-configuration-directory}.
|
||||
@end defopt
|
||||
|
||||
@c Fixme: function v. option, but neither used.
|
||||
@c @findex url-cache-expired
|
||||
@c @defopt url-cache-expired
|
||||
@c This is a function to decide whether or not a cache entry has expired.
|
||||
@c It takes two times as it parameters and returns non-@code{nil} if the
|
||||
@c second time is ``too old'' when compared with the first time.
|
||||
@c @end defopt
|
||||
|
||||
@defopt url-cache-creation-function
|
||||
The cache relies on a scheme for mapping URLs to files in the cache.
|
||||
This variable names a function which sets the type of cache to use.
|
||||
|
@ -768,6 +760,22 @@ more likely to conflict with other files.
|
|||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@defun url-cache-expired
|
||||
This function returns non-nil if a cache entry has expired (or is absent).
|
||||
The arguments are a URL and optional expiration delay in seconds
|
||||
(default @var{url-cache-expire-time}).
|
||||
@end defun
|
||||
|
||||
@defopt url-cache-expire-time
|
||||
This variable is the default number of seconds to use for the
|
||||
expire-time argument of the function @code{url-cache-expired}.
|
||||
@end defopt
|
||||
|
||||
@defun url-fetch-from-cache
|
||||
This function takes a URL as its argument and returns a buffer
|
||||
containing the data cached for that URL.
|
||||
@end defun
|
||||
|
||||
@c Fixme: never actually used currently?
|
||||
@c @defopt url-standalone-mode
|
||||
@c @cindex Relying on cache
|
||||
|
|
|
@ -1121,8 +1121,8 @@ A regular match expression used to match compressed man file extensions
|
|||
for which decompressors are available and handled by auto-compression
|
||||
mode. It should begin with @code{\\.} and end with @code{\\'} and
|
||||
@emph{must not} be optional. The default value is
|
||||
@code{"\\.\\(g?z\\|bz2\\)\\'"}, which matches the @code{gzip} and
|
||||
@code{bzip2} compression extensions.
|
||||
@code{"\\.\\(g?z\\|bz2\\|xz\\)\\'"}, which matches the @code{gzip},
|
||||
@code{bzip2}, and @code{xz} compression extensions.
|
||||
|
||||
@emph{Do not change this unless you are sure you know what you are doing!}
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2010-09-21 Eric Ludlam <zappo@gnu.org>
|
||||
|
||||
* srecode/java.srt: Make NAME be a prompt.
|
||||
|
||||
2010-09-13 Michael Albinus <michael.albinus@gmx.de>
|
||||
|
||||
* NEWS: Some Tramp methods are discontinued.
|
||||
|
|
11
etc/NEWS
11
etc/NEWS
|
@ -561,10 +561,13 @@ by the Graphic Control Extension of the image.
|
|||
** XML and HTML parsing
|
||||
|
||||
*** If Emacs is compiled with libxml2 support (which is the default),
|
||||
two new Emacs Lisp-level functions are defined: `html-parse-string'
|
||||
(which will parse "real world" HTML) and `xml-parse-string' (which
|
||||
parses XML). Both return an Emacs Lisp parse tree. See the Emacs
|
||||
Lisp Reference Manual for details.
|
||||
two new Emacs Lisp-level functions are defined:
|
||||
`xml-parse-html-string-internal' (which will parse "real world" HTML)
|
||||
and `xml-parse-string-internal' (which parses XML). Both return an
|
||||
Emacs Lisp parse tree.
|
||||
|
||||
FIXME: These should be front-ended by xml.el.
|
||||
|
||||
|
||||
** Isearch
|
||||
|
||||
|
|
|
@ -40,6 +40,8 @@ This can be used in place of the default appt-message-warning-time.
|
|||
|
||||
* Lisp changes in Emacs 23.3
|
||||
|
||||
** `e' and `pi' are now called `float-e' and `float-pi'.
|
||||
The old names are obsolete.
|
||||
** The use of unintern without an obarray arg is declared obsolete.
|
||||
|
||||
** New function byte-to-string, like char-to-string but for bytes.
|
||||
|
|
|
@ -83,7 +83,7 @@ public Class {{?NAME}} {{#PARENTS}}{{#FIRST}}extends {{/FIRST}}{{#NOTFIRST}}impl
|
|||
template include :blank
|
||||
"An include statement."
|
||||
----
|
||||
import {{NAME}};
|
||||
import {{?NAME}};
|
||||
----
|
||||
|
||||
context misc
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2010-09-25 Ulrich Mueller <ulm@gentoo.org>
|
||||
|
||||
* etags.c (compressors, print_language_names): Support xz compression.
|
||||
|
||||
2010-08-11 Jan Djärv <jan.h.d@swipnet.se>
|
||||
|
||||
* fakemail.c: Include stdlib.h for getenv. Remove declaration of
|
||||
|
|
|
@ -561,6 +561,7 @@ static compressor compressors[] =
|
|||
{ "gz", "gzip -d -c"},
|
||||
{ "GZ", "gzip -d -c"},
|
||||
{ "bz2", "bzip2 -d -c" },
|
||||
{ "xz", "xz -d -c" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -874,7 +875,7 @@ followed by the name of an interpreter. If no such sequence is found,\n\
|
|||
Fortran is tried first; if no tags are found, C is tried next.\n\
|
||||
When parsing any C file, a \"class\" or \"template\" keyword\n\
|
||||
switches to C++.");
|
||||
puts ("Compressed files are supported using gzip and bzip2.\n\
|
||||
puts ("Compressed files are supported using gzip, bzip2, and xz.\n\
|
||||
\n\
|
||||
For detailed help on a given language use, for example,\n\
|
||||
etags --help --lang=ada.");
|
||||
|
|
1174
lisp/ChangeLog
1174
lisp/ChangeLog
File diff suppressed because it is too large
Load diff
|
@ -1140,7 +1140,7 @@
|
|||
(rcirc-keepalive-seconds): Remove variable.
|
||||
(rcirc-server-name, rcirc-timeout-timer, rcirc-connecting)
|
||||
(rcirc-process, rcirc-user-disconnect): New variables.
|
||||
(rcirc-connect): Initalize new variables.
|
||||
(rcirc-connect): Initialize new variables.
|
||||
(rcirc-keepalive): Don't send keepalive pings before connection
|
||||
is completed.
|
||||
(rcirc-sentinel): Do mark all channels with activity when
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2009-02-07 Dave Love <fx@gnu.org>
|
||||
|
||||
* net/tls.el (open-tls-stream): Don't query killing process.
|
||||
|
||||
2009-06-21 Chong Yidong <cyd@stupidchicken.com>
|
||||
|
||||
* Branch for 23.1.
|
||||
|
|
|
@ -8121,7 +8121,7 @@
|
|||
* dired.el (dired-get-filename): Return filename verbatim if
|
||||
LOCALP is `verbatim'.
|
||||
* dired-aux.el (dired-add-entry): Call `dired-get-filename' with
|
||||
`verbatim' so that we don't inadvertently delete a non-existant
|
||||
`verbatim' so that we don't inadvertently delete a non-existent
|
||||
directory name.
|
||||
|
||||
2000-11-27 Kenichi Handa <handa@etl.go.jp>
|
||||
|
|
|
@ -369,7 +369,8 @@ documentation for an example.")
|
|||
Used for repeating operations in calculator-repR/L.")
|
||||
|
||||
(defvar calculator-registers ; use user-bindings first
|
||||
(append calculator-user-registers (list (cons ?e e) (cons ?p pi)))
|
||||
(append calculator-user-registers
|
||||
(list (cons ?e float-e) (cons ?p float-pi)))
|
||||
"The association list of calculator register values.")
|
||||
|
||||
(defvar calculator-saved-global-map nil
|
||||
|
@ -1300,7 +1301,7 @@ arguments."
|
|||
(calculator-funcall __f__ x y))))
|
||||
(fset 'D (function
|
||||
(lambda (x)
|
||||
(if calculator-deg (/ (* x 180) pi) x))))
|
||||
(if calculator-deg (/ (* x 180) float-pi) x))))
|
||||
(unwind-protect (eval f)
|
||||
(if Fbound (fset 'F Fsave) (fmakunbound 'F))
|
||||
(if Dbound (fset 'D Dsave) (fmakunbound 'D)))))
|
||||
|
|
|
@ -334,30 +334,42 @@ displayed in a window:
|
|||
(if (or force ; eg initialize, diary save
|
||||
(null appt-prev-comp-time) ; first check
|
||||
(< cur-comp-time appt-prev-comp-time)) ; new day
|
||||
(condition-case nil
|
||||
(if appt-display-diary
|
||||
(let ((diary-hook
|
||||
(if (assoc 'appt-make-list diary-hook)
|
||||
diary-hook
|
||||
(cons 'appt-make-list diary-hook))))
|
||||
(diary))
|
||||
(let* ((diary-display-function 'appt-make-list)
|
||||
(d-buff (find-buffer-visiting diary-file))
|
||||
(selective
|
||||
(if d-buff ; diary buffer exists
|
||||
(with-current-buffer d-buff
|
||||
diary-selective-display))))
|
||||
;; FIXME why not using diary-list-entries with
|
||||
;; non-nil LIST-ONLY?
|
||||
(diary)
|
||||
;; If the diary buffer existed before this command,
|
||||
;; restore its display state. Otherwise, kill it.
|
||||
(if d-buff
|
||||
;; Displays the diary buffer.
|
||||
(or selective (diary-show-all-entries))
|
||||
(and (setq d-buff (find-buffer-visiting diary-file))
|
||||
(kill-buffer d-buff)))))
|
||||
(error nil)))
|
||||
(ignore-errors
|
||||
(if appt-display-diary
|
||||
(let ((diary-hook
|
||||
(if (assoc 'appt-make-list diary-hook)
|
||||
diary-hook
|
||||
(cons 'appt-make-list diary-hook))))
|
||||
(diary))
|
||||
(let* ((diary-display-function 'appt-make-list)
|
||||
(d-buff (find-buffer-visiting diary-file))
|
||||
(selective
|
||||
(if d-buff ; diary buffer exists
|
||||
(with-current-buffer d-buff
|
||||
diary-selective-display)))
|
||||
d-buff2)
|
||||
;; Not displaying the diary, so we can ignore
|
||||
;; diary-number-of-entries. Since appt.el only
|
||||
;; works on a daily basis, no need for more entries.
|
||||
;; FIXME why not using diary-list-entries with
|
||||
;; non-nil LIST-ONLY?
|
||||
(diary 1)
|
||||
;; If the diary buffer existed before this command,
|
||||
;; restore its display state. Otherwise, kill it.
|
||||
(and (setq d-buff2 (find-buffer-visiting diary-file))
|
||||
(if d-buff
|
||||
(or selective
|
||||
(with-current-buffer d-buff2
|
||||
(if diary-selective-display
|
||||
;; diary-show-all-entries displays
|
||||
;; the diary buffer.
|
||||
(diary-unhide-everything))))
|
||||
;; FIXME does not kill any included diary files.
|
||||
;; The real issue is that (diary) should not
|
||||
;; have the side effect of visiting all the
|
||||
;; diary files. It is not really appt.el's job to
|
||||
;; clean up this mess...
|
||||
(kill-buffer d-buff2)))))))
|
||||
(setq appt-prev-comp-time cur-comp-time
|
||||
appt-mode-string nil
|
||||
appt-display-count nil)
|
||||
|
@ -573,6 +585,17 @@ appointment package (if it is not already active)."
|
|||
(let ((entry-list diary-entries-list)
|
||||
(new-time-string "")
|
||||
time-string)
|
||||
;; Below, we assume diary-entries-list was in date
|
||||
;; order. It is, unless something on
|
||||
;; diary-list-entries-hook has changed it, eg
|
||||
;; diary-include-other-files (bug#7019). It must be
|
||||
;; in date order if number = 1.
|
||||
(and diary-list-entries-hook
|
||||
appt-display-diary
|
||||
(not (eq diary-number-of-entries 1))
|
||||
(not (memq (car (last diary-list-entries-hook))
|
||||
'(diary-sort-entries sort-diary-entries)))
|
||||
(setq entry-list (sort entry-list 'diary-entry-compare)))
|
||||
;; Skip diary entries for dates before today.
|
||||
(while (and entry-list
|
||||
(calendar-date-compare
|
||||
|
|
|
@ -711,14 +711,26 @@ The arguments are DATE and NUMBER; the entries selected are those
|
|||
for NUMBER days starting with date DATE. The other entries are hidden
|
||||
using overlays. If NUMBER is less than 1, this function does nothing.
|
||||
|
||||
Returns a list of all relevant diary entries found, if any, in order by date.
|
||||
Returns a list of all relevant diary entries found.
|
||||
The list entries have the form ((MONTH DAY YEAR) STRING SPECIFIER) where
|
||||
\(MONTH DAY YEAR) is the date of the entry, STRING is the entry text, and
|
||||
SPECIFIER is the applicability. If the variable `diary-list-include-blanks'
|
||||
is non-nil, this list includes a dummy diary entry consisting of the empty
|
||||
string for a date with no diary entries.
|
||||
|
||||
After the list is prepared, the following hooks are run:
|
||||
If entries are being produced for multiple dates (i.e., NUMBER > 1),
|
||||
then this function normally returns the entries from any given
|
||||
diary file in date order. The entries for any given day are in
|
||||
the order in which they were found in the file, not necessarily
|
||||
in time-of-day order. Note that any functions present on the
|
||||
hooks (see below) may add entries, or change the order. For
|
||||
example, `diary-include-other-diary-files' adds entries from any
|
||||
include files that it finds to the end of the original list. The
|
||||
entries from each file will be in date order, but the overall
|
||||
list will not be. If you want the entire list to be in time order,
|
||||
add `diary-sort-entries' to the end of `diary-list-entries-hook'.
|
||||
|
||||
After the initial list is prepared, the following hooks are run:
|
||||
|
||||
`diary-nongregorian-listing-hook' can cull dates from the diary
|
||||
and each included file, for example to process Islamic diary
|
||||
|
|
|
@ -753,12 +753,12 @@ The values of `calendar-daylight-savings-starts',
|
|||
(sin (mod
|
||||
(+ (cadr x)
|
||||
(* (nth 2 x) U))
|
||||
(* 2 pi)))))
|
||||
(* 2 float-pi)))))
|
||||
solar-data-list)))))
|
||||
(aberration
|
||||
(* 0.0000001 (- (* 17 (cos (+ 3.10 (* 62830.14 U)))) 973)))
|
||||
(A1 (mod (+ 2.18 (* U (+ -3375.70 (* 0.36 U)))) (* 2 pi)))
|
||||
(A2 (mod (+ 3.51 (* U (+ 125666.39 (* 0.10 U)))) (* 2 pi)))
|
||||
(A1 (mod (+ 2.18 (* U (+ -3375.70 (* 0.36 U)))) (* 2 float-pi)))
|
||||
(A2 (mod (+ 3.51 (* U (+ 125666.39 (* 0.10 U)))) (* 2 float-pi)))
|
||||
(nutation (* -0.0000001 (+ (* 834 (sin A1)) (* 64 (sin A2))))))
|
||||
(mod (radians-to-degrees (+ longitude aberration nutation)) 360.0)))
|
||||
|
||||
|
|
|
@ -97,20 +97,20 @@ and type 2 is the list (HIGH LOW MICRO)."
|
|||
(autoload 'timezone-make-date-arpa-standard "timezone")
|
||||
|
||||
;;;###autoload
|
||||
;; `parse-time-string' isn't sufficiently general or robust. It fails
|
||||
;; to grok some of the formats that timezone does (e.g. dodgy
|
||||
;; post-2000 stuff from some Elms) and either fails or returns bogus
|
||||
;; values. timezone-make-date-arpa-standard should help.
|
||||
(defun date-to-time (date)
|
||||
"Parse a string DATE that represents a date-time and return a time value.
|
||||
If DATE lacks timezone information, GMT is assumed."
|
||||
(condition-case ()
|
||||
(apply 'encode-time
|
||||
(parse-time-string
|
||||
;; `parse-time-string' isn't sufficiently general or
|
||||
;; robust. It fails to grok some of the formats that
|
||||
;; timezone does (e.g. dodgy post-2000 stuff from some
|
||||
;; Elms) and either fails or returns bogus values. Lars
|
||||
;; reverted this change, but that loses non-trivially
|
||||
;; often for me. -- fx
|
||||
(timezone-make-date-arpa-standard date)))
|
||||
(error (error "Invalid date: %s" date))))
|
||||
(apply 'encode-time (parse-time-string date))
|
||||
(error (condition-case ()
|
||||
(apply 'encode-time
|
||||
(parse-time-string
|
||||
(timezone-make-date-arpa-standard date)))
|
||||
(error (error "Invalid date: %s" date))))))
|
||||
|
||||
;; Bit of a mess. Emacs has float-time since at least 21.1.
|
||||
;; This file is synced to Gnus, and XEmacs packages may have been written
|
||||
|
@ -317,10 +317,10 @@ This function does not work for SECONDS greater than `most-positive-fixnum'."
|
|||
(setq start (match-end 0)
|
||||
spec (match-string 1 string))
|
||||
(unless (string-equal spec "%")
|
||||
;; `assoc-string' is not available in XEmacs or Emacs 21. So when
|
||||
;; compiling Gnus (`time-date.el' is part of Gnus) with XEmacs or
|
||||
;; Emacs 21, we get a warning here. But `format-seconds' is not
|
||||
;; used anywhere in Gnus so it's not a real problem. --rsteib
|
||||
;; `assoc-string' is not available in XEmacs. So when compiling
|
||||
;; Gnus (`time-date.el' is part of Gnus) with XEmacs, we get
|
||||
;; a warning here. But `format-seconds' is not used anywhere in
|
||||
;; Gnus so it's not a real problem. --rsteib
|
||||
(or (setq match (assoc-string spec units t))
|
||||
(error "Bad format specifier: `%s'" spec))
|
||||
(if (assoc-string spec usedunits t)
|
||||
|
|
1452
lisp/cedet/ChangeLog
Normal file
1452
lisp/cedet/ChangeLog
Normal file
File diff suppressed because it is too large
Load diff
|
@ -73,6 +73,12 @@ SCOPE is the scope of the search, such as 'project or 'subdirs."
|
|||
)
|
||||
(cedet-cscope-call (list "-d" "-L" idx searchtext))))
|
||||
|
||||
(defun cedet-cscope-create (flags)
|
||||
"Create a CScope database at the current directory.
|
||||
FLAGS are additional flags to pass to cscope beyond the
|
||||
options -cR."
|
||||
(cedet-cscope-call (append (list "-cR") flags)))
|
||||
|
||||
(defun cedet-cscope-call (flags)
|
||||
"Call CScope with the list of FLAGS."
|
||||
(let ((b (get-buffer-create "*CEDET CScope*"))
|
||||
|
@ -113,13 +119,19 @@ Return a fully qualified filename."
|
|||
If DIR is not supplied, use the current default directory.
|
||||
This works by running cscope on a bogus symbol, and looking for
|
||||
the error code."
|
||||
(interactive "DDirectory: ")
|
||||
(save-excursion
|
||||
(let ((default-directory (or dir default-directory)))
|
||||
(set-buffer (cedet-cscope-call (list "-d" "-L" "-7" "moose")))
|
||||
(goto-char (point-min))
|
||||
(if (looking-at "[^ \n]*cscope: ")
|
||||
nil
|
||||
t))))
|
||||
(let ((ans (looking-at "[^ \n]*cscope: ")))
|
||||
(if (called-interactively-p 'interactive)
|
||||
(if ans
|
||||
(message "No support for CScope in %s" default-directory)
|
||||
(message "CScope is supported in %s" default-directory))
|
||||
(if ans
|
||||
nil
|
||||
t))))))
|
||||
|
||||
(defun cedet-cscope-version-check (&optional noerror)
|
||||
"Check the version of the installed CScope command.
|
||||
|
@ -151,6 +163,14 @@ return nil."
|
|||
(message "CScope %s - Good enough for CEDET." rev))
|
||||
t)))))
|
||||
|
||||
(defun cedet-cscope-create/update-database (&optional dir)
|
||||
"Create a CScope database in DIR.
|
||||
CScope will automatically choose incremental rebuild if
|
||||
there is already a database in DIR."
|
||||
(interactive "DDirectory: ")
|
||||
(let ((default-directory dir))
|
||||
(cedet-cscope-create nil)))
|
||||
|
||||
(provide 'cedet-cscope)
|
||||
|
||||
;; arch-tag: 9973f1ad-f13b-4399-bc67-7f488478d78d
|
||||
|
|
|
@ -34,6 +34,12 @@
|
|||
:type 'string
|
||||
:group 'cedet)
|
||||
|
||||
(defcustom cedet-global-gtags-command "gtags"
|
||||
"Command name for the GNU Global gtags executable.
|
||||
GTAGS is used to create the tags table queried by the 'global' command."
|
||||
:type 'string
|
||||
:group 'cedet)
|
||||
|
||||
;;; Code:
|
||||
(defun cedet-gnu-global-search (searchtext texttype type scope)
|
||||
"Perform a search with GNU Global, return the created buffer.
|
||||
|
@ -76,6 +82,19 @@ SCOPE is the scope of the search, such as 'project or 'subdirs."
|
|||
flags)
|
||||
b))
|
||||
|
||||
(defun cedet-gnu-global-gtags-call (flags)
|
||||
"Create GNU Global TAGS using gtags with FLAGS."
|
||||
(let ((b (get-buffer-create "*CEDET Global gtags*"))
|
||||
(cd default-directory)
|
||||
)
|
||||
(with-current-buffer b
|
||||
(setq default-directory cd)
|
||||
(erase-buffer))
|
||||
(apply 'call-process cedet-global-gtags-command
|
||||
nil b nil
|
||||
flags)
|
||||
b))
|
||||
|
||||
(defun cedet-gnu-global-expand-filename (filename)
|
||||
"Expand the FILENAME with GNU Global.
|
||||
Return a fully qualified filename."
|
||||
|
@ -153,6 +172,18 @@ return nil."
|
|||
;; Return the results
|
||||
(nreverse hits))))
|
||||
|
||||
(defun cedet-gnu-global-create/update-database (&optional dir)
|
||||
"Create a GNU Global database in DIR.
|
||||
If a database already exists, then just update it."
|
||||
(interactive "DDirectory: ")
|
||||
(let ((root (cedet-gnu-global-root dir)))
|
||||
(if root (setq dir root))
|
||||
(let ((default-directory dir))
|
||||
(cedet-gnu-global-gtags-call
|
||||
(when root
|
||||
'("-i");; Incremental update flag.
|
||||
)))))
|
||||
|
||||
(provide 'cedet-global)
|
||||
|
||||
;; arch-tag: 0d0d3ac2-91ef-4820-bb2b-1d59ccf38392
|
||||
|
|
|
@ -44,6 +44,11 @@
|
|||
:type 'string
|
||||
:group 'cedet)
|
||||
|
||||
(defcustom cedet-idutils-make-command "mkid"
|
||||
"Command name for the ID Utils executable for creating token databases."
|
||||
:type 'string
|
||||
:group 'cedet)
|
||||
|
||||
(defun cedet-idutils-search (searchtext texttype type scope)
|
||||
"Perform a search with ID Utils, return the created buffer.
|
||||
SEARCHTEXT is text to find.
|
||||
|
@ -105,6 +110,20 @@ Return the created buffer with with program output."
|
|||
flags)
|
||||
b))
|
||||
|
||||
(defun cedet-idutils-mkid-call (flags)
|
||||
"Call ID Utils mkid with the list of FLAGS.
|
||||
Return the created buffer with with program output."
|
||||
(let ((b (get-buffer-create "*CEDET mkid*"))
|
||||
(cd default-directory)
|
||||
)
|
||||
(with-current-buffer b
|
||||
(setq default-directory cd)
|
||||
(erase-buffer))
|
||||
(apply 'call-process cedet-idutils-make-command
|
||||
nil b nil
|
||||
flags)
|
||||
b))
|
||||
|
||||
;;; UTIL CALLS
|
||||
;;
|
||||
(defun cedet-idutils-expand-filename (filename)
|
||||
|
@ -172,6 +191,12 @@ return nil."
|
|||
(message "ID Utils %s - Good enough for CEDET." rev))
|
||||
t)))))
|
||||
|
||||
(defun cedet-idutils-create/update-database (&optional dir)
|
||||
"Create an IDUtils database in DIR.
|
||||
IDUtils must start from scratch when updating a database."
|
||||
(interactive "DDirectory: ")
|
||||
(let ((default-directory dir))
|
||||
(cedet-idutils-mkid-call nil)))
|
||||
|
||||
(provide 'cedet-idutils)
|
||||
|
||||
|
|
|
@ -36,19 +36,19 @@
|
|||
|
||||
(declare-function inversion-find-version "inversion")
|
||||
|
||||
(defconst cedet-version "1.0pre7"
|
||||
(defconst cedet-version "1.0"
|
||||
"Current version of CEDET.")
|
||||
|
||||
(defconst cedet-packages
|
||||
`(
|
||||
;;PACKAGE MIN-VERSION
|
||||
(cedet ,cedet-version)
|
||||
(eieio "1.2")
|
||||
(semantic "2.0pre7")
|
||||
(srecode "1.0pre7")
|
||||
(ede "1.0pre7")
|
||||
(speedbar "1.0.3"))
|
||||
"Table of CEDET packages to install.")
|
||||
(eieio "1.3")
|
||||
(semantic "2.0")
|
||||
(srecode "1.0")
|
||||
(ede "1.0")
|
||||
(speedbar "1.0"))
|
||||
"Table of CEDET packages installed.")
|
||||
|
||||
(defvar cedet-menu-map ;(make-sparse-keymap "CEDET menu")
|
||||
(let ((map (make-sparse-keymap "CEDET menu")))
|
||||
|
|
File diff suppressed because it is too large
Load diff
128
lisp/cedet/ede/auto.el
Normal file
128
lisp/cedet/ede/auto.el
Normal file
|
@ -0,0 +1,128 @@
|
|||
;;; ede/auto.el --- Autoload features for EDE
|
||||
|
||||
;; Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Eric M. Ludlam <zappo@gnu.org>
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs 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 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; EDE Autoloads are a way to refer to different project types without
|
||||
;; loading those projects into Emacs.
|
||||
;;
|
||||
;; These routines are used to detect a project in a filesystem before
|
||||
;; handing over control to the usual EDE project system.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'eieio)
|
||||
|
||||
(defclass ede-project-autoload ()
|
||||
((name :initarg :name
|
||||
:documentation "Name of this project type")
|
||||
(file :initarg :file
|
||||
:documentation "The lisp file belonging to this class.")
|
||||
(proj-file :initarg :proj-file
|
||||
:documentation "Name of a project file of this type.")
|
||||
(proj-root :initarg :proj-root
|
||||
:type function
|
||||
:documentation "A function symbol to call for the project root.
|
||||
This function takes no arguments, and returns the current directories
|
||||
root, if available. Leave blank to use the EDE directory walking
|
||||
routine instead.")
|
||||
(initializers :initarg :initializers
|
||||
:initform nil
|
||||
:documentation
|
||||
"Initializers passed to the project object.
|
||||
These are used so there can be multiple types of projects
|
||||
associated with a single object class, based on the initilizeres used.")
|
||||
(load-type :initarg :load-type
|
||||
:documentation "Fn symbol used to load this project file.")
|
||||
(class-sym :initarg :class-sym
|
||||
:documentation "Symbol representing the project class to use.")
|
||||
(new-p :initarg :new-p
|
||||
:initform t
|
||||
:documentation
|
||||
"Non-nil if this is an option when a user creates a project.")
|
||||
)
|
||||
"Class representing minimal knowledge set to run preliminary EDE functions.
|
||||
When more advanced functionality is needed from a project type, that projects
|
||||
type is required and the load function used.")
|
||||
|
||||
(defvar ede-project-class-files
|
||||
(list
|
||||
(ede-project-autoload "edeproject-makefile"
|
||||
:name "Make" :file 'ede/proj
|
||||
:proj-file "Project.ede"
|
||||
:load-type 'ede-proj-load
|
||||
:class-sym 'ede-proj-project)
|
||||
(ede-project-autoload "edeproject-automake"
|
||||
:name "Automake" :file 'ede/proj
|
||||
:proj-file "Project.ede"
|
||||
:initializers '(:makefile-type Makefile.am)
|
||||
:load-type 'ede-proj-load
|
||||
:class-sym 'ede-proj-project)
|
||||
(ede-project-autoload "automake"
|
||||
:name "automake" :file 'ede/project-am
|
||||
:proj-file "Makefile.am"
|
||||
:load-type 'project-am-load
|
||||
:class-sym 'project-am-makefile
|
||||
:new-p nil))
|
||||
"List of vectors defining how to determine what type of projects exist.")
|
||||
|
||||
;;; EDE project-autoload methods
|
||||
;;
|
||||
(defmethod ede-project-root ((this ede-project-autoload))
|
||||
"If a project knows its root, return it here.
|
||||
Allows for one-project-object-for-a-tree type systems."
|
||||
nil)
|
||||
|
||||
(defmethod ede-project-root-directory ((this ede-project-autoload)
|
||||
&optional file)
|
||||
"If a project knows its root, return it here.
|
||||
Allows for one-project-object-for-a-tree type systems.
|
||||
Optional FILE is the file to test. If there is no FILE, use
|
||||
the current buffer."
|
||||
(when (not file)
|
||||
(setq file default-directory))
|
||||
(when (slot-boundp this :proj-root)
|
||||
(let ((rootfcn (oref this proj-root)))
|
||||
(when rootfcn
|
||||
(condition-case nil
|
||||
(funcall rootfcn file)
|
||||
(error
|
||||
(funcall rootfcn)))
|
||||
))))
|
||||
|
||||
(defmethod ede-dir-to-projectfile ((this ede-project-autoload) dir)
|
||||
"Return a full file name of project THIS found in DIR.
|
||||
Return nil if the project file does not exist."
|
||||
(let* ((d (file-name-as-directory dir))
|
||||
(root (ede-project-root-directory this d))
|
||||
(pf (oref this proj-file))
|
||||
(f (cond ((stringp pf)
|
||||
(expand-file-name pf (or root d)))
|
||||
((and (symbolp pf) (fboundp pf))
|
||||
(funcall pf (or root d)))))
|
||||
)
|
||||
(when (and f (file-exists-p f))
|
||||
f)))
|
||||
|
||||
|
||||
(provide 'ede/auto)
|
||||
|
||||
;;; ede/auto.el ends here
|
|
@ -27,20 +27,8 @@
|
|||
|
||||
;;; Code:
|
||||
(require 'autoconf)
|
||||
|
||||
(defvar autoconf-new-automake-string
|
||||
"dnl Process this file with autoconf to produce a configure script
|
||||
|
||||
AC_INIT(%s)
|
||||
AM_INIT_AUTOMAKE([%s], 0)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
dnl End the configure script.
|
||||
AC_OUTPUT(Makefile, [date > stamp-h] )\n"
|
||||
"This string is used to initialize a new configure.in.
|
||||
The default is designed to be used with automake.
|
||||
The first %s will be filled with the test file.
|
||||
The second %s will be filled with the program name.")
|
||||
(declare-function ede-srecode-setup "ede/srecode")
|
||||
(declare-function ede-srecode-insert "ede/srecode")
|
||||
|
||||
(defun autoconf-new-program (rootdir program testfile)
|
||||
"Initialize a new configure.in in ROOTDIR for PROGRAM using TESTFILE.
|
||||
|
@ -49,6 +37,7 @@ PROGRAM is the program to be configured.
|
|||
TESTFILE is the file used with AC_INIT.
|
||||
configure the initial configure script using `autoconf-new-automake-string'"
|
||||
(interactive "DRoot Dir: \nsProgram: \nsTest File: ")
|
||||
(require 'ede/srecode)
|
||||
(if (bufferp rootdir)
|
||||
(set-buffer rootdir)
|
||||
(let ((cf1 (expand-file-name "configure.in" rootdir))
|
||||
|
@ -62,7 +51,12 @@ configure the initial configure script using `autoconf-new-automake-string'"
|
|||
(find-file cf2)))
|
||||
;; Note, we only ask about overwrite if a string/path is specified.
|
||||
(erase-buffer)
|
||||
(insert (format autoconf-new-automake-string testfile program)))
|
||||
(ede-srecode-setup)
|
||||
(ede-srecode-insert
|
||||
"file:ede-empty"
|
||||
"TEST_FILE" testfile
|
||||
"PROGRAM" program)
|
||||
)
|
||||
|
||||
(defvar autoconf-preferred-macro-order
|
||||
'("AC_INIT"
|
||||
|
@ -151,42 +145,44 @@ From the autoconf manual:
|
|||
(beginning-of-line)
|
||||
(looking-at (concat "\\(A[CM]_" macro "\\|" macro "\\)"))))
|
||||
|
||||
(defun autoconf-find-last-macro (macro)
|
||||
(defun autoconf-find-last-macro (macro &optional ignore-bol)
|
||||
"Move to the last occurrence of MACRO in FILE, and return that point.
|
||||
The last macro is usually the one in which we would like to insert more
|
||||
items such as CHECK_HEADERS."
|
||||
(let ((op (point)))
|
||||
(let ((op (point)) (atbol (if ignore-bol "" "^")))
|
||||
(goto-char (point-max))
|
||||
(if (re-search-backward (concat "^" (regexp-quote macro) "\\s-*\\((\\|$\\)") nil t)
|
||||
(if (re-search-backward (concat atbol (regexp-quote macro) "\\s-*\\((\\|$\\)") nil t)
|
||||
(progn
|
||||
(beginning-of-line)
|
||||
(unless ignore-bol (beginning-of-line))
|
||||
(point))
|
||||
(goto-char op)
|
||||
nil)))
|
||||
|
||||
(defun autoconf-parameter-strip (param)
|
||||
"Strip the parameter PARAM of whitespace and miscellaneous characters."
|
||||
(when (string-match "^\\s-*\\[?\\s-*" param)
|
||||
;; force greedy match for \n.
|
||||
(when (string-match "\\`\n*\\s-*\\[?\\s-*" param)
|
||||
(setq param (substring param (match-end 0))))
|
||||
(when (string-match "\\s-*\\]?\\s-*$" param)
|
||||
(when (string-match "\\s-*\\]?\\s-*\\'" param)
|
||||
(setq param (substring param 0 (match-beginning 0))))
|
||||
param)
|
||||
|
||||
(defun autoconf-parameters-for-macro (macro)
|
||||
(defun autoconf-parameters-for-macro (macro &optional ignore-bol ignore-case)
|
||||
"Retrieve the parameters to MACRO.
|
||||
Returns a list of the arguments passed into MACRO as strings."
|
||||
(save-excursion
|
||||
(when (autoconf-find-last-macro macro)
|
||||
(forward-sexp 1)
|
||||
(mapcar
|
||||
#'autoconf-parameter-strip
|
||||
(when (looking-at "(")
|
||||
(let* ((start (+ (point) 1))
|
||||
(end (save-excursion
|
||||
(forward-sexp 1)
|
||||
(- (point) 1)))
|
||||
(ans (buffer-substring-no-properties start end)))
|
||||
(split-string ans "," t)))))))
|
||||
(let ((case-fold-search ignore-case))
|
||||
(save-excursion
|
||||
(when (autoconf-find-last-macro macro ignore-bol)
|
||||
(forward-sexp 1)
|
||||
(mapcar
|
||||
#'autoconf-parameter-strip
|
||||
(when (looking-at "(")
|
||||
(let* ((start (+ (point) 1))
|
||||
(end (save-excursion
|
||||
(forward-sexp 1)
|
||||
(- (point) 1)))
|
||||
(ans (buffer-substring-no-properties start end)))
|
||||
(split-string ans "," t))))))))
|
||||
|
||||
(defun autoconf-position-for-macro (macro)
|
||||
"Position the cursor where a new MACRO could be inserted.
|
||||
|
|
636
lisp/cedet/ede/base.el
Normal file
636
lisp/cedet/ede/base.el
Normal file
|
@ -0,0 +1,636 @@
|
|||
;;; ede/base.el --- Baseclasses for EDE.
|
||||
|
||||
;; Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Eric M. Ludlam <zappo@gnu.org>
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs 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 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; Baseclasses for EDE.
|
||||
;;
|
||||
;; Contains all the base structures needed by EDE.
|
||||
|
||||
;;; Code:
|
||||
(require 'eieio)
|
||||
(require 'eieio-speedbar)
|
||||
(require 'ede/auto)
|
||||
|
||||
;; Defined in ede.el:
|
||||
(defvar ede-projects)
|
||||
(defvar ede-object)
|
||||
(defvar ede-object-root-project)
|
||||
|
||||
(declare-function data-debug-new-buffer "data-debug")
|
||||
(declare-function data-debug-insert-object-slots "eieio-datadebug")
|
||||
(declare-function ede-parent-project "ede" (&optional obj))
|
||||
(declare-function ede-current-project "ede" (&optional dir))
|
||||
|
||||
;;; TARGET
|
||||
;;
|
||||
;; The TARGET is an entity in a project that knows about files
|
||||
;; and features of those files.
|
||||
|
||||
(defclass ede-target (eieio-speedbar-directory-button)
|
||||
((buttonface :initform speedbar-file-face) ;override for superclass
|
||||
(name :initarg :name
|
||||
:type string
|
||||
:custom string
|
||||
:label "Name"
|
||||
:group (default name)
|
||||
:documentation "Name of this target.")
|
||||
;; @todo - I think this should be "dir", and not "path".
|
||||
(path :initarg :path
|
||||
:type string
|
||||
;:custom string
|
||||
;:label "Path to target"
|
||||
;:group (default name)
|
||||
:documentation "The path to the sources of this target.
|
||||
Relative to the path of the project it belongs to.")
|
||||
(source :initarg :source
|
||||
:initform nil
|
||||
;; I'd prefer a list of strings.
|
||||
:type list
|
||||
:custom (repeat (string :tag "File"))
|
||||
:label "Source Files"
|
||||
:group (default source)
|
||||
:documentation "Source files in this target.")
|
||||
(versionsource :initarg :versionsource
|
||||
:initform nil
|
||||
:type list
|
||||
:custom (repeat (string :tag "File"))
|
||||
:label "Source Files with Version String"
|
||||
:group (source)
|
||||
:documentation
|
||||
"Source files with a version string in them.
|
||||
These files are checked for a version string whenever the EDE version
|
||||
of the master project is changed. When strings are found, the version
|
||||
previously there is updated.")
|
||||
;; Class level slots
|
||||
;;
|
||||
(sourcetype :allocation :class
|
||||
:type list ;; list of symbols
|
||||
:documentation
|
||||
"A list of `ede-sourcecode' objects this class will handle.
|
||||
This is used to match target objects with the compilers they can use, and
|
||||
which files this object is interested in."
|
||||
:accessor ede-object-sourcecode)
|
||||
(keybindings :allocation :class
|
||||
:initform (("D" . ede-debug-target))
|
||||
:documentation
|
||||
"Keybindings specialized to this type of target."
|
||||
:accessor ede-object-keybindings)
|
||||
(menu :allocation :class
|
||||
:initform ( [ "Debug target" ede-debug-target
|
||||
(ede-buffer-belongs-to-target-p) ]
|
||||
[ "Run target" ede-run-target
|
||||
(ede-buffer-belongs-to-target-p) ]
|
||||
)
|
||||
:documentation "Menu specialized to this type of target."
|
||||
:accessor ede-object-menu)
|
||||
)
|
||||
"A target is a structure that describes a file set that produces something.
|
||||
Targets, as with 'Make', is an entity that will manage a file set
|
||||
and knows how to compile or otherwise transform those files into some
|
||||
other desired outcome.")
|
||||
|
||||
;;; PROJECT/PLACEHOLDER
|
||||
;;
|
||||
;; Project placeholders are minimum parts of a project used
|
||||
;; by the project cache. The project cache can refer to these placeholders,
|
||||
;; and swap them out with the real-deal when that project is loaded.
|
||||
;;
|
||||
(defclass ede-project-placeholder (eieio-speedbar-directory-button)
|
||||
((name :initarg :name
|
||||
:initform "Untitled"
|
||||
:type string
|
||||
:custom string
|
||||
:label "Name"
|
||||
:group (default name)
|
||||
:documentation "The name used when generating distribution files.")
|
||||
(version :initarg :version
|
||||
:initform "1.0"
|
||||
:type string
|
||||
:custom string
|
||||
:label "Version"
|
||||
:group (default name)
|
||||
:documentation "The version number used when distributing files.")
|
||||
(directory :type string
|
||||
:initarg :directory
|
||||
:documentation "Directory this project is associated with.")
|
||||
(dirinode :documentation "The inode id for :directory.")
|
||||
(file :type string
|
||||
:initarg :file
|
||||
:documentation "File name where this project is stored.")
|
||||
(rootproject ; :initarg - no initarg, don't save this slot!
|
||||
:initform nil
|
||||
:type (or null ede-project-placeholder-child)
|
||||
:documentation "Pointer to our root project.")
|
||||
)
|
||||
"Placeholder object for projects not loaded into memory.
|
||||
Projects placeholders will be stored in a user specific location
|
||||
and querying them will cause the actual project to get loaded.")
|
||||
|
||||
;;; PROJECT
|
||||
;;
|
||||
;; An EDE project controls a set of TARGETS, and can also contain
|
||||
;; multiple SUBPROJECTS.
|
||||
;;
|
||||
;; The project defines a set of features that need to be built from
|
||||
;; files, in addition as to controlling what to do with the file set,
|
||||
;; such as creating distributions, compilation, and web sites.
|
||||
;;
|
||||
;; Projects can also affect how EDE works, by changing what appears in
|
||||
;; the EDE menu, or how some keys are bound.
|
||||
;;
|
||||
(defclass ede-project (ede-project-placeholder)
|
||||
((subproj :initform nil
|
||||
:type list
|
||||
:documentation "Sub projects controlled by this project.
|
||||
For Automake based projects, each directory is treated as a project.")
|
||||
(targets :initarg :targets
|
||||
:type list
|
||||
:custom (repeat (object :objectcreatefcn ede-new-target-custom))
|
||||
:label "Local Targets"
|
||||
:group (targets)
|
||||
:documentation "List of top level targets in this project.")
|
||||
(locate-obj :type (or null ede-locate-base-child)
|
||||
:documentation
|
||||
"A locate object to use as a backup to `ede-expand-filename'.")
|
||||
(tool-cache :initarg :tool-cache
|
||||
:type list
|
||||
:custom (repeat object)
|
||||
:label "Tool: "
|
||||
:group tools
|
||||
:documentation "List of tool cache configurations in this project.
|
||||
This allows any tool to create, manage, and persist project-specific settings.")
|
||||
(mailinglist :initarg :mailinglist
|
||||
:initform ""
|
||||
:type string
|
||||
:custom string
|
||||
:label "Mailing List Address"
|
||||
:group name
|
||||
:documentation
|
||||
"An email address where users might send email for help.")
|
||||
(web-site-url :initarg :web-site-url
|
||||
:initform ""
|
||||
:type string
|
||||
:custom string
|
||||
:label "Web Site URL"
|
||||
:group name
|
||||
:documentation "URL to this projects web site.
|
||||
This is a URL to be sent to a web site for documentation.")
|
||||
(web-site-directory :initarg :web-site-directory
|
||||
:initform ""
|
||||
:custom string
|
||||
:label "Web Page Directory"
|
||||
:group name
|
||||
:documentation
|
||||
"A directory where web pages can be found by Emacs.
|
||||
For remote locations use a path compatible with ange-ftp or EFS.
|
||||
You can also use TRAMP for use with rcp & scp.")
|
||||
(web-site-file :initarg :web-site-file
|
||||
:initform ""
|
||||
:custom string
|
||||
:label "Web Page File"
|
||||
:group name
|
||||
:documentation
|
||||
"A file which contains the home page for this project.
|
||||
This file can be relative to slot `web-site-directory'.
|
||||
This can be a local file, use ange-ftp, EFS, or TRAMP.")
|
||||
(ftp-site :initarg :ftp-site
|
||||
:initform ""
|
||||
:type string
|
||||
:custom string
|
||||
:label "FTP site"
|
||||
:group name
|
||||
:documentation
|
||||
"FTP site where this project's distribution can be found.
|
||||
This FTP site should be in Emacs form, as needed by `ange-ftp', but can
|
||||
also be of a form used by TRAMP for use with scp, or rcp.")
|
||||
(ftp-upload-site :initarg :ftp-upload-site
|
||||
:initform ""
|
||||
:type string
|
||||
:custom string
|
||||
:label "FTP Upload site"
|
||||
:group name
|
||||
:documentation
|
||||
"FTP Site to upload new distributions to.
|
||||
This FTP site should be in Emacs form as needed by `ange-ftp'.
|
||||
If this slot is nil, then use `ftp-site' instead.")
|
||||
(configurations :initarg :configurations
|
||||
:initform ("debug" "release")
|
||||
:type list
|
||||
:custom (repeat string)
|
||||
:label "Configuration Options"
|
||||
:group (settings)
|
||||
:documentation "List of available configuration types.
|
||||
Individual target/project types can form associations between a configuration,
|
||||
and target specific elements such as build variables.")
|
||||
(configuration-default :initarg :configuration-default
|
||||
:initform "debug"
|
||||
:custom string
|
||||
:label "Current Configuration"
|
||||
:group (settings)
|
||||
:documentation "The default configuration.")
|
||||
(local-variables :initarg :local-variables
|
||||
:initform nil
|
||||
:custom (repeat (cons (sexp :tag "Variable")
|
||||
(sexp :tag "Value")))
|
||||
:label "Project Local Variables"
|
||||
:group (settings)
|
||||
:documentation "Project local variables")
|
||||
(keybindings :allocation :class
|
||||
:initform (("D" . ede-debug-target)
|
||||
("R" . ede-run-target))
|
||||
:documentation "Keybindings specialized to this type of target."
|
||||
:accessor ede-object-keybindings)
|
||||
(menu :allocation :class
|
||||
:initform
|
||||
(
|
||||
[ "Update Version" ede-update-version ede-object ]
|
||||
[ "Version Control Status" ede-vc-project-directory ede-object ]
|
||||
[ "Edit Project Homepage" ede-edit-web-page
|
||||
(and ede-object (oref (ede-toplevel) web-site-file)) ]
|
||||
[ "Browse Project URL" ede-web-browse-home
|
||||
(and ede-object
|
||||
(not (string= "" (oref (ede-toplevel) web-site-url)))) ]
|
||||
"--"
|
||||
[ "Rescan Project Files" ede-rescan-toplevel t ]
|
||||
[ "Edit Projectfile" ede-edit-file-target
|
||||
(ede-buffer-belongs-to-project-p) ]
|
||||
)
|
||||
:documentation "Menu specialized to this type of target."
|
||||
:accessor ede-object-menu)
|
||||
)
|
||||
"Top level EDE project specification.
|
||||
All specific project types must derive from this project."
|
||||
:method-invocation-order :depth-first)
|
||||
|
||||
;;; Important macros for doing commands.
|
||||
;;
|
||||
(defmacro ede-with-projectfile (obj &rest forms)
|
||||
"For the project in which OBJ resides, execute FORMS."
|
||||
(list 'save-window-excursion
|
||||
(list 'let* (list
|
||||
(list 'pf
|
||||
(list 'if (list 'obj-of-class-p
|
||||
obj 'ede-target)
|
||||
;; @todo -I think I can change
|
||||
;; this to not need ede-load-project-file
|
||||
;; but I'm not sure how to test well.
|
||||
(list 'ede-load-project-file
|
||||
(list 'oref obj 'path))
|
||||
obj))
|
||||
'(dbka (get-file-buffer (oref pf file))))
|
||||
'(if (not dbka) (find-file (oref pf file))
|
||||
(switch-to-buffer dbka))
|
||||
(cons 'progn forms)
|
||||
'(if (not dbka) (kill-buffer (current-buffer))))))
|
||||
(put 'ede-with-projectfile 'lisp-indent-function 1)
|
||||
|
||||
;;; The EDE persistent cache.
|
||||
;;
|
||||
;; The cache is a way to mark where all known projects live without
|
||||
;; loading those projects into memory, or scanning for them each time
|
||||
;; emacs starts.
|
||||
;;
|
||||
(defcustom ede-project-placeholder-cache-file
|
||||
(locate-user-emacs-file "ede-projects.el" ".projects.ede")
|
||||
"File containing the list of projects EDE has viewed."
|
||||
:group 'ede
|
||||
:type 'file)
|
||||
|
||||
(defvar ede-project-cache-files nil
|
||||
"List of project files EDE has seen before.")
|
||||
|
||||
(defun ede-save-cache ()
|
||||
"Save a cache of EDE objects that Emacs has seen before."
|
||||
(interactive)
|
||||
(let ((p ede-projects)
|
||||
(c ede-project-cache-files)
|
||||
(recentf-exclude '( (lambda (f) t) ))
|
||||
)
|
||||
(condition-case nil
|
||||
(progn
|
||||
(set-buffer (find-file-noselect ede-project-placeholder-cache-file t))
|
||||
(erase-buffer)
|
||||
(insert ";; EDE project cache file.
|
||||
;; This contains a list of projects you have visited.\n(")
|
||||
(while p
|
||||
(when (and (car p) (ede-project-p p))
|
||||
(let ((f (oref (car p) file)))
|
||||
(when (file-exists-p f)
|
||||
(insert "\n \"" f "\""))))
|
||||
(setq p (cdr p)))
|
||||
(while c
|
||||
(insert "\n \"" (car c) "\"")
|
||||
(setq c (cdr c)))
|
||||
(insert "\n)\n")
|
||||
(condition-case nil
|
||||
(save-buffer 0)
|
||||
(error
|
||||
(message "File %s could not be saved."
|
||||
ede-project-placeholder-cache-file)))
|
||||
(kill-buffer (current-buffer))
|
||||
)
|
||||
(error
|
||||
(message "File %s could not be read."
|
||||
ede-project-placeholder-cache-file))
|
||||
|
||||
)))
|
||||
|
||||
(defun ede-load-cache ()
|
||||
"Load the cache of EDE projects."
|
||||
(save-excursion
|
||||
(let ((cachebuffer nil))
|
||||
(condition-case nil
|
||||
(progn
|
||||
(setq cachebuffer
|
||||
(find-file-noselect ede-project-placeholder-cache-file t))
|
||||
(set-buffer cachebuffer)
|
||||
(goto-char (point-min))
|
||||
(let ((c (read (current-buffer)))
|
||||
(new nil)
|
||||
(p ede-projects))
|
||||
;; Remove loaded projects from the cache.
|
||||
(while p
|
||||
(setq c (delete (oref (car p) file) c))
|
||||
(setq p (cdr p)))
|
||||
;; Remove projects that aren't on the filesystem
|
||||
;; anymore.
|
||||
(while c
|
||||
(when (file-exists-p (car c))
|
||||
(setq new (cons (car c) new)))
|
||||
(setq c (cdr c)))
|
||||
;; Save it
|
||||
(setq ede-project-cache-files (nreverse new))))
|
||||
(error nil))
|
||||
(when cachebuffer (kill-buffer cachebuffer))
|
||||
)))
|
||||
|
||||
;;; Get the cache usable.
|
||||
|
||||
;; @TODO - Remove this cache setup, or use this for something helpful.
|
||||
;;(add-hook 'kill-emacs-hook 'ede-save-cache)
|
||||
;;(when (not noninteractive)
|
||||
;; ;; No need to load the EDE cache if we aren't interactive.
|
||||
;; ;; This occurs during batch byte-compiling of other tools.
|
||||
;; (ede-load-cache))
|
||||
|
||||
|
||||
;;; METHODS
|
||||
;;
|
||||
;; The methods in ede-base handle project related behavior, and DO NOT
|
||||
;; related to EDE mode commands directory, such as keybindings.
|
||||
;;
|
||||
;; Mode related methods are in ede.el. These methods are related
|
||||
;; project specific activities not directly tied to a keybinding.
|
||||
(defmethod ede-subproject-relative-path ((proj ede-project) &optional parent-in)
|
||||
"Get a path name for PROJ which is relative to the parent project.
|
||||
If PARENT is specified, then be relative to the PARENT project.
|
||||
Specifying PARENT is useful for sub-sub projects relative to the root project."
|
||||
(let* ((parent (or parent-in (ede-parent-project proj)))
|
||||
(dir (file-name-directory (oref proj file))))
|
||||
(if (and parent (not (eq parent proj)))
|
||||
(file-relative-name dir (file-name-directory (oref parent file)))
|
||||
"")))
|
||||
|
||||
(defmethod ede-subproject-p ((proj ede-project))
|
||||
"Return non-nil if PROJ is a sub project."
|
||||
;; @TODO - Use this in more places, and also pay attention to
|
||||
;; metasubproject in ede-proj.el
|
||||
(ede-parent-project proj))
|
||||
|
||||
|
||||
;;; Default descriptive methods for EDE classes
|
||||
;;
|
||||
;; These are methods which you might want to override, but there is
|
||||
;; no need to in most situations because they are either a) simple, or
|
||||
;; b) cosmetic.
|
||||
|
||||
(defmethod ede-name ((this ede-target))
|
||||
"Return the name of THIS target."
|
||||
(oref this name))
|
||||
|
||||
(defmethod ede-target-name ((this ede-target))
|
||||
"Return the name of THIS target, suitable for make or debug style commands."
|
||||
(oref this name))
|
||||
|
||||
(defmethod ede-name ((this ede-project))
|
||||
"Return a short-name for THIS project file.
|
||||
Do this by extracting the lowest directory name."
|
||||
(oref this name))
|
||||
|
||||
(defmethod ede-description ((this ede-project))
|
||||
"Return a description suitable for the minibuffer about THIS."
|
||||
(format "Project %s: %d subprojects, %d targets."
|
||||
(ede-name this) (length (oref this subproj))
|
||||
(length (oref this targets))))
|
||||
|
||||
(defmethod ede-description ((this ede-target))
|
||||
"Return a description suitable for the minibuffer about THIS."
|
||||
(format "Target %s: with %d source files."
|
||||
(ede-name this) (length (oref this source))))
|
||||
|
||||
;;; HEADERS/DOC
|
||||
;;
|
||||
;; Targets and projects are often associated with other files, such as
|
||||
;; header files, documentation files and the like. Have strong
|
||||
;; associations can make useful user commands to quickly navigate
|
||||
;; between the files base on their associations.
|
||||
;;
|
||||
(defun ede-header-file ()
|
||||
"Return the header file for the current buffer.
|
||||
Not all buffers need headers, so return nil if no applicable."
|
||||
(if ede-object
|
||||
(ede-buffer-header-file ede-object (current-buffer))
|
||||
nil))
|
||||
|
||||
(defmethod ede-buffer-header-file ((this ede-project) buffer)
|
||||
"Return nil, projects don't have header files."
|
||||
nil)
|
||||
|
||||
(defmethod ede-buffer-header-file ((this ede-target) buffer)
|
||||
"There are no default header files in EDE.
|
||||
Do a quick check to see if there is a Header tag in this buffer."
|
||||
(with-current-buffer buffer
|
||||
(if (re-search-forward "::Header:: \\([a-zA-Z0-9.]+\\)" nil t)
|
||||
(buffer-substring-no-properties (match-beginning 1)
|
||||
(match-end 1))
|
||||
(let ((src (ede-target-sourcecode this))
|
||||
(found nil))
|
||||
(while (and src (not found))
|
||||
(setq found (ede-buffer-header-file (car src) (buffer-file-name))
|
||||
src (cdr src)))
|
||||
found))))
|
||||
|
||||
(defun ede-documentation-files ()
|
||||
"Return the documentation files for the current buffer.
|
||||
Not all buffers need documentations, so return nil if no applicable.
|
||||
Some projects may have multiple documentation files, so return a list."
|
||||
(if ede-object
|
||||
(ede-buffer-documentation-files ede-object (current-buffer))
|
||||
nil))
|
||||
|
||||
(defmethod ede-buffer-documentation-files ((this ede-project) buffer)
|
||||
"Return all documentation in project THIS based on BUFFER."
|
||||
;; Find the info node.
|
||||
(ede-documentation this))
|
||||
|
||||
(defmethod ede-buffer-documentation-files ((this ede-target) buffer)
|
||||
"Check for some documentation files for THIS.
|
||||
Also do a quick check to see if there is a Documentation tag in this BUFFER."
|
||||
(with-current-buffer buffer
|
||||
(if (re-search-forward "::Documentation:: \\([a-zA-Z0-9.]+\\)" nil t)
|
||||
(buffer-substring-no-properties (match-beginning 1)
|
||||
(match-end 1))
|
||||
;; Check the master project
|
||||
(let ((cp (ede-toplevel)))
|
||||
(ede-buffer-documentation-files cp (current-buffer))))))
|
||||
|
||||
(defmethod ede-documentation ((this ede-project))
|
||||
"Return a list of files that provide documentation.
|
||||
Documentation is not for object THIS, but is provided by THIS for other
|
||||
files in the project."
|
||||
(let ((targ (oref this targets))
|
||||
(proj (oref this subproj))
|
||||
(found nil))
|
||||
(while targ
|
||||
(setq found (append (ede-documentation (car targ)) found)
|
||||
targ (cdr targ)))
|
||||
(while proj
|
||||
(setq found (append (ede-documentation (car proj)) found)
|
||||
proj (cdr proj)))
|
||||
found))
|
||||
|
||||
(defmethod ede-documentation ((this ede-target))
|
||||
"Return a list of files that provide documentation.
|
||||
Documentation is not for object THIS, but is provided by THIS for other
|
||||
files in the project."
|
||||
nil)
|
||||
|
||||
(defun ede-html-documentation-files ()
|
||||
"Return a list of HTML documentation files associated with this project."
|
||||
(ede-html-documentation (ede-toplevel))
|
||||
)
|
||||
|
||||
(defmethod ede-html-documentation ((this ede-project))
|
||||
"Return a list of HTML files provided by project THIS."
|
||||
|
||||
)
|
||||
|
||||
;;; Default "WANT" methods.
|
||||
;;
|
||||
;; These methods are used to determine if a target "wants", or could
|
||||
;; somehow handle a file, or some source type.
|
||||
;;
|
||||
(defmethod ede-want-file-p ((this ede-target) file)
|
||||
"Return non-nil if THIS target wants FILE."
|
||||
;; By default, all targets reference the source object, and let it decide.
|
||||
(let ((src (ede-target-sourcecode this)))
|
||||
(while (and src (not (ede-want-file-p (car src) file)))
|
||||
(setq src (cdr src)))
|
||||
src))
|
||||
|
||||
(defmethod ede-want-file-source-p ((this ede-target) file)
|
||||
"Return non-nil if THIS target wants FILE."
|
||||
;; By default, all targets reference the source object, and let it decide.
|
||||
(let ((src (ede-target-sourcecode this)))
|
||||
(while (and src (not (ede-want-file-source-p (car src) file)))
|
||||
(setq src (cdr src)))
|
||||
src))
|
||||
|
||||
(defmethod ede-target-sourcecode ((this ede-target))
|
||||
"Return the sourcecode objects which THIS permits."
|
||||
(let ((sc (oref this sourcetype))
|
||||
(rs nil))
|
||||
(while (and (listp sc) sc)
|
||||
(setq rs (cons (symbol-value (car sc)) rs)
|
||||
sc (cdr sc)))
|
||||
rs))
|
||||
|
||||
|
||||
;;; Debugging.
|
||||
;;
|
||||
(defun ede-adebug-project ()
|
||||
"Run adebug against the current EDE project.
|
||||
Display the results as a debug list."
|
||||
(interactive)
|
||||
(require 'data-debug)
|
||||
(when (ede-current-project)
|
||||
(data-debug-new-buffer "*Analyzer ADEBUG*")
|
||||
(data-debug-insert-object-slots (ede-current-project) "")
|
||||
))
|
||||
|
||||
(defun ede-adebug-project-parent ()
|
||||
"Run adebug against the current EDE parent project.
|
||||
Display the results as a debug list."
|
||||
(interactive)
|
||||
(require 'data-debug)
|
||||
(when (ede-parent-project)
|
||||
(data-debug-new-buffer "*Analyzer ADEBUG*")
|
||||
(data-debug-insert-object-slots (ede-parent-project) "")
|
||||
))
|
||||
|
||||
(defun ede-adebug-project-root ()
|
||||
"Run adebug against the current EDE parent project.
|
||||
Display the results as a debug list."
|
||||
(interactive)
|
||||
(require 'data-debug)
|
||||
(when (ede-toplevel)
|
||||
(data-debug-new-buffer "*Analyzer ADEBUG*")
|
||||
(data-debug-insert-object-slots (ede-toplevel) "")
|
||||
))
|
||||
|
||||
|
||||
|
||||
;;; TOPLEVEL PROJECT
|
||||
;;
|
||||
;; The toplevel project is a way to identify the EDE structure that belongs
|
||||
;; to the top of a project.
|
||||
|
||||
(defun ede-toplevel (&optional subproj)
|
||||
"Return the ede project which is the root of the current project.
|
||||
Optional argument SUBPROJ indicates a subproject to start from
|
||||
instead of the current project."
|
||||
(or ede-object-root-project
|
||||
(let* ((cp (or subproj (ede-current-project))))
|
||||
(or (and cp (ede-project-root cp))
|
||||
(progn
|
||||
(while (ede-parent-project cp)
|
||||
(setq cp (ede-parent-project cp)))
|
||||
cp)))))
|
||||
|
||||
|
||||
;;; Hooks & Autoloads
|
||||
;;
|
||||
;; These let us watch various activities, and respond appropriately.
|
||||
|
||||
;; (add-hook 'edebug-setup-hook
|
||||
;; (lambda ()
|
||||
;; (def-edebug-spec ede-with-projectfile
|
||||
;; (form def-body))))
|
||||
|
||||
(provide 'ede/base)
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "loaddefs.el"
|
||||
;; generated-autoload-load-name: "ede/base"
|
||||
;; End:
|
||||
|
||||
;;; ede/base.el ends here
|
|
@ -131,7 +131,7 @@
|
|||
;; (add-to-list 'ede-project-class-files
|
||||
;; (ede-project-autoload "cpp-root"
|
||||
;; :name "CPP ROOT"
|
||||
;; :file 'ede-cpp-root
|
||||
;; :file 'ede/cpp-root
|
||||
;; :proj-file 'MY-FILE-FOR-DIR
|
||||
;; :proj-root 'MY-ROOT-FCN
|
||||
;; :load-type 'MY-LOAD
|
||||
|
@ -237,6 +237,18 @@ ROOTPROJ is nil, since there is only one project."
|
|||
;; Snoop through our master list.
|
||||
(ede-cpp-root-file-existing dir))
|
||||
|
||||
;;;###autoload
|
||||
(add-to-list 'ede-project-class-files
|
||||
(ede-project-autoload "cpp-root"
|
||||
:name "CPP ROOT"
|
||||
:file 'ede/cpp-root
|
||||
:proj-file 'ede-cpp-root-project-file-for-dir
|
||||
:proj-root 'ede-cpp-root-project-root
|
||||
:load-type 'ede-cpp-root-load
|
||||
:class-sym 'ede-cpp-root
|
||||
:new-p nil)
|
||||
t)
|
||||
|
||||
;;; CLASSES
|
||||
;;
|
||||
;; EDE sets up projects with two kinds of objects.
|
||||
|
@ -504,6 +516,21 @@ Also set up the lexical preprocessor map."
|
|||
"Get the pre-processor map for project THIS."
|
||||
(ede-preprocessor-map (ede-target-parent this)))
|
||||
|
||||
;;; Quick Hack
|
||||
(defun ede-create-lots-of-projects-under-dir (dir projfile &rest attributes)
|
||||
"Create a bunch of projects under directory DIR.
|
||||
PROJFILE is a file name sans directory that indicates a subdirectory
|
||||
is a project directory.
|
||||
Generic ATTRIBUTES, such as :include-path can be added.
|
||||
Note: This needs some work."
|
||||
(let ((files (directory-files dir t)))
|
||||
(dolist (F files)
|
||||
(if (file-exists-p (expand-file-name projfile F))
|
||||
`(ede-cpp-root-project (file-name-nondirectory F)
|
||||
:name (file-name-nondirectory F)
|
||||
:file (expand-file-name projfile F)
|
||||
attributes)))))
|
||||
|
||||
(provide 'ede/cpp-root)
|
||||
|
||||
;; Local variables:
|
||||
|
|
215
lisp/cedet/ede/custom.el
Normal file
215
lisp/cedet/ede/custom.el
Normal file
|
@ -0,0 +1,215 @@
|
|||
;;; ede.el --- customization of EDE projects.
|
||||
|
||||
;; Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Eric M. Ludlam <zappo@gnu.org>
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs 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 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; Customization commands/hooks for EDE.
|
||||
;;
|
||||
;; EIEIO supports customizing objects, and EDE uses this to allow
|
||||
;; users to change basic settings in their projects.
|
||||
;;
|
||||
|
||||
;;; Code:
|
||||
;;; Customization
|
||||
;;
|
||||
;; Routines for customizing projects and targets.
|
||||
|
||||
(require 'ede)
|
||||
(eval-when-compile (require 'eieio-custom))
|
||||
|
||||
(defvar eieio-ede-old-variables nil
|
||||
"The old variables for a project.")
|
||||
|
||||
;;; Customization Commands
|
||||
;;
|
||||
;; These commands initialize custoization of EDE control objects.
|
||||
|
||||
;;;###autoload
|
||||
(defun ede-customize-project ()
|
||||
"Edit fields of the current project through EIEIO & Custom."
|
||||
(interactive)
|
||||
(require 'eieio-custom)
|
||||
(let* ((ov (oref (ede-current-project) local-variables))
|
||||
(cp (ede-current-project)))
|
||||
(ede-customize cp)
|
||||
(make-local-variable 'eieio-ede-old-variables)
|
||||
(setq eieio-ede-old-variables ov)))
|
||||
|
||||
;;;###autoload
|
||||
(defalias 'customize-project 'ede-customize-project)
|
||||
|
||||
;;;###autoload
|
||||
(defun ede-customize-current-target()
|
||||
"Edit fields of the current target through EIEIO & Custom."
|
||||
(interactive)
|
||||
(require 'eieio-custom)
|
||||
(if (not (obj-of-class-p ede-object ede-target))
|
||||
(error "Current file is not part of a target"))
|
||||
(ede-customize-target ede-object))
|
||||
|
||||
;;;###autoload
|
||||
(defalias 'customize-target 'ede-customize-current-target)
|
||||
|
||||
(defun ede-customize-target (obj)
|
||||
"Edit fields of the current target through EIEIO & Custom.
|
||||
OBJ is the target object to customize."
|
||||
(require 'eieio-custom)
|
||||
(if (and obj (not (obj-of-class-p obj ede-target)))
|
||||
(error "No logical target to customize"))
|
||||
(ede-customize obj))
|
||||
|
||||
(defmethod ede-customize ((proj ede-project))
|
||||
"Customize the EDE project PROJ."
|
||||
(eieio-customize-object proj 'default))
|
||||
|
||||
(defmethod ede-customize ((target ede-target))
|
||||
"Customize the EDE TARGET."
|
||||
(eieio-customize-object target 'default))
|
||||
|
||||
;;; Target Sorting
|
||||
;;
|
||||
;; Target order can be important, but custom doesn't support a way
|
||||
;; to resort items in a list. This function by David Engster allows
|
||||
;; targets to be re-arranged.
|
||||
|
||||
(defvar ede-project-sort-targets-order nil
|
||||
"Variable for tracking target order in `ede-project-sort-targets'.")
|
||||
|
||||
;;;###autoload
|
||||
(defun ede-project-sort-targets ()
|
||||
"Create a custom-like buffer for sorting targets of current project."
|
||||
(interactive)
|
||||
(let ((proj (ede-current-project))
|
||||
(count 1)
|
||||
current order)
|
||||
(switch-to-buffer (get-buffer-create "*EDE sort targets*"))
|
||||
(erase-buffer)
|
||||
(setq ede-object-project proj)
|
||||
(widget-create 'push-button
|
||||
:notify (lambda (&rest ignore)
|
||||
(let ((targets (oref ede-object-project targets))
|
||||
cur newtargets)
|
||||
(while (setq cur (pop ede-project-sort-targets-order))
|
||||
(setq newtargets (append newtargets
|
||||
(list (nth cur targets)))))
|
||||
(oset ede-object-project targets newtargets))
|
||||
(ede-commit-project ede-object-project)
|
||||
(kill-buffer))
|
||||
" Accept ")
|
||||
(widget-insert " ")
|
||||
(widget-create 'push-button
|
||||
:notify (lambda (&rest ignore)
|
||||
(kill-buffer))
|
||||
" Cancel ")
|
||||
(widget-insert "\n\n")
|
||||
(setq ede-project-sort-targets-order nil)
|
||||
(mapc (lambda (x)
|
||||
(add-to-ordered-list
|
||||
'ede-project-sort-targets-order
|
||||
x x))
|
||||
(number-sequence 0 (1- (length (oref proj targets)))))
|
||||
(ede-project-sort-targets-list)
|
||||
(use-local-map widget-keymap)
|
||||
(widget-setup)
|
||||
(goto-char (point-min))))
|
||||
|
||||
(defun ede-project-sort-targets-list ()
|
||||
"Sort the target list while using `ede-project-sort-targets'."
|
||||
(save-excursion
|
||||
(let ((count 0)
|
||||
(targets (oref ede-object-project targets))
|
||||
(inhibit-read-only t)
|
||||
(inhibit-modification-hooks t))
|
||||
(goto-char (point-min))
|
||||
(forward-line 2)
|
||||
(delete-region (point) (point-max))
|
||||
(while (< count (length targets))
|
||||
(if (> count 0)
|
||||
(widget-create 'push-button
|
||||
:notify `(lambda (&rest ignore)
|
||||
(let ((cur ede-project-sort-targets-order))
|
||||
(add-to-ordered-list
|
||||
'ede-project-sort-targets-order
|
||||
(nth ,count cur)
|
||||
(1- ,count))
|
||||
(add-to-ordered-list
|
||||
'ede-project-sort-targets-order
|
||||
(nth (1- ,count) cur) ,count))
|
||||
(ede-project-sort-targets-list))
|
||||
" Up ")
|
||||
(widget-insert " "))
|
||||
(if (< count (1- (length targets)))
|
||||
(widget-create 'push-button
|
||||
:notify `(lambda (&rest ignore)
|
||||
(let ((cur ede-project-sort-targets-order))
|
||||
(add-to-ordered-list
|
||||
'ede-project-sort-targets-order
|
||||
(nth ,count cur) (1+ ,count))
|
||||
(add-to-ordered-list
|
||||
'ede-project-sort-targets-order
|
||||
(nth (1+ ,count) cur) ,count))
|
||||
(ede-project-sort-targets-list))
|
||||
" Down ")
|
||||
(widget-insert " "))
|
||||
(widget-insert (concat " " (number-to-string (1+ count)) ".: "
|
||||
(oref (nth (nth count ede-project-sort-targets-order)
|
||||
targets) name) "\n"))
|
||||
(setq count (1+ count))))))
|
||||
|
||||
;;; Customization hooks
|
||||
;;
|
||||
;; These hooks are used when finishing up a customization.
|
||||
(defmethod eieio-done-customizing ((proj ede-project))
|
||||
"Call this when a user finishes customizing PROJ."
|
||||
(let ((ov eieio-ede-old-variables)
|
||||
(nv (oref proj local-variables)))
|
||||
(setq eieio-ede-old-variables nil)
|
||||
(while ov
|
||||
(if (not (assoc (car (car ov)) nv))
|
||||
(save-excursion
|
||||
(mapc (lambda (b)
|
||||
(set-buffer b)
|
||||
(kill-local-variable (car (car ov))))
|
||||
(ede-project-buffers proj))))
|
||||
(setq ov (cdr ov)))
|
||||
(mapc (lambda (b) (ede-set-project-variables proj b))
|
||||
(ede-project-buffers proj))))
|
||||
|
||||
;; These two methods should be implemented by subclasses of
|
||||
;; project and targets in order to account for user specified
|
||||
;; changes.
|
||||
(defmethod eieio-done-customizing ((target ede-target))
|
||||
"Call this when a user finishes customizing TARGET."
|
||||
nil)
|
||||
|
||||
(defmethod ede-commit-project ((proj ede-project))
|
||||
"Commit any change to PROJ to its file."
|
||||
nil
|
||||
)
|
||||
|
||||
(provide 'ede/custom)
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "loaddefs.el"
|
||||
;; generated-autoload-load-name: "ede/custom"
|
||||
;; End:
|
||||
|
||||
;;; ede/custom.el ends here
|
|
@ -76,11 +76,11 @@ negative, force off."
|
|||
"Add files to Target: "))))
|
||||
(dolist (file (dired-get-marked-files t))
|
||||
(project-add-file target file)
|
||||
;; Find the buffer for this files, and set it's ede-object
|
||||
;; Find the buffer for this files, and set its ede-object
|
||||
(if (get-file-buffer file)
|
||||
(with-current-buffer (get-file-buffer file)
|
||||
(setq ede-object nil)
|
||||
(setq ede-object (ede-buffer-object (current-buffer)))))))
|
||||
(with-current-buffer (get-file-buffer file)
|
||||
(setq ede-object nil)
|
||||
(setq ede-object (ede-buffer-object (current-buffer)))))))
|
||||
|
||||
(provide 'ede/dired)
|
||||
|
||||
|
|
|
@ -133,6 +133,18 @@ ROOTPROJ is nil, since there is only one project."
|
|||
)
|
||||
)
|
||||
|
||||
;;;###autoload
|
||||
(add-to-list 'ede-project-class-files
|
||||
(ede-project-autoload "emacs"
|
||||
:name "EMACS ROOT"
|
||||
:file 'ede/emacs
|
||||
:proj-file "src/emacs.c"
|
||||
:proj-root 'ede-emacs-project-root
|
||||
:load-type 'ede-emacs-load
|
||||
:class-sym 'ede-emacs-project
|
||||
:new-p nil)
|
||||
t)
|
||||
|
||||
(defclass ede-emacs-target-c (ede-target)
|
||||
()
|
||||
"EDE Emacs Project target for C code.
|
||||
|
@ -150,7 +162,7 @@ All directories need at least one target.")
|
|||
|
||||
(defmethod initialize-instance ((this ede-emacs-project)
|
||||
&rest fields)
|
||||
"Make sure the :file is fully expanded."
|
||||
"Make sure the targets slot is bound."
|
||||
(call-next-method)
|
||||
(unless (slot-boundp this 'targets)
|
||||
(oset this :targets nil)))
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
(declare-function ede-locate-file-in-hash "ede/locate")
|
||||
(declare-function ede-locate-add-file-to-hash "ede/locate")
|
||||
(declare-function ede-locate-file-in-project "ede/locate")
|
||||
(declare-function ede-locate-flush-hash "ede/locate")
|
||||
|
||||
(defvar ede--disable-inode nil
|
||||
"Set to 't' to simulate systems w/out inode support.")
|
||||
|
@ -57,44 +58,29 @@ the current EDE project."
|
|||
(ede-project-root-directory (ede-current-project))))
|
||||
(find-file fname)))
|
||||
|
||||
(defun ede-flush-project-hash ()
|
||||
"Flush the file locate hash for the current project."
|
||||
(interactive)
|
||||
(require 'ede/locate)
|
||||
(let* ((loc (ede-get-locator-object (ede-current-project))))
|
||||
(ede-locate-flush-hash loc)))
|
||||
|
||||
;;; Placeholders for ROOT directory scanning on base objects
|
||||
;;
|
||||
(defmethod ede-project-root ((this ede-project-placeholder))
|
||||
"If a project knows it's root, return it here.
|
||||
"If a project knows its root, return it here.
|
||||
Allows for one-project-object-for-a-tree type systems."
|
||||
(oref this rootproject))
|
||||
|
||||
(defmethod ede-project-root-directory ((this ede-project-placeholder)
|
||||
&optional file)
|
||||
"If a project knows it's root, return it here.
|
||||
"If a project knows its root, return it here.
|
||||
Allows for one-project-object-for-a-tree type systems.
|
||||
Optional FILE is the file to test. It is ignored in preference
|
||||
of the anchor file for the project."
|
||||
(file-name-directory (expand-file-name (oref this file))))
|
||||
|
||||
|
||||
(defmethod ede-project-root ((this ede-project-autoload))
|
||||
"If a project knows it's root, return it here.
|
||||
Allows for one-project-object-for-a-tree type systems."
|
||||
nil)
|
||||
|
||||
(defmethod ede-project-root-directory ((this ede-project-autoload)
|
||||
&optional file)
|
||||
"If a project knows it's root, return it here.
|
||||
Allows for one-project-object-for-a-tree type systems.
|
||||
Optional FILE is the file to test. If there is no FILE, use
|
||||
the current buffer."
|
||||
(when (not file)
|
||||
(setq file default-directory))
|
||||
(when (slot-boundp this :proj-root)
|
||||
(let ((rootfcn (oref this proj-root)))
|
||||
(when rootfcn
|
||||
(condition-case nil
|
||||
(funcall rootfcn file)
|
||||
(error
|
||||
(funcall rootfcn)))
|
||||
))))
|
||||
|
||||
(defmethod ede--project-inode ((proj ede-project-placeholder))
|
||||
"Get the inode of the directory project PROJ is in."
|
||||
(if (slot-boundp proj 'dirinode)
|
||||
|
@ -262,27 +248,30 @@ Do this whenever a new project is created, as opposed to loaded."
|
|||
(defun ede-directory-project-p (dir &optional force)
|
||||
"Return a project description object if DIR has a project.
|
||||
Optional argument FORCE means to ignore a hash-hit of 'nomatch.
|
||||
This depends on an up to date `ede-project-class-files' variable."
|
||||
(let* ((dirtest (expand-file-name dir))
|
||||
(match (ede-directory-project-from-hash dirtest)))
|
||||
(cond
|
||||
((and (eq match 'nomatch) (not force))
|
||||
nil)
|
||||
((and match (not (eq match 'nomatch)))
|
||||
match)
|
||||
(t
|
||||
(let ((types ede-project-class-files)
|
||||
(ret nil))
|
||||
;; Loop over all types, loading in the first type that we find.
|
||||
(while (and types (not ret))
|
||||
(if (ede-dir-to-projectfile (car types) dirtest)
|
||||
(progn
|
||||
;; We found one! Require it now since we will need it.
|
||||
(require (oref (car types) file))
|
||||
(setq ret (car types))))
|
||||
(setq types (cdr types)))
|
||||
(ede-directory-project-add-description-to-hash dirtest (or ret 'nomatch))
|
||||
ret)))))
|
||||
This depends on an up to date `ede-project-class-files' variable.
|
||||
Any directory that contains the file .ede-ignore will allways
|
||||
return nil."
|
||||
(when (not (file-exists-p (expand-file-name ".ede-ignore" dir)))
|
||||
(let* ((dirtest (expand-file-name dir))
|
||||
(match (ede-directory-project-from-hash dirtest)))
|
||||
(cond
|
||||
((and (eq match 'nomatch) (not force))
|
||||
nil)
|
||||
((and match (not (eq match 'nomatch)))
|
||||
match)
|
||||
(t
|
||||
(let ((types ede-project-class-files)
|
||||
(ret nil))
|
||||
;; Loop over all types, loading in the first type that we find.
|
||||
(while (and types (not ret))
|
||||
(if (ede-dir-to-projectfile (car types) dirtest)
|
||||
(progn
|
||||
;; We found one! Require it now since we will need it.
|
||||
(require (oref (car types) file))
|
||||
(setq ret (car types))))
|
||||
(setq types (cdr types)))
|
||||
(ede-directory-project-add-description-to-hash dirtest (or ret 'nomatch))
|
||||
ret))))))
|
||||
|
||||
;;; TOPLEVEL
|
||||
;;
|
||||
|
@ -324,7 +313,7 @@ nil is returned if the current directory is not a part of a project."
|
|||
;; If PROJ didn't know, or there is no PROJ, then
|
||||
|
||||
;; Loop up to the topmost project, and then load that single
|
||||
;; project, and it's sub projects. When we are done, identify the
|
||||
;; project, and its sub projects. When we are done, identify the
|
||||
;; sub-project object belonging to file.
|
||||
(while (and (not ans) newpath proj)
|
||||
(setq toppath newpath
|
||||
|
@ -338,24 +327,6 @@ nil is returned if the current directory is not a part of a project."
|
|||
)
|
||||
(or ans toppath))))))
|
||||
|
||||
;;; TOPLEVEL PROJECT
|
||||
;;
|
||||
;; The toplevel project is a way to identify the EDE structure that belongs
|
||||
;; to the top of a project.
|
||||
|
||||
(defun ede-toplevel (&optional subproj)
|
||||
"Return the ede project which is the root of the current project.
|
||||
Optional argument SUBPROJ indicates a subproject to start from
|
||||
instead of the current project."
|
||||
(or ede-object-root-project
|
||||
(let* ((cp (or subproj (ede-current-project)))
|
||||
)
|
||||
(or (and cp (ede-project-root cp))
|
||||
(progn
|
||||
(while (ede-parent-project cp)
|
||||
(setq cp (ede-parent-project cp)))
|
||||
cp)))))
|
||||
|
||||
;;; DIRECTORY CONVERSION STUFF
|
||||
;;
|
||||
(defmethod ede-convert-path ((this ede-project) path)
|
||||
|
@ -372,11 +343,13 @@ Argument THIS is the project to convert PATH to."
|
|||
(substring fptf (match-end 0))
|
||||
(error "Cannot convert relativize path %s" fp))))))
|
||||
|
||||
(defmethod ede-convert-path ((this ede-target) path)
|
||||
(defmethod ede-convert-path ((this ede-target) path &optional project)
|
||||
"Convert path in a standard way for a given project.
|
||||
Default to making it project relative.
|
||||
Argument THIS is the project to convert PATH to."
|
||||
(let ((proj (ede-target-parent this)))
|
||||
Argument THIS is the project to convert PATH to.
|
||||
Optional PROJECT is the project that THIS belongs to. Associating
|
||||
a target to a project is expensive, so using this can speed things up."
|
||||
(let ((proj (or project (ede-target-parent this))))
|
||||
(if proj
|
||||
(let ((p (ede-convert-path proj path))
|
||||
(lp (or (oref this path) "")))
|
||||
|
@ -406,7 +379,8 @@ FILENAME should be just a filename which occurs in a directory controlled
|
|||
by this project.
|
||||
Optional argument FORCE forces the default filename to be provided even if it
|
||||
doesn't exist.
|
||||
If FORCE equals 'newfile, then the cache is ignored."
|
||||
If FORCE equals 'newfile, then the cache is ignored and a new file in THIS
|
||||
is returned."
|
||||
(require 'ede/locate)
|
||||
(let* ((loc (ede-get-locator-object this))
|
||||
(ha (ede-locate-file-in-hash loc filename))
|
||||
|
@ -467,17 +441,8 @@ doesn't exist."
|
|||
(proj (oref this subproj))
|
||||
(found nil))
|
||||
;; find it Locally.
|
||||
(setq found
|
||||
(cond ((file-exists-p (expand-file-name filename path))
|
||||
(expand-file-name filename path))
|
||||
((file-exists-p (expand-file-name (concat "include/" filename) path))
|
||||
(expand-file-name (concat "include/" filename) path))
|
||||
(t
|
||||
(while (and (not found) proj)
|
||||
(setq found (when (car proj)
|
||||
(ede-expand-filename (car proj) filename))
|
||||
proj (cdr proj)))
|
||||
found)))
|
||||
(setq found (or (ede-expand-filename-local this filename)
|
||||
(ede-expand-filename-impl-via-subproj this filename)))
|
||||
;; Use an external locate tool.
|
||||
(when (not found)
|
||||
(require 'ede/locate)
|
||||
|
@ -485,6 +450,30 @@ doesn't exist."
|
|||
;; Return it
|
||||
found))
|
||||
|
||||
(defmethod ede-expand-filename-local ((this ede-project) filename)
|
||||
"Expand filename locally to project THIS with filesystem tests."
|
||||
(let ((path (ede-project-root-directory this)))
|
||||
(cond ((file-exists-p (expand-file-name filename path))
|
||||
(expand-file-name filename path))
|
||||
((file-exists-p (expand-file-name (concat "include/" filename) path))
|
||||
(expand-file-name (concat "include/" filename) path)))))
|
||||
|
||||
(defmethod ede-expand-filename-impl-via-subproj ((this ede-project) filename)
|
||||
"Return a fully qualified file name based on project THIS.
|
||||
FILENAME should be just a filename which occurs in a directory controlled
|
||||
by this project."
|
||||
(let ((proj (list (ede-toplevel this)))
|
||||
(found nil))
|
||||
;; find it Locally.
|
||||
(while (and (not found) proj)
|
||||
(let ((thisproj (car proj)))
|
||||
(setq proj (append (cdr proj) (oref thisproj subproj)))
|
||||
(setq found (when thisproj
|
||||
(ede-expand-filename-local thisproj filename)))
|
||||
))
|
||||
;; Return it
|
||||
found))
|
||||
|
||||
(defmethod ede-expand-filename ((this ede-target) filename &optional force)
|
||||
"Return a fully qualified file name based on target THIS.
|
||||
FILENAME should be a filename which occurs in a directory in which THIS works.
|
||||
|
|
442
lisp/cedet/ede/generic.el
Normal file
442
lisp/cedet/ede/generic.el
Normal file
|
@ -0,0 +1,442 @@
|
|||
;;; ede/generic.el --- Base Support for generic build systems
|
||||
|
||||
;; Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Eric M. Ludlam <eric@siege-engine.com>
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs 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 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; There are a lot of build systems out there, and EDE can't support
|
||||
;; them all fully. The ede-generic.el system is the base for
|
||||
;; supporting alternate build systems in a simple way, automatically.
|
||||
;;
|
||||
;; The structure is for the ede-generic baseclass, which is augmented
|
||||
;; by simple sub-classes that can be created by users on an as needed
|
||||
;; basis. The generic system will have targets for many language
|
||||
;; types, and create the targets on an as needed basis. All
|
||||
;; sub-project types will recycle the same generic target types.
|
||||
;;
|
||||
;; The generic target types will only be implemented for languages
|
||||
;; where having EDE support actually matters, with a single MISC to
|
||||
;; represent anything else.
|
||||
;;
|
||||
;; TOO MANY PROJECTS DETECTED:
|
||||
;;
|
||||
;; If enabling ede-generic support starts identifying too many
|
||||
;; projects, drop a file called `.ede-ignore' into any directory where
|
||||
;; you do not want a project to be.
|
||||
;;
|
||||
;; Customization:
|
||||
;;
|
||||
;; Since these projects are all so increadibly generic, a user will
|
||||
;; need to configure some aspects of the project by hand. In order to
|
||||
;; enable this without configuring the project objects directly (which
|
||||
;; are auto-generated) a special ede-generic-confg object is defined to
|
||||
;; hold the basics. Generic projects will identify and use these
|
||||
;; config files.
|
||||
;;
|
||||
;; Adding support for new projects:
|
||||
;;
|
||||
;; To add support to EDE Generic for new project types is very quick.
|
||||
;; See the end of this file for examples such as CMake and SCons.
|
||||
;;
|
||||
;; Support consists of one class for your project, specifying the file
|
||||
;; name used by the project system you want to support. It also
|
||||
;; should implement th method `ede-generic-setup-configuration' to
|
||||
;; prepopulate the configurable portion of the generic project with
|
||||
;; build details.
|
||||
;;
|
||||
;; Lastly, call `ede-generic-new-autoloader' to setup your project so
|
||||
;; EDE can use it.
|
||||
;;
|
||||
;; Adding support for new types of source code:
|
||||
;;
|
||||
;; Sources of different types are supported with a simple class which
|
||||
;; subclasses `ede-generic-target'. The slots `shortname' and
|
||||
;; `extension' should be given new initial values.
|
||||
;;
|
||||
;; Optionally, any target method used by EDE can then be overriden.
|
||||
;; The ede-generic-target-c-cpp has some example methods setting up
|
||||
;; the pre-processor map and system include path.
|
||||
;;
|
||||
;; NOTE: It is not necessary to modify ede-generic.el to add any of
|
||||
;; the above described support features.
|
||||
|
||||
(require 'eieio-opt)
|
||||
(require 'ede)
|
||||
(require 'semantic/db)
|
||||
|
||||
;;; Code:
|
||||
;;
|
||||
;; Start with the configuration system
|
||||
(defclass ede-generic-config (eieio-persistent)
|
||||
((extension :initform ".ede")
|
||||
(file-header-line :initform ";; EDE Generic Project Configuration")
|
||||
(project :initform nil
|
||||
:documentation
|
||||
"The project this config is bound to.")
|
||||
;; Generic customizations
|
||||
(build-command :initarg :build-command
|
||||
:initform "make -k"
|
||||
:type string
|
||||
:custom string
|
||||
:group (default build)
|
||||
:documentation
|
||||
"Command used for building this project.")
|
||||
(debug-command :initarg :debug-command
|
||||
:initform "gdb "
|
||||
:type string
|
||||
:custom string
|
||||
:group (default build)
|
||||
:documentation
|
||||
"Command used for debugging this project.")
|
||||
;; C target customixations
|
||||
(c-include-path :initarg :c-include-path
|
||||
:initform nil
|
||||
:type list
|
||||
:custom (repeat (string :tag "Path"))
|
||||
:group c
|
||||
:documentation
|
||||
"The include path used by C/C++ projects.")
|
||||
(c-preprocessor-table :initarg :c-preprocessor-table
|
||||
:initform nil
|
||||
:type list
|
||||
:custom (repeat (cons (string :tag "Macro")
|
||||
(string :tag "Value")))
|
||||
:group c
|
||||
:documentation
|
||||
"Preprocessor Symbols for this project.")
|
||||
(c-preprocessor-files :initarg :c-preprocessor-files
|
||||
:initform nil
|
||||
:type list
|
||||
:custom (repeat (string :tag "Include File")))
|
||||
)
|
||||
"User Configuration object for a generic project.")
|
||||
|
||||
(defun ede-generic-load (dir &optional rootproj)
|
||||
"Return a Generic Project object if there is a match.
|
||||
Return nil if there isn't one.
|
||||
Argument DIR is the directory it is created for.
|
||||
ROOTPROJ is nil, since there is only one project."
|
||||
;; Doesn't already exist, so lets make one.
|
||||
(let* ((alobj ede-constructing)
|
||||
(this nil))
|
||||
(when (not alobj) (error "Cannot load generic project without the autoload instance"))
|
||||
|
||||
(setq this
|
||||
(funcall (oref alobj class-sym)
|
||||
(symbol-name (oref alobj class-sym))
|
||||
:name (file-name-nondirectory
|
||||
(directory-file-name dir))
|
||||
:version "1.0"
|
||||
:directory (file-name-as-directory dir)
|
||||
:file (expand-file-name (oref alobj :proj-file)) ))
|
||||
(ede-add-project-to-global-list this)
|
||||
))
|
||||
|
||||
;;; Base Classes for the system
|
||||
(defclass ede-generic-target (ede-target)
|
||||
((shortname :initform ""
|
||||
:type string
|
||||
:allocation :class
|
||||
:documentation
|
||||
"Something prepended to the target name.")
|
||||
(extension :initform ""
|
||||
:type string
|
||||
:allocation :class
|
||||
:documentation
|
||||
"Regular expression representing the extension used for this target.
|
||||
subclasses of this base target will override the default value.")
|
||||
)
|
||||
"Baseclass for all targets belonging to the generic ede system."
|
||||
:abstract t)
|
||||
|
||||
(defclass ede-generic-project (ede-project)
|
||||
((buildfile :initform ""
|
||||
:type string
|
||||
:allocation :class
|
||||
:documentation "The file name that identifies a project of this type.
|
||||
The class allocated value is replace by different sub classes.")
|
||||
(config :initform nil
|
||||
:type (or null ede-generic-config)
|
||||
:documentation
|
||||
"The configuration object for this project.")
|
||||
)
|
||||
"The baseclass for all generic EDE project types."
|
||||
:abstract t)
|
||||
|
||||
(defmethod initialize-instance ((this ede-generic-project)
|
||||
&rest fields)
|
||||
"Make sure the targets slot is bound."
|
||||
(call-next-method)
|
||||
(unless (slot-boundp this 'targets)
|
||||
(oset this :targets nil))
|
||||
)
|
||||
|
||||
(defmethod ede-generic-get-configuration ((proj ede-generic-project))
|
||||
"Return the configuration for the project PROJ."
|
||||
(let ((config (oref proj config)))
|
||||
(when (not config)
|
||||
(let ((fname (expand-file-name "EDEConfig.el"
|
||||
(oref proj :directory))))
|
||||
(if (file-exists-p fname)
|
||||
;; Load in the configuration
|
||||
(setq config (eieio-persistent-read fname))
|
||||
;; Create a new one.
|
||||
(setq config (ede-generic-config
|
||||
"Configuration"
|
||||
:file fname))
|
||||
;; Set initial values based on project.
|
||||
(ede-generic-setup-configuration proj config))
|
||||
;; Link things together.
|
||||
(oset proj config config)
|
||||
(oset config project proj)))
|
||||
config))
|
||||
|
||||
(defmethod ede-generic-setup-configuration ((proj ede-generic-project) config)
|
||||
"Default configuration setup method."
|
||||
nil)
|
||||
|
||||
(defmethod ede-commit-project ((proj ede-generic-project))
|
||||
"Commit any change to PROJ to its file."
|
||||
(let ((config (ede-generic-get-configuration proj)))
|
||||
(ede-commit config)))
|
||||
|
||||
;;; A list of different targets
|
||||
(defclass ede-generic-target-c-cpp (ede-generic-target)
|
||||
((shortname :initform "C/C++")
|
||||
(extension :initform "\\([ch]\\(pp\\|xx\\|\\+\\+\\)?\\|cc\\|hh\\|CC?\\)"))
|
||||
"EDE Generic Project target for C and C++ code.
|
||||
All directories need at least one target.")
|
||||
|
||||
(defclass ede-generic-target-el (ede-generic-target)
|
||||
((shortname :initform "ELisp")
|
||||
(extension :initform "el"))
|
||||
"EDE Generic Project target for Emacs Lisp code.
|
||||
All directories need at least one target.")
|
||||
|
||||
(defclass ede-generic-target-fortran (ede-generic-target)
|
||||
((shortname :initform "Fortran")
|
||||
(extension :initform "[fF]9[05]\\|[fF]\\|for"))
|
||||
"EDE Generic Project target for Fortran code.
|
||||
All directories need at least one target.")
|
||||
|
||||
(defclass ede-generic-target-texi (ede-generic-target)
|
||||
((shortname :initform "Texinfo")
|
||||
(extension :initform "texi"))
|
||||
"EDE Generic Project target for texinfo code.
|
||||
All directories need at least one target.")
|
||||
|
||||
;; MISC must always be last since it will always match the file.
|
||||
(defclass ede-generic-target-misc (ede-generic-target)
|
||||
((shortname :initform "Misc")
|
||||
(extension :initform ""))
|
||||
"EDE Generic Project target for Misc files.
|
||||
All directories need at least one target.")
|
||||
|
||||
;;; Automatic target aquisition.
|
||||
(defun ede-generic-find-matching-target (class dir targets)
|
||||
"Find a target that is a CLASS and is in DIR in the list of TARGETS."
|
||||
(let ((match nil))
|
||||
(dolist (T targets)
|
||||
(when (and (object-of-class-p T class)
|
||||
(string= (oref T :path) dir))
|
||||
(setq match T)
|
||||
))
|
||||
match))
|
||||
|
||||
(defmethod ede-find-target ((proj ede-generic-project) buffer)
|
||||
"Find an EDE target in PROJ for BUFFER.
|
||||
If one doesn't exist, create a new one for this directory."
|
||||
(let* ((ext (file-name-extension (buffer-file-name buffer)))
|
||||
(classes (eieio-build-class-alist 'ede-generic-target t))
|
||||
(cls nil)
|
||||
(targets (oref proj targets))
|
||||
(dir default-directory)
|
||||
(ans nil)
|
||||
)
|
||||
;; Pick a matching class type.
|
||||
(when ext
|
||||
(dolist (C classes)
|
||||
(let* ((classsym (intern (car C)))
|
||||
(extreg (oref classsym extension)))
|
||||
(when (and (not (string= extreg ""))
|
||||
(string-match (concat "^" extreg "$") ext))
|
||||
(setq cls classsym)))))
|
||||
(when (not cls) (setq cls 'ede-generic-target-misc))
|
||||
;; find a pre-existing matching target
|
||||
(setq ans (ede-generic-find-matching-target cls dir targets))
|
||||
;; Create a new instance if there wasn't one
|
||||
(when (not ans)
|
||||
(setq ans (make-instance
|
||||
cls
|
||||
:name (oref cls shortname)
|
||||
:path dir
|
||||
:source nil))
|
||||
(object-add-to-list proj :targets ans)
|
||||
)
|
||||
ans))
|
||||
|
||||
;;; C/C++ support
|
||||
(defmethod ede-preprocessor-map ((this ede-generic-target-c-cpp))
|
||||
"Get the pre-processor map for some generic C code."
|
||||
(let* ((proj (ede-target-parent this))
|
||||
(root (ede-project-root proj))
|
||||
(config (ede-generic-get-configuration proj))
|
||||
filemap
|
||||
)
|
||||
;; Preprocessor files
|
||||
(dolist (G (oref config :c-preprocessor-files))
|
||||
(let ((table (semanticdb-file-table-object
|
||||
(ede-expand-filename root G))))
|
||||
(when table
|
||||
(when (semanticdb-needs-refresh-p table)
|
||||
(semanticdb-refresh-table table))
|
||||
(setq filemap (append filemap (oref table lexical-table)))
|
||||
)))
|
||||
;; The core table
|
||||
(setq filemap (append filemap (oref config :c-preprocessor-table)))
|
||||
|
||||
filemap
|
||||
))
|
||||
|
||||
(defmethod ede-system-include-path ((this ede-generic-target-c-cpp))
|
||||
"Get the system include path used by project THIS."
|
||||
(let* ((proj (ede-target-parent this))
|
||||
(config (ede-generic-get-configuration proj)))
|
||||
(oref config c-include-path)))
|
||||
|
||||
;;; Customization
|
||||
;;
|
||||
(defmethod ede-customize ((proj ede-generic-project))
|
||||
"Customize the EDE project PROJ."
|
||||
(let ((config (ede-generic-get-configuration proj)))
|
||||
(eieio-customize-object config)))
|
||||
|
||||
(defmethod ede-customize ((target ede-generic-target))
|
||||
"Customize the EDE TARGET."
|
||||
;; Nothing unique for the targets, use the project.
|
||||
(ede-customize-project))
|
||||
|
||||
(defmethod eieio-done-customizing ((config ede-generic-config))
|
||||
"Called when EIEIO is done customizing the configuration object.
|
||||
We need to go back through the old buffers, and update them with
|
||||
the new configuration."
|
||||
(ede-commit config)
|
||||
;; Loop over all the open buffers, and re-apply.
|
||||
(ede-map-targets
|
||||
(oref config project)
|
||||
(lambda (target)
|
||||
(ede-map-target-buffers
|
||||
target
|
||||
(lambda (b)
|
||||
(with-current-buffer b
|
||||
(ede-apply-target-options)))))))
|
||||
|
||||
(defmethod ede-commit ((config ede-generic-config))
|
||||
"Commit all changes to the configuration to disk."
|
||||
(eieio-persistent-save config))
|
||||
|
||||
;;; Creating Derived Projects:
|
||||
;;
|
||||
;; Derived projects need an autoloader so that EDE can find the
|
||||
;; different projects on disk.
|
||||
(defun ede-generic-new-autoloader (internal-name external-name
|
||||
projectfile class)
|
||||
"Add a new EDE Autoload instance for identifying a generic project.
|
||||
INTERNAL-NAME is a long name that identifies thsi project type.
|
||||
EXTERNAL-NAME is a shorter human readable name to describe the project.
|
||||
PROJECTFILE is a file name that identifies a project of this type to EDE, such as
|
||||
a Makefile, or SConstruct file.
|
||||
CLASS is the EIEIO class that is used to track this project. It should subclass
|
||||
the class `ede-generic-project' project."
|
||||
(add-to-list 'ede-project-class-files
|
||||
(ede-project-autoload internal-name
|
||||
:name external-name
|
||||
:file 'ede/generic
|
||||
:proj-file projectfile
|
||||
:load-type 'ede-generic-load
|
||||
:class-sym class
|
||||
:new-p nil)
|
||||
;; Generics must go at the end, since more specific types
|
||||
;; can create Makefiles also.
|
||||
t))
|
||||
|
||||
;;;###autoload
|
||||
(defun ede-enable-generic-projects ()
|
||||
"Enable generic project loaders."
|
||||
(interactive)
|
||||
(ede-generic-new-autoloader "edeproject-makefile" "Make"
|
||||
"Makefile" 'ede-generic-makefile-project)
|
||||
(ede-generic-new-autoloader "edeproject-scons" "SCons"
|
||||
"SConstruct" 'ede-generic-scons-project)
|
||||
(ede-generic-new-autoloader "edeproject-cmake" "CMake"
|
||||
"CMakeLists" 'ede-generic-cmake-project)
|
||||
)
|
||||
|
||||
|
||||
;;; SPECIFIC TYPES OF GENERIC BUILDS
|
||||
;;
|
||||
|
||||
;;; MAKEFILE
|
||||
|
||||
(defclass ede-generic-makefile-project (ede-generic-project)
|
||||
((buildfile :initform "Makefile")
|
||||
)
|
||||
"Generic Project for makefiles.")
|
||||
|
||||
(defmethod ede-generic-setup-configuration ((proj ede-generic-makefile-project) config)
|
||||
"Setup a configuration for Make."
|
||||
(oset config build-command "make -k")
|
||||
(oset config debug-command "gdb ")
|
||||
)
|
||||
|
||||
|
||||
;;; SCONS
|
||||
(defclass ede-generic-scons-project (ede-generic-project)
|
||||
((buildfile :initform "SConstruct")
|
||||
)
|
||||
"Generic Project for scons.")
|
||||
|
||||
(defmethod ede-generic-setup-configuration ((proj ede-generic-scons-project) config)
|
||||
"Setup a configuration for SCONS."
|
||||
(oset config build-command "scons")
|
||||
(oset config debug-command "gdb ")
|
||||
)
|
||||
|
||||
|
||||
;;; CMAKE
|
||||
(defclass ede-generic-cmake-project (ede-generic-project)
|
||||
((buildfile :initform "CMakeLists")
|
||||
)
|
||||
"Generic Project for cmake.")
|
||||
|
||||
(defmethod ede-generic-setup-configuration ((proj ede-generic-cmake-project) config)
|
||||
"Setup a configuration for CMake."
|
||||
(oset config build-command "cmake")
|
||||
(oset config debug-command "gdb ")
|
||||
)
|
||||
|
||||
(provide 'ede/generic)
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "loaddefs.el"
|
||||
;; generated-autoload-load-name: "ede/generic"
|
||||
;; End:
|
||||
|
||||
;;; ede/generic.el ends here
|
|
@ -112,6 +112,18 @@ ROOTPROJ is nil, since there is only one project."
|
|||
)
|
||||
)
|
||||
|
||||
;;;###autoload
|
||||
(add-to-list 'ede-project-class-files
|
||||
(ede-project-autoload "linux"
|
||||
:name "LINUX ROOT"
|
||||
:file 'ede/linux
|
||||
:proj-file "scripts/ver_linux"
|
||||
:proj-root 'ede-linux-project-root
|
||||
:load-type 'ede-linux-load
|
||||
:class-sym 'ede-linux-project
|
||||
:new-p nil)
|
||||
t)
|
||||
|
||||
(defclass ede-linux-target-c (ede-target)
|
||||
()
|
||||
"EDE Linux Project target for C code.
|
||||
|
@ -124,7 +136,7 @@ All directories need at least one target.")
|
|||
|
||||
(defmethod initialize-instance ((this ede-linux-project)
|
||||
&rest fields)
|
||||
"Make sure the :file is fully expanded."
|
||||
"Make sure the targets slot is bound."
|
||||
(call-next-method)
|
||||
(unless (slot-boundp this 'targets)
|
||||
(oset this :targets nil)))
|
||||
|
|
|
@ -121,7 +121,7 @@ based on `ede-locate-setup-options'."
|
|||
;; Basic setup.
|
||||
(call-next-method)
|
||||
;; Make sure we have a hash table.
|
||||
(oset loc hash (make-hash-table :test 'equal))
|
||||
(ede-locate-flush-hash loc)
|
||||
)
|
||||
|
||||
(defmethod ede-locate-ok-in-project :static ((loc ede-locate-base)
|
||||
|
@ -129,6 +129,10 @@ based on `ede-locate-setup-options'."
|
|||
"Is it ok to use this project type under ROOT."
|
||||
t)
|
||||
|
||||
(defmethod ede-locate-flush-hash ((loc ede-locate-base))
|
||||
"For LOC, flush hashtable and start from scratch."
|
||||
(oset loc hash (make-hash-table :test 'equal)))
|
||||
|
||||
(defmethod ede-locate-file-in-hash ((loc ede-locate-base)
|
||||
filestring)
|
||||
"For LOC, is the file FILESTRING in our hashtable?"
|
||||
|
@ -160,6 +164,13 @@ that created this EDE locate object."
|
|||
nil
|
||||
)
|
||||
|
||||
(defmethod ede-locate-create/update-root-database :STATIC
|
||||
((loc ede-locate-base) root)
|
||||
"Create or update the database for the current project.
|
||||
You cannot create projects for the baseclass."
|
||||
(error "Cannot create/update a database of type %S"
|
||||
(object-name loc)))
|
||||
|
||||
;;; LOCATE
|
||||
;;
|
||||
;; Using the standard unix "locate" command.
|
||||
|
@ -242,6 +253,11 @@ that created this EDE locate object."
|
|||
(let ((default-directory (oref loc root)))
|
||||
(cedet-gnu-global-expand-filename filesubstring)))
|
||||
|
||||
(defmethod ede-locate-create/update-root-database :STATIC
|
||||
((loc ede-locate-global) root)
|
||||
"Create or update the GNU Global database for the current project."
|
||||
(cedet-gnu-global-create/update-database root))
|
||||
|
||||
;;; IDUTILS
|
||||
;;
|
||||
(defclass ede-locate-idutils (ede-locate-base)
|
||||
|
@ -280,6 +296,11 @@ that created this EDE locate object."
|
|||
(let ((default-directory (oref loc root)))
|
||||
(cedet-idutils-expand-filename filesubstring)))
|
||||
|
||||
(defmethod ede-locate-create/update-root-database :STATIC
|
||||
((loc ede-locate-idutils) root)
|
||||
"Create or update the GNU Global database for the current project."
|
||||
(cedet-idutils-create/update-database root))
|
||||
|
||||
;;; CSCOPE
|
||||
;;
|
||||
(defclass ede-locate-cscope (ede-locate-base)
|
||||
|
@ -315,6 +336,11 @@ that created this EDE locate object."
|
|||
(let ((default-directory (oref loc root)))
|
||||
(cedet-cscope-expand-filename filesubstring)))
|
||||
|
||||
(defmethod ede-locate-create/update-root-database :STATIC
|
||||
((loc ede-locate-cscope) root)
|
||||
"Create or update the GNU Global database for the current project."
|
||||
(cedet-cscope-create/update-database root))
|
||||
|
||||
(provide 'ede/locate)
|
||||
|
||||
;; Local variables:
|
||||
|
|
|
@ -126,7 +126,11 @@ don't do it. A value of nil means to just do it.")
|
|||
|
||||
(while compilation-in-progress
|
||||
(accept-process-output)
|
||||
(sit-for 1))
|
||||
;; If sit for indicates that input is waiting, then
|
||||
;; read and discard whatever it is that is going on.
|
||||
(when (not (sit-for 1))
|
||||
(read-event nil nil .1)
|
||||
))
|
||||
|
||||
(with-current-buffer "*compilation*"
|
||||
(goto-char (point-max))
|
||||
|
|
|
@ -262,6 +262,18 @@ Execute BODY in a location where a value can be placed."
|
|||
(goto-char (point-max))))
|
||||
(put 'ede-pmake-insert-variable-shared 'lisp-indent-function 1)
|
||||
|
||||
(defmacro ede-pmake-insert-variable-once (varname &rest body)
|
||||
"Add VARNAME into the current Makefile if it doesn't exist.
|
||||
Execute BODY in a location where a value can be placed."
|
||||
`(let ((addcr t) (v ,varname))
|
||||
(unless (re-search-backward (concat "^" v "\\s-*=") nil t)
|
||||
(insert v "=")
|
||||
,@body
|
||||
(if addcr (insert "\n"))
|
||||
(goto-char (point-max)))
|
||||
))
|
||||
(put 'ede-pmake-insert-variable-once 'lisp-indent-function 1)
|
||||
|
||||
;;; SOURCE VARIABLE NAME CONSTRUCTION
|
||||
|
||||
(defsubst ede-pmake-varname (obj)
|
||||
|
@ -369,10 +381,14 @@ NOTE: Not yet in use! This is part of an SRecode conversion of
|
|||
conf-table))
|
||||
(let* ((top "")
|
||||
(tmp this))
|
||||
;; Use relative paths for subdirs.
|
||||
(while (ede-parent-project tmp)
|
||||
(setq tmp (ede-parent-project tmp)
|
||||
top (concat "../" top)))
|
||||
(insert "\ntop=" top))
|
||||
;; If this is the top, then use CURDIR.
|
||||
(if (and (not (oref this metasubproject)) (string= top ""))
|
||||
(insert "\ntop=\"$(CURDIR)\"/")
|
||||
(insert "\ntop=" top)))
|
||||
(insert "\nede_FILES=" (file-name-nondirectory (oref this file)) " "
|
||||
(file-name-nondirectory (ede-proj-dist-makefile this)) "\n"))
|
||||
|
||||
|
@ -425,14 +441,13 @@ sources variable."
|
|||
(link (ede-proj-linkers this))
|
||||
(name (ede-proj-makefile-target-name this))
|
||||
(src (oref this source)))
|
||||
(ede-proj-makefile-insert-object-variables (car comp) name src)
|
||||
(dolist (obj comp)
|
||||
(ede-compiler-only-once obj
|
||||
(ede-proj-makefile-insert-variables obj)))
|
||||
(ede-proj-makefile-insert-object-variables (car comp) name src)
|
||||
(while link
|
||||
(ede-linker-only-once (car link)
|
||||
(ede-proj-makefile-insert-variables (car link)))
|
||||
(setq link (cdr link)))))
|
||||
(dolist (linker link)
|
||||
(ede-linker-only-once linker
|
||||
(ede-proj-makefile-insert-variables linker)))))
|
||||
|
||||
(defmethod ede-proj-makefile-insert-automake-pre-variables
|
||||
((this ede-proj-target))
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
(defclass ede-proj-target-makefile-archive
|
||||
(ede-proj-target-makefile-objectcode)
|
||||
((availablelinkers :initform (ede-archive-linker)))
|
||||
((availablelinkers :initform '(ede-archive-linker)))
|
||||
"This target generates an object code archive.")
|
||||
|
||||
(defvar ede-archive-linker
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
;;; Code:
|
||||
(defclass ede-proj-target-aux (ede-proj-target)
|
||||
((sourcetype :initform (ede-aux-source)))
|
||||
((sourcetype :initform '(ede-aux-source)))
|
||||
"This target consists of aux files such as READMEs and COPYING.")
|
||||
|
||||
(defvar ede-aux-source
|
||||
|
|
|
@ -36,8 +36,8 @@
|
|||
((menu :initform nil)
|
||||
(keybindings :initform nil)
|
||||
(phony :initform t)
|
||||
(sourcetype :initform (ede-source-emacs))
|
||||
(availablecompilers :initform (ede-emacs-compiler ede-xemacs-compiler))
|
||||
(sourcetype :initform '(ede-source-emacs))
|
||||
(availablecompilers :initform '(ede-emacs-compiler ede-xemacs-compiler))
|
||||
(aux-packages :initarg :aux-packages
|
||||
:initform nil
|
||||
:type list
|
||||
|
@ -259,7 +259,7 @@ is found, such as a `-version' variable, or the standard header."
|
|||
;; Autoload generators
|
||||
;;
|
||||
(defclass ede-proj-target-elisp-autoloads (ede-proj-target-elisp)
|
||||
((availablecompilers :initform (ede-emacs-cedet-autogen-compiler))
|
||||
((availablecompilers :initform '(ede-emacs-cedet-autogen-compiler))
|
||||
(aux-packages :initform ("cedet-autogen"))
|
||||
(phony :initform t)
|
||||
(autoload-file :initarg :autoload-file
|
||||
|
|
|
@ -31,9 +31,9 @@
|
|||
(defclass ede-proj-target-makefile-info (ede-proj-target-makefile)
|
||||
((menu :initform nil)
|
||||
(keybindings :initform nil)
|
||||
(availablecompilers :initform (ede-makeinfo-compiler
|
||||
ede-texi2html-compiler))
|
||||
(sourcetype :initform (ede-makeinfo-source))
|
||||
(availablecompilers :initform '(ede-makeinfo-compiler
|
||||
ede-texi2html-compiler))
|
||||
(sourcetype :initform '(ede-makeinfo-source))
|
||||
(mainmenu :initarg :mainmenu
|
||||
:initform ""
|
||||
:type string
|
||||
|
|
|
@ -35,8 +35,8 @@
|
|||
|
||||
;; FIXME this isn't how you spell "miscellaneous". :(
|
||||
(defclass ede-proj-target-makefile-miscelaneous (ede-proj-target-makefile)
|
||||
((sourcetype :initform (ede-misc-source))
|
||||
(availablecompilers :initform (ede-misc-compile))
|
||||
((sourcetype :initform '(ede-misc-source))
|
||||
(availablecompilers :initform '(ede-misc-compile))
|
||||
(submakefile :initarg :submakefile
|
||||
:initform ""
|
||||
:type string
|
||||
|
|
|
@ -39,28 +39,32 @@
|
|||
(configuration-variables :initform ("debug" . (("CFLAGS" . "-g")
|
||||
("LDFLAGS" . "-g"))))
|
||||
;; @TODO - add an include path.
|
||||
(availablecompilers :initform (ede-gcc-compiler
|
||||
ede-g++-compiler
|
||||
ede-gfortran-compiler
|
||||
ede-gfortran-module-compiler
|
||||
;; More C and C++ compilers, plus
|
||||
;; fortran or pascal can be added here
|
||||
))
|
||||
(availablelinkers :initform (ede-g++-linker
|
||||
ede-cc-linker
|
||||
ede-gfortran-linker
|
||||
ede-ld-linker
|
||||
;; Add more linker thingies here.
|
||||
))
|
||||
(sourcetype :initform (ede-source-c
|
||||
ede-source-c++
|
||||
ede-source-f77
|
||||
ede-source-f90
|
||||
;; ede-source-other
|
||||
;; This object should take everything that
|
||||
;; gets compiled into objects like fortran
|
||||
;; and pascal.
|
||||
))
|
||||
(availablecompilers :initform '(ede-gcc-compiler
|
||||
ede-g++-compiler
|
||||
ede-gfortran-compiler
|
||||
ede-gfortran-module-compiler
|
||||
ede-lex-compiler
|
||||
ede-yacc-compiler
|
||||
;; More C and C++ compilers, plus
|
||||
;; fortran or pascal can be added here
|
||||
))
|
||||
(availablelinkers :initform '(ede-g++-linker
|
||||
ede-cc-linker
|
||||
ede-ld-linker
|
||||
ede-gfortran-linker
|
||||
;; Add more linker thingies here.
|
||||
))
|
||||
(sourcetype :initform '(ede-source-c
|
||||
ede-source-c++
|
||||
ede-source-f77
|
||||
ede-source-f90
|
||||
ede-source-lex
|
||||
ede-source-yacc
|
||||
;; ede-source-other
|
||||
;; This object should take everything that
|
||||
;; gets compiled into objects like fortran
|
||||
;; and pascal.
|
||||
))
|
||||
)
|
||||
"Abstract class for Makefile based object code generating targets.
|
||||
Belonging to this group assumes you could make a .o from an element source
|
||||
|
@ -115,15 +119,15 @@ file.")
|
|||
:name "cc"
|
||||
:sourcetype '(ede-source-c)
|
||||
:variables '(("C_LINK" . "$(CC) $(CFLAGS) $(LDFLAGS) -L."))
|
||||
:commands '("$(C_LINK) -o $@ $^")
|
||||
:commands '("$(C_LINK) -o $@ $^ $(LDDEPS)")
|
||||
:objectextention "")
|
||||
"Linker for C sourcecode.")
|
||||
|
||||
(defvar ede-source-c++
|
||||
(ede-sourcecode "ede-source-c++"
|
||||
:name "C++"
|
||||
:sourcepattern "\\.\\(cpp\\|cc\\|cxx\\)$"
|
||||
:auxsourcepattern "\\.\\(hpp\\|hh?\\|hxx\\)$"
|
||||
:sourcepattern "\\.\\(c\\(pp?\\|c\\|xx\\|++\\)\\|C\\\(PP\\)?\\)$"
|
||||
:auxsourcepattern "\\.\\(hpp?\\|hh?\\|hxx\\|H\\)$"
|
||||
:garbagepattern '("*.o" "*.obj" ".deps/*.P" ".lo"))
|
||||
"C++ source code definition.")
|
||||
|
||||
|
@ -158,11 +162,43 @@ file.")
|
|||
;; Only use this linker when c++ exists.
|
||||
:sourcetype '(ede-source-c++)
|
||||
:variables '(("CXX_LINK" . "$(CXX) $(CFLAGS) $(LDFLAGS) -L."))
|
||||
:commands '("$(CXX_LINK) -o $@ $^")
|
||||
:commands '("$(CXX_LINK) -o $@ $^ $(LDDEPS)")
|
||||
:autoconf '("AC_PROG_CXX")
|
||||
:objectextention "")
|
||||
"Linker needed for c++ programs.")
|
||||
|
||||
;;; LEX
|
||||
(defvar ede-source-lex
|
||||
(ede-sourcecode "ede-source-lex"
|
||||
:name "lex"
|
||||
:sourcepattern "\\.l\\(l\\|pp\\|++\\)")
|
||||
"Lex source code definition.
|
||||
No garbage pattern since it creates C or C++ code.")
|
||||
|
||||
(defvar ede-lex-compiler
|
||||
(ede-object-compiler
|
||||
"ede-lex-compiler"
|
||||
;; Can we support regular makefiles too??
|
||||
:autoconf '("AC_PROG_LEX")
|
||||
:sourcetype '(ede-source-lex))
|
||||
"Compiler used for Lexical source.")
|
||||
|
||||
;;; YACC
|
||||
(defvar ede-source-yacc
|
||||
(ede-sourcecode "ede-source-yacc"
|
||||
:name "yacc"
|
||||
:sourcepattern "\\.y\\(y\\|pp\\|++\\)")
|
||||
"Yacc source code definition.
|
||||
No garbage pattern since it creates C or C++ code.")
|
||||
|
||||
(defvar ede-yacc-compiler
|
||||
(ede-object-compiler
|
||||
"ede-yacc-compiler"
|
||||
;; Can we support regular makefiles too??
|
||||
:autoconf '("AC_PROG_YACC")
|
||||
:sourcetype '(ede-source-yacc))
|
||||
"Compiler used for yacc/bison grammar files source.")
|
||||
|
||||
;;; Fortran Compiler/Linker
|
||||
;;
|
||||
;; Contributed by David Engster
|
||||
|
@ -233,7 +269,7 @@ file.")
|
|||
:name "ld"
|
||||
:variables '(("LD" . "ld")
|
||||
("LD_LINK" . "$(LD) $(LDFLAGS) -L."))
|
||||
:commands '("$(LD_LINK) -o $@ $^")
|
||||
:commands '("$(LD_LINK) -o $@ $^ $(LDDEPS)")
|
||||
:objectextention "")
|
||||
"Linker needed for c++ programs.")
|
||||
|
||||
|
|
|
@ -34,14 +34,14 @@
|
|||
;;; Code:
|
||||
(defclass ede-proj-target-makefile-program
|
||||
(ede-proj-target-makefile-objectcode)
|
||||
((ldlibs :initarg :ldlibs
|
||||
:initform nil
|
||||
:type list
|
||||
:custom (repeat (string :tag "Library"))
|
||||
:documentation
|
||||
"Libraries, such as \"m\" or \"Xt\" which this program depends on.
|
||||
The linker flag \"-l\" is automatically prepended. Do not include a \"lib\"
|
||||
prefix, or a \".so\" suffix.
|
||||
((ldlibs-local :initarg :ldlibs-local
|
||||
:initform nil
|
||||
:type list
|
||||
:custom (repeat (string :tag "Local Library"))
|
||||
:documentation
|
||||
"Libraries that are part of this project.
|
||||
The full path to these libraries should be specified, such as:
|
||||
../lib/libMylib.la or ../ar/myArchive.a
|
||||
|
||||
Note: Currently only used for Automake projects."
|
||||
)
|
||||
|
@ -51,10 +51,21 @@ Note: Currently only used for Automake projects."
|
|||
:custom (repeat (string :tag "Link Flag"))
|
||||
:documentation
|
||||
"Additional flags to add when linking this target.
|
||||
Use ldlibs to add addition libraries. Use this to specify specific
|
||||
options to the linker.
|
||||
Use this to specify specific options to the linker.
|
||||
A Common use may be to add -L to specify in-project locations of libraries
|
||||
specified with ldlibs.")
|
||||
(ldlibs :initarg :ldlibs
|
||||
:initform nil
|
||||
:type list
|
||||
:custom (repeat (string :tag "Library"))
|
||||
:documentation
|
||||
"Libraries, such as \"m\" or \"Xt\" which this program depends on.
|
||||
The linker flag \"-l\" is automatically prepended. Do not include a \"lib\"
|
||||
prefix, or a \".so\" suffix.
|
||||
Use the 'ldflags' slot to specify where in-project libraries might be.
|
||||
|
||||
Note: Not currently used. This bug needs to be fixed.")
|
||||
Note: Currently only used for Automake projects."
|
||||
)
|
||||
)
|
||||
"This target is an executable program.")
|
||||
|
||||
|
@ -70,27 +81,24 @@ Note: Not currently used. This bug needs to be fixed.")
|
|||
"Insert bin_PROGRAMS variables needed by target THIS."
|
||||
(ede-pmake-insert-variable-shared
|
||||
(concat (ede-name this) "_LDADD")
|
||||
(mapc (lambda (c) (insert " -l" c)) (oref this ldlibs)))
|
||||
;; For other targets THIS depends on
|
||||
;;
|
||||
;; NOTE: FIX THIS
|
||||
;;
|
||||
;;(ede-pmake-insert-variable-shared
|
||||
;; (concat (ede-name this) "_DEPENDENCIES")
|
||||
;; (mapcar (lambda (d) (insert d)) (oref this FOOOOOOOO)))
|
||||
(mapc (lambda (l) (insert " " l)) (oref this ldlibs-local))
|
||||
(mapc (lambda (c) (insert " " c)) (oref this ldflags))
|
||||
(when (oref this ldlibs)
|
||||
(mapc (lambda (d) (insert " -l" d)) (oref this ldlibs)))
|
||||
)
|
||||
(call-next-method))
|
||||
|
||||
(defmethod ede-proj-makefile-insert-rules ((this ede-proj-target-makefile-program))
|
||||
"Insert rules needed by THIS target."
|
||||
(let ((ede-proj-compiler-object-linkflags
|
||||
(mapconcat 'identity (oref this ldflags) " ")))
|
||||
(defmethod ede-proj-makefile-insert-variables ((this ede-proj-target-makefile-program))
|
||||
"Insert variables needed by the compiler THIS."
|
||||
(call-next-method)
|
||||
(let ((lf (mapconcat 'identity (oref this ldflags) " ")))
|
||||
(with-slots (ldlibs) this
|
||||
(if ldlibs
|
||||
(setq ede-proj-compiler-object-linkflags
|
||||
(concat ede-proj-compiler-object-linkflags
|
||||
" -l"
|
||||
(mapconcat 'identity ldlibs " -l")))))
|
||||
(call-next-method)))
|
||||
(setq lf
|
||||
(concat lf " -l" (mapconcat 'identity ldlibs " -l")))))
|
||||
;; LDFLAGS as needed.
|
||||
(when (and lf (not (string= "" lf)))
|
||||
(ede-pmake-insert-variable-once "LDDEPS" (insert lf)))))
|
||||
|
||||
(defmethod project-debug-target ((obj ede-proj-target-makefile-program))
|
||||
"Debug a program target OBJ."
|
||||
|
|
|
@ -34,15 +34,15 @@
|
|||
;;; Code:
|
||||
(defclass ede-proj-target-makefile-shared-object
|
||||
(ede-proj-target-makefile-program)
|
||||
((availablecompilers :initform (ede-gcc-libtool-shared-compiler
|
||||
;;ede-gcc-shared-compiler
|
||||
ede-g++-libtool-shared-compiler
|
||||
;;ede-g++-shared-compiler
|
||||
))
|
||||
(availablelinkers :initform (ede-cc-linker-libtool
|
||||
ede-g++-linker-libtool
|
||||
;; Add more linker thingies here.
|
||||
))
|
||||
((availablecompilers :initform '(ede-gcc-libtool-shared-compiler
|
||||
;;ede-gcc-shared-compiler
|
||||
ede-g++-libtool-shared-compiler
|
||||
;;ede-g++-shared-compiler
|
||||
))
|
||||
(availablelinkers :initform '(ede-cc-linker-libtool
|
||||
ede-g++-linker-libtool
|
||||
;; Add more linker thingies here.
|
||||
))
|
||||
(ldflags :custom (repeat (string :tag "Libtool flag"))
|
||||
:documentation
|
||||
"Additional flags to add when linking this shared library.
|
||||
|
@ -124,7 +124,7 @@ Use ldlibs to add addition libraries.")
|
|||
:rules (list (ede-makefile-rule
|
||||
"c++-inference-rule-libtool"
|
||||
:target "%.o"
|
||||
:dependencies "%.c"
|
||||
:dependencies "%.cpp"
|
||||
:rules '("@echo '$(LTCOMPILE) -o $@ $<'; \\"
|
||||
"$(LTCOMPILE) -o $@ $<"
|
||||
)
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
;; rebuild. The targets provided in ede-proj can be augmented with
|
||||
;; additional target types inherited directly from `ede-proj-target'.
|
||||
|
||||
;; (eval-and-compile '(require 'ede))
|
||||
(require 'ede/proj-comp)
|
||||
(require 'ede/make)
|
||||
|
||||
|
@ -336,7 +335,9 @@ Argument TARGET is the project we are completing customization on."
|
|||
(or (string= (file-name-nondirectory (oref this file)) f)
|
||||
(string= (ede-proj-dist-makefile this) f)
|
||||
(string-match "Makefile\\(\\.\\(in\\|am\\)\\)?$" f)
|
||||
(string-match "config\\(ure\\.in\\|\\.stutus\\)?$" f)
|
||||
(string-match "config\\(ure\\.\\(in\\|ac\\)\\|\\.status\\)?$" f)
|
||||
(string-match "config.h\\(\\.in\\)?" f)
|
||||
(member f '("AUTHORS" "NEWS" "COPYING" "INSTALL" "README"))
|
||||
)))
|
||||
|
||||
(defmethod ede-buffer-mine ((this ede-proj-target) buffer)
|
||||
|
@ -398,11 +399,11 @@ Argument TARGET is the project we are completing customization on."
|
|||
:source nil)))
|
||||
|
||||
(defmethod project-delete-target ((this ede-proj-target))
|
||||
"Delete the current target THIS from it's parent project."
|
||||
"Delete the current target THIS from its parent project."
|
||||
(let ((p (ede-current-project))
|
||||
(ts (oref this source)))
|
||||
;; Loop across all sources. If it exists in a buffer,
|
||||
;; clear it's object.
|
||||
;; clear its object.
|
||||
(while ts
|
||||
(let* ((default-directory (oref this path))
|
||||
(b (get-file-buffer (car ts))))
|
||||
|
@ -413,7 +414,7 @@ Argument TARGET is the project we are completing customization on."
|
|||
(setq ede-object nil)
|
||||
(ede-apply-object-keymap))))))
|
||||
(setq ts (cdr ts)))
|
||||
;; Remove THIS from it's parent.
|
||||
;; Remove THIS from its parent.
|
||||
;; The two vectors should be pointer equivalent.
|
||||
(oset p targets (delq this (oref p targets)))
|
||||
(ede-proj-save (ede-current-project))))
|
||||
|
@ -447,15 +448,13 @@ FILE must be massaged by `ede-convert-path'."
|
|||
|
||||
(defmethod project-make-dist ((this ede-proj-project))
|
||||
"Build a distribution for the project based on THIS target."
|
||||
;; I'm a lazy bum, so I'll make a makefile for doing this sort
|
||||
;; of thing, and rely only on that small section of code.
|
||||
(let ((pm (ede-proj-dist-makefile this))
|
||||
(df (project-dist-files this)))
|
||||
(if (and (file-exists-p (car df))
|
||||
(not (y-or-n-p "Dist file already exists. Rebuild? ")))
|
||||
(error "Try `ede-update-version' before making a distribution"))
|
||||
(ede-proj-setup-buildenvironment this)
|
||||
(if (string= (file-name-nondirectory pm) "Makefile.am")
|
||||
(if (ede-proj-automake-p this)
|
||||
(setq pm (expand-file-name "Makefile"
|
||||
(file-name-directory pm))))
|
||||
(compile (concat ede-make-command " -f " pm " dist"))))
|
||||
|
@ -473,7 +472,7 @@ Argument COMMAND is the command to use when compiling."
|
|||
(let ((pm (ede-proj-dist-makefile proj))
|
||||
(default-directory (file-name-directory (oref proj file))))
|
||||
(ede-proj-setup-buildenvironment proj)
|
||||
(if (string= (file-name-nondirectory pm) "Makefile.am")
|
||||
(if (ede-proj-automake-p proj)
|
||||
(setq pm (expand-file-name "Makefile"
|
||||
(file-name-directory pm))))
|
||||
(compile (concat ede-make-command" -f " pm " all"))))
|
||||
|
@ -539,7 +538,15 @@ Converts all symbols into the objects to be used."
|
|||
(if (ede-want-any-source-files-p (symbol-value (car st)) sources)
|
||||
(let ((c (ede-proj-find-compiler avail (car st))))
|
||||
(if c (setq comp (cons c comp)))))
|
||||
(setq st (cdr st)))))
|
||||
(setq st (cdr st)))
|
||||
;; Provide a good error msg.
|
||||
(unless comp
|
||||
(error "Could not find compiler match for source code extension \"%s\".
|
||||
You may need to add support for this type of file."
|
||||
(if sources
|
||||
(file-name-extension (car sources))
|
||||
"")))
|
||||
))
|
||||
;; Return the disovered compilers
|
||||
comp)))
|
||||
|
||||
|
@ -664,18 +671,9 @@ Optional argument FORCE will force items to be regenerated."
|
|||
(let ((root (or (ede-project-root this) this))
|
||||
)
|
||||
(setq ede-projects (delq root ede-projects))
|
||||
(ede-proj-load (ede-project-root-directory root))
|
||||
(ede-load-project-file (ede-project-root-directory root))
|
||||
))
|
||||
|
||||
(defmethod project-rescan ((this ede-proj-target) readstream)
|
||||
"Rescan target THIS from the read list READSTREAM."
|
||||
(setq readstream (cdr (cdr readstream))) ;; constructor/name
|
||||
(while readstream
|
||||
(let ((tag (car readstream))
|
||||
(val (car (cdr readstream))))
|
||||
(eieio-oset this tag val))
|
||||
(setq readstream (cdr (cdr readstream)))))
|
||||
|
||||
(provide 'ede/proj)
|
||||
|
||||
;; arch-tag: eb8a40f8-0d2c-41c4-b273-af04101d1cdf
|
||||
|
|
|
@ -30,27 +30,19 @@
|
|||
;; fashion.
|
||||
;;
|
||||
;; project-am uses the structure defined in all good GNU projects with
|
||||
;; the Automake file as it's base template, and then maintains that
|
||||
;; the Automake file as its base template, and then maintains that
|
||||
;; information during edits, automatically updating the automake file
|
||||
;; where appropriate.
|
||||
|
||||
|
||||
;; (eval-and-compile
|
||||
;; ;; Compatibility for makefile mode.
|
||||
;; (condition-case nil
|
||||
;; (require 'makefile "make-mode")
|
||||
;; (error (require 'make-mode "make-mode")))
|
||||
|
||||
;; ;; Requiring the .el files prevents incomplete builds.
|
||||
;; (require 'eieio "eieio.el")
|
||||
;; (require 'ede "ede.el"))
|
||||
|
||||
(require 'make-mode)
|
||||
(require 'ede)
|
||||
(require 'ede/make)
|
||||
(require 'ede/makefile-edit)
|
||||
(require 'semantic/find) ;; for semantic-find-tags-by-...
|
||||
(require 'ede/autoconf-edit)
|
||||
|
||||
(declare-function autoconf-parameters-for-macro "ede/autoconf-edit")
|
||||
(declare-function ede-shell-run-something "ede/shell")
|
||||
(eval-when-compile (require 'compile))
|
||||
|
||||
;;; Code:
|
||||
|
@ -104,7 +96,7 @@
|
|||
;; ("ltlibcustom" project-am-lib ".*?_LTLIBRARIES" t)
|
||||
)
|
||||
"Alist of type names and the type of object to create for them.
|
||||
Each entry is of th form:
|
||||
Each entry is of the form:
|
||||
(EMACSNAME CLASS AUTOMAKEVAR INDIRECT)
|
||||
where EMACSNAME is a name for Emacs to use.
|
||||
CLASS is the EDE target class to represent the target.
|
||||
|
@ -113,6 +105,23 @@ AUTOMAKEVAR is the Automake variable to identify. This cannot be a
|
|||
INDIRECT is optional. If it is non-nil, then the variable in
|
||||
question lists other variables that need to be looked up.")
|
||||
|
||||
|
||||
(defconst project-am-meta-type-alist
|
||||
'((project-am-program "_PROGRAMS$" t)
|
||||
(project-am-lib "_\\(LIBS\\|LIBRARIES\\|LTLIBRARIES\\)$" t)
|
||||
|
||||
;; direct primary target use a dummy object (man target)
|
||||
;; update to: * 3.3 Uniform in automake-1.11 info node.
|
||||
(project-am-man "_\\(DATA\\|HEADERS\\|PYTHON\\|JAVA\\|SCRIPTS\\|MANS\\|TEXINFOS\\)$" nil)
|
||||
)
|
||||
"Alist of meta-target type, each entry has form:
|
||||
(CLASS REGEXPVAR INDIRECT)
|
||||
where CLASS is the EDE target class for target.
|
||||
REGEXPVAR is the regexp used in `semantic-find-tags-by-name-regexp'.
|
||||
INDIRECT is optional. If it is non-nil, then the variable in it have
|
||||
other meta-variable based on this name.")
|
||||
|
||||
|
||||
(defclass project-am-target (ede-target)
|
||||
nil
|
||||
"Base target class for everything in project-am.")
|
||||
|
@ -291,16 +300,6 @@ buffer being in order to provide a smart default target type."
|
|||
;; Rescan the object in this makefile.
|
||||
(project-rescan ede-object))))
|
||||
|
||||
;(defun project-am-rescan-toplevel ()
|
||||
; "Rescan all projects in which the current buffer resides."
|
||||
; (interactive)
|
||||
; (let* ((tlof (project-am-find-topmost-level default-directory))
|
||||
; (tlo (project-am-load tlof))
|
||||
; (ede-deep-rescan t)) ; scan deep in this case.
|
||||
; ;; tlo is the top level object for whatever file we are in
|
||||
; ;; or nil. If we have an object, call the rescan method.
|
||||
; (if tlo (project-am-rescan tlo))))
|
||||
|
||||
;;
|
||||
;; NOTE TO SELF
|
||||
;;
|
||||
|
@ -406,6 +405,7 @@ Argument COMMAND is the command to use for compiling the target."
|
|||
|
||||
(defmethod project-run-target ((obj project-am-objectcode))
|
||||
"Run the current project target in comint buffer."
|
||||
(require 'ede/shell)
|
||||
(let ((tb (get-buffer-create " *padt*"))
|
||||
(dd (oref obj path))
|
||||
(cmd nil))
|
||||
|
@ -429,45 +429,17 @@ Argument COMMAND is the command to use for compiling the target."
|
|||
|
||||
;;; Project loading and saving
|
||||
;;
|
||||
(defun project-am-load (project &optional rootproj)
|
||||
"Read an automakefile PROJECT into our data structure.
|
||||
Make sure that the tree down to our makefile is complete so that there
|
||||
is cohesion in the project. Return the project file (or sub-project).
|
||||
(defun project-am-load (directory &optional rootproj)
|
||||
"Read an automakefile DIRECTORY into our data structure.
|
||||
If a given set of projects has already been loaded, then do nothing
|
||||
but return the project for the directory given.
|
||||
Optional ROOTPROJ is the root EDE project."
|
||||
;; @TODO - rationalize this to the newer EDE way of doing things.
|
||||
(setq project (expand-file-name project))
|
||||
(let* ((ede-constructing t)
|
||||
(fn (project-am-find-topmost-level (file-name-as-directory project)))
|
||||
(amo nil)
|
||||
(trimmed (if (string-match (regexp-quote fn)
|
||||
project)
|
||||
(replace-match "" t t project)
|
||||
""))
|
||||
(subdir nil))
|
||||
(setq amo (object-assoc (expand-file-name "Makefile.am" fn)
|
||||
'file ede-projects))
|
||||
(if amo
|
||||
(error "Synchronous error in ede/project-am objects")
|
||||
(let ((project-am-constructing t))
|
||||
(setq amo (project-am-load-makefile fn))))
|
||||
(if (not amo)
|
||||
nil
|
||||
;; Now scan down from amo, and find the current directory
|
||||
;; from the PROJECT file.
|
||||
(while (< 0 (length trimmed))
|
||||
(if (string-match "\\([a-zA-Z0-9.-]+\\)/" trimmed)
|
||||
(setq subdir (match-string 0 trimmed)
|
||||
trimmed (replace-match "" t t trimmed))
|
||||
(error "Error scanning down path for project"))
|
||||
(setq amo (project-am-subtree
|
||||
amo
|
||||
(expand-file-name "Makefile.am"
|
||||
(expand-file-name subdir fn)))
|
||||
fn (expand-file-name subdir fn)))
|
||||
amo)
|
||||
))
|
||||
(let* ((ede-constructiong t)
|
||||
(amo (object-assoc (expand-file-name "Makefile.am" directory)
|
||||
'file ede-projects)))
|
||||
(when (not amo)
|
||||
(setq amo (project-am-load-makefile directory)))
|
||||
amo))
|
||||
|
||||
(defun project-am-find-topmost-level (dir)
|
||||
"Find the topmost automakefile starting with DIR."
|
||||
|
@ -488,17 +460,19 @@ Kill the makefile if it was not loaded before the load."
|
|||
(fb nil)
|
||||
(kb (get-file-buffer fn)))
|
||||
(if (not (file-exists-p fn))
|
||||
nil
|
||||
(save-excursion
|
||||
(if kb (setq fb kb)
|
||||
;; We need to find-file this thing, but don't use
|
||||
;; any semantic features.
|
||||
(let ((semantic-init-hook nil))
|
||||
(setq fb (find-file-noselect fn)))
|
||||
)
|
||||
(set-buffer fb)
|
||||
(prog1 ,@forms
|
||||
(if (not kb) (kill-buffer (current-buffer))))))))
|
||||
nil
|
||||
(save-excursion
|
||||
(if kb (setq fb kb)
|
||||
;; We need to find-file this thing, but don't use
|
||||
;; any semantic features.
|
||||
(let ((semantic-init-hook nil)
|
||||
(recentf-exclude '( (lambda (f) t) ))
|
||||
)
|
||||
(setq fb (find-file-noselect fn)))
|
||||
)
|
||||
(set-buffer fb)
|
||||
(prog1 ,@forms
|
||||
(if (not kb) (kill-buffer (current-buffer))))))))
|
||||
(put 'project-am-with-makefile-current 'lisp-indent-function 1)
|
||||
|
||||
(add-hook 'edebug-setup-hook
|
||||
|
@ -507,14 +481,18 @@ Kill the makefile if it was not loaded before the load."
|
|||
(form def-body))))
|
||||
|
||||
|
||||
(defun project-am-load-makefile (path)
|
||||
(defun project-am-load-makefile (path &optional suggestedname)
|
||||
"Convert PATH into a project Makefile, and return its project object.
|
||||
It does not check for existing project objects. Use `project-am-load'."
|
||||
It does not check for existing project objects. Use `project-am-load'.
|
||||
Optional argument SUGGESTEDNAME will be the project name.
|
||||
This is used when subprojects are made in named subdirectories."
|
||||
(project-am-with-makefile-current path
|
||||
(if (and ede-object (project-am-makefile-p ede-object))
|
||||
ede-object
|
||||
(let* ((pi (project-am-package-info path))
|
||||
(pn (or (nth 0 pi) (project-am-last-dir fn)))
|
||||
(sfn (when suggestedname
|
||||
(project-am-last-dir suggestedname)))
|
||||
(pn (or sfn (nth 0 pi) (project-am-last-dir fn)))
|
||||
(ver (or (nth 1 pi) "0.0"))
|
||||
(bug (nth 2 pi))
|
||||
(cof (nth 3 pi))
|
||||
|
@ -532,21 +510,6 @@ It does not check for existing project objects. Use `project-am-load'."
|
|||
ampf))))
|
||||
|
||||
;;; Methods:
|
||||
(defmethod ede-find-target ((amf project-am-makefile) buffer)
|
||||
"Fetch the target belonging to BUFFER."
|
||||
(or (call-next-method)
|
||||
(let ((targ (oref amf targets))
|
||||
(sobj (oref amf subproj))
|
||||
(obj nil))
|
||||
(while (and targ (not obj))
|
||||
(if (ede-buffer-mine (car targ) buffer)
|
||||
(setq obj (car targ)))
|
||||
(setq targ (cdr targ)))
|
||||
(while (and sobj (not obj))
|
||||
(setq obj (project-am-buffer-object (car sobj) buffer)
|
||||
sobj (cdr sobj)))
|
||||
obj)))
|
||||
|
||||
(defmethod project-targets-for-file ((proj project-am-makefile))
|
||||
"Return a list of targets the project PROJ."
|
||||
(oref proj targets))
|
||||
|
@ -556,44 +519,110 @@ It does not check for existing project objects. Use `project-am-load'."
|
|||
CURRPROJ is the current project being scanned.
|
||||
DIR is the directory to apply to new targets."
|
||||
(let* ((otargets (oref currproj targets))
|
||||
;; `ntargets' results in complete targets list
|
||||
;; not only the new targets by diffing.
|
||||
(ntargets nil)
|
||||
(tmp nil)
|
||||
)
|
||||
(mapc
|
||||
;; Map all the different types
|
||||
(lambda (typecar)
|
||||
(let ((macro (nth 2 typecar))
|
||||
(class (nth 1 typecar))
|
||||
(indirect (nth 3 typecar))
|
||||
;(name (car typecar))
|
||||
)
|
||||
(if indirect
|
||||
;; Map all the found objects
|
||||
(mapc (lambda (lstcar)
|
||||
(setq tmp (object-assoc lstcar 'name otargets))
|
||||
(when (not tmp)
|
||||
(setq tmp (apply class lstcar :name lstcar
|
||||
:path dir nil)))
|
||||
(project-rescan tmp)
|
||||
(setq ntargets (cons tmp ntargets)))
|
||||
(makefile-macro-file-list macro))
|
||||
;; Non-indirect will have a target whos sources
|
||||
;; are actual files, not names of other targets.
|
||||
(let ((files (makefile-macro-file-list macro)))
|
||||
(when files
|
||||
(setq tmp (object-assoc macro 'name otargets))
|
||||
(when (not tmp)
|
||||
(setq tmp (apply class macro :name macro
|
||||
:path dir nil)))
|
||||
(project-rescan tmp)
|
||||
(setq ntargets (cons tmp ntargets))
|
||||
))
|
||||
)
|
||||
))
|
||||
project-am-type-alist)
|
||||
ntargets))
|
||||
|
||||
(defmethod project-rescan ((this project-am-makefile))
|
||||
(mapc
|
||||
;; Map all the different types
|
||||
(lambda (typecar)
|
||||
(let ((macro (nth 2 typecar))
|
||||
(class (nth 1 typecar))
|
||||
(indirect (nth 3 typecar))
|
||||
)
|
||||
(if indirect
|
||||
;; Map all the found objects
|
||||
(mapc (lambda (lstcar)
|
||||
(setq tmp (object-assoc lstcar 'name otargets))
|
||||
(when (not tmp)
|
||||
(setq tmp (apply class lstcar :name lstcar
|
||||
:path dir nil)))
|
||||
(project-rescan tmp)
|
||||
(setq ntargets (cons tmp ntargets)))
|
||||
(makefile-macro-file-list macro))
|
||||
;; Non-indirect will have a target whos sources
|
||||
;; are actual files, not names of other targets.
|
||||
(let ((files (makefile-macro-file-list macro)))
|
||||
(when files
|
||||
(setq tmp (object-assoc macro 'name otargets))
|
||||
(when (not tmp)
|
||||
(setq tmp (apply class macro :name macro
|
||||
:path dir nil)))
|
||||
(project-rescan tmp)
|
||||
(setq ntargets (cons tmp ntargets))
|
||||
))
|
||||
)
|
||||
))
|
||||
project-am-type-alist)
|
||||
|
||||
;; At now check variables for meta-target regexp
|
||||
;; We have to check ntargets to avoid useless rescan.
|
||||
;; Also we have check otargets to prevent duplication.
|
||||
(mapc
|
||||
(lambda (typecar)
|
||||
(let ((class (nth 0 typecar))
|
||||
(metaregex (nth 1 typecar))
|
||||
(indirect (nth 2 typecar)))
|
||||
(if indirect
|
||||
;; Map all the found objects
|
||||
(mapc
|
||||
(lambda (lstcar)
|
||||
(unless (object-assoc lstcar 'name ntargets)
|
||||
(or
|
||||
(setq tmp (object-assoc lstcar 'name otargets))
|
||||
(setq tmp (apply class lstcar :name lstcar
|
||||
:path dir nil)))
|
||||
(project-rescan tmp)
|
||||
(setq ntargets (cons tmp ntargets))))
|
||||
;; build a target list to map over
|
||||
(let (atargets)
|
||||
(dolist (TAG
|
||||
(semantic-find-tags-by-name-regexp
|
||||
metaregex (semantic-find-tags-by-class
|
||||
'variable (semantic-fetch-tags))))
|
||||
;; default-value have to be a list
|
||||
(when (cadr (assoc ':default-value TAG))
|
||||
(setq atargets
|
||||
(append
|
||||
(nreverse (cadr (assoc ':default-value TAG)))
|
||||
atargets))))
|
||||
(nreverse atargets)))
|
||||
|
||||
;; else not indirect, TODO: FIX various direct meta type in a sane way.
|
||||
(dolist (T (semantic-find-tags-by-name-regexp
|
||||
metaregex (semantic-find-tags-by-class
|
||||
'variable (semantic-fetch-tags))))
|
||||
(unless (setq tmp (object-assoc (car T) 'name ntargets))
|
||||
(or (setq tmp (object-assoc (car T) 'name otargets))
|
||||
;; we are really new
|
||||
(setq tmp (apply class (car T) :name (car T)
|
||||
:path dir nil)))
|
||||
(project-rescan tmp)
|
||||
(setq ntargets (cons tmp ntargets))))
|
||||
)))
|
||||
project-am-meta-type-alist)
|
||||
ntargets))
|
||||
|
||||
(defun project-am-expand-subdirlist (place subdirs)
|
||||
"Store in PLACE the SUBDIRS expanded from variables.
|
||||
Strip out duplicates, and recurse on variables."
|
||||
(mapc (lambda (sp)
|
||||
(let ((var (makefile-extract-varname-from-text sp)))
|
||||
(if var
|
||||
;; If it is a variable, expand that variable, and keep going.
|
||||
(project-am-expand-subdirlist
|
||||
place (makefile-macro-file-list var))
|
||||
;; Else, add SP in if it isn't a dup.
|
||||
(if (member sp (symbol-value place))
|
||||
nil ; don't do it twice.
|
||||
(set place (cons sp (symbol-value place))) ;; add
|
||||
))))
|
||||
subdirs)
|
||||
)
|
||||
|
||||
(defmethod project-rescan ((this project-am-makefile) &optional suggestedname)
|
||||
"Rescan the makefile for all targets and sub targets."
|
||||
(project-am-with-makefile-current (file-name-directory (oref this file))
|
||||
;;(message "Scanning %s..." (oref this file))
|
||||
|
@ -603,10 +632,10 @@ DIR is the directory to apply to new targets."
|
|||
(bug (nth 2 pi))
|
||||
(cof (nth 3 pi))
|
||||
(osubproj (oref this subproj))
|
||||
(csubproj (or
|
||||
;; If DIST_SUBDIRS doesn't exist, then go for the
|
||||
;; static list of SUBDIRS. The DIST version should
|
||||
;; contain SUBDIRS plus extra stuff.
|
||||
;; 1/30/10 - We need to append these two lists together,
|
||||
;; then strip out duplicates. Expanding this list (via
|
||||
;; references to other variables should also strip out dups
|
||||
(csubproj (append
|
||||
(makefile-macro-file-list "DIST_SUBDIRS")
|
||||
(makefile-macro-file-list "SUBDIRS")))
|
||||
(csubprojexpanded nil)
|
||||
|
@ -617,79 +646,57 @@ DIR is the directory to apply to new targets."
|
|||
(tmp nil)
|
||||
(ntargets (project-am-scan-for-targets this dir))
|
||||
)
|
||||
|
||||
(and pn (string= (directory-file-name
|
||||
(oref this directory))
|
||||
(directory-file-name
|
||||
(project-am-find-topmost-level
|
||||
(oref this directory))))
|
||||
(oset this name pn)
|
||||
(and pv (oset this version pv))
|
||||
(and bug (oset this mailinglist bug))
|
||||
(oset this configureoutputfiles cof))
|
||||
|
||||
; ;; LISP is different. Here there is only one kind of lisp (that I know of
|
||||
; ;; anyway) so it doesn't get mapped when it is found.
|
||||
; (if (makefile-move-to-macro "lisp_LISP")
|
||||
; (let ((tmp (project-am-lisp "lisp"
|
||||
; :name "lisp"
|
||||
; :path dir)))
|
||||
; (project-rescan tmp)
|
||||
; (setq ntargets (cons tmp ntargets))))
|
||||
;
|
||||
(if suggestedname
|
||||
(oset this name (project-am-last-dir suggestedname))
|
||||
;; Else, setup toplevel project info.
|
||||
(and pn (string= (directory-file-name
|
||||
(oref this directory))
|
||||
(directory-file-name
|
||||
(project-am-find-topmost-level
|
||||
(oref this directory))))
|
||||
(oset this name pn)
|
||||
(and pv (oset this version pv))
|
||||
(and bug (oset this mailinglist bug))
|
||||
(oset this configureoutputfiles cof)))
|
||||
;; Now that we have this new list, chuck the old targets
|
||||
;; and replace it with the new list of targets I just created.
|
||||
(oset this targets (nreverse ntargets))
|
||||
;; We still have a list of targets. For all buffers, make sure
|
||||
;; their object still exists!
|
||||
|
||||
;; FIGURE THIS OUT
|
||||
|
||||
(mapc (lambda (sp)
|
||||
(let ((var (makefile-extract-varname-from-text sp))
|
||||
)
|
||||
(if (not var)
|
||||
(setq csubprojexpanded (cons sp csubprojexpanded))
|
||||
;; If it is a variable, expand that variable, and keep going.
|
||||
(let ((varexp (makefile-macro-file-list var)))
|
||||
(dolist (V varexp)
|
||||
(setq csubprojexpanded (cons V csubprojexpanded)))))
|
||||
))
|
||||
csubproj)
|
||||
|
||||
(project-am-expand-subdirlist 'csubprojexpanded csubproj)
|
||||
;; Ok, now lets look at all our sub-projects.
|
||||
(mapc (lambda (sp)
|
||||
(let* ((subdir (file-name-as-directory
|
||||
(expand-file-name
|
||||
sp (file-name-directory (oref this :file)))))
|
||||
(submake (expand-file-name
|
||||
"Makefile.am"
|
||||
subdir)))
|
||||
(if (string= submake (oref this :file))
|
||||
nil ;; don't recurse.. please!
|
||||
|
||||
;; For each project id found, see if we need to recycle,
|
||||
;; and if we do not, then make a new one. Check the deep
|
||||
;; rescan value for behavior patterns.
|
||||
(setq tmp (object-assoc
|
||||
submake
|
||||
'file osubproj))
|
||||
(if (not tmp)
|
||||
(setq tmp
|
||||
(condition-case nil
|
||||
;; In case of problem, ignore it.
|
||||
(project-am-load-makefile subdir)
|
||||
(error nil)))
|
||||
;; If we have tmp, then rescan it only if deep mode.
|
||||
(if ede-deep-rescan
|
||||
(project-rescan tmp)))
|
||||
;; Tac tmp onto our list of things to keep, but only
|
||||
;; if tmp was found.
|
||||
(when tmp
|
||||
;;(message "Adding %S" (object-print tmp))
|
||||
(setq nsubproj (cons tmp nsubproj)))))
|
||||
)
|
||||
(nreverse csubprojexpanded))
|
||||
(let* ((subdir (file-name-as-directory
|
||||
(expand-file-name
|
||||
sp (file-name-directory (oref this :file)))))
|
||||
(submake (expand-file-name
|
||||
"Makefile.am"
|
||||
subdir)))
|
||||
(if (string= submake (oref this :file))
|
||||
nil ;; don't recurse.. please!
|
||||
;; For each project id found, see if we need to recycle,
|
||||
;; and if we do not, then make a new one. Check the deep
|
||||
;; rescan value for behavior patterns.
|
||||
(setq tmp (object-assoc
|
||||
submake
|
||||
'file osubproj))
|
||||
(if (not tmp)
|
||||
(setq tmp
|
||||
(condition-case nil
|
||||
;; In case of problem, ignore it.
|
||||
(project-am-load-makefile subdir subdir)
|
||||
(error nil)))
|
||||
;; If we have tmp, then rescan it only if deep mode.
|
||||
(if ede-deep-rescan
|
||||
(project-rescan tmp subdir)))
|
||||
;; Tac tmp onto our list of things to keep, but only
|
||||
;; if tmp was found.
|
||||
(when tmp
|
||||
;;(message "Adding %S" (object-print tmp))
|
||||
(setq nsubproj (cons tmp nsubproj)))))
|
||||
)
|
||||
(nreverse csubprojexpanded))
|
||||
(oset this subproj nsubproj)
|
||||
;; All elements should be updated now.
|
||||
)))
|
||||
|
@ -698,12 +705,16 @@ DIR is the directory to apply to new targets."
|
|||
(defmethod project-rescan ((this project-am-program))
|
||||
"Rescan object THIS."
|
||||
(oset this :source (makefile-macro-file-list (project-am-macro this)))
|
||||
(unless (oref this :source)
|
||||
(oset this :source (list (concat (oref this :name) ".c"))))
|
||||
(oset this :ldadd (makefile-macro-file-list
|
||||
(concat (oref this :name) "_LDADD"))))
|
||||
|
||||
(defmethod project-rescan ((this project-am-lib))
|
||||
"Rescan object THIS."
|
||||
(oset this :source (makefile-macro-file-list (project-am-macro this))))
|
||||
(oset this :source (makefile-macro-file-list (project-am-macro this)))
|
||||
(unless (oref this :source)
|
||||
(oset this :source (list (concat (file-name-sans-extension (oref this :name)) ".c")))))
|
||||
|
||||
(defmethod project-rescan ((this project-am-texinfo))
|
||||
"Rescan object THIS."
|
||||
|
@ -728,19 +739,6 @@ DIR is the directory to apply to new targets."
|
|||
(defmethod project-rescan ((this project-am-extra-dist))
|
||||
"Rescan object THIS."
|
||||
(oset this :source (makefile-macro-file-list "EXTRA_DIST")))
|
||||
;; NOTE: The below calls 'file' then checks that it is some sort of
|
||||
;; text file. The file command may not be available on all platforms
|
||||
;; and some files may not exist yet. (ie - auto-generated)
|
||||
|
||||
;;(mapc
|
||||
;; (lambda (f)
|
||||
;; ;; prevent garbage to be parsed, could we use :aux ?
|
||||
;; (if (and (not (member f (oref this :source)))
|
||||
;; (string-match-p "ASCII\\|text"
|
||||
;; (shell-command-to-string
|
||||
;; (concat "file " f))))
|
||||
;; (oset this :source (cons f (oref this :source)))))
|
||||
;; (makefile-macro-file-list "EXTRA_DIST")))
|
||||
|
||||
(defmethod project-am-macro ((this project-am-objectcode))
|
||||
"Return the default macro to 'edit' for this object type."
|
||||
|
@ -810,22 +808,24 @@ nil means that this buffer belongs to no-one."
|
|||
|
||||
(defmethod ede-buffer-mine ((this project-am-objectcode) buffer)
|
||||
"Return t if object THIS lays claim to the file in BUFFER."
|
||||
(member (file-name-nondirectory (buffer-file-name buffer))
|
||||
(member (file-relative-name (buffer-file-name buffer) (oref this :path))
|
||||
(oref this :source)))
|
||||
|
||||
(defmethod ede-buffer-mine ((this project-am-texinfo) buffer)
|
||||
"Return t if object THIS lays claim to the file in BUFFER."
|
||||
(let ((bfn (buffer-file-name buffer)))
|
||||
(or (string= (oref this :name) (file-name-nondirectory bfn))
|
||||
(member (file-name-nondirectory bfn) (oref this :include)))))
|
||||
(let ((bfn (file-relative-name (buffer-file-name buffer)
|
||||
(oref this :path))))
|
||||
(or (string= (oref this :name) bfn)
|
||||
(member bfn (oref this :include)))))
|
||||
|
||||
(defmethod ede-buffer-mine ((this project-am-man) buffer)
|
||||
"Return t if object THIS lays claim to the file in BUFFER."
|
||||
(string= (oref this :name) (buffer-file-name buffer)))
|
||||
(string= (oref this :name)
|
||||
(file-relative-name (buffer-file-name buffer) (oref this :path))))
|
||||
|
||||
(defmethod ede-buffer-mine ((this project-am-lisp) buffer)
|
||||
"Return t if object THIS lays claim to the file in BUFFER."
|
||||
(member (file-name-nondirectory (buffer-file-name buffer))
|
||||
(member (file-relative-name (buffer-file-name buffer) (oref this :path))
|
||||
(oref this :source)))
|
||||
|
||||
(defmethod project-am-subtree ((ampf project-am-makefile) subdir)
|
||||
|
@ -956,7 +956,6 @@ Kill the Configure buffer if it was not already in a buffer."
|
|||
(cond
|
||||
;; Try configure.in or configure.ac
|
||||
(conf-in
|
||||
(require 'ede/autoconf-edit)
|
||||
(project-am-with-config-current conf-in
|
||||
(let ((aci (autoconf-parameters-for-macro "AC_INIT"))
|
||||
(aia (autoconf-parameters-for-macro "AM_INIT_AUTOMAKE"))
|
||||
|
@ -982,7 +981,7 @@ Kill the Configure buffer if it was not already in a buffer."
|
|||
(t acf))))
|
||||
(if (> (length outfiles) 1)
|
||||
(setq configfiles outfiles)
|
||||
(setq configfiles (split-string (car outfiles) " " t)))
|
||||
(setq configfiles (split-string (car outfiles) "\\s-" t)))
|
||||
)
|
||||
))
|
||||
)
|
||||
|
@ -1007,6 +1006,18 @@ Calculates the info with `project-am-extract-package-info'."
|
|||
(when top (setq dir (oref top :directory)))
|
||||
(project-am-extract-package-info dir)))
|
||||
|
||||
;; for simple per project include path extension
|
||||
(defmethod ede-system-include-path ((this project-am-makefile))
|
||||
"Return `project-am-localvars-include-path', usually local variable
|
||||
per file or in .dir-locals.el or similar."
|
||||
(bound-and-true-p project-am-localvars-include-path))
|
||||
|
||||
(defmethod ede-system-include-path ((this project-am-target))
|
||||
"Return `project-am-localvars-include-path', usually local variable
|
||||
per file or in .dir-locals.el or similar."
|
||||
(bound-and-true-p project-am-localvars-include-path))
|
||||
|
||||
|
||||
(provide 'ede/project-am)
|
||||
|
||||
;; arch-tag: 528db935-f186-4240-b647-e305c5b784a2
|
||||
|
|
|
@ -70,7 +70,7 @@ COMMAND is a text string representing the thing to be run."
|
|||
(defmethod ede-shell-buffer ((target ede-target))
|
||||
"Get the buffer for running shell commands for TARGET."
|
||||
(let ((name (ede-name target)))
|
||||
(get-buffer-create (format "*EDE Shell %s" name))))
|
||||
(get-buffer-create (format "*EDE Shell %s*" name))))
|
||||
|
||||
(provide 'ede/shell)
|
||||
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; NOTE: EDE Simple Projects are considered obsolete. Use generic
|
||||
;; projects instead. They have much better automatic support and
|
||||
;; simpler configuration.
|
||||
;;
|
||||
;; A vast majority of projects use non-EDE project techniques, such
|
||||
;; as hand written Makefiles, or other IDE's.
|
||||
;;
|
||||
|
@ -41,6 +45,14 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
(add-to-list 'ede-project-class-files
|
||||
(ede-project-autoload "simple-overlay"
|
||||
:name "Simple" :file 'ede/simple
|
||||
:proj-file 'ede-simple-projectfile-for-dir
|
||||
:load-type 'ede-simple-load
|
||||
:class-sym 'ede-simple-project)
|
||||
t)
|
||||
|
||||
(defcustom ede-simple-save-directory "~/.ede"
|
||||
"*Directory where simple EDE project overlays are saved."
|
||||
:group 'ede
|
||||
|
|
|
@ -108,7 +108,7 @@ Argument DIR is the directory from which to derive the list of objects."
|
|||
;;; Some special commands useful in EDE
|
||||
;;
|
||||
(defun ede-speedbar-remove-file-from-target ()
|
||||
"Remove the file at point from it's target."
|
||||
"Remove the file at point from its target."
|
||||
(interactive)
|
||||
(if (stringp (speedbar-line-token))
|
||||
(progn
|
||||
|
|
|
@ -43,7 +43,9 @@
|
|||
(srecode-map-update-map t)
|
||||
;; We don't call this unless we need it. Load in the templates.
|
||||
(srecode-load-tables-for-mode 'makefile-mode)
|
||||
(srecode-load-tables-for-mode 'makefile-mode 'ede))
|
||||
(srecode-load-tables-for-mode 'makefile-mode 'ede)
|
||||
(srecode-load-tables-for-mode 'autoconf-mode)
|
||||
(srecode-load-tables-for-mode 'autoconf-mode 'ede))
|
||||
|
||||
(defmacro ede-srecode-insert-with-dictionary (template &rest forms)
|
||||
"Insert TEMPLATE after executing FORMS with a dictionary.
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
;;; Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Eric M. Ludlam <eric@siege-engine.com>
|
||||
;; Version: 1.0
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
|
@ -57,10 +58,14 @@
|
|||
(error nil)))
|
||||
|
||||
(defcustom pulse-flag (pulse-available-p)
|
||||
"*Non-nil means to pulse the overlay face for momentary highlighting.
|
||||
Pulsing involves a bright highlight that slowly shifts to the background
|
||||
color. Non-nil just means to highlight with an unchanging color for a short
|
||||
time.
|
||||
"Whether to use pulsing for momentary highlighting.
|
||||
Pulsing involves a bright highlight that slowly shifts to the
|
||||
background color.
|
||||
|
||||
If the value is nil, highlight with an unchanging color until a
|
||||
key is pressed.
|
||||
If the value is `never', do no coloring at all.
|
||||
Any other value means to the default pulsing behavior.
|
||||
|
||||
If `pulse-flag' is non-nil, but `pulse-available-p' is nil, then
|
||||
this flag is ignored."
|
||||
|
@ -178,22 +183,23 @@ Be sure to call `pulse-reset-face' after calling pulse."
|
|||
Optional argument FACE specifies the fact to do the highlighting."
|
||||
(overlay-put o 'original-face (overlay-get o 'face))
|
||||
(add-to-list 'pulse-momentary-overlay o)
|
||||
(if (or (not pulse-flag) (not (pulse-available-p)))
|
||||
;; Provide a face... clear on next command
|
||||
(progn
|
||||
(overlay-put o 'face (or face 'pulse-highlight-start-face))
|
||||
(add-hook 'pre-command-hook
|
||||
'pulse-momentary-unhighlight)
|
||||
)
|
||||
;; pulse it.
|
||||
(unwind-protect
|
||||
(if (eq pulse-flag 'never)
|
||||
nil
|
||||
(if (or (not pulse-flag) (not (pulse-available-p)))
|
||||
;; Provide a face... clear on next command
|
||||
(progn
|
||||
(overlay-put o 'face 'pulse-highlight-face)
|
||||
;; The pulse function puts FACE onto 'pulse-highlight-face.
|
||||
;; Thus above we put our face on the overlay, but pulse
|
||||
;; with a reference face needed for the color.
|
||||
(pulse face))
|
||||
(pulse-momentary-unhighlight))))
|
||||
(overlay-put o 'face (or face 'pulse-highlight-start-face))
|
||||
(add-hook 'pre-command-hook
|
||||
'pulse-momentary-unhighlight))
|
||||
;; pulse it.
|
||||
(unwind-protect
|
||||
(progn
|
||||
(overlay-put o 'face 'pulse-highlight-face)
|
||||
;; The pulse function puts FACE onto 'pulse-highlight-face.
|
||||
;; Thus above we put our face on the overlay, but pulse
|
||||
;; with a reference face needed for the color.
|
||||
(pulse face))
|
||||
(pulse-momentary-unhighlight)))))
|
||||
|
||||
(defun pulse-momentary-unhighlight ()
|
||||
"Unhighlight a line recently highlighted."
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
;; Author: Eric M. Ludlam <zappo@gnu.org>
|
||||
;; Keywords: syntax tools
|
||||
;; Version: 2.0pre7
|
||||
;; Version: 2.0
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
|||
(require 'semantic/tag)
|
||||
(require 'semantic/lex)
|
||||
|
||||
(defvar semantic-version "2.0pre7"
|
||||
(defvar semantic-version "2.0"
|
||||
"Current version of Semantic.")
|
||||
|
||||
(declare-function inversion-test "inversion")
|
||||
|
@ -876,6 +876,7 @@ Throw away all the old tags, and recreate the tag database."
|
|||
;; (define-key km "i" 'senator-isearch-toggle-semantic-mode)
|
||||
(define-key map "\C-c,j" 'semantic-complete-jump-local)
|
||||
(define-key map "\C-c,J" 'semantic-complete-jump)
|
||||
(define-key map "\C-c,m" 'semantic-complete-jump-local-members)
|
||||
(define-key map "\C-c,g" 'semantic-symref-symbol)
|
||||
(define-key map "\C-c,G" 'semantic-symref)
|
||||
(define-key map "\C-c,p" 'senator-previous-tag)
|
||||
|
@ -886,6 +887,7 @@ Throw away all the old tags, and recreate the tag database."
|
|||
(define-key map "\C-c,\M-w" 'senator-copy-tag)
|
||||
(define-key map "\C-c,\C-y" 'senator-yank-tag)
|
||||
(define-key map "\C-c,r" 'senator-copy-tag-to-register)
|
||||
(define-key map "\C-c,," 'semantic-force-refresh)
|
||||
(define-key map [?\C-c ?, up] 'senator-transpose-tags-up)
|
||||
(define-key map [?\C-c ?, down] 'senator-transpose-tags-down)
|
||||
(define-key map "\C-c,l" 'semantic-analyze-possible-completions)
|
||||
|
@ -951,6 +953,9 @@ Throw away all the old tags, and recreate the tag database."
|
|||
(define-key navigate-menu [semantic-complete-jump]
|
||||
'(menu-item "Find Tag Globally..." semantic-complete-jump
|
||||
:help "Read a tag name and find it in the current project"))
|
||||
(define-key navigate-menu [semantic-complete-jump-local-members]
|
||||
'(menu-item "Find Local Members ..." semantic-complete-jump-local-members
|
||||
:help "Read a tag name and find a local member with that name"))
|
||||
(define-key navigate-menu [semantic-complete-jump-local]
|
||||
'(menu-item "Find Tag in This Buffer..." semantic-complete-jump-local
|
||||
:help "Read a tag name and find it in this buffer"))
|
||||
|
|
|
@ -253,7 +253,7 @@ Optional argument THROWSYM specifies a symbol the throw on non-recoverable error
|
|||
(tag nil) ; tag return list
|
||||
(tagtype nil) ; tag types return list
|
||||
(fname nil)
|
||||
(miniscope (clone scope))
|
||||
(miniscope (when scope (clone scope)))
|
||||
)
|
||||
;; First order check. Is this wholely contained in the typecache?
|
||||
(setq tmp (semanticdb-typecache-find sequence))
|
||||
|
@ -297,11 +297,12 @@ Optional argument THROWSYM specifies a symbol the throw on non-recoverable error
|
|||
;; and we can use it directly.
|
||||
(cond ((semantic-tag-of-class-p tmp 'type)
|
||||
;; update the miniscope when we need to analyze types directly.
|
||||
(let ((rawscope
|
||||
(apply 'append
|
||||
(mapcar 'semantic-tag-type-members
|
||||
tagtype))))
|
||||
(oset miniscope fullscope rawscope))
|
||||
(when miniscope
|
||||
(let ((rawscope
|
||||
(apply 'append
|
||||
(mapcar 'semantic-tag-type-members
|
||||
tagtype))))
|
||||
(oset miniscope fullscope rawscope)))
|
||||
;; Now analayze the type to remove metatypes.
|
||||
(or (semantic-analyze-type tmp miniscope)
|
||||
tmp))
|
||||
|
@ -351,7 +352,7 @@ Optional argument SCOPE specifies a scope object which has
|
|||
additional tags which are in SCOPE and do not need prefixing to
|
||||
find.
|
||||
|
||||
This is a wrapper on top of semanticdb, semanticdb-typecache,
|
||||
This is a wrapper on top of semanticdb, semanticdb typecache,
|
||||
semantic-scope, and semantic search functions. Almost all
|
||||
searches use the same arguments."
|
||||
(let ((namelst (if (consp name) name ;; test if pre-split.
|
||||
|
|
|
@ -63,11 +63,15 @@ Used as options when completing.")
|
|||
;;; MAIN completion calculator
|
||||
;;
|
||||
;;;###autoload
|
||||
(define-overloadable-function semantic-analyze-possible-completions (context)
|
||||
(define-overloadable-function semantic-analyze-possible-completions (context &rest flags)
|
||||
"Return a list of semantic tags which are possible completions.
|
||||
CONTEXT is either a position (such as point), or a precalculated
|
||||
context. Passing in a context is useful if the caller also needs
|
||||
to access parts of the analysis.
|
||||
The remaining FLAGS arguments are passed to the mode specific completion engine.
|
||||
Bad flags should be ignored by modes that don't use them.
|
||||
See `semantic-analyze-possible-completions-default' for details on the default FLAGS.
|
||||
|
||||
Completions run through the following filters:
|
||||
* Elements currently in scope
|
||||
* Constants currently in scope
|
||||
|
@ -98,9 +102,13 @@ in a buffer."
|
|||
(get-buffer-window "*Possible Completions*")))
|
||||
ans)))
|
||||
|
||||
(defun semantic-analyze-possible-completions-default (context)
|
||||
(defun semantic-analyze-possible-completions-default (context &optional flags)
|
||||
"Default method for producing smart completions.
|
||||
Argument CONTEXT is an object specifying the locally derived context."
|
||||
Argument CONTEXT is an object specifying the locally derived context.
|
||||
The optional argument FLAGS changes which return options are returned.
|
||||
FLAGS can be any number of:
|
||||
'no-tc - do not apply data-type constraint.
|
||||
'no-unique - do not apply unique by name filtering."
|
||||
(let* ((a context)
|
||||
(desired-type (semantic-analyze-type-constraint a))
|
||||
(desired-class (oref a prefixclass))
|
||||
|
@ -109,8 +117,13 @@ Argument CONTEXT is an object specifying the locally derived context."
|
|||
(completetext nil)
|
||||
(completetexttype nil)
|
||||
(scope (oref a scope))
|
||||
(localvar (oref scope localvar))
|
||||
(c nil))
|
||||
(localvar (when scope (oref scope localvar)))
|
||||
(origc nil)
|
||||
(c nil)
|
||||
(any nil)
|
||||
(do-typeconstraint (not (memq 'no-tc flags)))
|
||||
(do-unique (not (memq 'no-unique flags)))
|
||||
)
|
||||
|
||||
;; Calculate what our prefix string is so that we can
|
||||
;; find all our matching text.
|
||||
|
@ -160,33 +173,36 @@ Argument CONTEXT is an object specifying the locally derived context."
|
|||
;; Argument list and local variables
|
||||
(semantic-find-tags-for-completion completetext localvar)
|
||||
;; The current scope
|
||||
(semantic-find-tags-for-completion completetext (oref scope fullscope))
|
||||
(semantic-find-tags-for-completion completetext (when scope (oref scope fullscope)))
|
||||
;; The world
|
||||
(semantic-analyze-find-tags-by-prefix completetext))
|
||||
)
|
||||
)
|
||||
|
||||
(let ((origc c)
|
||||
(let ((loopc c)
|
||||
(dtname (semantic-tag-name desired-type)))
|
||||
|
||||
;; Save off our first batch of completions
|
||||
(setq origc c)
|
||||
|
||||
;; Reset c.
|
||||
(setq c nil)
|
||||
|
||||
;; Loop over all the found matches, and catagorize them
|
||||
;; as being possible features.
|
||||
(while origc
|
||||
(while (and loopc do-typeconstraint)
|
||||
|
||||
(cond
|
||||
;; Strip operators
|
||||
((semantic-tag-get-attribute (car origc) :operator-flag)
|
||||
((semantic-tag-get-attribute (car loopc) :operator-flag)
|
||||
nil
|
||||
)
|
||||
|
||||
;; If we are completing from within some prefix,
|
||||
;; then we want to exclude constructors and destructors
|
||||
((and completetexttype
|
||||
(or (semantic-tag-get-attribute (car origc) :constructor-flag)
|
||||
(semantic-tag-get-attribute (car origc) :destructor-flag)))
|
||||
(or (semantic-tag-get-attribute (car loopc) :constructor-flag)
|
||||
(semantic-tag-get-attribute (car loopc) :destructor-flag)))
|
||||
nil
|
||||
)
|
||||
|
||||
|
@ -197,17 +213,17 @@ Argument CONTEXT is an object specifying the locally derived context."
|
|||
;; Ok, we now have a completion list based on the text we found
|
||||
;; we want to complete on. Now filter that stream against the
|
||||
;; type we want to search for.
|
||||
((string= dtname (semantic-analyze-type-to-name (semantic-tag-type (car origc))))
|
||||
(setq c (cons (car origc) c))
|
||||
((string= dtname (semantic-analyze-type-to-name (semantic-tag-type (car loopc))))
|
||||
(setq c (cons (car loopc) c))
|
||||
)
|
||||
|
||||
;; Now anything that is a compound type which could contain
|
||||
;; additional things which are of the desired type
|
||||
((semantic-tag-type (car origc))
|
||||
(let ((att (semantic-analyze-tag-type (car origc) scope))
|
||||
((semantic-tag-type (car loopc))
|
||||
(let ((att (semantic-analyze-tag-type (car loopc) scope))
|
||||
)
|
||||
(if (and att (semantic-tag-type-members att))
|
||||
(setq c (cons (car origc) c))))
|
||||
(setq c (cons (car loopc) c))))
|
||||
)
|
||||
|
||||
) ; cond
|
||||
|
@ -215,11 +231,11 @@ Argument CONTEXT is an object specifying the locally derived context."
|
|||
|
||||
;; No desired type, no other restrictions. Just add.
|
||||
(t
|
||||
(setq c (cons (car origc) c)))
|
||||
(setq c (cons (car loopc) c)))
|
||||
|
||||
); cond
|
||||
|
||||
(setq origc (cdr origc)))
|
||||
(setq loopc (cdr loopc)))
|
||||
|
||||
(when desired-type
|
||||
;; Some types, like the enum in C, have special constant values that
|
||||
|
@ -241,15 +257,16 @@ Argument CONTEXT is an object specifying the locally derived context."
|
|||
(when desired-class
|
||||
(setq c (semantic-analyze-tags-of-class-list c desired-class)))
|
||||
|
||||
;; Pull out trash.
|
||||
;; NOTE TO SELF: Is this too slow?
|
||||
;; OTHER NOTE: Do we not want to strip duplicates by name and
|
||||
;; only by position? When are duplicate by name but not by tag
|
||||
;; useful?
|
||||
(setq c (semantic-unique-tag-table-by-name c))
|
||||
(if do-unique
|
||||
(if c
|
||||
;; Pull out trash.
|
||||
;; NOTE TO SELF: Is this too slow?
|
||||
(setq c (semantic-unique-tag-table-by-name c))
|
||||
(setq c (semantic-unique-tag-table-by-name origc)))
|
||||
(when (not c)
|
||||
(setq c origc)))
|
||||
|
||||
;; All done!
|
||||
|
||||
c))
|
||||
|
||||
(provide 'semantic/analyze/complete)
|
||||
|
|
|
@ -54,6 +54,8 @@
|
|||
|
||||
))
|
||||
|
||||
;; @TODO - If this happens, but the last found type is
|
||||
;; a datatype, then the below is wrong
|
||||
(defun semantic-analyzer-debug-found-prefix (ctxt)
|
||||
"Debug the prefix found by the analyzer output CTXT."
|
||||
(let* ((pf (oref ctxt prefix))
|
||||
|
@ -97,7 +99,7 @@ Argument COMP are possible completions here."
|
|||
)
|
||||
(with-output-to-temp-buffer (help-buffer)
|
||||
(with-current-buffer standard-output
|
||||
(princ "Unable to find prefix ")
|
||||
(princ "Unable to find symbol ")
|
||||
(princ prefix)
|
||||
(princ ".\n\n")
|
||||
|
||||
|
@ -217,7 +219,7 @@ Argument COMP are possible completions here."
|
|||
(when (not dt) (error "Missing Innertype debugger is confused"))
|
||||
(with-output-to-temp-buffer (help-buffer)
|
||||
(with-current-buffer standard-output
|
||||
(princ "Cannot find prefix \"")
|
||||
(princ "Cannot find symbol \"")
|
||||
(princ prefixitem)
|
||||
(princ "\" in datatype:
|
||||
")
|
||||
|
@ -550,24 +552,25 @@ PARENT is a possible parent (by nesting) tag."
|
|||
(let ((str (semantic-format-tag-prototype tag parent)))
|
||||
(if (and (semantic-tag-with-position-p tag)
|
||||
(semantic-tag-file-name tag))
|
||||
(insert-button str
|
||||
'mouse-face 'custom-button-pressed-face
|
||||
'tag tag
|
||||
'action
|
||||
`(lambda (button)
|
||||
(let ((buff nil)
|
||||
(pnt nil))
|
||||
(save-excursion
|
||||
(semantic-go-to-tag
|
||||
(button-get button 'tag))
|
||||
(setq buff (current-buffer))
|
||||
(setq pnt (point)))
|
||||
(if (get-buffer-window buff)
|
||||
(select-window (get-buffer-window buff))
|
||||
(pop-to-buffer buff t))
|
||||
(goto-char pnt)
|
||||
(pulse-line-hook-function)))
|
||||
)
|
||||
(with-current-buffer standard-output
|
||||
(insert-button str
|
||||
'mouse-face 'custom-button-pressed-face
|
||||
'tag tag
|
||||
'action
|
||||
`(lambda (button)
|
||||
(let ((buff nil)
|
||||
(pnt nil))
|
||||
(save-excursion
|
||||
(semantic-go-to-tag
|
||||
(button-get button 'tag))
|
||||
(setq buff (current-buffer))
|
||||
(setq pnt (point)))
|
||||
(if (get-buffer-window buff)
|
||||
(select-window (get-buffer-window buff))
|
||||
(pop-to-buffer buff t))
|
||||
(goto-char pnt)
|
||||
(pulse-line-hook-function)))
|
||||
))
|
||||
(princ "\"")
|
||||
(princ str)
|
||||
(princ "\""))
|
||||
|
|
|
@ -104,6 +104,7 @@ Use `semantic-analyze-current-tag' to debug this fcn."
|
|||
"Return the implementations derived in the reference analyzer REFS.
|
||||
Optional argument IN-BUFFER indicates that the returned tag should be in an active buffer."
|
||||
(let ((allhits (oref refs rawsearchdata))
|
||||
(tag (oref refs :tag))
|
||||
(impl nil)
|
||||
)
|
||||
(semanticdb-find-result-mapc
|
||||
|
@ -113,7 +114,8 @@ Optional argument IN-BUFFER indicates that the returned tag should be in an acti
|
|||
(aT (cdr ans))
|
||||
(aDB (car ans))
|
||||
)
|
||||
(when (not (semantic-tag-prototype-p aT))
|
||||
(when (and (not (semantic-tag-prototype-p aT))
|
||||
(semantic-tag-similar-p tag aT :prototype-flag :parent))
|
||||
(when in-buffer (save-excursion (semantic-go-to-tag aT aDB)))
|
||||
(push aT impl))))
|
||||
allhits)
|
||||
|
@ -123,6 +125,7 @@ Optional argument IN-BUFFER indicates that the returned tag should be in an acti
|
|||
"Return the prototypes derived in the reference analyzer REFS.
|
||||
Optional argument IN-BUFFER indicates that the returned tag should be in an active buffer."
|
||||
(let ((allhits (oref refs rawsearchdata))
|
||||
(tag (oref refs :tag))
|
||||
(proto nil))
|
||||
(semanticdb-find-result-mapc
|
||||
(lambda (T DB)
|
||||
|
@ -131,7 +134,8 @@ Optional argument IN-BUFFER indicates that the returned tag should be in an acti
|
|||
(aT (cdr ans))
|
||||
(aDB (car ans))
|
||||
)
|
||||
(when (semantic-tag-prototype-p aT)
|
||||
(when (and (semantic-tag-prototype-p aT)
|
||||
(semantic-tag-similar-p tag aT :prototype-flag :parent))
|
||||
(when in-buffer (save-excursion (semantic-go-to-tag aT aDB)))
|
||||
(push aT proto))))
|
||||
allhits)
|
||||
|
@ -142,8 +146,8 @@ Optional argument IN-BUFFER indicates that the returned tag should be in an acti
|
|||
(defun semantic--analyze-refs-full-lookup (tag scope)
|
||||
"Perform a full lookup for all occurrences of TAG in the current project.
|
||||
TAG should be the tag currently under point.
|
||||
PARENT is the list of tags that are parents to TAG by
|
||||
containment, as opposed to reference."
|
||||
SCOPE is the scope the cursor is in. From this a list of parents is
|
||||
derived. If SCOPE does not have parents, then only a simple lookup is done."
|
||||
(if (not (oref scope parents))
|
||||
;; If this tag has some named parent, but is not
|
||||
(semantic--analyze-refs-full-lookup-simple tag)
|
||||
|
@ -177,20 +181,36 @@ CLASS is the class of the tag that ought to be returned."
|
|||
ans))
|
||||
|
||||
(defun semantic--analyze-refs-find-tags-with-parent (find-results parents)
|
||||
"Find in FIND-RESULTS all tags with PARNTS.
|
||||
"Find in FIND-RESULTS all tags with PARENTS.
|
||||
NAME is the name of the tag needing finding.
|
||||
PARENTS is a list of names."
|
||||
(let ((ans nil))
|
||||
(let ((ans nil) (usingnames nil))
|
||||
;; Loop over the find-results passed in.
|
||||
(semanticdb-find-result-mapc
|
||||
(lambda (tag db)
|
||||
(let* ((p (semantic-tag-named-parent tag))
|
||||
(ps (when (stringp p)
|
||||
(semantic-analyze-split-name p))))
|
||||
(ps (when (stringp p) (semantic-analyze-split-name p))))
|
||||
(when (stringp ps) (setq ps (list ps)))
|
||||
(when (and ps (equal ps parents))
|
||||
;; We could optimize this, but it seems unlikely.
|
||||
(push (list db tag) ans))
|
||||
))
|
||||
(when ps
|
||||
;; If there is a perfect match, then use it.
|
||||
(if (equal ps parents)
|
||||
(push (list db tag) ans))
|
||||
;; No match, find something from our list of using names.
|
||||
;; Do we need to split UN?
|
||||
(save-excursion
|
||||
(semantic-go-to-tag tag db)
|
||||
(setq usingnames nil)
|
||||
(let ((imports (semantic-ctxt-imported-packages)))
|
||||
;; Derive the names from all the using statements.
|
||||
(mapc (lambda (T)
|
||||
(setq usingnames
|
||||
(cons (semantic-format-tag-name-from-anything T) usingnames)))
|
||||
imports))
|
||||
(dolist (UN usingnames)
|
||||
(when (equal (cons UN ps) parents)
|
||||
(push (list db tag) ans)
|
||||
(setq usingnames (cdr usingnames))))
|
||||
))))
|
||||
find-results)
|
||||
ans))
|
||||
|
||||
|
@ -206,7 +226,7 @@ TAG should be the tag currently under point."
|
|||
;; Find all hits for the first parent name.
|
||||
(brute (semanticdb-find-tags-collector
|
||||
(lambda (table tags)
|
||||
(semanticdb-find-tags-by-name-method table name tags)
|
||||
(semanticdb-deep-find-tags-by-name-method table name tags)
|
||||
)
|
||||
nil nil t))
|
||||
;; Prime the answer.
|
||||
|
@ -214,6 +234,7 @@ TAG should be the tag currently under point."
|
|||
)
|
||||
;; First parent is already search to initialize "brute".
|
||||
(setq plist (cdr plist))
|
||||
|
||||
;; Go through the list of parents, and try to find matches.
|
||||
;; As we cycle through plist, for each level look for NAME,
|
||||
;; and compare the named-parent, and also dive into the next item of
|
||||
|
@ -253,7 +274,8 @@ Only works for tags in the global namespace."
|
|||
(lambda (table tags)
|
||||
(semanticdb-find-tags-by-name-method table name tags)
|
||||
)
|
||||
nil nil t))
|
||||
nil ;; This may need to be the entire project??
|
||||
nil t))
|
||||
)
|
||||
|
||||
(when (and (not brute) (not noerror))
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
(declare-function semantic-brute-find-tag-by-attribute "semantic/find")
|
||||
(declare-function semanticdb-minor-mode-p "semantic/db-mode")
|
||||
(declare-function semanticdb-needs-refresh-p "semantic/db")
|
||||
(declare-function semanticdb-typecache-faux-namespace "semantic/db-typecache")
|
||||
(declare-function c-forward-conditional "cc-cmds")
|
||||
(declare-function ede-system-include-path "ede")
|
||||
|
||||
|
@ -158,7 +159,7 @@ part of the preprocessor map.")
|
|||
Each entry is a cons cell like this:
|
||||
( \"KEYWORD\" . \"REPLACEMENT\" )
|
||||
Where KEYWORD is the macro that gets replaced in the lexical phase,
|
||||
and REPLACEMENT is a string that is inserted in it's place. Empty string
|
||||
and REPLACEMENT is a string that is inserted in its place. Empty string
|
||||
implies that the lexical analyzer will discard KEYWORD when it is encountered.
|
||||
|
||||
Alternately, it can be of the form:
|
||||
|
@ -295,6 +296,7 @@ Moves completely over balanced #if blocks."
|
|||
(cond
|
||||
((looking-at "^\\s-*#\\s-*if")
|
||||
;; We found a nested if. Skip it.
|
||||
;; @TODO - can we use the new c-scan-conditionals
|
||||
(c-forward-conditional 1))
|
||||
((looking-at "^\\s-*#\\s-*elif")
|
||||
;; We need to let the preprocessor analize this one.
|
||||
|
@ -348,7 +350,6 @@ Uses known macro tables in SPP to determine what block to skip."
|
|||
;; (message "%s %s yes" ift sym)
|
||||
(beginning-of-line)
|
||||
(setq pt (point))
|
||||
;;(c-forward-conditional 1)
|
||||
;; This skips only a section of a conditional. Once that section
|
||||
;; is opened, encountering any new #else or related conditional
|
||||
;; should be skipped.
|
||||
|
@ -356,8 +357,8 @@ Uses known macro tables in SPP to determine what block to skip."
|
|||
(setq semantic-lex-end-point (point))
|
||||
(semantic-push-parser-warning (format "Skip #%s %s" ift sym)
|
||||
pt (point))
|
||||
;; (semantic-lex-push-token
|
||||
;; (semantic-lex-token 'c-preprocessor-skip pt (point)))
|
||||
;; (semantic-lex-push-token
|
||||
;; (semantic-lex-token 'c-preprocessor-skip pt (point)))
|
||||
nil)
|
||||
;; Else, don't ignore it, but do handle the internals.
|
||||
;;(message "%s %s no" ift sym)
|
||||
|
@ -703,58 +704,60 @@ the regular parser."
|
|||
(symtext (semantic-lex-token-text lexicaltoken))
|
||||
(macros (get-text-property 0 'macros symtext))
|
||||
)
|
||||
(with-current-buffer buf
|
||||
(erase-buffer)
|
||||
(when (not (eq major-mode mode))
|
||||
(save-match-data
|
||||
(if (> semantic-c-parse-token-hack-depth 5)
|
||||
nil
|
||||
(with-current-buffer buf
|
||||
(erase-buffer)
|
||||
(when (not (eq major-mode mode))
|
||||
(save-match-data
|
||||
|
||||
;; Protect against user hooks throwing errors.
|
||||
(condition-case nil
|
||||
(funcall mode)
|
||||
(error
|
||||
(if (y-or-n-p
|
||||
(format "There was an error initializing %s in buffer \"%s\". Debug your hooks? "
|
||||
mode (buffer-name)))
|
||||
(semantic-c-debug-mode-init mode)
|
||||
(message "Macro parsing state may be broken...")
|
||||
(sit-for 1))))
|
||||
) ; save match data
|
||||
;; Protect against user hooks throwing errors.
|
||||
(condition-case nil
|
||||
(funcall mode)
|
||||
(error
|
||||
(if (y-or-n-p
|
||||
(format "There was an error initializing %s in buffer \"%s\". Debug your hooks? "
|
||||
mode (buffer-name)))
|
||||
(semantic-c-debug-mode-init mode)
|
||||
(message "Macro parsing state may be broken...")
|
||||
(sit-for 1))))
|
||||
) ; save match data
|
||||
|
||||
;; Hack in mode-local
|
||||
(activate-mode-local-bindings)
|
||||
;; CHEATER! The following 3 lines are from
|
||||
;; `semantic-new-buffer-fcn', but we don't want to turn
|
||||
;; on all the other annoying modes for this little task.
|
||||
(setq semantic-new-buffer-fcn-was-run t)
|
||||
(semantic-lex-init)
|
||||
(semantic-clear-toplevel-cache)
|
||||
(remove-hook 'semantic-lex-reset-hooks 'semantic-lex-spp-reset-hook
|
||||
t)
|
||||
)
|
||||
;; Get the macro symbol table right.
|
||||
(setq semantic-lex-spp-dynamic-macro-symbol-obarray spp-syms)
|
||||
;; (message "%S" macros)
|
||||
(dolist (sym macros)
|
||||
(semantic-lex-spp-symbol-set (car sym) (cdr sym)))
|
||||
;; Hack in mode-local
|
||||
(activate-mode-local-bindings)
|
||||
;; CHEATER! The following 3 lines are from
|
||||
;; `semantic-new-buffer-fcn', but we don't want to turn
|
||||
;; on all the other annoying modes for this little task.
|
||||
(setq semantic-new-buffer-fcn-was-run t)
|
||||
(semantic-lex-init)
|
||||
(semantic-clear-toplevel-cache)
|
||||
(remove-hook 'semantic-lex-reset-hooks 'semantic-lex-spp-reset-hook
|
||||
t)
|
||||
)
|
||||
;; Get the macro symbol table right.
|
||||
(setq semantic-lex-spp-dynamic-macro-symbol-obarray spp-syms)
|
||||
;; (message "%S" macros)
|
||||
(dolist (sym macros)
|
||||
(semantic-lex-spp-symbol-set (car sym) (cdr sym)))
|
||||
|
||||
(insert symtext)
|
||||
(insert symtext)
|
||||
|
||||
(setq stream
|
||||
(semantic-parse-region-default
|
||||
(point-min) (point-max) nonterminal depth returnonerror))
|
||||
(setq stream
|
||||
(semantic-parse-region-default
|
||||
(point-min) (point-max) nonterminal depth returnonerror))
|
||||
|
||||
;; Clean up macro symbols
|
||||
(dolist (sym macros)
|
||||
(semantic-lex-spp-symbol-remove (car sym)))
|
||||
;; Clean up macro symbols
|
||||
(dolist (sym macros)
|
||||
(semantic-lex-spp-symbol-remove (car sym)))
|
||||
|
||||
;; Convert the text of the stream.
|
||||
(dolist (tag stream)
|
||||
;; Only do two levels here 'cause I'm lazy.
|
||||
(semantic--tag-set-overlay tag (list start end))
|
||||
(dolist (stag (semantic-tag-components-with-overlays tag))
|
||||
(semantic--tag-set-overlay stag (list start end))
|
||||
))
|
||||
)
|
||||
;; Convert the text of the stream.
|
||||
(dolist (tag stream)
|
||||
;; Only do two levels here 'cause I'm lazy.
|
||||
(semantic--tag-set-overlay tag (list start end))
|
||||
(dolist (stag (semantic-tag-components-with-overlays tag))
|
||||
(semantic--tag-set-overlay stag (list start end))
|
||||
))
|
||||
))
|
||||
stream))
|
||||
|
||||
(defvar semantic-c-debug-mode-init-last-mode nil
|
||||
|
@ -920,8 +923,34 @@ now.
|
|||
;; of type "typedef".
|
||||
;; Each elt of NAME is ( STARS NAME )
|
||||
(let ((vl nil)
|
||||
(names (semantic-tag-name tag)))
|
||||
(names (semantic-tag-name tag))
|
||||
(super (semantic-tag-get-attribute tag :superclasses))
|
||||
(addlast nil))
|
||||
|
||||
(when (and (semantic-tag-of-type-p tag "typedef")
|
||||
(semantic-tag-of-class-p super 'type)
|
||||
(semantic-tag-type-members super))
|
||||
;; This is a typedef of a real type. Extract
|
||||
;; the super class, and stick it into the tags list.
|
||||
(setq addlast super)
|
||||
|
||||
;; Clone super and remove the members IFF super has a name.
|
||||
;; Note: anonymous struct/enums that are typedef'd shouldn't
|
||||
;; exist in the top level type list, so they will appear only
|
||||
;; in the :typedef slot of the typedef.
|
||||
(setq super (semantic-tag-clone super))
|
||||
(if (not (string= (semantic-tag-name super) ""))
|
||||
(semantic-tag-put-attribute super :members nil)
|
||||
(setq addlast nil))
|
||||
|
||||
;; Add in props to the full superclass.
|
||||
(when addlast
|
||||
(semantic--tag-copy-properties tag addlast)
|
||||
(semantic--tag-set-overlay addlast (semantic-tag-overlay tag)))
|
||||
)
|
||||
|
||||
(while names
|
||||
|
||||
(setq vl (cons (semantic-tag-new-type
|
||||
(nth 1 (car names)) ; name
|
||||
"typedef"
|
||||
|
@ -938,16 +967,18 @@ now.
|
|||
;; is expanded out as. Just the
|
||||
;; name shows up as a parent of this
|
||||
;; typedef.
|
||||
:typedef
|
||||
(semantic-tag-get-attribute tag :superclasses)
|
||||
:typedef super
|
||||
;;(semantic-tag-type-superclasses tag)
|
||||
:documentation
|
||||
(semantic-tag-docstring tag))
|
||||
vl))
|
||||
(semantic--tag-copy-properties tag (car vl))
|
||||
(semantic--tag-set-overlay (car vl)
|
||||
(semantic-tag-overlay tag))
|
||||
(semantic--tag-set-overlay (car vl) (semantic-tag-overlay tag))
|
||||
(setq names (cdr names)))
|
||||
|
||||
;; Add typedef superclass last.
|
||||
(when addlast (setq vl (cons addlast vl)))
|
||||
|
||||
vl))
|
||||
((and (listp (car tag))
|
||||
(semantic-tag-of-class-p (car tag) 'variable))
|
||||
|
@ -999,6 +1030,7 @@ Optional argument STAR and REF indicate the number of * and & in the typedef."
|
|||
(car tokenpart)))
|
||||
(and (stringp (car (nth 2 tokenpart)))
|
||||
(string= (car (nth 2 tokenpart)) (car tokenpart)))
|
||||
(nth 10 tokenpart) ; initializers
|
||||
)
|
||||
(not (car (nth 3 tokenpart)))))
|
||||
(fcnpointer (string-match "^\\*" (car tokenpart)))
|
||||
|
@ -1029,7 +1061,10 @@ Optional argument STAR and REF indicate the number of * and & in the typedef."
|
|||
(semantic-tag-new-type
|
||||
;; name
|
||||
(or (car semantic-c-classname)
|
||||
(car (nth 2 tokenpart)))
|
||||
(let ((split (semantic-analyze-split-name-c-mode
|
||||
(car (nth 2 tokenpart)))))
|
||||
(if (stringp split) split
|
||||
(car (last split)))))
|
||||
;; type
|
||||
(or (cdr semantic-c-classname)
|
||||
"class")
|
||||
|
@ -1580,6 +1615,48 @@ DO NOT return the list of tags encompassing point."
|
|||
tagreturn
|
||||
))
|
||||
|
||||
(define-mode-local-override semantic-ctxt-imported-packages c++-mode (&optional point)
|
||||
"Return the list of using tag types in scope of POINT."
|
||||
(when point (goto-char (point)))
|
||||
(let ((tagsaroundpoint (semantic-find-tag-by-overlay))
|
||||
(namereturn nil)
|
||||
(tmp nil)
|
||||
)
|
||||
;; Collect using statements from the top level.
|
||||
(setq tmp (semantic-find-tags-by-class 'using (current-buffer)))
|
||||
(dolist (T tmp) (setq namereturn (cons (semantic-tag-type T) namereturn)))
|
||||
;; Move through the tags around point looking for more using statements
|
||||
(while (cdr tagsaroundpoint) ; don't search the last one
|
||||
(setq tmp (semantic-find-tags-by-class 'using (semantic-tag-components (car tagsaroundpoint))))
|
||||
(dolist (T tmp) (setq namereturn (cons (semantic-tag-type T) namereturn)))
|
||||
(setq tagsaroundpoint (cdr tagsaroundpoint))
|
||||
)
|
||||
namereturn))
|
||||
|
||||
(define-mode-local-override semanticdb-expand-nested-tag c++-mode (tag)
|
||||
"Expand TAG if it has a fully qualified name.
|
||||
For types with a :parent, create faux namespaces to put TAG into."
|
||||
(let ((p (semantic-tag-get-attribute tag :parent)))
|
||||
(if (and p (semantic-tag-of-class-p tag 'type))
|
||||
;; Expand the tag
|
||||
(let ((s (semantic-analyze-split-name p))
|
||||
(newtag (semantic-tag-copy tag nil t)))
|
||||
;; Erase the qualified name.
|
||||
(semantic-tag-put-attribute newtag :parent nil)
|
||||
;; Fixup the namespace name
|
||||
(setq s (if (stringp s) (list s) (nreverse s)))
|
||||
;; Loop over all the parents, creating the nested
|
||||
;; namespace.
|
||||
(require 'semantic/db-typecache)
|
||||
(dolist (namespace s)
|
||||
(setq newtag (semanticdb-typecache-faux-namespace
|
||||
namespace (list newtag)))
|
||||
)
|
||||
;; Return the last created namespace.
|
||||
newtag)
|
||||
;; Else, return tag unmodified.
|
||||
tag)))
|
||||
|
||||
(define-mode-local-override semantic-get-local-variables c++-mode ()
|
||||
"Do what `semantic-get-local-variables' does, plus add `this' if needed."
|
||||
(let* ((origvar (semantic-get-local-variables-default))
|
||||
|
@ -1759,7 +1836,9 @@ DO NOT return the list of tags encompassing point."
|
|||
(princ "\n")
|
||||
))
|
||||
|
||||
(when (arrayp semantic-lex-spp-project-macro-symbol-obarray)
|
||||
(when (and (boundp 'ede-object)
|
||||
ede-object
|
||||
(arrayp semantic-lex-spp-project-macro-symbol-obarray))
|
||||
(princ "\n Project symbol map:\n")
|
||||
(when (and (boundp 'ede-object) ede-object)
|
||||
(princ " Your project symbol map is derived from the EDE object:\n ")
|
||||
|
|
|
@ -1206,6 +1206,27 @@ Uses semanticdb for searching all tags in the current project."
|
|||
(require 'semantic/db-find)
|
||||
(semanticdb-brute-deep-find-tags-for-completion prefix (oref obj path)))
|
||||
|
||||
;;; Current Datatype member search.
|
||||
(defclass semantic-collector-local-members (semantic-collector-project-abstract)
|
||||
((scope :initform nil
|
||||
:type (or null semantic-scope-cache)
|
||||
:documentation
|
||||
"The scope the local members are being completed from."))
|
||||
"Completion engine for tags in a project.")
|
||||
|
||||
(defmethod semantic-collector-calculate-completions-raw
|
||||
((obj semantic-collector-local-members) prefix completionlist)
|
||||
"Calculate the completions for prefix from completionlist."
|
||||
(let* ((scope (or (oref obj scope)
|
||||
(oset obj scope (semantic-calculate-scope))))
|
||||
(localstuff (oref scope scope)))
|
||||
(list
|
||||
(cons
|
||||
(oref scope :table)
|
||||
(semantic-find-tags-for-completion prefix localstuff)))))
|
||||
;(semanticdb-brute-deep-find-tags-for-completion prefix (oref obj path))))
|
||||
|
||||
;;; Smart completion collector
|
||||
(defclass semantic-collector-analyze-completions (semantic-collector-abstract)
|
||||
((context :initarg :context
|
||||
:type semantic-analyze-context
|
||||
|
@ -1800,6 +1821,28 @@ HISTORY is a symbol representing a variable to store the history in."
|
|||
history)
|
||||
)
|
||||
|
||||
(defun semantic-complete-read-tag-local-members (prompt &optional
|
||||
default-tag
|
||||
initial-input
|
||||
history)
|
||||
"Ask for a tag by name from the local type members.
|
||||
Available tags are from the the current scope.
|
||||
Completion options are presented in a traditional way, with highlighting
|
||||
to resolve same-name collisions.
|
||||
PROMPT is a string to prompt with.
|
||||
DEFAULT-TAG is a semantic tag or string to use as the default value.
|
||||
If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.
|
||||
HISTORY is a symbol representing a variable to store the history in."
|
||||
(semantic-complete-read-tag-engine
|
||||
(semantic-collector-local-members prompt :buffer (current-buffer))
|
||||
(semantic-displayor-traditional-with-focus-highlight "simple")
|
||||
;;(semantic-displayor-tooltip "simple")
|
||||
prompt
|
||||
default-tag
|
||||
initial-input
|
||||
history)
|
||||
)
|
||||
|
||||
(defun semantic-complete-read-tag-project (prompt &optional
|
||||
default-tag
|
||||
initial-input
|
||||
|
@ -1979,7 +2022,7 @@ completion works."
|
|||
|
||||
;;;###autoload
|
||||
(defun semantic-complete-jump-local ()
|
||||
"Jump to a semantic symbol."
|
||||
"Jump to a local semantic symbol."
|
||||
(interactive)
|
||||
(let ((tag (semantic-complete-read-tag-buffer-deep "Jump to symbol: ")))
|
||||
(when (semantic-tag-p tag)
|
||||
|
@ -2004,6 +2047,23 @@ completion works."
|
|||
(semantic-tag-class tag)
|
||||
(semantic-tag-name tag)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun semantic-complete-jump-local-members ()
|
||||
"Jump to a semantic symbol."
|
||||
(interactive)
|
||||
(let* ((tag (semantic-complete-read-tag-local-members "Jump to symbol: ")))
|
||||
(when (semantic-tag-p tag)
|
||||
(let ((start (condition-case nil (semantic-tag-start tag)
|
||||
(error nil))))
|
||||
(unless start
|
||||
(error "Tag %s has no location" (semantic-format-tag-prototype tag)))
|
||||
(push-mark)
|
||||
(goto-char start)
|
||||
(semantic-momentary-highlight-tag tag)
|
||||
(message "%S: %s "
|
||||
(semantic-tag-class tag)
|
||||
(semantic-tag-name tag))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun semantic-complete-analyze-and-replace ()
|
||||
"Perform prompt completion to do in buffer completion.
|
||||
|
@ -2075,15 +2135,17 @@ use `semantic-complete-analyze-inline' to complete."
|
|||
|
||||
;; Prepare for doing completion, but exit quickly if there is keyboard
|
||||
;; input.
|
||||
(when (and (not (semantic-exit-on-input 'csi
|
||||
(semantic-fetch-tags)
|
||||
(semantic-throw-on-input 'csi)
|
||||
nil))
|
||||
(= arg 1)
|
||||
(not (semantic-exit-on-input 'csi
|
||||
(semantic-analyze-current-context)
|
||||
(semantic-throw-on-input 'csi)
|
||||
nil)))
|
||||
(when (save-window-excursion
|
||||
(save-excursion
|
||||
(and (not (semantic-exit-on-input 'csi
|
||||
(semantic-fetch-tags)
|
||||
(semantic-throw-on-input 'csi)
|
||||
nil))
|
||||
(= arg 1)
|
||||
(not (semantic-exit-on-input 'csi
|
||||
(semantic-analyze-current-context)
|
||||
(semantic-throw-on-input 'csi)
|
||||
nil)))))
|
||||
(condition-case nil
|
||||
(semantic-complete-analyze-inline)
|
||||
;; Ignore errors. Seems likely that we'll get some once in a while.
|
||||
|
|
|
@ -599,12 +599,18 @@ that may or may not have a name.)")
|
|||
"Return a list of scoped types by name for the current context at POINT.
|
||||
This is very different for various languages, and does nothing unless
|
||||
overridden."
|
||||
(if point (goto-char point))
|
||||
(let ((case-fold-search semantic-case-fold))
|
||||
;; We need to look at TYPES within the bounds of locally parse arguments.
|
||||
;; C needs to find using statements and the like too. Bleh.
|
||||
nil
|
||||
))
|
||||
nil)
|
||||
|
||||
(define-overloadable-function semantic-ctxt-imported-packages (&optional point)
|
||||
"Return a list of package tags or names which are being imported at POINT.
|
||||
The return value is a list of strings which are package names
|
||||
that are implied in code. Thus a C++ symbol:
|
||||
foo::bar();
|
||||
where there is a statement such as:
|
||||
using baz;
|
||||
means that the first symbol might be:
|
||||
baz::foo::bar();"
|
||||
nil)
|
||||
|
||||
(provide 'semantic/ctxt)
|
||||
|
||||
|
|
|
@ -245,7 +245,7 @@ If DB is not specified, then use the current database."
|
|||
;; @todo - It should ask if we are not called from a hook.
|
||||
;; How?
|
||||
(if (or supress-questions
|
||||
(y-or-n-p (format "Skip Error: %S ?" (car (cdr foo)))))
|
||||
(y-or-n-p (format "Skip Error: %s ?" (car (cdr foo)))))
|
||||
(message "Save Error: %S: %s" (car (cdr foo))
|
||||
objname)
|
||||
(error "%S" (car (cdr foo))))))))
|
||||
|
|
|
@ -202,7 +202,7 @@ This class will cache data derived during various searches.")
|
|||
(when (oref idx type-cache)
|
||||
(semantic-reset (oref idx type-cache)))
|
||||
;; Clear the scope. Scope doesn't have the data it needs to track
|
||||
;; it's own reset.
|
||||
;; its own reset.
|
||||
(semantic-scope-reset-cache)
|
||||
)
|
||||
|
||||
|
@ -262,13 +262,13 @@ This class will cache data derived during various searches.")
|
|||
"Translate PATH into a list of semantic tables.
|
||||
Path translation involves identifying the PATH input argument
|
||||
in one of the following ways:
|
||||
nil - Take the current buffer, and use it's include list
|
||||
nil - Take the current buffer, and use its include list
|
||||
buffer - Use that buffer's include list.
|
||||
filename - Use that file's include list. If the file is not
|
||||
in a buffer, see of there is a semanticdb table for it. If
|
||||
not, read that file into a buffer.
|
||||
tag - Get that tag's buffer of file file. See above.
|
||||
table - Search that table, and it's include list.
|
||||
table - Search that table, and its include list.
|
||||
find result - Search the results of a previous find.
|
||||
|
||||
In addition, once the base path is found, there is the possibility of
|
||||
|
@ -1006,9 +1006,14 @@ is still made current."
|
|||
(when norm
|
||||
;; The normalized tags can now be found based on that
|
||||
;; tags table.
|
||||
(semanticdb-set-buffer (car norm))
|
||||
;; Now reset ans
|
||||
(setq ans (cdr norm))
|
||||
(condition-case foo
|
||||
(progn
|
||||
(semanticdb-set-buffer (car norm))
|
||||
;; Now reset ans
|
||||
(setq ans (cdr norm)))
|
||||
;; Don't error for this case, but don't store
|
||||
;; the thing either.
|
||||
(no-method-definition nil))
|
||||
))
|
||||
)
|
||||
;; Return the tag.
|
||||
|
@ -1019,10 +1024,10 @@ is still made current."
|
|||
FCN takes two arguments. The first is a TAG, and the
|
||||
second is a DB from whence TAG originated.
|
||||
Returns result."
|
||||
(mapc (lambda (sublst)
|
||||
(mapc (lambda (tag)
|
||||
(funcall fcn tag (car sublst)))
|
||||
(cdr sublst)))
|
||||
(mapc (lambda (sublst-icky)
|
||||
(mapc (lambda (tag-icky)
|
||||
(funcall fcn tag-icky (car sublst-icky)))
|
||||
(cdr sublst-icky)))
|
||||
result)
|
||||
result)
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ if optional DONT-ERR-IF-NOT-AVAILABLE is non-nil; else throw an error."
|
|||
'(omniscience))
|
||||
)
|
||||
(if dont-err-if-not-available
|
||||
(message "No Global support in %s" default-directory)
|
||||
nil; (message "No Global support in %s" default-directory)
|
||||
(error "No Global support in %s" default-directory))
|
||||
))
|
||||
|
||||
|
|
|
@ -217,6 +217,14 @@ Adds a filename and copies the tags."
|
|||
(semanticdb-full-filename table)
|
||||
tags))
|
||||
|
||||
(defun semanticdb-typecache-faux-namespace (name members)
|
||||
"Create a new namespace tag with NAME and a set of MEMBERS.
|
||||
The new tag will be a faux tag, used as a placeholder in a typecache."
|
||||
(let ((tag (semantic-tag-new-type name "namespace" members nil)))
|
||||
;; Make sure we mark this as a fake tag.
|
||||
(semantic-tag-set-faux tag)
|
||||
tag))
|
||||
|
||||
(defun semanticdb-typecache-merge-streams (cache1 cache2)
|
||||
"Merge into CACHE1 and CACHE2 together. The Caches will be merged in place."
|
||||
(if (or (and (not cache1) (not cache2))
|
||||
|
@ -256,23 +264,22 @@ Adds a filename and copies the tags."
|
|||
(setq ans (cons next ans))
|
||||
;; ELSE - We have a NAME match.
|
||||
(setq type (semantic-tag-type next))
|
||||
(if (semantic-tag-of-type-p prev type) ; Are they the same datatype
|
||||
(if (or (semantic-tag-of-type-p prev type) ; Are they the same datatype
|
||||
(semantic-tag-faux-p prev)
|
||||
(semantic-tag-faux-p next) ; or either a faux tag?
|
||||
)
|
||||
;; Same Class, we can do a merge.
|
||||
(cond
|
||||
((and (semantic-tag-of-class-p next 'type)
|
||||
(string= type "namespace"))
|
||||
;; Namespaces - merge the children together.
|
||||
(setcar ans
|
||||
(semantic-tag-new-type
|
||||
(semanticdb-typecache-faux-namespace
|
||||
(semantic-tag-name prev) ; - they are the same
|
||||
"namespace" ; - we know this as fact
|
||||
(semanticdb-typecache-merge-streams
|
||||
(semanticdb-typecache-safe-tag-members prev)
|
||||
(semanticdb-typecache-safe-tag-members next))
|
||||
nil ; - no attributes
|
||||
))
|
||||
;; Make sure we mark this as a fake tag.
|
||||
(semantic-tag-set-faux (car ans))
|
||||
)
|
||||
((semantic-tag-prototype-p next)
|
||||
;; NEXT is a prototype... so keep previous.
|
||||
|
@ -299,6 +306,12 @@ Adds a filename and copies the tags."
|
|||
;;; Refresh / Query API
|
||||
;;
|
||||
;; Queries that can be made for the typecache.
|
||||
(define-overloadable-function semanticdb-expand-nested-tag (tag)
|
||||
"Expand TAG from fully qualified names.
|
||||
If TAG has fully qualified names, expand it to a series of nested
|
||||
namespaces instead."
|
||||
tag)
|
||||
|
||||
(defmethod semanticdb-typecache-file-tags ((table semanticdb-abstract-table))
|
||||
"No tags available from non-file based tables."
|
||||
nil)
|
||||
|
@ -313,10 +326,13 @@ all included files."
|
|||
|
||||
;; Make sure our file-tags list is up to date.
|
||||
(when (not (oref cache filestream))
|
||||
(let ((tags (semantic-find-tags-by-class 'type table)))
|
||||
(let ((tags (semantic-find-tags-by-class 'type table))
|
||||
(exptags nil))
|
||||
(when tags
|
||||
(setq tags (semanticdb-typecache-safe-tag-list tags table))
|
||||
(oset cache filestream (semanticdb-typecache-merge-streams tags nil)))))
|
||||
(dolist (T tags)
|
||||
(push (semanticdb-expand-nested-tag T) exptags))
|
||||
(oset cache filestream (semanticdb-typecache-merge-streams exptags nil)))))
|
||||
|
||||
;; Return our cache.
|
||||
(oref cache filestream)
|
||||
|
@ -372,6 +388,7 @@ a master list."
|
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;;; Search Routines
|
||||
;;
|
||||
;;;###autoload
|
||||
(define-overloadable-function semanticdb-typecache-find (type &optional path find-file-match)
|
||||
"Search the typecache for TYPE in PATH.
|
||||
|
@ -386,16 +403,20 @@ TYPE is the datatype to find.
|
|||
PATH is the search path, which should be one table object.
|
||||
If FIND-FILE-MATCH is non-nil, then force the file belonging to the
|
||||
found tag to be loaded."
|
||||
(semanticdb-typecache-find-method (or path semanticdb-current-table)
|
||||
type find-file-match))
|
||||
(if (not (and (featurep 'semanticdb) semanticdb-current-database))
|
||||
nil ;; No DB, no search
|
||||
(save-excursion
|
||||
(semanticdb-typecache-find-method (or path semanticdb-current-table)
|
||||
type find-file-match))))
|
||||
|
||||
(defun semanticdb-typecache-find-by-name-helper (name table)
|
||||
"Find the tag with NAME in TABLE, which is from a typecache.
|
||||
If more than one tag has NAME in TABLE, we will prefer the tag that
|
||||
is of class 'type."
|
||||
(let* ((names (semantic-find-tags-by-name name table))
|
||||
(types (semantic-find-tags-by-class 'type names)))
|
||||
(or (car-safe types) (car-safe names))))
|
||||
(nmerge (semanticdb-typecache-merge-streams names nil))
|
||||
(types (semantic-find-tags-by-class 'type nmerge)))
|
||||
(or (car-safe types) (car-safe nmerge))))
|
||||
|
||||
(defmethod semanticdb-typecache-find-method ((table semanticdb-abstract-table)
|
||||
type find-file-match)
|
||||
|
|
|
@ -542,10 +542,25 @@ Optional argument FORCE will force a refresh even if the file in question
|
|||
is not in a buffer. Avoid using FORCE for most uses, as an old cache
|
||||
may be sufficient for the general case. Forced updates can be slow.
|
||||
This will call `semantic-fetch-tags' if that file is in memory."
|
||||
(when (or (semanticdb-in-buffer-p obj) force)
|
||||
(cond
|
||||
;;
|
||||
;; Already in a buffer, just do it.
|
||||
((semanticdb-in-buffer-p obj)
|
||||
(semanticdb-set-buffer obj)
|
||||
(semantic-fetch-tags))
|
||||
;;
|
||||
;; Not in a buffer. Forcing a load.
|
||||
(force
|
||||
;; Patch from Iain Nicol. --
|
||||
;; @TODO: I wonder if there is a way to recycle
|
||||
;; semanticdb-create-table-for-file-not-in-buffer
|
||||
(save-excursion
|
||||
(semanticdb-set-buffer obj)
|
||||
(semantic-fetch-tags))))
|
||||
(let ((buff (semantic-find-file-noselect
|
||||
(semanticdb-full-filename obj))))
|
||||
(set-buffer buff)
|
||||
(semantic-fetch-tags)
|
||||
;; Kill off the buffer if it didn't exist when we were called.
|
||||
(kill-buffer buff))))))
|
||||
|
||||
(defmethod semanticdb-needs-refresh-p ((obj semanticdb-table))
|
||||
"Return non-nil of OBJ's tag list is out of date.
|
||||
|
@ -808,12 +823,14 @@ Always append `semanticdb-project-system-databases' if
|
|||
(setq root (run-hook-with-args-until-success
|
||||
'semanticdb-project-root-functions
|
||||
dir))
|
||||
;; Find roots based on strings
|
||||
(while (and roots (not root))
|
||||
(let ((r (file-truename (car roots))))
|
||||
(if (string-match (concat "^" (regexp-quote r)) dir)
|
||||
(setq root r)))
|
||||
(setq roots (cdr roots)))
|
||||
(if root
|
||||
(setq root (file-truename root))
|
||||
;; Else, Find roots based on strings
|
||||
(while roots
|
||||
(let ((r (file-truename (car roots))))
|
||||
(if (string-match (concat "^" (regexp-quote r)) dir)
|
||||
(setq root r)))
|
||||
(setq roots (cdr roots))))
|
||||
|
||||
;; If no roots are found, use this directory.
|
||||
(unless root (setq root dir))
|
||||
|
|
|
@ -45,7 +45,7 @@ Optional FACE specifies the face to use."
|
|||
))
|
||||
|
||||
(defun semantic-unhighlight-tag (tag)
|
||||
"Unhighlight TAG, restoring it's previous face."
|
||||
"Unhighlight TAG, restoring its previous face."
|
||||
(let ((o (semantic-tag-overlay tag)))
|
||||
(semantic-overlay-put o 'face (car (semantic-overlay-get o 'old-face)))
|
||||
(semantic-overlay-put o 'old-face (cdr (semantic-overlay-get o 'old-face)))
|
||||
|
|
|
@ -118,7 +118,7 @@ Used by the decoration style: `semantic-decoration-on-includes'."
|
|||
'((((class color) (background dark))
|
||||
(:background "#900000"))
|
||||
(((class color) (background light))
|
||||
(:background "#ff5050")))
|
||||
(:background "#fff0f0")))
|
||||
"*Face used to show includes that cannot be found.
|
||||
Used by the decoration style: `semantic-decoration-on-unknown-includes'."
|
||||
:group 'semantic-faces)
|
||||
|
@ -302,16 +302,19 @@ This mode provides a nice context menu on the include statements."
|
|||
)
|
||||
))
|
||||
|
||||
(let ((ol (semantic-decorate-tag tag
|
||||
(semantic-tag-start tag)
|
||||
(semantic-tag-end tag)
|
||||
face))
|
||||
)
|
||||
(semantic-overlay-put ol 'mouse-face 'highlight)
|
||||
(semantic-overlay-put ol 'keymap map)
|
||||
(semantic-overlay-put ol 'help-echo
|
||||
"Header File : mouse-3 - Context menu")
|
||||
)))
|
||||
;; @TODO - if not a tag w/ a position, we need to get one. How?
|
||||
|
||||
(when (semantic-tag-with-position-p tag)
|
||||
(let ((ol (semantic-decorate-tag tag
|
||||
(semantic-tag-start tag)
|
||||
(semantic-tag-end tag)
|
||||
face))
|
||||
)
|
||||
(semantic-overlay-put ol 'mouse-face 'highlight)
|
||||
(semantic-overlay-put ol 'keymap map)
|
||||
(semantic-overlay-put ol 'help-echo
|
||||
"Header File : mouse-3 - Context menu")
|
||||
))))
|
||||
|
||||
;;; Regular Include Functions
|
||||
;;
|
||||
|
|
|
@ -208,7 +208,8 @@ provided mode, not from the current major mode."
|
|||
mode 'semantic-dependency-system-include-path))
|
||||
(edesys (when (and (featurep 'ede) ede-minor-mode
|
||||
ede-object)
|
||||
(ede-system-include-path ede-object)))
|
||||
(ede-system-include-path
|
||||
(if (listp ede-object) (car ede-object) ede-object))))
|
||||
(locp (mode-local-value
|
||||
mode 'semantic-dependency-include-path))
|
||||
(found nil))
|
||||
|
|
|
@ -78,7 +78,8 @@ just the lexical token and not the string."
|
|||
(start (if starttag
|
||||
(semantic-tag-end starttag)
|
||||
(point-min))))
|
||||
(when (re-search-backward comment-start-skip start t)
|
||||
(when (and comment-start-skip
|
||||
(re-search-backward comment-start-skip start t))
|
||||
;; We found a comment that doesn't belong to the body
|
||||
;; of a function.
|
||||
(semantic-doc-snarf-comment-for-tag nosnarf)))
|
||||
|
|
|
@ -310,6 +310,17 @@ FILE, NOWARN, RAWFILE, and WILDCARDS are passed into `find-file-noselect'"
|
|||
(find-file-noselect file nowarn rawfile wildcards)))
|
||||
))
|
||||
|
||||
;;; Database restriction settings
|
||||
;;
|
||||
(defmacro semanticdb-without-unloaded-file-searches (forms)
|
||||
"Execute FORMS with `unloaded' removed from the current throttle."
|
||||
`(let ((semanticdb-find-default-throttle
|
||||
(if (featurep 'semanticdb-find)
|
||||
(remq 'unloaded semanticdb-find-default-throttle)
|
||||
nil)))
|
||||
,forms))
|
||||
(put 'semanticdb-without-unloaded-file-searches 'lisp-indent-function 1)
|
||||
|
||||
|
||||
;; ;;; Editor goodies ;-)
|
||||
;; ;;
|
||||
|
|
|
@ -928,6 +928,12 @@ Lisp code."
|
|||
;; If running interactively, eval declarations and epilogue
|
||||
;; code, then pop to the buffer visiting the generated file.
|
||||
(eval-region (point) (point-max))
|
||||
;; Loop over the defvars and eval them explicitly to force
|
||||
;; them to be evaluated and ready to use.
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "(defvar " nil t)
|
||||
(eval-defun nil))
|
||||
;; Move cursor to a logical spot in the generated code.
|
||||
(goto-char (point-min))
|
||||
(pop-to-buffer (current-buffer))
|
||||
;; The generated code has been evaluated and updated into
|
||||
|
|
|
@ -243,6 +243,7 @@ tag with greater section value than LEVEL is found."
|
|||
semantic-imenu-bucketize-file nil
|
||||
semantic-imenu-bucketize-type-members nil
|
||||
senator-step-at-start-end-tag-classes '(section)
|
||||
senator-step-at-tag-classes '(section)
|
||||
semantic-stickyfunc-sticky-classes '(section)
|
||||
)
|
||||
(semantic-install-function-overrides
|
||||
|
|
|
@ -40,7 +40,8 @@
|
|||
(require 'pulse)
|
||||
(eval-when-compile
|
||||
(require 'semantic/analyze)
|
||||
(require 'semantic/analyze/refs))
|
||||
(require 'semantic/analyze/refs)
|
||||
(require 'semantic/find))
|
||||
|
||||
(declare-function imenu--mouse-menu "imenu")
|
||||
|
||||
|
@ -57,14 +58,6 @@
|
|||
:group 'semantic
|
||||
:type semantic-format-tag-custom-list)
|
||||
|
||||
(defvar semantic-ia-cache nil
|
||||
"Cache of the last completion request.
|
||||
Of the form ( POINT . COMPLETIONS ) where POINT is a location in the
|
||||
buffer where the completion was requested. COMPLETONS is the list
|
||||
of semantic tag names that provide logical completions from that
|
||||
location.")
|
||||
(make-variable-buffer-local 'semantic-ia-cache)
|
||||
|
||||
;;; COMPLETION HELPER
|
||||
;;
|
||||
;; This overload function handles inserting a tag
|
||||
|
@ -86,23 +79,16 @@ location.")
|
|||
(insert "("))
|
||||
(t nil))))
|
||||
|
||||
(declare-function semantic-analyze-possible-completions
|
||||
"semantic/analyze/complete")
|
||||
(defalias 'semantic-ia-get-completions 'semantic-ia-get-completions-deprecated
|
||||
"`Semantic-ia-get-completions' is obsolete.
|
||||
Use `semantic-analyze-possible-completions' instead.")
|
||||
|
||||
(defun semantic-ia-get-completions (context point)
|
||||
"Fetch the completion of CONTEXT at POINT.
|
||||
Supports caching."
|
||||
;; Cache the current set of symbols so that we can get at
|
||||
;; them quickly the second time someone presses the
|
||||
;; complete button.
|
||||
(let ((symbols
|
||||
(if (and semantic-ia-cache
|
||||
(= point (car semantic-ia-cache)))
|
||||
(cdr semantic-ia-cache)
|
||||
(semantic-analyze-possible-completions context))))
|
||||
;; Set the cache
|
||||
(setq semantic-ia-cache (cons point symbols))
|
||||
symbols))
|
||||
(defun semantic-ia-get-completions-deprecated (context point)
|
||||
"A function to help transition away from `semantic-ia-get-completions'.
|
||||
Return completions based on CONTEXT at POINT.
|
||||
You should not use this, nor the aliased version.
|
||||
Use `semantic-analyze-possible-completions' instead."
|
||||
(semantic-analyze-possible-completions context))
|
||||
|
||||
;;;###autoload
|
||||
(defun semantic-ia-complete-symbol (&optional pos)
|
||||
|
@ -119,7 +105,7 @@ Completion options are calculated with `semantic-analyze-possible-completions'."
|
|||
;;
|
||||
;; The second step derives completions from that context.
|
||||
(let* ((a (semantic-analyze-current-context pos))
|
||||
(syms (semantic-ia-get-completions a pos))
|
||||
(syms (semantic-analyze-possible-completions a))
|
||||
(pre (car (reverse (oref a prefix)))))
|
||||
;; If PRE was actually an already completed symbol, it doesn't
|
||||
;; come in as a string, but as a tag instead.
|
||||
|
@ -173,7 +159,7 @@ Completion options are calculated with `semantic-analyze-possible-completions'."
|
|||
"Pop up a tooltip for completion at POINT."
|
||||
(interactive "d")
|
||||
(let* ((a (semantic-analyze-current-context point))
|
||||
(syms (semantic-ia-get-completions a point))
|
||||
(syms (semantic-analyze-possible-completions a))
|
||||
(x (mod (- (current-column) (window-hscroll))
|
||||
(window-width)))
|
||||
(y (save-excursion
|
||||
|
@ -212,8 +198,48 @@ Completion options are calculated with `semantic-analyze-possible-completions'."
|
|||
;; tag associated with the current context.
|
||||
(semantic-analyze-interesting-tag ctxt)))
|
||||
)
|
||||
(when pf
|
||||
(message "%s" (semantic-format-tag-summarize pf nil t)))))
|
||||
(if pf
|
||||
(message "%s" (semantic-format-tag-summarize pf nil t))
|
||||
(message "No summary info availalble"))))
|
||||
|
||||
;;; Variants
|
||||
;;
|
||||
;; Show all variants for the symbol under point.
|
||||
|
||||
;;;###autoload
|
||||
(defun semantic-ia-show-variants (point)
|
||||
"Display a list of all variants for the symbol under POINT."
|
||||
(interactive "P")
|
||||
(let* ((ctxt (semantic-analyze-current-context point))
|
||||
(comp nil))
|
||||
|
||||
;; We really want to look at the function if we are on an
|
||||
;; argument. Are there some additional rules we care about for
|
||||
;; changing the CTXT we look at?
|
||||
(when (semantic-analyze-context-functionarg-p ctxt)
|
||||
(goto-char (cdr (oref ctxt bounds)))
|
||||
(setq ctxt (semantic-analyze-current-context (point))))
|
||||
|
||||
;; Get the "completion list", but remove ALL filters to get the master list
|
||||
;; of all the possible things.
|
||||
(setq comp (semantic-analyze-possible-completions ctxt 'no-unique 'no-tc))
|
||||
|
||||
;; Special case for a single type. List the constructors?
|
||||
(when (and (= (length comp) 1) (semantic-tag-of-class-p (car comp) 'type))
|
||||
(setq comp (semantic-find-tags-by-name (semantic-tag-name (car comp))
|
||||
(semantic-tag-type-members (car comp)))))
|
||||
|
||||
;; Display the results.
|
||||
(cond ((= (length comp) 0)
|
||||
(message "No Variants found."))
|
||||
((= (length comp) 1)
|
||||
(message "%s" (semantic-format-tag-summarize (car comp) nil t)))
|
||||
(t
|
||||
(with-output-to-temp-buffer "*Symbol Variants*"
|
||||
(semantic-analyze-princ-sequence comp "" (current-buffer)))
|
||||
(shrink-window-if-larger-than-buffer
|
||||
(get-buffer-window "*Symbol Variants*")))
|
||||
)))
|
||||
|
||||
;;; FAST Jump
|
||||
;;
|
||||
|
@ -354,18 +380,21 @@ See `semantic-ia-fast-jump' for details on how it works.
|
|||
;; The default tries to find a comment in front of the tag
|
||||
;; and then strings off comment prefixes.
|
||||
(let ((doc (semantic-documentation-for-tag (car pf))))
|
||||
(with-output-to-temp-buffer "*TAG DOCUMENTATION*"
|
||||
(princ "Tag: ")
|
||||
(princ (semantic-format-tag-prototype (car pf)))
|
||||
(princ "\n")
|
||||
(princ "\n")
|
||||
(princ "Snarfed Documentation: ")
|
||||
(princ "\n")
|
||||
(princ "\n")
|
||||
(if doc
|
||||
(princ doc)
|
||||
(princ " Documentation unavailable."))
|
||||
)))
|
||||
(if (or (null doc) (string= doc ""))
|
||||
(message "Doc unavailable for: %s"
|
||||
(semantic-format-tag-prototype (car pf)))
|
||||
(with-output-to-temp-buffer "*TAG DOCUMENTATION*"
|
||||
(princ "Tag: ")
|
||||
(princ (semantic-format-tag-prototype (car pf)))
|
||||
(princ "\n")
|
||||
(princ "\n")
|
||||
(princ "Snarfed Documentation: ")
|
||||
(princ "\n")
|
||||
(princ "\n")
|
||||
(if doc
|
||||
(princ doc)
|
||||
(princ " Documentation unavailable."))
|
||||
))))
|
||||
(t
|
||||
(message "Unknown tag.")))
|
||||
))
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
(defvar eldoc-last-message)
|
||||
(declare-function eldoc-message "eldoc")
|
||||
(declare-function semantic-analyze-interesting-tag "semantic/analyze")
|
||||
(declare-function semantic-analyze-unsplit-name "semantic/analyze/fcn")
|
||||
(declare-function semantic-complete-analyze-inline-idle "semantic/complete")
|
||||
(declare-function semanticdb-deep-find-tags-by-name "semantic/db-find")
|
||||
(declare-function semanticdb-save-all-db-idle "semantic/db")
|
||||
|
@ -294,12 +295,18 @@ call additional functions registered with the timer calls."
|
|||
;;
|
||||
;; Unlike the shorter timer, the WORK timer will kick of tasks that
|
||||
;; may take a long time to complete.
|
||||
(defcustom semantic-idle-work-parse-neighboring-files-flag t
|
||||
(defcustom semantic-idle-work-parse-neighboring-files-flag nil
|
||||
"*Non-nil means to parse files in the same dir as the current buffer.
|
||||
Disable to prevent lots of excessive parsing in idle time."
|
||||
:group 'semantic
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom semantic-idle-work-update-headers-flag nil
|
||||
"*Non-nil means to parse through header files in idle time.
|
||||
Disable to prevent idle time parsing of many files. If completion
|
||||
is called that work will be done then instead."
|
||||
:group 'semantic
|
||||
:type 'boolean)
|
||||
|
||||
(defun semantic-idle-work-for-one-buffer (buffer)
|
||||
"Do long-processing work for BUFFER.
|
||||
|
@ -312,6 +319,9 @@ Returns t if all processing succeeded."
|
|||
(semantic-idle-scheduler-refresh-tags)
|
||||
t)
|
||||
|
||||
;; Option to disable this work.
|
||||
semantic-idle-work-update-headers-flag
|
||||
|
||||
;; Force all our include files to get read in so we
|
||||
;; are ready to provide good smart completion and idle
|
||||
;; summary information
|
||||
|
@ -603,6 +613,11 @@ turned on in every Semantic-supported buffer.")
|
|||
;;; SUMMARY MODE
|
||||
;;
|
||||
;; A mode similar to eldoc using semantic
|
||||
(defcustom semantic-idle-truncate-long-summaries t
|
||||
"Truncate summaries that are too long to fit in the minibuffer.
|
||||
This can prevent minibuffer resizing in idle time."
|
||||
:group 'semantic
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom semantic-idle-summary-function
|
||||
'semantic-format-tag-summarize-with-file
|
||||
|
@ -654,21 +669,16 @@ Use the semantic analyzer to find the symbol information."
|
|||
"Return a string message describing the current context.
|
||||
This function will disable loading of previously unloaded files
|
||||
by semanticdb as a time-saving measure."
|
||||
(let (
|
||||
(semanticdb-find-default-throttle
|
||||
(if (featurep 'semantic/db-find)
|
||||
(remq 'unloaded semanticdb-find-default-throttle)
|
||||
nil))
|
||||
)
|
||||
(save-excursion
|
||||
;; use whicever has success first.
|
||||
(or
|
||||
(semantic-idle-summary-current-symbol-keyword)
|
||||
(semanticdb-without-unloaded-file-searches
|
||||
(save-excursion
|
||||
;; use whichever has success first.
|
||||
(or
|
||||
(semantic-idle-summary-current-symbol-keyword)
|
||||
|
||||
(semantic-idle-summary-current-symbol-info-context)
|
||||
(semantic-idle-summary-current-symbol-info-context)
|
||||
|
||||
(semantic-idle-summary-current-symbol-info-brutish)
|
||||
))))
|
||||
(semantic-idle-summary-current-symbol-info-brutish)
|
||||
))))
|
||||
|
||||
(defvar semantic-idle-summary-out-of-context-faces
|
||||
'(
|
||||
|
@ -732,6 +742,14 @@ current tag to display information."
|
|||
(let ((w (1- (window-width (minibuffer-window)))))
|
||||
(if (> (length str) w)
|
||||
(setq str (substring str 0 w)))))
|
||||
;; I borrowed some bits from eldoc to shorten the
|
||||
;; message.
|
||||
(when semantic-idle-truncate-long-summaries
|
||||
(let ((ea-width (1- (window-width (minibuffer-window))))
|
||||
(strlen (length str)))
|
||||
(when (> strlen ea-width)
|
||||
(setq str (substring str 0 ea-width)))))
|
||||
;; Display it
|
||||
(eldoc-message str))))
|
||||
|
||||
(define-minor-mode semantic-idle-summary-mode
|
||||
|
@ -791,12 +809,12 @@ turned on in every Semantic-supported buffer."
|
|||
;; of all uses of the symbol that is under the cursor.
|
||||
;;
|
||||
;; This is to mimic the Eclipse tool of a similar nature.
|
||||
(defvar semantic-idle-summary-highlight-face 'region
|
||||
"Face used for the summary highlight.")
|
||||
(defvar semantic-idle-symbol-highlight-face 'region
|
||||
"Face used for highlighting local symbols.")
|
||||
|
||||
(defun semantic-idle-summary-maybe-highlight (tag)
|
||||
"Perhaps add highlighting onto TAG.
|
||||
TAG was found as the thing under point. If it happens to be
|
||||
(defun semantic-idle-symbol-maybe-highlight (tag)
|
||||
"Perhaps add highlighting to the symbol represented by TAG.
|
||||
TAG was found as the symbol under point. If it happens to be
|
||||
visible, then highlight it."
|
||||
(require 'pulse)
|
||||
(let* ((region (when (and (semantic-tag-p tag)
|
||||
|
@ -817,12 +835,12 @@ visible, then highlight it."
|
|||
(point) (get-buffer-window (current-buffer) 'visible))
|
||||
(if (< (semantic-overlay-end region) (point-at-eol))
|
||||
(pulse-momentary-highlight-overlay
|
||||
region semantic-idle-summary-highlight-face)
|
||||
region semantic-idle-symbol-highlight-face)
|
||||
;; Not the same
|
||||
(pulse-momentary-highlight-region
|
||||
(semantic-overlay-start region)
|
||||
(point-at-eol)
|
||||
semantic-idle-summary-highlight-face)))
|
||||
semantic-idle-symbol-highlight-face)))
|
||||
))
|
||||
((vectorp region)
|
||||
(let ((start (aref region 0))
|
||||
|
@ -842,17 +860,19 @@ visible, then highlight it."
|
|||
(pulse-momentary-highlight-region
|
||||
start (if (<= end (point-at-eol)) end
|
||||
(point-at-eol))
|
||||
semantic-idle-summary-highlight-face)))
|
||||
semantic-idle-symbol-highlight-face)))
|
||||
))))
|
||||
nil))
|
||||
|
||||
(define-semantic-idle-service semantic-idle-tag-highlight
|
||||
"Highlight the tag, and references of the symbol under point.
|
||||
(define-semantic-idle-service semantic-idle-local-symbol-highlight
|
||||
"Highlight the tag and symbol references of the symbol under point.
|
||||
Call `semantic-analyze-current-context' to find the reference tag.
|
||||
Call `semantic-symref-hits-in-region' to identify local references."
|
||||
(require 'pulse)
|
||||
(when (semantic-idle-summary-useful-context-p)
|
||||
(let* ((ctxt (semantic-analyze-current-context))
|
||||
(let* ((ctxt
|
||||
(semanticdb-without-unloaded-file-searches
|
||||
(semantic-analyze-current-context)))
|
||||
(Hbounds (when ctxt (oref ctxt bounds)))
|
||||
(target (when ctxt (car (reverse (oref ctxt prefix)))))
|
||||
(tag (semantic-current-tag))
|
||||
|
@ -862,7 +882,7 @@ Call `semantic-symref-hits-in-region' to identify local references."
|
|||
(when ctxt
|
||||
;; Highlight the original tag? Protect against problems.
|
||||
(condition-case nil
|
||||
(semantic-idle-summary-maybe-highlight target)
|
||||
(semantic-idle-symbol-maybe-highlight target)
|
||||
(error nil))
|
||||
;; Identify all hits in this current tag.
|
||||
(when (semantic-tag-p target)
|
||||
|
@ -871,7 +891,7 @@ Call `semantic-symref-hits-in-region' to identify local references."
|
|||
target (lambda (start end prefix)
|
||||
(when (/= start (car Hbounds))
|
||||
(pulse-momentary-highlight-region
|
||||
start end semantic-idle-summary-highlight-face))
|
||||
start end semantic-idle-symbol-highlight-face))
|
||||
(semantic-throw-on-input 'symref-highlight)
|
||||
)
|
||||
(semantic-tag-start tag)
|
||||
|
@ -891,7 +911,7 @@ If ARG is positive or nil, enable, if it is negative, disable."
|
|||
;; When turning off, disable other idle modes.
|
||||
(when (null global-semantic-idle-scheduler-mode)
|
||||
(global-semantic-idle-summary-mode -1)
|
||||
(global-semantic-idle-tag-highlight-mode -1)
|
||||
(global-semantic-idle-local-symbol-highlight-mode -1)
|
||||
(global-semantic-idle-completions-mode -1))
|
||||
(semantic-toggle-minor-mode-globally
|
||||
'semantic-idle-scheduler-mode
|
||||
|
@ -903,25 +923,23 @@ If ARG is positive or nil, enable, if it is negative, disable."
|
|||
;; This mode uses tooltips to display a (hopefully) short list of possible
|
||||
;; completions available for the text under point. It provides
|
||||
;; NO provision for actually filling in the values from those completions.
|
||||
(defun semantic-idle-completions-end-of-symbol-p ()
|
||||
"Return non-nil if the cursor is at the END of a symbol.
|
||||
If the cursor is in the middle of a symbol, then we shouldn't be
|
||||
doing fancy completions."
|
||||
(not (looking-at "\\w\\|\\s_")))
|
||||
|
||||
(defun semantic-idle-completion-list-default ()
|
||||
"Calculate and display a list of completions."
|
||||
(when (semantic-idle-summary-useful-context-p)
|
||||
(when (and (semantic-idle-summary-useful-context-p)
|
||||
(semantic-idle-completions-end-of-symbol-p))
|
||||
;; This mode can be fragile. Ignore problems.
|
||||
;; If something doesn't do what you expect, run
|
||||
;; the below command by hand instead.
|
||||
(condition-case nil
|
||||
(let (
|
||||
;; Don't go loading in oodles of header libraries in
|
||||
;; IDLE time.
|
||||
(semanticdb-find-default-throttle
|
||||
(if (featurep 'semantic/db-find)
|
||||
(remq 'unloaded semanticdb-find-default-throttle)
|
||||
nil))
|
||||
)
|
||||
;; Use idle version.
|
||||
(require 'semantic/complete)
|
||||
(semantic-complete-analyze-inline-idle)
|
||||
(semanticdb-without-unloaded-file-searches
|
||||
;; Use idle version.
|
||||
(semantic-complete-analyze-inline-idle)
|
||||
)
|
||||
(error nil))
|
||||
))
|
||||
|
@ -949,6 +967,347 @@ completion.
|
|||
;; Add the ability to override sometime.
|
||||
(semantic-idle-completion-list-default))
|
||||
|
||||
|
||||
;;; Breadcrumbs for tag under point
|
||||
;;
|
||||
;; Service that displays a breadcrumbs indication of the tag under
|
||||
;; point and its parents in the header or mode line.
|
||||
;;
|
||||
|
||||
(defcustom semantic-idle-breadcrumbs-display-function
|
||||
#'semantic-idle-breadcrumbs--display-in-header-line
|
||||
"Function to display the tag under point in idle time.
|
||||
This function should take a list of Semantic tags as its only
|
||||
argument. The tags are sorted according to their nesting order,
|
||||
starting with the outermost tag. The function should call
|
||||
`semantic-idle-breadcrumbs-format-tag-list-function' to convert
|
||||
the tag list into a string."
|
||||
:group 'semantic
|
||||
:type '(choice
|
||||
(const :tag "Display in header line"
|
||||
semantic-idle-breadcrumbs--display-in-header-line)
|
||||
(const :tag "Display in mode line"
|
||||
semantic-idle-breadcrumbs--display-in-mode-line)
|
||||
(function :tag "Other function")))
|
||||
|
||||
(defcustom semantic-idle-breadcrumbs-format-tag-list-function
|
||||
#'semantic-idle-breadcrumbs--format-linear
|
||||
"Function to format the list of tags containing point.
|
||||
This function should take a list of Semantic tags and an optional
|
||||
maximum length of the produced string as its arguments. The
|
||||
maximum length is a hint and can be ignored. When the maximum
|
||||
length is omitted, an unconstrained string should be
|
||||
produced. The tags are sorted according to their nesting order,
|
||||
starting with the outermost tag. Single tags should be formatted
|
||||
using `semantic-idle-breadcrumbs-format-tag-function' unless
|
||||
special formatting is required."
|
||||
:group 'semantic
|
||||
:type '(choice
|
||||
(const :tag "Format tags as list, innermost last"
|
||||
semantic-idle-breadcrumbs--format-linear)
|
||||
(const :tag "Innermost tag with details, followed by remaining tags"
|
||||
semantic-idle-breadcrumbs--format-innermost-first)
|
||||
(function :tag "Other function")))
|
||||
|
||||
(defcustom semantic-idle-breadcrumbs-format-tag-function
|
||||
#'semantic-format-tag-abbreviate
|
||||
"Function to call to format information about tags.
|
||||
This function should take a single argument, a Semantic tag, and
|
||||
return a string to display.
|
||||
Some useful functions are found in `semantic-format-tag-functions'."
|
||||
:group 'semantic
|
||||
:type semantic-format-tag-custom-list)
|
||||
|
||||
(defcustom semantic-idle-breadcrumbs-separator 'mode-specific
|
||||
"Specify how to separate tags in the breadcrumbs string.
|
||||
An arbitrary string or a mode-specific scope nesting
|
||||
string (like, for example, \"::\" in C++, or \".\" in Java) can
|
||||
be used."
|
||||
:group 'semantic
|
||||
:type '(choice
|
||||
(const :tag "Use mode specific separator"
|
||||
mode-specific)
|
||||
(string :tag "Specify separator string")))
|
||||
|
||||
(defcustom semantic-idle-breadcrumbs-header-line-prefix
|
||||
semantic-stickyfunc-indent-string ;; TODO not optimal
|
||||
"String used to indent the breadcrumbs string.
|
||||
Customize this string to match the space used by scrollbars and
|
||||
fringe."
|
||||
:group 'semantic
|
||||
:type 'string)
|
||||
|
||||
(defvar semantic-idle-breadcrumbs-popup-menu nil
|
||||
"Menu used when a tag displayed by `semantic-idle-breadcrumbs-mode' is clicked.")
|
||||
|
||||
(defun semantic-idle-breadcrumbs--popup-menu (event)
|
||||
"Popup a menu that displays things to do to the clicked tag.
|
||||
Argument EVENT describes the event that caused this function to
|
||||
be called."
|
||||
(interactive "e")
|
||||
(let ((old-window (selected-window))
|
||||
(window (semantic-event-window event)))
|
||||
(select-window window t)
|
||||
(semantic-popup-menu semantic-idle-breadcrumbs-popup-menu)
|
||||
(select-window old-window)))
|
||||
|
||||
(defmacro semantic-idle-breadcrumbs--tag-function (function)
|
||||
"Return lambda expression calling FUNCTION when called from a popup."
|
||||
`(lambda (event)
|
||||
(interactive "e")
|
||||
(let* ((old-window (selected-window))
|
||||
(window (semantic-event-window event))
|
||||
(column (car (nth 6 (nth 1 event)))) ;; TODO semantic-event-column?
|
||||
(tag (progn
|
||||
(select-window window t)
|
||||
(plist-get
|
||||
(text-properties-at column header-line-format)
|
||||
'tag))))
|
||||
(,function tag)
|
||||
(select-window old-window)))
|
||||
)
|
||||
|
||||
;; TODO does this work for mode-line case?
|
||||
(defvar semantic-idle-breadcrumbs-popup-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
;; mouse-1 goes to clicked tag
|
||||
(define-key map
|
||||
[ header-line mouse-1 ]
|
||||
(semantic-idle-breadcrumbs--tag-function
|
||||
semantic-go-to-tag))
|
||||
;; mouse-3 pops up a context menu
|
||||
(define-key map
|
||||
[ header-line mouse-3 ]
|
||||
'semantic-idle-breadcrumbs--popup-menu)
|
||||
map)
|
||||
"Keymap for semantic idle breadcrumbs minor mode.")
|
||||
|
||||
(easy-menu-define
|
||||
semantic-idle-breadcrumbs-popup-menu
|
||||
semantic-idle-breadcrumbs-popup-map
|
||||
"Semantic Breadcrumbs Mode Menu"
|
||||
(list
|
||||
"Breadcrumb Tag"
|
||||
(semantic-menu-item
|
||||
(vector
|
||||
"Go to Tag"
|
||||
(semantic-idle-breadcrumbs--tag-function
|
||||
semantic-go-to-tag)
|
||||
:active t
|
||||
:help "Jump to this tag"))
|
||||
;; TODO these entries need minor changes (optional tag argument) in
|
||||
;; senator-copy-tag etc
|
||||
;; (semantic-menu-item
|
||||
;; (vector
|
||||
;; "Copy Tag"
|
||||
;; (semantic-idle-breadcrumbs--tag-function
|
||||
;; senator-copy-tag)
|
||||
;; :active t
|
||||
;; :help "Copy this tag"))
|
||||
;; (semantic-menu-item
|
||||
;; (vector
|
||||
;; "Kill Tag"
|
||||
;; (semantic-idle-breadcrumbs--tag-function
|
||||
;; senator-kill-tag)
|
||||
;; :active t
|
||||
;; :help "Kill tag text to the kill ring, and copy the tag to
|
||||
;; the tag ring"))
|
||||
;; (semantic-menu-item
|
||||
;; (vector
|
||||
;; "Copy Tag to Register"
|
||||
;; (semantic-idle-breadcrumbs--tag-function
|
||||
;; senator-copy-tag-to-register)
|
||||
;; :active t
|
||||
;; :help "Copy this tag"))
|
||||
;; (semantic-menu-item
|
||||
;; (vector
|
||||
;; "Narrow to Tag"
|
||||
;; (semantic-idle-breadcrumbs--tag-function
|
||||
;; senator-narrow-to-defun)
|
||||
;; :active t
|
||||
;; :help "Narrow to the bounds of the current tag"))
|
||||
;; (semantic-menu-item
|
||||
;; (vector
|
||||
;; "Fold Tag"
|
||||
;; (semantic-idle-breadcrumbs--tag-function
|
||||
;; senator-fold-tag-toggle)
|
||||
;; :active t
|
||||
;; :style 'toggle
|
||||
;; :selected '(let ((tag (semantic-current-tag)))
|
||||
;; (and tag (semantic-tag-folded-p tag)))
|
||||
;; :help "Fold the current tag to one line"))
|
||||
"---"
|
||||
(semantic-menu-item
|
||||
(vector
|
||||
"About this Header Line"
|
||||
(lambda ()
|
||||
(interactive)
|
||||
(describe-function 'semantic-idle-breadcrumbs-mode))
|
||||
:active t
|
||||
:help "Display help about this header line."))
|
||||
)
|
||||
)
|
||||
|
||||
(define-semantic-idle-service semantic-idle-breadcrumbs
|
||||
"Display breadcrumbs for the tag under point and its parents."
|
||||
(let* ((scope (semantic-calculate-scope))
|
||||
(tag-list (if scope
|
||||
;; If there is a scope, extract the tag and its
|
||||
;; parents.
|
||||
(append (oref scope parents)
|
||||
(when (oref scope tag)
|
||||
(list (oref scope tag))))
|
||||
;; Fall back to tags by overlay
|
||||
(semantic-find-tag-by-overlay))))
|
||||
;; Display the tags.
|
||||
(funcall semantic-idle-breadcrumbs-display-function tag-list)))
|
||||
|
||||
(defun semantic-idle-breadcrumbs--display-in-header-line (tag-list)
|
||||
"Display the tags in TAG-LIST in the header line of their buffer."
|
||||
(let ((width (- (nth 2 (window-edges))
|
||||
(nth 0 (window-edges)))))
|
||||
;; Format TAG-LIST and put the formatted string into the header
|
||||
;; line.
|
||||
(setq header-line-format
|
||||
(concat
|
||||
semantic-idle-breadcrumbs-header-line-prefix
|
||||
(if tag-list
|
||||
(semantic-idle-breadcrumbs--format-tag-list
|
||||
tag-list
|
||||
(- width
|
||||
(length semantic-idle-breadcrumbs-header-line-prefix)))
|
||||
(propertize
|
||||
"<not on tags>"
|
||||
'face
|
||||
'font-lock-comment-face)))))
|
||||
|
||||
;; Update the header line.
|
||||
(force-mode-line-update))
|
||||
|
||||
(defun semantic-idle-breadcrumbs--display-in-mode-line (tag-list)
|
||||
"Display the tags in TAG-LIST in the mode line of their buffer.
|
||||
TODO THIS FUNCTION DOES NOT WORK YET."
|
||||
|
||||
(error "This function does not work yet")
|
||||
|
||||
(let ((width (- (nth 2 (window-edges))
|
||||
(nth 0 (window-edges)))))
|
||||
(setq mode-line-format
|
||||
(semantic-idle-breadcrumbs--format-tag-list tag-list width)))
|
||||
|
||||
(force-mode-line-update))
|
||||
|
||||
(defun semantic-idle-breadcrumbs--format-tag-list (tag-list max-length)
|
||||
"Format TAG-LIST using configured functions respecting MAX-LENGTH.
|
||||
If the initial formatting result is longer than MAX-LENGTH, it is
|
||||
shortened at the beginning."
|
||||
;; Format TAG-LIST using the configured formatting function.
|
||||
(let* ((complete-format (funcall
|
||||
semantic-idle-breadcrumbs-format-tag-list-function
|
||||
tag-list max-length))
|
||||
;; Determine length of complete format.
|
||||
(complete-length (length complete-format)))
|
||||
;; Shorten string if necessary.
|
||||
(if (<= complete-length max-length)
|
||||
complete-format
|
||||
(concat "... "
|
||||
(substring
|
||||
complete-format
|
||||
(- complete-length (- max-length 4))))))
|
||||
)
|
||||
|
||||
(defun semantic-idle-breadcrumbs--format-linear
|
||||
(tag-list &optional max-length)
|
||||
"Format TAG-LIST as a linear list, starting with the outermost tag.
|
||||
MAX-LENGTH is not used."
|
||||
(require 'semantic/analyze/fcn)
|
||||
(let* ((format-pieces (mapcar
|
||||
#'semantic-idle-breadcrumbs--format-tag
|
||||
tag-list))
|
||||
;; Format tag list, putting configured separators between the
|
||||
;; tags.
|
||||
(complete-format (cond
|
||||
;; Mode specific separator.
|
||||
((eq semantic-idle-breadcrumbs-separator
|
||||
'mode-specific)
|
||||
(semantic-analyze-unsplit-name format-pieces))
|
||||
|
||||
;; Custom separator.
|
||||
((stringp semantic-idle-breadcrumbs-separator)
|
||||
(mapconcat
|
||||
#'identity
|
||||
format-pieces
|
||||
semantic-idle-breadcrumbs-separator)))))
|
||||
complete-format)
|
||||
)
|
||||
|
||||
(defun semantic-idle-breadcrumbs--format-innermost-first
|
||||
(tag-list &optional max-length)
|
||||
"Format TAG-LIST placing the innermost tag first, separated from its parents.
|
||||
If MAX-LENGTH is non-nil, the innermost tag is shortened."
|
||||
(let* (;; Separate and format remaining tags. Calculate length of
|
||||
;; resulting string.
|
||||
(rest-tags (butlast tag-list))
|
||||
(rest-format (if rest-tags
|
||||
(concat
|
||||
" | "
|
||||
(semantic-idle-breadcrumbs--format-linear
|
||||
rest-tags))
|
||||
""))
|
||||
(rest-length (length rest-format))
|
||||
;; Format innermost tag and calculate length of resulting
|
||||
;; string.
|
||||
(inner-format (semantic-idle-breadcrumbs--format-tag
|
||||
(car (last tag-list))
|
||||
#'semantic-format-tag-prototype))
|
||||
(inner-length (length inner-format))
|
||||
;; Calculate complete length and shorten string for innermost
|
||||
;; tag if MAX-LENGTH is non-nil and the complete string is
|
||||
;; too long.
|
||||
(complete-length (+ inner-length rest-length))
|
||||
(inner-short (if (and max-length
|
||||
(<= complete-length max-length))
|
||||
inner-format
|
||||
(concat (substring
|
||||
inner-format
|
||||
0
|
||||
(- inner-length
|
||||
(- complete-length max-length)
|
||||
4))
|
||||
" ..."))))
|
||||
;; Concat both parts.
|
||||
(concat inner-short rest-format))
|
||||
)
|
||||
|
||||
(defun semantic-idle-breadcrumbs--format-tag (tag &optional format-function)
|
||||
"Format TAG using the configured function or FORMAT-FUNCTION.
|
||||
This function also adds text properties for help-echo, mouse
|
||||
highlighting and a keymap."
|
||||
(let ((formatted (funcall
|
||||
(or format-function
|
||||
semantic-idle-breadcrumbs-format-tag-function)
|
||||
tag nil t)))
|
||||
(add-text-properties
|
||||
0 (length formatted)
|
||||
(list
|
||||
'tag
|
||||
tag
|
||||
'help-echo
|
||||
(format
|
||||
"Tag %s
|
||||
Type: %s
|
||||
mouse-1: jump to tag
|
||||
mouse-3: popup context menu"
|
||||
(semantic-tag-name tag)
|
||||
(semantic-tag-class tag))
|
||||
'mouse-face
|
||||
'highlight
|
||||
'keymap
|
||||
semantic-idle-breadcrumbs-popup-map)
|
||||
formatted)
|
||||
formatted))
|
||||
|
||||
|
||||
(provide 'semantic/idle)
|
||||
|
||||
;; Local variables:
|
||||
|
|
|
@ -99,7 +99,7 @@ A nil value means to keep them in the same order.
|
|||
Overriden to nil if `semantic-imenu-bucketize-file' is nil."
|
||||
:group 'semantic-imenu
|
||||
:type 'boolean)
|
||||
(make-variable-buffer-local 'semantic-imenu-bucketize-type-parts)
|
||||
(make-variable-buffer-local 'semantic-imenu-bucketize-type-members)
|
||||
(semantic-varalias-obsolete 'semantic-imenu-bucketize-type-parts
|
||||
'semantic-imenu-bucketize-type-members "23.2")
|
||||
|
||||
|
|
|
@ -864,42 +864,45 @@ and variable state from the current buffer."
|
|||
semantic-lex-spp-expanded-macro-stack
|
||||
))
|
||||
)
|
||||
(with-current-buffer buf
|
||||
(erase-buffer)
|
||||
;; Below is a painful hack to make sure everything is setup correctly.
|
||||
(when (not (eq major-mode mode))
|
||||
(save-match-data
|
||||
(if (> semantic-lex-spp-hack-depth 5)
|
||||
nil
|
||||
(with-current-buffer buf
|
||||
(erase-buffer)
|
||||
;; Below is a painful hack to make sure everything is setup correctly.
|
||||
(when (not (eq major-mode mode))
|
||||
(save-match-data
|
||||
|
||||
;; Protect against user-hooks that throw errors.
|
||||
(condition-case nil
|
||||
(funcall mode)
|
||||
(error nil))
|
||||
;; Protect against user-hooks that throw errors.
|
||||
(condition-case nil
|
||||
(funcall mode)
|
||||
(error nil))
|
||||
|
||||
;; Hack in mode-local
|
||||
(activate-mode-local-bindings)
|
||||
;; CHEATER! The following 3 lines are from
|
||||
;; `semantic-new-buffer-fcn', but we don't want to turn
|
||||
;; on all the other annoying modes for this little task.
|
||||
(setq semantic-new-buffer-fcn-was-run t)
|
||||
(semantic-lex-init)
|
||||
(semantic-clear-toplevel-cache)
|
||||
(remove-hook 'semantic-lex-reset-hooks 'semantic-lex-spp-reset-hook
|
||||
t)
|
||||
))
|
||||
;; Hack in mode-local
|
||||
(activate-mode-local-bindings)
|
||||
|
||||
;; Second Cheat: copy key variables regarding macro state from the
|
||||
;; the originating buffer we are parsing. We need to do this every time
|
||||
;; since the state changes.
|
||||
(dolist (V important-vars)
|
||||
(set V (semantic-buffer-local-value V origbuff)))
|
||||
(insert text)
|
||||
(goto-char (point-min))
|
||||
;; CHEATER! The following 3 lines are from
|
||||
;; `semantic-new-buffer-fcn', but we don't want to turn
|
||||
;; on all the other annoying modes for this little task.
|
||||
(setq semantic-new-buffer-fcn-was-run t)
|
||||
(semantic-lex-init)
|
||||
(semantic-clear-toplevel-cache)
|
||||
(remove-hook 'semantic-lex-reset-hooks 'semantic-lex-spp-reset-hook
|
||||
t)
|
||||
))
|
||||
|
||||
(setq fresh-toks (semantic-lex-spp-stream-for-macro (point-max))))
|
||||
;; Second Cheat: copy key variables regarding macro state from the
|
||||
;; the originating buffer we are parsing. We need to do this every time
|
||||
;; since the state changes.
|
||||
(dolist (V important-vars)
|
||||
(set V (semantic-buffer-local-value V origbuff)))
|
||||
(insert text)
|
||||
(goto-char (point-min))
|
||||
|
||||
(dolist (tok fresh-toks)
|
||||
(when (memq (semantic-lex-token-class tok) '(symbol semantic-list))
|
||||
(setq toks (cons tok toks))))
|
||||
(setq fresh-toks (semantic-lex-spp-stream-for-macro (point-max))))
|
||||
|
||||
(dolist (tok fresh-toks)
|
||||
(when (memq (semantic-lex-token-class tok) '(symbol semantic-list))
|
||||
(setq toks (cons tok toks)))))
|
||||
|
||||
(nreverse toks)))
|
||||
|
||||
|
|
|
@ -1810,8 +1810,8 @@ what syntax class CHAR has.")
|
|||
|
||||
(defvar semantic-ignore-comments t
|
||||
"Default comment handling.
|
||||
t means to strip comments when flexing. Nil means to keep comments
|
||||
as part of the token stream.")
|
||||
The value t means to strip comments when flexing; nil means
|
||||
to keep comments as part of the token stream.")
|
||||
(make-variable-buffer-local 'semantic-ignore-comments)
|
||||
|
||||
(defvar semantic-flex-enable-newlines nil
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
:documentation
|
||||
"The list of types currently in scope.
|
||||
For C++, this would contain anonymous namespaces known, and
|
||||
anything labled by a `using' statement.")
|
||||
anything labeled by a `using' statement.")
|
||||
(parents :initform nil
|
||||
:documentation
|
||||
"List of parents in scope w/in the body of this function.
|
||||
|
@ -239,8 +239,11 @@ are from nesting data types."
|
|||
)
|
||||
;; In case of arg lists or some-such, throw out non-types.
|
||||
(while (and stack (not (semantic-tag-of-class-p pparent 'type)))
|
||||
(setq stack (cdr stack)
|
||||
pparent (car (cdr stack))))
|
||||
(setq stack (cdr stack) pparent (car (cdr stack))))
|
||||
|
||||
;; Remove duplicates
|
||||
(while (member pparent scopetypes)
|
||||
(setq stack (cdr stack) pparent (car (cdr stack))))
|
||||
|
||||
;; Step 1:
|
||||
;; Analyze the stack of tags we are nested in as parents.
|
||||
|
@ -611,7 +614,7 @@ whose tags can be searched when needed, OR it may be a scope object."
|
|||
;; to do any of the stuff related to variables and what-not.
|
||||
(setq tmpscope (semantic-scope-cache "mini"))
|
||||
(let* ( ;; Step 1:
|
||||
(scopetypes (semantic-analyze-scoped-types (point)))
|
||||
(scopetypes (cons type (semantic-analyze-scoped-types (point))))
|
||||
(parents (semantic-analyze-scope-nested-tags (point) scopetypes))
|
||||
;;(parentinherited (semantic-analyze-scope-lineage-tags parents scopetypes))
|
||||
(lscope nil)
|
||||
|
|
|
@ -463,7 +463,7 @@ include the default behavior, and merely extend your own."
|
|||
)
|
||||
|
||||
(defun semantic-tag-external-member-parent-default (tag)
|
||||
"Return the name of TAGs parent only if TAG is not defined in it's parent."
|
||||
"Return the name of TAGs parent only if TAG is not defined in its parent."
|
||||
;; Use only the extra spec because a type has a parent which
|
||||
;; means something completely different.
|
||||
(let ((tp (semantic-tag-get-attribute tag :parent)))
|
||||
|
@ -473,7 +473,7 @@ include the default behavior, and merely extend your own."
|
|||
(define-overloadable-function semantic-tag-external-member-p (parent tag)
|
||||
"Return non-nil if PARENT is the parent of TAG.
|
||||
TAG is an external member of PARENT when it is somehow tagged
|
||||
as having PARENT as it's parent.
|
||||
as having PARENT as its parent.
|
||||
PARENT and TAG must both be semantic tags.
|
||||
|
||||
The default behavior, if not overridden with
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
(declare-function data-debug-insert-object-slots "eieio-datadebug")
|
||||
(declare-function ede-toplevel "ede/files")
|
||||
(declare-function ede-project-root-directory "ede/files")
|
||||
(declare-function ede-up-directory "ede/files")
|
||||
|
||||
;;; Code:
|
||||
(defvar semantic-symref-tool 'detect
|
||||
|
@ -98,16 +99,27 @@ is supported.
|
|||
|
||||
If no tools are supported, then 'grep is assumed.")
|
||||
|
||||
(defun semantic-symref-calculate-rootdir ()
|
||||
"Calculate the root directory for a symref search.
|
||||
Start with and EDE project, or use the default directory."
|
||||
(let* ((rootproj (when (and (featurep 'ede) ede-minor-mode)
|
||||
(ede-toplevel)))
|
||||
(rootdirbase (if rootproj
|
||||
(ede-project-root-directory rootproj)
|
||||
default-directory)))
|
||||
(if (and rootproj (condition-case nil
|
||||
;; Hack for subprojects.
|
||||
(oref rootproj :metasubproject)
|
||||
(error nil)))
|
||||
(ede-up-directory rootdirbase)
|
||||
rootdirbase)))
|
||||
|
||||
(defun semantic-symref-detect-symref-tool ()
|
||||
"Detect the symref tool to use for the current buffer."
|
||||
(if (not (eq semantic-symref-tool 'detect))
|
||||
semantic-symref-tool
|
||||
;; We are to perform a detection for the right tool to use.
|
||||
(let* ((rootproj (when (and (featurep 'ede) ede-minor-mode)
|
||||
(ede-toplevel)))
|
||||
(rootdir (if rootproj
|
||||
(ede-project-root-directory rootproj)
|
||||
default-directory))
|
||||
(let* ((rootdir (semantic-symref-calculate-rootdir))
|
||||
(tools semantic-symref-tool-alist))
|
||||
(while (and tools (eq semantic-symref-tool 'detect))
|
||||
(when (funcall (car (car tools)) rootdir)
|
||||
|
|
|
@ -30,10 +30,6 @@
|
|||
(require 'semantic/symref)
|
||||
(require 'grep)
|
||||
|
||||
(defvar ede-minor-mode)
|
||||
(declare-function ede-toplevel "ede/files")
|
||||
(declare-function ede-project-root-directory "ede/files")
|
||||
|
||||
;;; Code:
|
||||
|
||||
;;; GREP
|
||||
|
@ -86,7 +82,7 @@ Optional argument MODE specifies the `major-mode' to test."
|
|||
" -o ")
|
||||
" \\)"))
|
||||
(t
|
||||
(error "Configuration for `semantic-symref-tool-grep' needed for %s" major-mode))
|
||||
(error "Customize `semantic-symref-filepattern-alist' for %s" major-mode))
|
||||
)))
|
||||
|
||||
(defvar semantic-symref-grep-expand-keywords
|
||||
|
@ -119,6 +115,12 @@ GREPPATTERN is the pattern used by grep."
|
|||
;;(message "New command: %s" cmd)
|
||||
cmd))
|
||||
|
||||
(defcustom semantic-symref-grep-shell "sh"
|
||||
"The shell command to use for executing find/grep.
|
||||
This shell should support pipe redirect syntax."
|
||||
:group 'semantic
|
||||
:type 'string)
|
||||
|
||||
(defmethod semantic-symref-perform-search ((tool semantic-symref-tool-grep))
|
||||
"Perform a search with Grep."
|
||||
;; Grep doesn't support some types of searches.
|
||||
|
@ -129,19 +131,7 @@ GREPPATTERN is the pattern used by grep."
|
|||
;; Find the root of the project, and do a find-grep...
|
||||
(let* (;; Find the file patterns to use.
|
||||
(pat (cdr (assoc major-mode semantic-symref-filepattern-alist)))
|
||||
(rootdir (cond
|
||||
;; Project root via EDE.
|
||||
((eq (oref tool :searchscope) 'project)
|
||||
(let ((rootproj (when (and (featurep 'ede) ede-minor-mode)
|
||||
(ede-toplevel))))
|
||||
(if rootproj
|
||||
(ede-project-root-directory rootproj)
|
||||
default-directory)))
|
||||
;; Calculate the target files as just in
|
||||
;; this directory... cause I'm lazy.
|
||||
((eq (oref tool :searchscope) 'target)
|
||||
default-directory)
|
||||
))
|
||||
(rootdir (semantic-symref-calculate-rootdir))
|
||||
(filepattern (semantic-symref-derive-find-filepatterns))
|
||||
;; Grep based flags.
|
||||
(grepflags (cond ((eq (oref tool :resulttype) 'file)
|
||||
|
@ -168,10 +158,10 @@ GREPPATTERN is the pattern used by grep."
|
|||
(let ((cmd (concat "find " default-directory " -type f " filepattern " -print0 "
|
||||
"| xargs -0 grep -H " grepflags "-e " greppat)))
|
||||
;;(message "Old command: %s" cmd)
|
||||
(call-process "sh" nil b nil "-c" cmd)
|
||||
(call-process semantic-symref-grep-shell nil b nil "-c" cmd)
|
||||
)
|
||||
(let ((cmd (semantic-symref-grep-use-template rootdir filepattern grepflags greppat)))
|
||||
(call-process "sh" nil b nil "-c" cmd))
|
||||
(call-process semantic-symref-grep-shell nil b nil "-c" cmd))
|
||||
))
|
||||
(setq ans (semantic-symref-parse-tool-output tool b))
|
||||
;; Return the answer
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
(require 'semantic/symref)
|
||||
(require 'semantic/complete)
|
||||
(require 'semantic/senator)
|
||||
(require 'pulse)
|
||||
|
||||
;;; Code:
|
||||
|
@ -42,9 +43,9 @@
|
|||
"Find references to the current tag.
|
||||
This command uses the currently configured references tool within the
|
||||
current project to find references to the current tag. The
|
||||
references are the organized by file and the name of the function
|
||||
references are organized by file and the name of the function
|
||||
they are used in.
|
||||
Display the references in`semantic-symref-results-mode'."
|
||||
Display the references in `semantic-symref-results-mode'."
|
||||
(interactive)
|
||||
(semantic-fetch-tags)
|
||||
(let ((ct (semantic-current-tag))
|
||||
|
@ -65,6 +66,24 @@ Display the references in`semantic-symref-results-mode'."
|
|||
"Find references to the symbol SYM.
|
||||
This command uses the currently configured references tool within the
|
||||
current project to find references to the input SYM. The
|
||||
references are organized by file and the name of the function
|
||||
they are used in.
|
||||
Display the references in `semantic-symref-results-mode'."
|
||||
(interactive (list (semantic-tag-name (semantic-complete-read-tag-buffer-deep
|
||||
"Symrefs for: "))))
|
||||
(semantic-fetch-tags)
|
||||
(let ((res nil)
|
||||
)
|
||||
;; Gather results and tags
|
||||
(message "Gathering References...")
|
||||
(setq res (semantic-symref-find-references-by-name sym))
|
||||
(semantic-symref-produce-list-on-results res sym)))
|
||||
|
||||
;;;###autoload
|
||||
(defun semantic-symref-regexp (sym)
|
||||
"Find references to the a symbol regexp SYM.
|
||||
This command uses the currently configured references tool within the
|
||||
current project to find references to the input SYM. The
|
||||
references are the organized by file and the name of the function
|
||||
they are used in.
|
||||
Display the references in`semantic-symref-results-mode'."
|
||||
|
@ -75,7 +94,7 @@ Display the references in`semantic-symref-results-mode'."
|
|||
)
|
||||
;; Gather results and tags
|
||||
(message "Gathering References...")
|
||||
(setq res (semantic-symref-find-references-by-name sym))
|
||||
(setq res (semantic-symref-find-text sym))
|
||||
(semantic-symref-produce-list-on-results res sym)))
|
||||
|
||||
|
||||
|
@ -110,11 +129,59 @@ Display the references in`semantic-symref-results-mode'."
|
|||
(define-key km "n" 'semantic-symref-list-next-line)
|
||||
(define-key km "p" 'semantic-symref-list-prev-line)
|
||||
(define-key km "q" 'semantic-symref-hide-buffer)
|
||||
(define-key km "\C-c\C-e" 'semantic-symref-list-expand-all)
|
||||
(define-key km "\C-c\C-r" 'semantic-symref-list-contract-all)
|
||||
(define-key km "R" 'semantic-symref-list-rename-open-hits)
|
||||
(define-key km "(" 'semantic-symref-list-create-macro-on-open-hit)
|
||||
(define-key km "E" 'semantic-symref-list-call-macro-on-open-hits)
|
||||
km)
|
||||
"Keymap used in `semantic-symref-results-mode'.")
|
||||
|
||||
(defvar semantic-symref-list-menu-entries
|
||||
(list
|
||||
"Symref"
|
||||
(semantic-menu-item
|
||||
["Toggle Line Open"
|
||||
semantic-symref-list-toggle-showing
|
||||
:active t
|
||||
:help "Toggle the current line open or closed."
|
||||
])
|
||||
(semantic-menu-item
|
||||
["Expand All Entries"
|
||||
semantic-symref-list-expand-all
|
||||
:active t
|
||||
:help "Expand every expandable entry."
|
||||
])
|
||||
(semantic-menu-item
|
||||
["Contract All Entries"
|
||||
semantic-symref-list-contract-all
|
||||
:active t
|
||||
:help "Close every expandable entry."
|
||||
])
|
||||
(semantic-menu-item
|
||||
["Rename Symbol in Open hits"
|
||||
semantic-symref-list-rename-open-hits
|
||||
:active t
|
||||
:help "Rename the searched for symbol in all hits that are currently open."
|
||||
])
|
||||
)
|
||||
"Menu entries for the Semantic Symref list mode.")
|
||||
|
||||
(defvar semantic-symref-list-menu nil
|
||||
"Menu keymap build from `semantic-symref-results-mode'.")
|
||||
|
||||
(easy-menu-define semantic-symref-list-menu
|
||||
semantic-symref-results-mode-map
|
||||
"Symref Mode Menu"
|
||||
semantic-symref-list-menu-entries)
|
||||
|
||||
(defcustom semantic-symref-auto-expand-results nil
|
||||
"Non-nil to expand symref results on buffer creation."
|
||||
:group 'semantic-symref
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom semantic-symref-results-mode-hook nil
|
||||
"*Hook run when `semantic-symref-results-mode' starts."
|
||||
"Hook run when `semantic-symref-results-mode' starts."
|
||||
:group 'semantic-symref
|
||||
:type 'hook)
|
||||
|
||||
|
@ -189,6 +256,10 @@ Some useful functions are found in `semantic-format-tag-functions'."
|
|||
|
||||
))
|
||||
|
||||
;; Auto expand
|
||||
(when semantic-symref-auto-expand-results
|
||||
(semantic-symref-list-expand-all))
|
||||
|
||||
;; Clean up the mess
|
||||
(toggle-read-only 1)
|
||||
(set-buffer-modified-p nil)
|
||||
|
@ -305,7 +376,8 @@ BUTTON is the button that was clicked."
|
|||
(win (selected-window))
|
||||
)
|
||||
(switch-to-buffer-other-window buff)
|
||||
(with-no-warnings (goto-line line))
|
||||
(goto-char (point-min))
|
||||
(forward-line (1- line))
|
||||
(pulse-momentary-highlight-one-line (point))
|
||||
(when (eq last-command-event ?\s) (select-window win))
|
||||
)
|
||||
|
@ -323,6 +395,158 @@ BUTTON is the button that was clicked."
|
|||
(forward-line -1)
|
||||
(back-to-indentation))
|
||||
|
||||
(defun semantic-symref-list-expand-all ()
|
||||
"Expand all the nodes in the current buffer."
|
||||
(interactive)
|
||||
(let ((start (make-marker)))
|
||||
(move-marker start (point))
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "\\[[+]\\]" nil t)
|
||||
(semantic-symref-list-toggle-showing))
|
||||
;; Restore position
|
||||
(goto-char start)))
|
||||
|
||||
(defun semantic-symref-list-contract-all ()
|
||||
"Expand all the nodes in the current buffer."
|
||||
(interactive)
|
||||
(let ((start (make-marker)))
|
||||
(move-marker start (point))
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "\\[[-]\\]" nil t)
|
||||
(semantic-symref-list-toggle-showing))
|
||||
;; Restore position
|
||||
(goto-char start)))
|
||||
|
||||
;;; UTILS
|
||||
;;
|
||||
;; List mode utils for understadning the current line
|
||||
|
||||
(defun semantic-symref-list-on-hit-p ()
|
||||
"Return the line number if the cursor is on a buffer line with a hit.
|
||||
Hits are the line of code from the buffer, not the tag summar or file lines."
|
||||
(save-excursion
|
||||
(end-of-line)
|
||||
(let* ((ol (car (semantic-overlays-at (1- (point)))))) ;; trust this for now
|
||||
(when ol (semantic-overlay-get ol 'line)))))
|
||||
|
||||
|
||||
;;; Keyboard Macros on a Hit
|
||||
;;
|
||||
;; Record a macro on a hit, and store in a special way for execution later.
|
||||
(defun semantic-symref-list-create-macro-on-open-hit ()
|
||||
"Record a keyboard macro at the location of the hit in the current list.
|
||||
Under point should be one hit for the active keyword. Move
|
||||
cursor to the beginning of that symbol, then record a macro as if
|
||||
`kmacro-start-macro' was pressed. Use `kmacro-end-macro',
|
||||
{kmacro-end-macro} to end the macro, and return to the symbol found list."
|
||||
(interactive)
|
||||
(let* ((oldsym (oref (oref semantic-symref-current-results
|
||||
:created-by)
|
||||
:searchfor))
|
||||
(ol (save-excursion
|
||||
(end-of-line)
|
||||
(car (semantic-overlays-at (1- (point))))))
|
||||
(tag (when ol (semantic-overlay-get ol 'tag)))
|
||||
(line (when ol (semantic-overlay-get ol 'line))))
|
||||
(when (not line)
|
||||
(error "Cannot create macro on a non-hit line"))
|
||||
;; Go there, and do something useful.
|
||||
(switch-to-buffer-other-window (semantic-tag-buffer tag))
|
||||
(goto-char (point-min))
|
||||
(forward-line (1- line))
|
||||
(when (not (re-search-forward (regexp-quote oldsym) (point-at-eol) t))
|
||||
(error "Cannot find hit. Cannot record macro"))
|
||||
(goto-char (match-beginning 0))
|
||||
;; Cursor is now in the right location. Start recording a macro.
|
||||
(kmacro-start-macro nil)
|
||||
;; Notify the user
|
||||
(message "Complete with C-x ). Use E in the symref buffer to call this macro.")))
|
||||
|
||||
(defun semantic-symref-list-call-macro-on-open-hits ()
|
||||
"Call the most recently created keyboard macro on each hit.
|
||||
Cursor is placed at the beginning of the symbol found, even if
|
||||
there is more than one symbol on the current line. The
|
||||
previously recorded macro is then executed."
|
||||
(interactive)
|
||||
(save-window-excursion
|
||||
(let ((count (semantic-symref-list-map-open-hits
|
||||
(lambda ()
|
||||
(switch-to-buffer (current-buffer))
|
||||
(kmacro-call-macro nil)))))
|
||||
(semantic-symref-list-update-open-hits)
|
||||
(message "Executed Macro %d times." count))))
|
||||
|
||||
;;; REFACTORING EDITS
|
||||
;;
|
||||
;; Utilities and features for refactoring across a list of hits.
|
||||
;;
|
||||
(defun semantic-symref-list-rename-open-hits (newname)
|
||||
"Rename the discovered symbol references to NEWNAME.
|
||||
Only renames the locations that are open in the symref list.
|
||||
Closed items will be skipped."
|
||||
(interactive
|
||||
(list (read-string "Rename to: "
|
||||
(oref (oref semantic-symref-current-results
|
||||
:created-by)
|
||||
:searchfor))))
|
||||
(let ((count (semantic-symref-list-map-open-hits
|
||||
(lambda () (replace-match newname nil t)))))
|
||||
(semantic-symref-list-update-open-hits)
|
||||
(message "Renamed %d occurrences." count)))
|
||||
|
||||
;;; REFACTORING UTILITIES
|
||||
;;
|
||||
;; Refactoring tools want to operate on only the "good" stuff the
|
||||
;; user selected.
|
||||
(defun semantic-symref-list-map-open-hits (function)
|
||||
"For every open hit in the symref buffer, perform FUNCTION.
|
||||
The `match-data' will be set to a successful hit of the searched for symbol.
|
||||
Return the number of occurrences FUNCTION was operated upon."
|
||||
|
||||
;; First Pass in this function - a straight rename.
|
||||
;; Second Pass - Allow context specification based on
|
||||
;; class members. (Not Done)
|
||||
|
||||
(let ((oldsym (oref (oref semantic-symref-current-results
|
||||
:created-by)
|
||||
:searchfor))
|
||||
(count 0))
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(while (not (eobp))
|
||||
;; Is this line a "hit" line?
|
||||
(let* ((ol (car (semantic-overlays-at (1- (point))))) ;; trust this for now
|
||||
(tag (when ol (semantic-overlay-get ol 'tag)))
|
||||
(line (when ol (semantic-overlay-get ol 'line))))
|
||||
(when line
|
||||
;; The "line" means we have an open hit.
|
||||
(with-current-buffer (semantic-tag-buffer tag)
|
||||
(goto-char (point-min))
|
||||
(forward-line (1- line))
|
||||
(beginning-of-line)
|
||||
(while (re-search-forward (regexp-quote oldsym) (point-at-eol) t)
|
||||
(setq count (1+ count))
|
||||
(save-excursion ;; Leave cursor after the matched name.
|
||||
(goto-char (match-beginning 0)) ;; Go to beginning of that sym
|
||||
(funcall function))))))
|
||||
;; Go to the next line
|
||||
(forward-line 1)
|
||||
(end-of-line)))
|
||||
count))
|
||||
|
||||
(defun semantic-symref-list-update-open-hits ()
|
||||
"Update the text for all the open hits in the symref list."
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "\\[-\\]" nil t)
|
||||
(end-of-line)
|
||||
(let* ((ol (car (semantic-overlays-at (1- (point))))) ;; trust this for now
|
||||
(tag (when ol (semantic-overlay-get ol 'tag))))
|
||||
;; If there is a tag, then close/open it.
|
||||
(when tag
|
||||
(semantic-symref-list-toggle-showing)
|
||||
(semantic-symref-list-toggle-showing))))))
|
||||
|
||||
(provide 'semantic/symref/list)
|
||||
|
||||
;; Local variables:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue