From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Arthur Miller Newsgroups: gmane.emacs.bugs Subject: bug#61817: 30.0.50; Project.el finds incorrect project roots in git worktrees Date: Wed, 01 Mar 2023 04:03:19 +0100 Message-ID: References: <5dea8e3b-4867-52f8-19fb-9bf5ab167f46@yandex.ru> <66ce5a8f-5321-47b2-b605-38a6aea19190@yandex.ru> <59fa389f-d954-8f5b-6378-fc28a60e98aa@yandex.ru> <5e69a4c8-21fc-89c9-4f03-3972cae178f0@yandex.ru> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="15993"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: 61817-done@debbugs.gnu.org To: Dmitry Gutov Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Wed Mar 01 04:07:26 2023 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pXCoN-0003s5-5h for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 01 Mar 2023 04:07:24 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pXClC-0001qo-1q; Tue, 28 Feb 2023 22:04:06 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pXCl9-0001jz-1z for bug-gnu-emacs@gnu.org; Tue, 28 Feb 2023 22:04:03 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pXCl8-0004wG-NA for bug-gnu-emacs@gnu.org; Tue, 28 Feb 2023 22:04:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1pXCl8-0005MW-IJ for bug-gnu-emacs@gnu.org; Tue, 28 Feb 2023 22:04:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Arthur Miller Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 01 Mar 2023 03:04:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 61817 X-GNU-PR-Package: emacs Original-Received: via spool by 61817-done@debbugs.gnu.org id=D61817.167763981120541 (code D ref 61817); Wed, 01 Mar 2023 03:04:02 +0000 Original-Received: (at 61817-done) by debbugs.gnu.org; 1 Mar 2023 03:03:31 +0000 Original-Received: from localhost ([127.0.0.1]:52290 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pXCkc-0005LF-Pv for submit@debbugs.gnu.org; Tue, 28 Feb 2023 22:03:31 -0500 Original-Received: from mail-vi1eur05olkn2019.outbound.protection.outlook.com ([40.92.90.19]:52809 helo=EUR05-VI1-obe.outbound.protection.outlook.com) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pXCka-0005Ky-4l for 61817-done@debbugs.gnu.org; Tue, 28 Feb 2023 22:03:29 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=IjPv73f+A33t6M0Zj9VOXJuZoH81DjeAnBaBFVdEJWLUqjSjfbaFLJrIBauVBai6sxlZp4vqqZOdIyNZMrQpRqw4YJyw5024xbwpUtywSu+cuSY3fb+3Oqgl4pHeVbUqHuiAUx088VY02P+TDck1yu60Jrfop0CgKz+SNnYCaCrU9vOYekoU5B17biU5imNTBmcNLROd5rzUQBpyS7tqL0czcZmoKI3v6pInc/iKodbH22v6PSv6gj8aAbFcTTOLSu1RbgAHeeHOZCAV1AYfKYlg8QGB4/OLkwe/t+EYuO1MUnq0tQsuK4JDtewa3OMjWKsiodN8oyKNtpS53P64VA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=NQQwPgaFVyzFAGS6gDMXQ1PQCx/wBekUEKJRr6zwdIE=; b=oYAtGWFj51GtINDhSgRvglNZ8b6PUvo4HK1FGkevP6wA0u8w6milVPcHfsuHmhmViVRO+8seLnn0olegzc4u+hDZ7yg1fpoYeeh9KZOeVChYJZ68Vv0autKvHcLSzG5mDAw8S+JnK0kY59Yd6PCyWJAt7mBOs8ztnC3GFiww7CWL/AA0Zzoj43joXUnRY/IfZ2lw/aB6TyKMK5WRRr2C4kF/2AkPA3H34AR5Lx7uqgMN/+cuI0mHGlwYDJGHv8vdZzQ91TQX8+zAsYI5NrZc0udFsAgKWriDLf4R09RaRvKSYF16kHbOOSv5bA8A9Z+xrjQJ/54DK1ny+mxxO1GBJg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=live.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=NQQwPgaFVyzFAGS6gDMXQ1PQCx/wBekUEKJRr6zwdIE=; b=SbN+ZKfjhZrsJ192OLHGueA+l5gZuGqEdXa3+2sw9GTigeEei2LgikZCa8w+X5n/me7j0xujRxgOwBviFhy4qbMqTxhbWPwlamZP5URoqijUAzjqb4UalagfJ/jLH/od8E8AcokDi5JE79tLQpa4Ioe/14V3fA9rwfBdfTXWPkJG8Mi+kymrJmCROdx+Mzn5UVTQbHkR8KpkvbD/gcmDjbUJQz/U9Ho8sVFqxC/DTIf6eGLj+ptiorjWB/ALHavq2GgbEtQXyqOZGNSYhdnLSociawSaEB9yy1kIjnlM63kiiWGUHvZuONGYw+JbyyMbVZY2AIWyq8n/ibdcbgJ8lQ== Original-Received: from AM9PR09MB4977.eurprd09.prod.outlook.com (2603:10a6:20b:304::20) by PR3PR09MB4425.eurprd09.prod.outlook.com (2603:10a6:102:37::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6156.18; Wed, 1 Mar 2023 03:03:21 +0000 Original-Received: from AM9PR09MB4977.eurprd09.prod.outlook.com ([fe80::e131:cc87:e164:befc]) by AM9PR09MB4977.eurprd09.prod.outlook.com ([fe80::e131:cc87:e164:befc%6]) with mapi id 15.20.6156.018; Wed, 1 Mar 2023 03:03:21 +0000 In-Reply-To: <5e69a4c8-21fc-89c9-4f03-3972cae178f0@yandex.ru> (Dmitry Gutov's message of "Wed, 1 Mar 2023 01:51:09 +0200") X-TMN: [GkIT9BCkeP+Wr9OaslUuFyRkliCEZmwW] X-ClientProxiedBy: FR0P281CA0123.DEUP281.PROD.OUTLOOK.COM (2603:10a6:d10:97::9) To AM9PR09MB4977.eurprd09.prod.outlook.com (2603:10a6:20b:304::20) X-Microsoft-Original-Message-ID: <87sfep6x36.fsf@live.com> X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AM9PR09MB4977:EE_|PR3PR09MB4425:EE_ X-MS-Office365-Filtering-Correlation-Id: 0c2a634b-2e89-45f0-e465-08db1a0183a0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: HyYCCJDyw/XxTN5vv9DGmDdsSHvrW+1cvlfr+SvTKUf4GW9fVulEP7IshI3kPSUoX5C0XmY6H6/uDFSkXWpJx71cE0ZtCckqKDBxYJodp2pKRta2xJrEroGewM6S0sUZFinLgjsfX3Yq6GIb5sWcT8/DPdVIseHWlih0yeVZpWO0xyEy4kE8fa/yVYt5IWzmTw2HCOCi6L4hzOHOsU2WClBDTVQtKlVGdKQmYvugmGHJC4l6xfS1SEp8+2iIVICX3Xdy4e97hIcW7IQnH7YF9HN1QNJtRrowDENc3/G0L30B9qLebJ19BCZgpVpS3EFQux31OzF4Z1pfxuRK77QcNKNpJZvKgVyoiWLlTt5GhXyBfhdi6/jIvr85KWgW+KCEPxw3Zy8YTrhQ2qzM7dwF5bfc6SZvx9HmuudSFJlLrR9QmxotWqs3y6ruSn5v7ywYjwMqYCbIGbPP8h9laayZIXFp/HCX7D9PXpiuB2bJUMkUp33tN9qYimh2PafYiFZbCcdtFuIKc6rJG90RmLR6NnarJ+lVW+L5XNZFixHdnYqnvSZP6YpXCx+UyJm3thkwP9rTyzEKsQSoEot0ulcqwFMTwivruz2wGsg6N1Dad4/IXb7Eiu0K53OoB7zRgdFmR5ozAxGXuM34FOiahgL67uRTicA5Va2TnfZ2P/qkl6c= X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: J5PjGM6JQokpHSgWZuGYujikVihRxD94X9gJPlQUBBXCnvb03ftHUsETPqGDKrMHEwGZaqNiMJxkSlQdEuqto9VNBBuKxc/kG26VoLjQzqw+0lKDA+960yTbcqCUoesjOFo/ILPi5KZz/T2amQ9KELkez/BIkUfsg3UAOPNDk6ihdPvBw24gM1FFOHVmKTLXYsnqFx4LQw7UUaPXoVralp9O8VPSROXlEVv3dzVuWrradPw5zSGjQ2LExUGdvUOG4T2qrQNV+V8ljajhb6v34LJ/TicQwyRvdVmO/luMxXF8ltzFf90nhQz/vmGB0gxiN1YGjZFXTH3ZDOFsSCkkGrOypOb/qO+JIZeFj7i/XZlNRMkGAQhKnNkjZAIMcGOF3p1mo3iFF8UhY/+78eyDm8UfasxHzue51OgyJXeVaWlckfPtpciahYn8rg1d8JPj14/5C681YS2hOxDY9PAIAxTWdeNIcD6FfGcneqDmYIIrWi7zyb5GZENyMzpSYcREW+B5lmKIhTk+FkTvHcprZJtuJnRvQW4tOi42QUO30N14ulLP18wrqrQ5hTl/2YNbtjkAHHplwHPS9W424ksYuhM4R3snub/zlW29FsEL8CNm1vosLgY+K43aYxrYOpAxUyUep5C39xnoIpdd1wRvWsVIPzX4PNCD4/cn/jrsh+RvWf69Q1DsVVFXnS/+W8h3DP1DdnvoqKEDecjqvP761SOWxvJiMNUUmS0r6sG1ADmegubOxHAlIaj03+ 8iPAAWGqipp2VXEaoTmJYR3++mASnaxlIHA15/UlrXXqM5oV8cgsMdBzFJ/NeH9G3uxiMBL1B81qPqdETPLlMo7bYqrXS7WqBI X-OriginatorOrg: sct-15-20-4755-11-msonline-outlook-64da6.templateTenant X-MS-Exchange-CrossTenant-Network-Message-Id: 0c2a634b-2e89-45f0-e465-08db1a0183a0 X-MS-Exchange-CrossTenant-AuthSource: AM9PR09MB4977.eurprd09.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 Mar 2023 03:03:21.4173 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: PR3PR09MB4425 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:257026 Archived-At: --=-=-= Content-Type: text/plain Dmitry Gutov writes: > Depending on how we might define a "project parent" in the future (probably as > "project of root's parent directory", though), and how the worktrees reside on > disk relative to the parent, these notions won't necessarily match. Sure, but I don't think they have to. I am just telling that we need both; my suggestion is to use project-vc-root, as the king of all roots; regardless of the shape of folder structures; and current-project-root for worktrees and what not. Just as a suggestion, more about this one little further below. >> If you have a branch "main", work in a branch X, and would like to test/fix >> something unrelated to X, wouldn't you create a new workree Y from clean "main"? >> It is a bit special case, which I personally use, so to automate this, "worktree" >> as root is not enough, I need the actual root. For other purposes I need the >> worktree. So as said, both are needed. Of course, worktree will be used more >> frequently for natural reasons. > > That sounds like a fine approach, though not the only possible one. Yeas; of course; there is never one approach only. > have a limited number of worktrees: some constant, and some for temporary > branches. I suppose it depends whether you need to create some configuration > files specific to the local system when deploying and testing a new repository > checkout. Exactly. The more general approach is to list branches with completing read and let user choose one to create a patch to. But the one I described is just a little quick-fix. M-x add-new-patch, and it does what I described above. >>> Whenever one chooses a different shape, though, they should consider how that >>> will affect the common uses. >> It is not about the shape; you can put a worktree as a subdirectory in a main >> repository, it does not need to be out of source tree; project.el will still not >> find the real git root. You can test it yourself in Emacs source: > > Indeed, it won't, because nobody told it it should traverse up to "worktree > parent", always or under certain condition. Exactly, so once in a worktree, current project.el can't find the "actual git root" as you called it. I would like it to be able too, so that I can use project.el as a "generic" library independent of VC system. > That structure would also be quite weird, though: root in dir A, but all project > files residing in some sub-sub-directory D of A. Doesn't that sound weird? Yes, it is very weird, and that why I too also make worktrees out of the main repo, parallel to it. I took it up because you wrote about choosing different shapes for directory structures and consequences, but I do same as you. > Then the question would be how to provide both of those pieces of information to > callers. If we add the constraint that it has to be in some abstract way > (independent from Git), then the answer is probably "no way". I am not sure myself; but obviously for the VC that does not support the feature, project-vc-root could return just what it returns now, and just act as a synonym for project-root, while for systems that do (git) it will return whatever actual root is? > I do believe that it's a "useful middleware". And a trait of such middlewares is > they usually try to present some abstraction over the implementation. Ok, can we then have some useful stuff like: project-add-new-patch and project-add-new-target or similar (I welcome better ideas); where at least some common actions are automated? project-vc-dir already does some VC stuff (push, pull etc), it can well provide some other useful abstractions? I can help to donate those, at least for Git, but the Git part is easy to write anyway. > If, perhaps, we would add a command doing something like the above to > project.el, or we envision somebody doing it in some popular extension, *and* it > would be possible to do with several project backends (maybe real and potential > ones), then that would sound like a feature for project.el. > > If a caller, OTOH, needs to know that they're working with Git, and with a > particular project backend, to do what they wanted, then that would be a poor > fit for the API. But we could try to fit in features in some other way. Adding > them to the VC package, perhaps. Exactly; I totally agree; that is why I have started discussion. I can do git-based everything easily myself, but instead of doing it git-based per definition I wanted to use project.el as an abstraction so my little project stuff can work in possibly other scenarios then just with Git. > I honestly don't understand EDE enough to have a solid opinion. But it did seem > to have some pronounced pieces that didn't make sense for projects I regularly > interact with. EDE seems interesting to me, because of the integration with rest of Emacs, speedbar etc, but I can't say I have much understanding of Ede myself. > That sounds like a decent feature, though one that is often taken up by command > line tools. It not quite clear what Emacs integration would add to > that. Besides, perhaps being able to write templates in Org, or something. As said: automation. I have nothing against command line, and I can certainly just write a little shell or elisp script to create a folder, copy some files, init git, generate some pieces etc. But everytime I do, manually, or writing a new script, I am repeating a set of dull steps, which are totally unnecessary and just take focus from what I really want to do. > Besides, perhaps being able to write templates in Org, or something. Well, I wouldn't say it is just "or something" and you don't need to use it in Org at all :). Org-capture does setup a small gui (read-key) and is easy to re-use. More important it provides a relatively familiar interface to writing Lisp property lists (capture templates) even to non-lispers :). org-capture is quite well accepted in Org community, I believe; and there are a lots of non-programmers which use it for wrting notes, mailes etc. I don't know; it is really small, already included, and usually already loaded into Emacs; and lots easier to use than some other alternatives to provide some basic gui and entry point for customization. I have attached a toy example for an illustration. I am sure I could resue transient, hydra, or just write my own too, but I want something that comes with Emacs which Hydra does not, and am not so familiar with transient myself, and I believe holds for lots of other people too. > But the beauty of it, it doesn't have to be strongly bound to project.el. It can > *use* project-current/project-root, but be a package of its own, with separate > naming/features/hooks and language/framework detection. Yes, of course, I know it can; that is what I already do. It does not even need to use Emacs, I can write it in Bash or as a script for cmd.exe; but that is not the quesiton. Currently I don't even use project.el, but as said, if it will provide more backends and abstractions, I would prefer to use it than to make my own git-specific everything. >> 2) better integration with tools for common workflow(s). Adding >> features, fixes, tests etc, is mostly about creating a new patch, which with >> addition of worktrees in Git can be super nicely automated. For example: add new >> library, or add new executable, or add new fix, it all boiles down to add new >> branch which leads to add new worktree, add a possible target in Makefile, >> create possibly a test file, probably some other thing. It would be nice to be >> able to say: M-x add-new-shared-library or M-x add-new-executable, or M-x >> add-new-fix and Emacs will do at least initial boilerplate. >> If you plan to add build tool support to project.el, it would be welcome :). > > Hmm, as I see it, this is split into two different parts: > > - Do a Git-specific thing (create a worktree), once per body of work. Yes, and to me this feels like a good target for an abstraction. Shouldn't something like that be in project-vc-dir app? > - Do a build tool specific thing, probably several. Again yes. That is the harder part, but there is a lot of freedom to implement just parts of it, and successively per tool, and so on, and the entry point could be the abstraction above. > The thing about the latter, you have described pretty well the general direction > of what features a hypothetical buildtool.el might contain. Alas, I have little > experience with languages where you regularly do things like that (adding new > shared libraries, new executables, other build artefacts), and it seems to be an > open question whether there is point in adding a language agnostic API on top of > that, or if people should just create c++-buildtool.el, java-buildtool.el, etc, > separately without trying to unify the UI. That does not have to be a build artefact, like .dll or .jar or .exe. It is just a "target". That is the beauty of Makefile which works just with targets and dependencies, and does not care what a target is. "clean" target as we know it from C or C++, or start or stop some web or system services are just as normal as building artefacts. > If somebody else wanted to work on this, though, probably a fair amount of > people on this list would welcome that, and help with advice/review/some later > contributions. Sure, I am happy to hear suggestions and opinions; especially if someone can help me to understand and re-use Ede for the tool integration. However; I am even more happy if you add something like project-vc-root (or choose any name you want), and some hooks or other abstraction for project-add/remove-* where * is any of patch, feature, target, ... something similar, I guess you get the idea :). Anyway, thank you for the kind answers and interesting discussion, and hope you don't mind I have deleted older parts; it was a bit hard tp read. so I have left just your latest and my answers (mostly); hope it is ok. --=-=-= Content-Type: text/plain Content-Disposition: attachment; filename=project-capture.el ;;; org-project.el --- Bootstrap projects with org-capture -*- lexical-binding: t; -*- ;; Copyright (C) 2022 Arthur Miller ;; Author: Arthur Miller ;; Keywords: ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; ;;; Code: ;;;; org-capture related code (require 'org-capture) (defvar org-project-root-dir nil) (defvar org-project-templates nil) (defvar org-project-mode-map (let ((map (make-sparse-keymap))) (define-key map [remap org-capture-finalize] #'org-project-finalize) (define-key map [remap org-capture-kill] #'org-project-kill) (define-key map [remap org-capture-refile] #'ignore) ;; be on the safe side map) "Keymap for `org-project-mode', a minor mode. Use this map to set additional keybindings for when Org mode is used for a project buffer.") (define-minor-mode org-project-mode "Minor mode to use in org-project-capture buffer." :lighter " Prj" (setq-local header-line-format (substitute-command-keys "\\Capture buffer. Finish \ `\\[org-capture-finalize]', abort `\\[org-capture-kill]'."))) (defun org-project-finalize (&optional stay-with-capture) "Finalize the capture process. With prefix argument STAY-WITH-CAPTURE, jump to the location of the captured item after finalizing." (interactive "P") (org-capture-finalize stay-with-capture) (let* ((desc (org-capture-get :description)) (func (or (org-capture-get :project-hook) (intern-soft (org-template-desc-to-func-name desc))))) (when (fboundp func) (funcall func)))) (defun org-project-kill () "Abort the current capture process." (interactive) (let ((org-note-abort t) (org-capture-before-finalize-hook nil) (org-capture-after-finalize-hook `(lambda nil (delete-directory ,default-directory t) (kill-buffer ,(org-capture-get :buffer))))) (org-capture-finalize))) ;;;; commands (defun org-project-new-project () (interactive) (let ((org-capture-templates org-project-templates) (org-capture-mode-hook (lambda () (org-project-mode 1)))) (org-capture))) (define-key global-map (kbd "C-S-n") #'org-project-new-project) ;;;; hooks (defun org-project-new () "Interactively create new directory for a project. Directory should not exist prior to call to this function." (let ((project-path (read-file-name "Project name: " org-project-root-dir nil nil nil))) (cond ((not (file-directory-p project-path)) (make-directory project-path) (let ((file-name (format "%s.org" (car (last (split-string project-path "/" t)))))) (find-file (expand-file-name file-name project-path)) (goto-char (point-min)))) (t (message "Directory %s already exists." project-path)))) (org-project-mode 1)) (defun org-template-desc-to-func-name (phrase) "Return string PHRASE as a Lisp symbol suitable to call as a function." (with-temp-buffer (insert phrase) (downcase-region 1 (point-max)) (goto-char 1) (while (re-search-forward "[ ]+" nil t) (replace-match "-")) (buffer-substring-no-properties 1 (point-max)))) ;;;; Test related (setq org-project-root-dir "~/repos/") (setq org-project-templates `(("w" "Web Projects") ("wb" "Bootstrap Project" plain (function org-project-new) "A Bootstrap Project" :project-hook my-bootstrap-hook) ("c" "C/C++ Projects") ("cc" "C Console Project" plain (function org-project-new) "A Command Line Project with C"))) ;; explicit hook trumps name-based hook (defun bootstrap-project () (message "THIS SHOULD NOT PRINT")) (defun my-bootstrap-hook () (message "MY BOOSTRAP HOOK")) ;; use name-based hook (defun c-console-project () (message "MY C CONSOLE PROJECT")) (provide 'org-project) ;;; org-project.el ends here --=-=-=--