From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Dmitry Gutov Newsgroups: gmane.emacs.devel Subject: Re: Unified project interface Date: Sun, 26 Jul 2015 05:11:41 +0300 Message-ID: <55B441DD.9060806@yandex.ru> References: <557039DB.4060607@yandex.ru> <85d21bbkqf.fsf@stephe-leake.org> <5570E86B.8070200@yandex.ru> <85iob2a2mm.fsf@stephe-leake.org> <55B2CDA4.8020207@yandex.ru> <868ua5caz6.fsf@stephe-leake.org> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit X-Trace: ger.gmane.org 1437876725 14214 80.91.229.3 (26 Jul 2015 02:12:05 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sun, 26 Jul 2015 02:12:05 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sun Jul 26 04:11:58 2015 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1ZJBPw-0004Nf-Q1 for ged-emacs-devel@m.gmane.org; Sun, 26 Jul 2015 04:11:57 +0200 Original-Received: from localhost ([::1]:49276 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZJBPv-0007mr-OV for ged-emacs-devel@m.gmane.org; Sat, 25 Jul 2015 22:11:55 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:55386) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZJBPq-0007mk-JJ for emacs-devel@gnu.org; Sat, 25 Jul 2015 22:11:52 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZJBPl-0000PQ-HU for emacs-devel@gnu.org; Sat, 25 Jul 2015 22:11:50 -0400 Original-Received: from mail-wi0-x229.google.com ([2a00:1450:400c:c05::229]:35519) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZJBPl-0000OY-5g for emacs-devel@gnu.org; Sat, 25 Jul 2015 22:11:45 -0400 Original-Received: by wibxm9 with SMTP id xm9so69975937wib.0 for ; Sat, 25 Jul 2015 19:11:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:subject:to:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-type:content-transfer-encoding; bh=S5ZxN2ub85Sdp+xLmg1EuaAKBHMtro2dWx0S53eruLo=; b=SoHd8R97bkigNWYqTSZA9wJ0h4woRogl4J5A07tqPjCAdizvfvmJR6H26Rte9kEpzT rKOLeT8psn1nNiwlrLEeKOJvoln8weZD3BphvbgD6lDED1KYnsox/uwDPnUDysDYayBs /wU2OWuk9MKN+OiYjFv8p5OKhgeH0aBaBKS9bl8VZBmHTzdfrju0XnTvUTsYd761INGV ghVXEFzPcD5RWhYp0MCu9XNlTa0DOnWczkwLFsNJ/v2iBMdT26VnwezK2X+nIkT4NjlE C8ApUwoSQTFWTi9xOKjjxKGkcMHw5u9C34WWkdKI7gdw5OtyJA5hr6Wwy9M8wHiXvh+g x7Og== X-Received: by 10.194.60.11 with SMTP id d11mr28439165wjr.143.1437876703916; Sat, 25 Jul 2015 19:11:43 -0700 (PDT) Original-Received: from [192.168.1.2] ([185.105.175.24]) by smtp.googlemail.com with ESMTPSA id ib9sm20267723wjb.2.2015.07.25.19.11.42 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 25 Jul 2015 19:11:43 -0700 (PDT) User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.0 In-Reply-To: <868ua5caz6.fsf@stephe-leake.org> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a00:1450:400c:c05::229 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:188087 Archived-At: Hi Stephen, Sorry for the delay; I had to think on it. On 07/25/2015 03:55 AM, Stephen Leake wrote: > I would suggest the terminology "main project" vs "included projects" > for this; the "main project" is the code you own; the "included > projects" are all the others (included the system includes). There's sense in this, but is "an included project you don't own, which is not in system includes" a significant use case? In my own experience, either the projects on which the current one depends are installed in system directories, and thus are indistinguishable from system includes (such as Ruby gems, installed via "gem install"), or the linked project's tree lives near the current one, and we can consider it a part of the main project, for the purposes of editing. Because even if the second project is a third-party dependency, sometimes you want to make changes to it anyway, and the user might get miffed if xref-query-replace prohibits that. > So this would be an argument to xref-find-regexp; > > (defun xref-find-regexp (regexp &optional not-included-projects) > "Search all files in all project directories for REGEXP. > If NOT-INCLUDED-PROJECTS is non-nil (default nil), search only the main > project. Otherwise, search the main project and included projects." It should probably be a new command, because otherwise specifying that second argument interactively would be a pain (C-u already makes xref-find-regexp ask a bunch of questions). > To implement this, project-search-path might want to be an alist of: > > (PROJECT-NAME ) > > where the first element is the main project and the rest are the > included ones. Maybe do it differently? If we do have linked projects (and the separation between main/included), some generic function, probably named differently, would return a list of those project instances. Then the caller will ask each instance for its root (or the directories). There's no need for the main project's search-path entry there, xref-find-regexp can just use its root (or the directories) as well. >> We have that in project-ignores now. > > Right. That's not consistent with current things like load-path. I Indeed. But maybe supporting ignores for project-search-path is not a big priority. There's not much to ignore in /usr/include, for instance. The directories in load-path also usually don't contain weird files or build artefacts (and when they do, it's not like elisp-search-path really can account for those). So maybe a good first approximation would be to simply not apply the ignores list to the project-search-path elements outside of the project tree. If that's not good enough, project-ignores can accept a directory as its argument (it must be among those returned by project-directories, or project-search-path), and return the appropriate ignores list. This will definitely help if each element in project-directories is a separate (e.g. Git) repository, with its own .gitignore. > should think at some point in the implementation of any "search project" > function you will want an explicit list of directories (and maybe files) > to search, which will be the union of project-search-path minus > project-ignores. So it seems simpler to specify that list directly. I'm not sure about that. It seems then the implementation will have to walk the whole project tree itself, and collect all directories that don't match the ignores (because .gitignore syntax allows not-anchored entries for directories). And if we're to support ignoring files (and obvious use case), it'll become a list of files, which can grow pretty big. I think it's better to delegate this job to 'find', as long as that doesn't force us to compromise on functionality. > The user interface (the syntax of the project file) could be structured > as includes and ignores (excludes). .gitignore also supports whitelisting entries (which override the excludes). I haven't gotten around to writing support for those. >> You're probably aware of similar tools. > > monotone, git, subversion ... :). Not sure about the other two, but Git doesn't need to be told the project root. It can be called from any directory, and works with relative paths quite well. > Recently I've been playing with Google's Android Studio (shudder; only > to make Emacs do what it does, I promise :). It defines a project root > by a dominating file. Of course. Why else one would be playing with it? ;) In this case, project-directories can return a list with one element. > On the other hand, AdaCore GPS (an Ada-specific IDE) defines a project > by a project file that specifies various lists of directories (source, > object, executable); there is no root directory. The project file itself > can be anywhere, it doesn't have to be in one of the listed directories. > That's what Emacs Ada mode does as well. In this case, it seems, the relevant project implementation will be based on user explicitly telling it where the project file lives (by calling a particular command, with a prompt), and then the project will be enabled globally, for the whole Emacs session. project-directories then will return some of the directories specified in the project file (except the object ones, maybe, if there's nothing we can edit there), but probably (?) not the one where the project file lies, if it's somewhere separately. Would there be any significant value in project-root returning the directory of the project file? > I think they are disjoint concepts. Nothing wrong with keeping both; > some tools will need them, some won't. That would mean documenting the distinction, so that implementers know what to do. I'm increasingly less clear on it. > If project-directories contains all directories (not just root ones), > this is just (file-name-directory path) . (file-name-non-directory > path). It would be. But I expect project-directories to only include the roots. IOW, no project-directories element should be a subdirectory of another. >> Then instead of project-root, a consumer will use (car >> (project-relativize-path default-directory)). > > I don't follow; that means the value of 'root directory' changes > depending on where the current file is. That's correct. If the file is inside the "main" project directory, it will use the main project root. If the file is in another directory, it's in a "linked" body of code (which would often be called a project as well), and its root is used. Atom has taken this approach: each element in atom.project.getDirectories() corresponds to a Git repository. See the link I sent previously, and also https://github.com/atom/atom/pull/3691. This may look wrong for certain configurations (your AdaCore example comes to mind), but would the concept of root be even useful in that case? > Given the variable project-root, it makes sense to define > project-relativize-path to return the portion of the path that is > relative to project-root, and error if there is no such portion (ie an > absolute path outside the root tree). Monotone has such a function in > the C++ code. Sure. But if project-root is not among project-directories, I'm not sure when, and for what cases, that directory can be used.