Git Product home page Git Product logo

deadgrep's Issues

Context awareness doesn't seem to work

Hi! In your readme, you write that if I'm in a git project, this will be used for the directory (instead of the current file's directory). This doesn't seem to work, however. What could be wrong?

[Feature Request] ability to loop through search hits

full-ack.el provides this functionality and it makes it really easy to do repo wide refactor

  1. make a search
  2. jump to first hit in the search result buffer
  3. start to record a macro C-x (
  4. Press enter (this will take you to the file and put the cursor at the start of the match)
  5. do the refactoring
  6. jump back to the search result buffer
  7. move to the nex hit
  8. finish the macro C-x (

The macro can now be applied for the rest of the hits using C-x e. The important functionality that makes this possible is the ability to move to the start of next search hit.

open results buffer in other window

thanks for this package, it seems to have quite a few nice features (i was using ag.el) but one thing that bothers me a lot is that the results buffer is displayed in the current window. i often use search to find context for code that i'm working on, and that code now disappears from the screen as soon as i search. ag.el opens in another window (another ‘column’ on my screen typically) and i can keep looking at the code from which i started my search.

it seems changing this is not possible. or is it?

[FR] possibility to change project-dir to super-project-dir

I use ripgrep on the command line to grep in a directory containing multiple git repos. Is it possible to change the directory used by deadgrep if deadgrep is started from a buffer, which is part of a git-repo? What I want is to search/grep in the super project instead of in the "current-project" returned by project-current.

Large single-line files hang Emacs

If there's a >1 MiB JSON file, all one line, which matches the search, then Emacs hangs whilst the regex is matched to the whole line. We should truncate before applying the regex.

Wgrep-like functionality?

Hello,

I am trying deadgrep, I wanted to say thank-you for the very nice UI.

I was wondering if there is a wgrep-like functionality?

Tramp support is broken on Windows

M-x deadgrep-debug

About your environment:
Platform: windows-nt
Emacs version: 26.1
Command: nil
default-directory: "c:/pscp:host:/directory"

Initial output from ripgrep:
nil

default-directory is c:/pscp:..., which should be /pscp:....

I did not track the cause yet, but git bisect points e961f42 is the first bad commit.

Args out of range error

screenshot 2018-07-11 18 38 33

Debugger entered--Lisp error: (args-out-of-range "\33[m\33[35minit.el\33[m:\33[m\33[32m51\33[m:;; Bootstrap `\33[m\33[31m\33[1muse-package\33[m'." 2319 2320)
  (match-string 1 "\33[m\33[35minit.el\33[m:\33[m\33[32m51\33[m:;; Bootstrap `\33[m\33[31m\33[1muse-package\33[m'.")
  (deadgrep--extract-regexp "\\`\33\\[0m\33\\[3[56]m\\(\\(?:.\\|\n\\)+?\\)\33\\[" "\33[m\33[35minit.el\33[m:\33[m\33[32m51\33[m:;; Bootstrap `\33[m\33[31m\33[1muse-package\33[m'.")
  (deadgrep--split-line "\33[m\33[35minit.el\33[m:\33[m\33[32m51\33[m:;; Bootstrap `\33[m\33[31m\33[1muse-package\33[m'.")
  (deadgrep--insert-output "\33[m\33[35minit.el\33[m:\33[m\33[32m51\33[m:;; Bootstrap `\33[m\33[31m\33[1muse-package\33[m'.\n\33[m\33[35minit.el\33[m:\33[m\33[32m52\33[m:(unless (package-installed-p '\33[m\33[31m\33[1muse-package\33[m)\n\33[m\33[35minit.el\33[m:\33[m\33[32m54\33[m:  (package-install '\33[m\33[31m\33[1muse-package\33[m))\n\33[m\33[35minit.el\33[m:\33[m\33[32m57\33[m:  (require '\33[m\33[31m\33[1muse-package\33[m))\n\33[m\33[35minit.el\33[m:\33[m\33[32m62\33[m:(setq \33[m\33[31m\33[1muse-package\33[m-always-ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m64\33[m:;; Check loading times with `\33[m\33[31m\33[1muse-package\33[m'.\n\33[m\33[35minit.el\33[m:\33[m\33[32m65\33[m:(setq \33[m\33[31m\33[1muse-package\33[m-verbose t)\n\33[m\33[35minit.el\33[m:\33[m\33[32m67\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-functions :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m68\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-dependencies :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m69\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-theme :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m70\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-defaults :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m71\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-platform :ensure nil)\n\33[m\33[35minit.el\33")
  (deadgrep--process-filter #<process rg use-package> "\33[m\33[35minit.el\33[m:\33[m\33[32m51\33[m:;; Bootstrap `\33[m\33[31m\33[1muse-package\33[m'.\n\33[m\33[35minit.el\33[m:\33[m\33[32m52\33[m:(unless (package-installed-p '\33[m\33[31m\33[1muse-package\33[m)\n\33[m\33[35minit.el\33[m:\33[m\33[32m54\33[m:  (package-install '\33[m\33[31m\33[1muse-package\33[m))\n\33[m\33[35minit.el\33[m:\33[m\33[32m57\33[m:  (require '\33[m\33[31m\33[1muse-package\33[m))\n\33[m\33[35minit.el\33[m:\33[m\33[32m62\33[m:(setq \33[m\33[31m\33[1muse-package\33[m-always-ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m64\33[m:;; Check loading times with `\33[m\33[31m\33[1muse-package\33[m'.\n\33[m\33[35minit.el\33[m:\33[m\33[32m65\33[m:(setq \33[m\33[31m\33[1muse-package\33[m-verbose t)\n\33[m\33[35minit.el\33[m:\33[m\33[32m67\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-functions :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m68\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-dependencies :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m69\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-theme :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m70\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-defaults :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m71\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-platform :ensure nil)\n\33[m\33[35minit.el\33")

I do have these packages loading which seems to contribute to the error (maybe).

;; Let Emacs color Ansi symbols.
;; https://stackoverflow.com/questions/13397737/ansi-coloring-in-compilation-mode
(defun +theme-color-compilation-buffer ()
  (ignore-errors
    (require 'ansi-color)
    (when (eq major-mode 'compilation-mode)
      (ansi-color-apply-on-region compilation-filter-start (point-max)))))

(add-hook 'compilation-filter-hook #'+theme-color-compilation-buffer)

(use-package xterm-color
  :ensure t
  :commands (xterm-color-filter)
  :init
  (add-hook 'comint-preoutput-filter-functions 'xterm-color-filter)
  (setq comint-output-filter-functions
        (remove 'ansi-color-process-output comint-output-filter-functions)))

always use deadgrep-executable

first of all, i really love this ui to ripgrep! thanks for that.

there is still a rg %s in the source, so it's not working for me. please always use deadgrep-executable.

Enable editable buffer and save changes to files

Feature request: Edit results in buffer and save all touched files.

Similar in spirit to wdired, make search results editable in buffer. C-c C-c would save any changes in all modified files.

Here's what that's like using helm-ag and pressing C-c C-e to open an editable buffer:

helm-ag-edit

Visit in other window without changing focus

It would be useful to quickly preview search results without having to change focus back and forth between deadgrep buffer and the target buffer

Maybe O (to match o) or v (for "view").

Doesn't work on Windows?

I have counsel-rg and rg.el working just fine on Windows (so rg can be found blah blah), but deadgrep is just sitting, spinning, never-ending, with no results. Anyone else test it on Windows?

Compatibility with evil-mode?

Hi, there seem to be issues with evil-mode. Results are returned fine but jumping to results or collapsing results is not possible. Are there plans for support?

Make projectile a soft dependency

It would be preferable to not require 'projectile in order to use this library. Indeed, the mechanism is already in place to allow for this via customizing deadgrep-project-root-function, however the (require 'projectile) statement prevents this by preventing 'deadgrep from loading if projectile is not loaded.

Changing this to (require 'projectile nil t) would permit me to use this library.

Many thanks!

Provide deadgrep on MELPA

I know that you already mentioned MELPA in the README, but I’m filing this issue to make sure I get notified when that’s done :)

Thanks!

Gracefully handle ripgrep warnings on binary files

Debugger entered--Lisp error: (args-out-of-range "WARNING: stopped searching binary file \033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m after match (found \"\\u{0}\" byte around offset 56544)" 65 146)
  match-string(1 "WARNING: stopped searching binary file \033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m after match (found \"\\u{0}\" byte around offset 56544)")
  deadgrep--extract-regexp("\\`\033\\[0m\033\\[3[56]m\\(?:\\./\\)?\\(\\(?:.\\|\n\\)+?\\)\033\\[" "WARNING: stopped searching binary file \033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m after match (found \"\\u{0}\" byte around offset 56544)")
  (list (deadgrep--extract-regexp deadgrep--filename-regexp line) (string-to-number (deadgrep--extract-regexp deadgrep--line-num-regexp line)) (deadgrep--propertize-hits (deadgrep--extract-regexp deadgrep--line-contents-regexp line)))
  deadgrep--split-line("WARNING: stopped searching binary file \033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m after match (found \"\\u{0}\" byte around offset 56544)")
  (let* ((truncate-p (> (length line) deadgrep-max-line-length)) (line (if truncate-p (substring line 0 deadgrep-max-line-length) line)) (--dash-source-157-- (deadgrep--split-line line)) (filename (car-safe (prog1 --dash-source-157-- (setq --dash-source-157-- (cdr --dash-source-157--))))) (line-num (car-safe (prog1 --dash-source-157-- (setq --dash-source-157-- (cdr --dash-source-157--))))) (content (car --dash-source-157--)) (formatted-line-num (s-pad-right deadgrep--position-column-width " " (number-to-string line-num))) (pretty-line-num (propertize formatted-line-num (quote face) (quote deadgrep-meta-face) (quote deadgrep-filename) filename (quote deadgrep-line-number) line-num (quote read-only) t (quote front-sticky) t (quote rear-nonsticky) t)) (pretty-filename (propertize filename (quote face) (quote deadgrep-filename-face) (quote deadgrep-filename) filename (quote read-only) t (quote front-sticky) t))) (cond ((null deadgrep--current-file) (setq deadgrep--imenu-alist (cons (cons filename (point)) deadgrep--imenu-alist)) (insert pretty-filename "\n")) ((not (equal deadgrep--current-file filename)) (setq deadgrep--imenu-alist (cons (cons filename (1+ (point))) deadgrep--imenu-alist)) (insert "\n" pretty-filename "\n"))) (setq deadgrep--current-file filename) (insert pretty-line-num content) (if truncate-p (progn (insert (propertize " ... (truncated)" (quote face) (quote deadgrep-meta-face))))) (insert "\n") (setq prev-line-num line-num))
  (cond ((s-blank\? line)) ((string= line "--") (let ((separator "--")) (if prev-line-num (progn (setq separator (s-repeat (log prev-line-num 10) "-")))) (insert (propertize (concat separator "\n") (quote face) (quote deadgrep-meta-face))))) ((not (s-matches-p deadgrep--color-code line)) (if deadgrep--current-file (progn (setq deadgrep--current-file nil) (insert "\n"))) (insert line "\n\n")) (t (let* ((truncate-p (> (length line) deadgrep-max-line-length)) (line (if truncate-p (substring line 0 deadgrep-max-line-length) line)) (--dash-source-157-- (deadgrep--split-line line)) (filename (car-safe (prog1 --dash-source-157-- (setq --dash-source-157-- ...)))) (line-num (car-safe (prog1 --dash-source-157-- (setq --dash-source-157-- ...)))) (content (car --dash-source-157--)) (formatted-line-num (s-pad-right deadgrep--position-column-width " " (number-to-string line-num))) (pretty-line-num (propertize formatted-line-num (quote face) (quote deadgrep-meta-face) (quote deadgrep-filename) filename (quote deadgrep-line-number) line-num (quote read-only) t (quote front-sticky) t (quote rear-nonsticky) t)) (pretty-filename (propertize filename (quote face) (quote deadgrep-filename-face) (quote deadgrep-filename) filename (quote read-only) t (quote front-sticky) t))) (cond ((null deadgrep--current-file) (setq deadgrep--imenu-alist (cons (cons filename ...) deadgrep--imenu-alist)) (insert pretty-filename "\n")) ((not (equal deadgrep--current-file filename)) (setq deadgrep--imenu-alist (cons (cons filename ...) deadgrep--imenu-alist)) (insert "\n" pretty-filename "\n"))) (setq deadgrep--current-file filename) (insert pretty-line-num content) (if truncate-p (progn (insert (propertize " ... (truncated)" (quote face) (quote deadgrep-meta-face))))) (insert "\n") (setq prev-line-num line-num))))
  (let ((line (car --dolist-tail--))) (cond ((s-blank\? line)) ((string= line "--") (let ((separator "--")) (if prev-line-num (progn (setq separator (s-repeat ... "-")))) (insert (propertize (concat separator "\n") (quote face) (quote deadgrep-meta-face))))) ((not (s-matches-p deadgrep--color-code line)) (if deadgrep--current-file (progn (setq deadgrep--current-file nil) (insert "\n"))) (insert line "\n\n")) (t (let* ((truncate-p (> (length line) deadgrep-max-line-length)) (line (if truncate-p (substring line 0 deadgrep-max-line-length) line)) (--dash-source-157-- (deadgrep--split-line line)) (filename (car-safe (prog1 --dash-source-157-- ...))) (line-num (car-safe (prog1 --dash-source-157-- ...))) (content (car --dash-source-157--)) (formatted-line-num (s-pad-right deadgrep--position-column-width " " (number-to-string line-num))) (pretty-line-num (propertize formatted-line-num (quote face) (quote deadgrep-meta-face) (quote deadgrep-filename) filename (quote deadgrep-line-number) line-num (quote read-only) t (quote front-sticky) t (quote rear-nonsticky) t)) (pretty-filename (propertize filename (quote face) (quote deadgrep-filename-face) (quote deadgrep-filename) filename (quote read-only) t (quote front-sticky) t))) (cond ((null deadgrep--current-file) (setq deadgrep--imenu-alist (cons ... deadgrep--imenu-alist)) (insert pretty-filename "\n")) ((not (equal deadgrep--current-file filename)) (setq deadgrep--imenu-alist (cons ... deadgrep--imenu-alist)) (insert "\n" pretty-filename "\n"))) (setq deadgrep--current-file filename) (insert pretty-line-num content) (if truncate-p (progn (insert (propertize " ... (truncated)" ... ...)))) (insert "\n") (setq prev-line-num line-num)))) (setq --dolist-tail-- (cdr --dolist-tail--)))
  (while --dolist-tail-- (let ((line (car --dolist-tail--))) (cond ((s-blank\? line)) ((string= line "--") (let ((separator "--")) (if prev-line-num (progn (setq separator ...))) (insert (propertize (concat separator "\n") (quote face) (quote deadgrep-meta-face))))) ((not (s-matches-p deadgrep--color-code line)) (if deadgrep--current-file (progn (setq deadgrep--current-file nil) (insert "\n"))) (insert line "\n\n")) (t (let* ((truncate-p (> ... deadgrep-max-line-length)) (line (if truncate-p ... line)) (--dash-source-157-- (deadgrep--split-line line)) (filename (car-safe ...)) (line-num (car-safe ...)) (content (car --dash-source-157--)) (formatted-line-num (s-pad-right deadgrep--position-column-width " " ...)) (pretty-line-num (propertize formatted-line-num ... ... ... filename ... line-num ... t ... t ... t)) (pretty-filename (propertize filename ... ... ... filename ... t ... t))) (cond ((null deadgrep--current-file) (setq deadgrep--imenu-alist ...) (insert pretty-filename "\n")) ((not ...) (setq deadgrep--imenu-alist ...) (insert "\n" pretty-filename "\n"))) (setq deadgrep--current-file filename) (insert pretty-line-num content) (if truncate-p (progn (insert ...))) (insert "\n") (setq prev-line-num line-num)))) (setq --dolist-tail-- (cdr --dolist-tail--))))
  (let ((--dolist-tail-- lines)) (while --dolist-tail-- (let ((line (car --dolist-tail--))) (cond ((s-blank\? line)) ((string= line "--") (let ((separator "--")) (if prev-line-num (progn ...)) (insert (propertize ... ... ...)))) ((not (s-matches-p deadgrep--color-code line)) (if deadgrep--current-file (progn (setq deadgrep--current-file nil) (insert "\n"))) (insert line "\n\n")) (t (let* ((truncate-p ...) (line ...) (--dash-source-157-- ...) (filename ...) (line-num ...) (content ...) (formatted-line-num ...) (pretty-line-num ...) (pretty-filename ...)) (cond (... ... ...) (... ... ...)) (setq deadgrep--current-file filename) (insert pretty-line-num content) (if truncate-p (progn ...)) (insert "\n") (setq prev-line-num line-num)))) (setq --dolist-tail-- (cdr --dolist-tail--)))))
  (save-excursion (goto-char (point-max)) (let ((--dolist-tail-- lines)) (while --dolist-tail-- (let ((line (car --dolist-tail--))) (cond ((s-blank\? line)) ((string= line "--") (let (...) (if prev-line-num ...) (insert ...))) ((not (s-matches-p deadgrep--color-code line)) (if deadgrep--current-file (progn ... ...)) (insert line "\n\n")) (t (let* (... ... ... ... ... ... ... ... ...) (cond ... ...) (setq deadgrep--current-file filename) (insert pretty-line-num content) (if truncate-p ...) (insert "\n") (setq prev-line-num line-num)))) (setq --dolist-tail-- (cdr --dolist-tail--))))))
  (let ((inhibit-read-only t) (lines (s-lines output)) prev-line-num) (if finished nil (setq deadgrep--remaining-output (-last-item lines)) (setq lines (butlast lines))) (save-excursion (goto-char (point-max)) (let ((--dolist-tail-- lines)) (while --dolist-tail-- (let ((line (car --dolist-tail--))) (cond ((s-blank\? line)) ((string= line "--") (let ... ... ...)) ((not ...) (if deadgrep--current-file ...) (insert line "\n\n")) (t (let* ... ... ... ... ... ... ...))) (setq --dolist-tail-- (cdr --dolist-tail--)))))))
  deadgrep--insert-output("\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m59\033[0m:(global-set-key (kbd \"<f12>\") #'\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m60\033[0m:(global-set-key (kbd \"C-c <f12>\") #'\033[0m\033[1m\033[31mswiper\033[0m-all)\n\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m64\033[0m:(global-set-key (kbd \"C-s\") #'\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m67\033[0m:;; matches with ivy (used by \033[0m\033[1m\033[31mswiper\033[0m). Anzu style.\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy-pkg.el\033[0m:\033[0m\033[32m9\033[0m:  :url \"https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m\")\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m215\033[0m:split into three packages: ‘ivy’, ‘\033[0m\033[1m\033[31mswiper\033[0m’ and ‘counsel’; you can simply\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m244\033[0m:     First clone the \033[0m\033[1m\033[31mSwiper\033[0m repository with:\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m246\033[0m:          cd ~/git && git clone https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m247\033[0m:          cd \033[0m\033[1m\033[31mswiper\033[0m && make compile\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m251\033[0m:          (add-to-list 'load-path \"~/git/\033[0m\033[1m\033[31mswiper\033[0m/\")\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m317\033[0m:          (global-set-key (kbd \"C-s\") '\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m353\033[0m:   ‘\033[0m\033[1m\033[31mswiper\033[0m’ or ‘counsel-M-x’ add more key bindings through the ‘keymap’\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m1100\033[0m:      '\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m1460\033[0m:     ‘post-command-hook’.  See ‘\033[0m\033[1m\033[31mswiper\033[0m’ for an example usage.\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m1479\033[0m:     interrupted with ‘C-g’.  See ‘\033[0m\033[1m\033[31mswiper\033[0m’ for an example usage.\nWARNING: stopped searching binary file \033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m after match (found \"\\u{0}\" byte around offset 56544)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m6\033[0m:;; URL: https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m202\033[0m:a behavior similar to `\033[0m\033[1m\033[31mswiper\033[0m'.\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m252\033[0m:`https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m/wiki/ivy-display-function'.\")\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1186\033[0m:                '(\033[0m\033[1m\033[31mswiper\033[0m \033[0m\033[1m\033[31mswiper\033[0m-isearch \033[0m\033[1m\033[31mswiper\033[0m-backward \033[0m\033[1m\033[31mswiper\033[0m-isearch-backward))\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1503\033[0m:                   (eq (ivy-state-caller ivy-last) '\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1821\033[0m:  '((\033[0m\033[1m\033[31mswiper\033[0m . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1822\033[0m:    (\033[0m\033[1m\033[31mswiper\033[0m-multi . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1823\033[0m:    (counsel-git-grep . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1824\033[0m:    (counsel-grep . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-async)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3280\033[0m:                  '(ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3281\033[0m:                    ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-async\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3282\033[0m:                    ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-async-backward\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3283\033[0m:                    ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-backward))\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3461\033[0m:               (not (eq caller '\033[0m\033[1m\033[31mswiper\033[0m")
  (save-current-buffer (set-buffer (process-buffer process)) (deadgrep--insert-output output))
  (progn (save-current-buffer (set-buffer (process-buffer process)) (deadgrep--insert-output output)))
  (if (buffer-live-p (process-buffer process)) (progn (save-current-buffer (set-buffer (process-buffer process)) (deadgrep--insert-output output))))
  deadgrep--process-filter(#<process rg swiper> "\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m59\033[0m:(global-set-key (kbd \"<f12>\") #'\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m60\033[0m:(global-set-key (kbd \"C-c <f12>\") #'\033[0m\033[1m\033[31mswiper\033[0m-all)\n\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m64\033[0m:(global-set-key (kbd \"C-s\") #'\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m67\033[0m:;; matches with ivy (used by \033[0m\033[1m\033[31mswiper\033[0m). Anzu style.\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy-pkg.el\033[0m:\033[0m\033[32m9\033[0m:  :url \"https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m\")\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m215\033[0m:split into three packages: ‘ivy’, ‘\033[0m\033[1m\033[31mswiper\033[0m’ and ‘counsel’; you can simply\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m244\033[0m:     First clone the \033[0m\033[1m\033[31mSwiper\033[0m repository with:\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m246\033[0m:          cd ~/git && git clone https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m247\033[0m:          cd \033[0m\033[1m\033[31mswiper\033[0m && make compile\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m251\033[0m:          (add-to-list 'load-path \"~/git/\033[0m\033[1m\033[31mswiper\033[0m/\")\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m317\033[0m:          (global-set-key (kbd \"C-s\") '\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m353\033[0m:   ‘\033[0m\033[1m\033[31mswiper\033[0m’ or ‘counsel-M-x’ add more key bindings through the ‘keymap’\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m1100\033[0m:      '\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m1460\033[0m:     ‘post-command-hook’.  See ‘\033[0m\033[1m\033[31mswiper\033[0m’ for an example usage.\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m1479\033[0m:     interrupted with ‘C-g’.  See ‘\033[0m\033[1m\033[31mswiper\033[0m’ for an example usage.\nWARNING: stopped searching binary file \033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m after match (found \"\\u{0}\" byte around offset 56544)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m6\033[0m:;; URL: https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m202\033[0m:a behavior similar to `\033[0m\033[1m\033[31mswiper\033[0m'.\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m252\033[0m:`https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m/wiki/ivy-display-function'.\")\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1186\033[0m:                '(\033[0m\033[1m\033[31mswiper\033[0m \033[0m\033[1m\033[31mswiper\033[0m-isearch \033[0m\033[1m\033[31mswiper\033[0m-backward \033[0m\033[1m\033[31mswiper\033[0m-isearch-backward))\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1503\033[0m:                   (eq (ivy-state-caller ivy-last) '\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1821\033[0m:  '((\033[0m\033[1m\033[31mswiper\033[0m . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1822\033[0m:    (\033[0m\033[1m\033[31mswiper\033[0m-multi . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1823\033[0m:    (counsel-git-grep . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1824\033[0m:    (counsel-grep . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-async)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3280\033[0m:                  '(ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3281\033[0m:                    ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-async\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3282\033[0m:                    ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-async-backward\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3283\033[0m:                    ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-backward))\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3461\033[0m:               (not (eq caller '\033[0m\033[1m\033[31mswiper\033[0m")

(optionally) prompt for root search directory

Thanks for deadgrep!

I often know I want to limit the search to a subtree of the (very large) auto-detected project root. Currently I can only do this by starting the search and then changing the directory, racing ripgrep who's currently busy reading lots of unneeded disk and loading it into the disk cache.

It would be nice if after invoking M-x deadgrep I got a second prompt for the search root directory, with the current auto-detected one pre-filled. I appreciate this is an extra keystroke for the current case, so it could also be a customize option to toggle this behaviour or not.

Do you think this is worth doing or is it too niche?

Messy search output

I ran deadgrep looking for use-package in my .emacs.d, but results are hard to read.

I think a picture describes it better.

shot

This is how I configured deadgrep:

(use-package deadgrep
  :load-path "~/githubs/deadgrep"
  :bind ("<f7>" . deadgrep))

And these are some details about my system:

GNU Emacs 27.0.50 (build 1, x86_64-debian-linux-gnu, GTK+ Version 3.22.30)
 of 2018-06-20

Repository revision: 3a47f3921bdaaf7b7d80dc3be05a5f1b1f2501eb
Configured using:
--host=x86_64-debian-linux-gnu

Emacs uptime: 3 minutes, 53 seconds
Colour theme: sanityinc-tomorrow-night
Operating system: Ubuntu 18.04 LTS
Window system: x11
Desktop environment: GNOME Shell 3.28.1

Support ripgrep 0.7

This is a pretty common release, and should just be a matter of supporting the correct colour codes.

Example output:

"�[m�[35mfoo/bar.txt�[m:�[m�[32m68�[m:    xxx�[m�[31m�[1msearch term�[mstuff

"wrong-type-argument markerp nil" error when changing option.

I got the error when changing directory (other options seem same) after C-u M-x deadgrep.
Using ELPA version of spinner and latest Git version of dash, s, projectile and deadgrep.

This commit 39fa9be seems the first bad commit.

Debugger entered--Lisp error: (wrong-type-argument markerp nil)
  set-marker(nil nil)
  (let ((start-point (point)) (inhibit-read-only t)) (erase-buffer) (setq deadgrep--hidden-files nil) (set-marker overlay-arrow-position nil) (setq deadgrep--current-file nil) (setq deadgrep--spinner nil) (setq deadgrep--remaining-output nil) (setq deadgrep--current-file nil) (setq deadgrep--debug-first-output nil) (deadgrep--write-heading) (goto-char (min (point-max) start-point)) (if deadgrep--postpone-start (deadgrep--write-postponed) (deadgrep--start deadgrep--search-term deadgrep--search-type deadgrep--search-case)))
  deadgrep-restart()
  deadgrep--directory(#<marker (moves after insertion) at 1 in *deadgrep dead ~/.emacs.d/lisp*>)
  button-activate(#<marker (moves after insertion) at 1 in *deadgrep dead ~/.emacs.d/lisp*> nil)
  push-button(137)
  funcall-interactively(push-button 137)
  call-interactively(push-button nil nil)
  command-execute(push-button)

M-x deadgrep-debug (Command nil as using C-u M-x deadgrep)

About your environment:
Platform: windows-nt
Emacs version: 26.1
Command: nil

Initial output from ripgrep:
nil

Use project-root

Project doesn't have to be a cons.

(project-root project) is more idiomatic.

Please add some keyboard shortcuts to the search UI

In search results, it would be super useful (for me) to have several shortcuts to change search parameters. For instance:

  • t: change search term
  • y s, y w, y r: change search type to strings, words, regexp
  • C s, C e, C i: set case to smart, sensitive, ignore
  • c n, c b, c a: change context to none, before, after
  • d: change directory
  • f a, f t, f g: change files to all, type, glob

In other words, please let me change all search parameters without having to move the point to a button and then hitting RET! :)

Smarter detection of language extension

Currently we consider foo.ml to be ml rather than ocaml. This means we miss out on *.mli files.

A better heuristic would be to match the language with the most extensions.

Maybe elgrep as an alternative.

Hi Wilfred,
since you are listing alternatives maybe you should include elgrep because it has some unique features.
See the Section on advanced search.
I think the most notable ones are:

  • Elgrep is pure Elisp if you do not grep pdf-files. (If you grep pdf-files pdftotext is used. But I actually want to switch to pdf-tools some time in the future.)
  • The advertized way to use Elgrep is via elgrep-menu. There you can make the specific settings for your usecase. At the end of the menu there is also a list of search queries. That is a kind of history. You can set all menu fields from a query already saved in the list. On demand you can even copy the shown code of a querry and paste it into your Elisp source code.
  • Elgrep can not only search for matches in files but also for matches in records. The record bounds determine what records are. They can be defined by regexp matches or function calls. If a record matches you can adjust the context such that the whole record is listed. By default only the matching lines are listed and the record boundaries match the beginning and the end of the file. So the whole file is one record.
  • Now that we know what a record is we can speak about matches. You can specify not only one regexp but a whole list of regexps. If all regexps match within the record all matches of the first regexp are listed (conjunction-operation). All regexps but the first one can also be negated. Negated ones may not match within the record to be listed.

The record thing, the multiple regexp thing, and negate thing make Elgrep even to a (admittingly simple) tool for queries in text based databases.

The many options have slowed it down a bit. Profiling and tuning is one of the next points in my development plan ;-) .

Best regards,
Tobias

Python files suggest yacc rather than py as the type

I'm using the latest version of deadgrep available on MELPA, and ripgrep 11.0.1. Emacs 26.2, Arch Linux.

(deadgrep--relevant-file-type "foobar.py" (deadgrep--type-list)) ;; yacc: *.y
(deadgrep--relevant-file-type "foobar.pyi" (deadgrep--type-list)) ;; swig: *.i

Looks like the heuristic can be improved further: .py has one exact match so it should be preferred over .y...

In fact this looks like deadgrep--matches-globs-p doesn't work correctly and treats the . as in a regexp instead of a glob:

(-filter (-lambda ((_type globs))
	   (deadgrep--matches-globs-p "foobar.py" globs))
	 (deadgrep--type-list))
;; result: (("py" ("*.py")) ("yacc" ("*.y")))

`query-replace` doesn't work with deadgrep-edit buffers

About your environment:
Platform: gnu/linux
Emacs version: 26.2
Command: nil
default-directory: "/home/brian/.emacs.d/"

Initial output from ripgrep:
nil


I'm on the latest master branch, commit 329119c.

If I run M-x query-replace from within a deadgrep-edit-mode buffer, it fails as I attempt to replace text.

Debugger entered--Lisp error: (error "Match data clobbered by buffer modification hooks")
  (replace-match "todo" t t)
  (replace-match-maybe-edit "todo" t t nil (179 183 #<buffer *deadgrep TODO ~/.emacs.d/*>) nil)
  (#f(compiled-function (from-string replacements query-flag regexp-flag delimited-flag &optional repeat-count map start end backward region-noncontiguous-p) "Subroutine of `query-replace'.  Its complexity handles interactive queries.\nDon't use this in your own program unless you want to query and set the mark\njust as `query-replace' does.  Instead, write a simple loop like this:\n\n  (while (re-search-forward \"foo[ \\t]+bar\" nil t)\n    (replace-match \"foobar\" nil nil))\n\nwhich will run faster and probably do exactly what you want.  Please\nsee the documentation of `replace-match' to find out how to simulate\n`case-replace'.\n\nThis function returns nil if and only if there were no matches to\nmake, or the user didn't cancel the call.\n\nREPLACEMENTS is either a string, a list of strings, or a cons cell\ncontaining a function and its first argument.  The function is\ncalled to generate each replacement like this:\n  (funcall (car replacements) (cdr replacements) replace-count)\nIt must return a string." #<bytecode 0x1f5c97>) "TODO" "todo" t nil nil nil nil nil nil nil nil)
  (ad-Advice-perform-replace #f(compiled-function (from-string replacements query-flag regexp-flag delimited-flag &optional repeat-count map start end backward region-noncontiguous-p) "Subroutine of `query-replace'.  Its complexity handles interactive queries.\nDon't use this in your own program unless you want to query and set the mark\njust as `query-replace' does.  Instead, write a simple loop like this:\n\n  (while (re-search-forward \"foo[ \\t]+bar\" nil t)\n    (replace-match \"foobar\" nil nil))\n\nwhich will run faster and probably do exactly what you want.  Please\nsee the documentation of `replace-match' to find out how to simulate\n`case-replace'.\n\nThis function returns nil if and only if there were no matches to\nmake, or the user didn't cancel the call.\n\nREPLACEMENTS is either a string, a list of strings, or a cons cell\ncontaining a function and its first argument.  The function is\ncalled to generate each replacement like this:\n  (funcall (car replacements) (cdr replacements) replace-count)\nIt must return a string." #<bytecode 0x1f5c97>) "TODO" "todo" t nil nil nil nil nil nil nil nil)
  (apply ad-Advice-perform-replace #f(compiled-function (from-string replacements query-flag regexp-flag delimited-flag &optional repeat-count map start end backward region-noncontiguous-p) "Subroutine of `query-replace'.  Its complexity handles interactive queries.\nDon't use this in your own program unless you want to query and set the mark\njust as `query-replace' does.  Instead, write a simple loop like this:\n\n  (while (re-search-forward \"foo[ \\t]+bar\" nil t)\n    (replace-match \"foobar\" nil nil))\n\nwhich will run faster and probably do exactly what you want.  Please\nsee the documentation of `replace-match' to find out how to simulate\n`case-replace'.\n\nThis function returns nil if and only if there were no matches to\nmake, or the user didn't cancel the call.\n\nREPLACEMENTS is either a string, a list of strings, or a cons cell\ncontaining a function and its first argument.  The function is\ncalled to generate each replacement like this:\n  (funcall (car replacements) (cdr replacements) replace-count)\nIt must return a string." #<bytecode 0x1f5c97>) ("TODO" "todo" t nil nil nil nil nil nil nil nil))
  (perform-replace "TODO" "todo" t nil nil nil nil nil nil nil nil)
  (query-replace "TODO" "todo" nil nil nil nil nil)
  (funcall-interactively query-replace "TODO" "todo" nil nil nil nil nil)
  (call-interactively query-replace nil nil)
  (command-execute query-replace)

Deadgrep lacks multi-directory support available through rg

M-x deadgrep calls deadgrep-project-root-function to get a directory, and passes that directory down to deadgrep--buffer.

I have a situation where I want to search through my directory tree, plus various other directory trees in on-disk caches stored elsewhere. The underlying rg command supports that:

       rg [OPTIONS] PATTERN [PATH...]

Deadgrep doesn't: the user can only request one PATH. Can you extend the code to support a single directory or a list of directories? Once that's in place it should be simple to dynamically bind deadgrep-project-root-function in new commands to do what I need.

(Ag has the same problem, and ages ago I hand-copied the appropriate function to my .emacs and tweaked it. It's a brittle approach, though.)

Activating swiper removes highlighting

Activating swiper in the deadgrep buffer removes all highlighting, never to come back (even after quitting swiper).

About your environment:
Platform: gnu/linux
Emacs version: 26.1
Command: /usr/bin/rg --color=ansi --line-number --no-heading --with-filename --fixed-strings --smart-case   -- use .
default-directory: "~/.emacs.d/"

Initial output from ripgrep:
"�[0m�[35m./README.md�[0m:�[0m�[32m9�[0m:means that �[0m�[1m�[31muse�[0mrs are not familiar with either the tool or the options the package configured for
�[0m�[35m./README.md�[0m:�[0m�[32m23�[0m:* By default `cmark` is �[0m�[1m�[31muse�[0md to markdown export/preview so it needs to be installed.
"

Please file bugs at https://github.com/Wilfred/deadgrep/issues/new
ripgrep 0.10.0
-SIMD -AVX (compiled)
+SIMD +AVX (runtime)

why not rg.el?

Hi Wilfred,
Just wanted to note that rg.el has many hidden niceties like grouping (rg-group-result), search the current word in the current project for files like the curent one (rg-dwim) and is also compatible with wgrep.

Not to deter you from deadgrep (Wilfredware is proved to always have an edge), but maybe trying to add to rg instead of of creating your own wheel.....

I recently discovered that m-? is bound to xref-find-definitions in many modes, that is intended to cover yet the same use case. It doesn't use compile-mode but its own xref--xref-buffer-mode.

Just my 2c on that :)

Incremental search / search as you type

Updating the results as the user types would make the UI more responsive and would greatly improve usability.

Maybe even immediately show the results for the words under point, that would make deadgrep feel much snappier.

Tramp support

Support running on a remote host if rg is installed there.

Add separator when set before/after context

Hi Wilfred, thx for your work! Love the UI of *deadgrep* buffer.

I have a idea of enhancing and want to share it with you:

let's assume that we have a sample file "sample.js":

const A = () => {
  console.log("I'm function A");
};

const B = () => {
  console.log("I'm function B");
};

const C = () => {
  console.log("I'm function C");
};

I use deadgrep to search "console" and the result will be:

Search term: function change
Search type: string words regexp
Case: smart sensitive ignore
Context: none before after

Directory: ~/XXXX
Files: all type glob

sample.js
2    console.log("I'm function A");
6    console.log("I'm function B");
10   console.log("I'm function C");

Then I change both "before" and "after" context to 1, and I will get:

Search term: function change
Search type: string words regexp
Case: smart sensitive ignore
Context: none before:1 after:1

Directory: ~/XXXX
Files: all type glob

sample.js
1  const A = () => {
2    console.log("I'm function A");
3  };
5  const B = () => {
6    console.log("I'm function B");
7  };
9  const C = () => {
10   console.log("I'm function C");
11 };

It's hard to see the boundary of different result and I think a divider would help:

Search term: function change
Search type: string words regexp
Case: smart sensitive ignore
Context: none before:1 after:1

Directory: ~/XXXX
Files: all type glob

sample.js
1  const A = () => {
2    console.log("I'm function A");
3  };
...
5  const B = () => {
6    console.log("I'm function B");
7  };
...
9  const C = () => {
10   console.log("I'm function C");
11 };

To add a divider, I can see results with context in same file more clearly. What's your opinion?


M-x deadgrep-debug:

About your environment:
Platform: darwin
Emacs version: 26.1
Command: nil

Initial output from ripgrep:
nil

ripgrep version: 0.9.0.

Don't show result separators for the last result in a file

Search term: paragraph-separate change
Search type: string words regexp
Case: smart sensitive ignore
Context: none before:0 after:1

Directory: ~/src/emacs/
Files: all type glob

CONTRIBUTE
390  paragraph-separate: "[ 	]*$"
391  coding: utf-8
---

lisp/shell.el
553    (setq-local paragraph-separate "\\'")
554    (setq-local paragraph-start comint-prompt-regexp)
---

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.