merge trunk

This commit is contained in:
Kenichi Handa 2010-09-27 14:42:43 +09:00
commit b3253cd4b4
325 changed files with 11987 additions and 8304 deletions

View file

@ -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
View file

@ -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}"

View file

@ -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}"

View file

@ -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.

View file

@ -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.
%

View file

@ -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.
%

View file

@ -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.
%

View file

@ -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.
%

View file

@ -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.
%

View file

@ -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.
%

View file

@ -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.
%

View file

@ -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.
%

View file

@ -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.
%

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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

View file

@ -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!}

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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.");

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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.

View file

@ -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>

View file

@ -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)))))

View file

@ -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

View file

@ -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

View file

@ -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)))

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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
View 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

View file

@ -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
View 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

View file

@ -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
View 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

View file

@ -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)

View file

@ -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)))

View file

@ -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
View 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

View file

@ -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)))

View file

@ -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:

View file

@ -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))

View file

@ -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))

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View file

@ -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

View file

@ -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.")

View file

@ -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."

View file

@ -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 $@ $<"
)

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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."

View file

@ -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"))

View file

@ -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.

View file

@ -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)

View file

@ -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 "\""))

View file

@ -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))

View file

@ -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 ")

View file

@ -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.

View file

@ -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)

View file

@ -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))))))))

View file

@ -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)

View file

@ -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))
))

View file

@ -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)

View file

@ -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))

View file

@ -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)))

View file

@ -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
;;

View file

@ -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))

View file

@ -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)))

View file

@ -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 ;-)
;; ;;

View file

@ -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

View file

@ -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

View file

@ -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.")))
))

View file

@ -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:

View file

@ -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")

View file

@ -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)))

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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