Commit Graph

57 Commits

Author SHA1 Message Date
Joshua Clayton
9cad495eb2
Conditionally import Data.Monoid.<> depending on version of base
Fixes #64
2016-08-20 05:22:51 -04:00
Joshua Clayton
fe3122cac4
Improve alias calculations
Previously, aliases were calculated twice:

1. when building out the list of terms to search for
2. when merging results into TermResults for grouping (and likelihood calcs)

This problem was masked by the fact that wildcard matching on both ends
was the same, with '%s'. However, the goal is to move away from simple
'%s' matching and do a system where transformations can be applied to
the text, which would address #18.

This moves us one step closer to fixing that issue.
2016-07-16 05:19:42 -04:00
Joshua Clayton
c23f123ea6
Continue to update Haskell style
This commit:

* Qualifies a number of imports across the codebase
* Aligns imports
2016-07-06 04:59:49 -04:00
Joshua Clayton
df64386552
Move around whitespace in description from help text 2016-07-02 06:57:29 -04:00
Joshua Clayton
2eeb54fe58
Haskell styles
This includes cosmetic changes to improve styles
2016-07-01 05:06:19 -04:00
Joshua Clayton
87d773c126
ask -> asks 2016-06-27 05:54:47 -04:00
Joshua Clayton
240b5bbb19 Support digesting on Linux with md5sum
This introduces behavior searching for an available program to calculate
digests across directories. OS X ships with md5, but on *nix-based
systems, it's md5sum. The output is largely the same, apart from the
final digest calculation, which includes a "file path":

    da52a1a5d5a3c9672371746e4d32708a  -

This strips the trailing whitespace and dash:

    da52a1a5d5a3c9672371746e4d32708a

Closes #49
2016-06-23 23:11:32 -04:00
Joshua Clayton
b65de02efc Display recent git SHAs per token
This creates a new "list" output format that includes a certain number
of git SHAs per token. This allows for perusal of the most recent
changes for a given token to understand what changed.
2016-06-21 23:02:37 -04:00
Joshua Clayton
cfa194b936 Roll up App into a monad transformer stack
This introduces a monad transformer stack to cover our reader (options
from the CLI) and except (for handling failure cases, initially missing
tags or invalid config).

This ensures errors are bubbled up appropriately (and halt program
execution) and the Options are available in the correct locations within
the app.

This also separates options parsing (which remains in app/Main.) from
translating those options into the correctly executed runner and
generated output.
2016-06-16 06:12:29 -04:00
Joshua Clayton
9ddbd0949c Rename to AppError and Main.hs code reorganization 2016-06-12 04:44:51 -04:00
Joshua Clayton
58e219eb2e Allow developer-authored configurations
This enables per-user and per-project configs, located in:

* ~/.unused.yml
* APP_ROOT/.unused.yml

Configurations stack upon each other, not replace; unused provides a
very base config, but additional configurations can be defined.

Per-user configs are best used to suit common types of projects at a
generic level. For example, a developer commonly working in Rails
applications might have a config at ~/.unused.yml for patterns like
Policy objects from Pundit, ActiveModel::Serializers, etc.

Per-project config would be less-generic patterns, ones where re-use
isn't likely or applicable.

See unused's global config:
https://github.com/joshuaclayton/unused/blob/master/data/config.yml

The structure is as follows:

    - name: Rails
      autoLowLikelihood:
        - name: Pundit
          pathStartsWith: app/policies
          pathEndsWith: .rb
          termEndsWith: Policy
          classOrModule: true
        - name: Pundit Helpers
          pathStartsWith: app/policies
          allowedTerms:
            - Scope
            - index?
            - new?
            - create?
            - show?
            - edit?
            - destroy?
            - resolve
    - name: Other Language
      autoLowLikelihood:
        - name: Thing
          pathEndsWith: .ex
          classOrModule: true

Name each item, and include an autoLowLikelihood key with multiple named
matchers. Each matcher can look for various formatting aspects,
including termStartsWith, termEndsWith, pathStartsWith, pathEndsWith,
classOrModule, and allowedTerms.
2016-06-10 06:16:41 -04:00
Joshua Clayton
ad9308a672 Encapsulate runtime config into a withRuntime wrapper 2016-06-09 06:44:18 -04:00
Joshua Clayton
7c26ae8e72 Move withoutCursor to wrap run
Why?
====

If parsing options fails, the program will exit; if
withoutCursor has been called prior to execParser, the program may exit
without any way to re-enable the cursor. This can cause confusion and
frustration for users.
2016-06-04 06:52:01 -04:00
Joshua Clayton
0505b4bff3 Re-enable cache by default
Why?

With SHA fingerprinting speeds improved drastically by
f618d8a796, we can now re-enable
caching by default.

This introduces a -C flag to disable the cache for a run.

Note that the cache is always invalidated when files are modified.
2016-06-04 06:44:41 -04:00
Joshua Clayton
792d0dca05 Minor reorganization within Main.hs 2016-06-02 08:22:53 -04:00
Joshua Clayton
6ffb098b20 Initial support of aliases based on wildcard matching
Why?
====

Dynamic languages, and Rails in particular, support some fun method
creation. One common pattern is, within RSpec, to create matchers
dynamically based on predicate methods. Two common examples are:

* `#admin?` gets converted to the matcher `#be_admin`
* `#has_active_todos?` gets converted to the matcher `#have_active_todos`

This especially comes into play when writing page objects with predicate
methods.

This change introduces the concept of aliases, a way to describe the
before/after for these transformations. This introduces a direct swap
with a wildcard value (%s), although this may change in the future to
support other transformations for pluralization, camel-casing, etc.

Externally, aliases are not grouped together by term; however, the
underlying counts are summed together, increasing the total occurrences
and likely pushing the individual method out of "high" likelihood into
"medium" or "low" likelihood.

Closes #19.
2016-06-01 22:16:44 -04:00
Joshua Clayton
4dfd788318 Extract views to a Views module
Why?
====

View logic was scattered all over the place; this introduces a views
module to encapsulate any corresponding view work into one spot.
2016-05-27 06:11:52 -04:00
Joshua Clayton
0d2470815d Simplify parsing and caching of results
Why?
====

Parsec is overkill when all that's really needed is splitting on
semicolons and converting a string to a non-negative Int.

One side-effect of this is to convert the caching mechanism from flat
text to CSV, with cassava handling (de-)serialization.

Additional
==========

Introduce ReaderT to calculate sha once per cache interaction

Previously, we were calculating the fingerprint (SHA) for match results
potentially twice, once when reading from the cache, and a second time
if no cache was found. This introduces a ReaderT to manage cache
interaction with a single fingerprint calculation.

This also abstracts what's being cached to only care about the fact that
the data can be converted to/from csv.
2016-05-26 21:37:11 -04:00
Joshua Clayton
db10b79f93 Extract results printing to separate function 2016-05-23 08:18:43 -04:00
Joshua Clayton
3f402120d9 Begin moving away from ParseResponse 2016-05-23 06:36:06 -04:00
Joshua Clayton
43edf288e2 Attempt to find and load tags automatically
Why?
====

Frequency of a tool's usage is determined by how easy it is to use the
tool. By having to pipe in ctags files all the time, and not provide any
guidance to the user, this program is merely a toy, since it's hard to
get right, and harder to explore.

This modifies the default behavior to look for a ctags file in a few
common locations, and lets the user choose a custom location if she so
chooses.

Resolves #35
2016-05-22 06:06:09 -04:00
Joshua Clayton
307dd2030f Introduce internal yaml configuration of auto low likelihood match handling
Why?
====

Handling low likelihood configuration was previously a huge pain,
because the syntax in Haskell was fairly terse. This introduces a yaml
format internally that ships with the app covering basic cases for
Rails, Phoenix, and Haskell. I could imagine getting baselines in here
for other languages and frameworks (especially ones I've used and am
comfortable with) as a baseline.

This also paves the way for searching for user-provided additions and
loading those configurations in addition to what we have here.
2016-05-21 05:34:18 -04:00
Joshua Clayton
2e3bb0e67c Users opt into using the cache
Why?
====

Calculating the SHA of the entire tree can be expensive; this shifts
reading from/writing to the cache to be configured via a switch in the
CLI.

In the future, it might make sense to store metadata about the repo,
including historical time to calculate both the SHA and non-cached
versions, to compare and choose which one to do intelligently.
2016-05-18 06:44:30 -04:00
Joshua Clayton
44ab0a1435 Read unchanged results from the cache
At some point, this also needs to md5 the tags list itself and factor
that in (since if the tagging algorithm changes, and new tokens get
uncovered, it'd invalidate the cache)
2016-05-16 21:48:36 -04:00
Joshua Clayton
2d65555b60 Wrap cursor management into one function 2016-05-15 16:14:40 -04:00
Joshua Clayton
790b62c999 Render base header as soon as we have tokens 2016-05-15 08:35:27 -04:00
Joshua Clayton
e70a7e4e0b Move line handling to occur when binding to results 2016-05-15 08:05:41 -04:00
Joshua Clayton
bcbc1b6462 Allow search result grouping
Why?
====

Grouping results can be helpful to view information differently, e.g. to
see highest-offending files or to remove grouping entirely.

This introduces a flag to allow overriding the default group (two levels
of directory)
2016-05-14 06:36:01 -04:00
Joshua Clayton
8d5e13c89e Use sensible defaults for the CLI
Why?
====

By default, people want to see an actionable, comprehensive list without
having to pass any flags into the program.

Previously, to see everything with high likelihood you'd need to provide
`-a --likelihood high`. This commit changes the program so that's the default.

It also introduces a `--all-likelihoods` flag (shorthand is `-a`) to see
everything, so if you want to opt into see it, you can. Finally, this
changes `-a` (to see everything) to `-s` (to see only single
occurrences, which was the previous default).
2016-05-11 11:31:52 -04:00
Joshua Clayton
56c083097d Fix indentation 2016-05-11 10:46:18 -04:00
Joshua Clayton
9407b91b3b Update help docs 2016-05-11 09:22:29 -04:00
Joshua Clayton
11d35a6263 Hook into interrupt to trigger other behavior
Why?
====

Unused hides the cursor and potentially does other things to the window that
may leave it in an odd state. This introduces a hook to run any state
cleanup, including re-enabling the cursor, when a user sends a SIGINT to
the program.
2016-05-10 05:35:28 -04:00
Joshua Clayton
ba8159f08d Ignore file and directory patterns 2016-05-07 16:28:41 -04:00
Joshua Clayton
ee1c4cd0f6 Add flag to filter by likelihood 2016-05-07 16:25:54 -04:00
Joshua Clayton
cb6eb12af4 Add switch to display all term results 2016-05-07 16:18:49 -04:00
Joshua Clayton
4fc984ce75 Fully extract parseSearchRunner 2016-05-07 16:07:43 -04:00
Joshua Clayton
9436f733b2 Extract option filtering to separate function 2016-05-07 15:39:09 -04:00
Joshua Clayton
1f5db58f5e Move additional functionality out of Types and into separate modules 2016-05-07 06:10:15 -04:00
Joshua Clayton
e34f6951f1 Add optparse-applicative for flags
This introduces the optparse-applicative library for parsing out any
subcommands/flags/args. Currently only supports --no-progress (-P).
2016-05-05 17:53:53 -04:00
Joshua Clayton
6781ba1f5b Move resetScreen out of case statement 2016-05-04 23:01:00 -04:00
Joshua Clayton
50399ec4b1 Add number of files and number of occurrences 2016-05-04 20:51:41 -04:00
Joshua Clayton
961585ce6e Follow naming conventions for record fields 2016-05-03 22:13:01 -04:00
Joshua Clayton
67e52ed017 Initial pass at RemovalLikelihood calculator 2016-05-03 21:41:03 -04:00
Joshua Clayton
02f90fdb7d Left-align and pad widths for term column 2016-05-03 09:59:06 -04:00
Joshua Clayton
49b7b65b17 Improve output by grouping by directory structure 2016-05-03 05:22:50 -04:00
Joshua Clayton
f5394e4b36 Clear screen before displaying matches 2016-05-03 05:13:58 -04:00
Joshua Clayton
3ddf0631a9 Display progress bar when running ag 2016-05-02 06:05:31 -04:00
Joshua Clayton
dcfaa9355e Refactor in preparation for progress bar 2016-05-02 06:03:26 -04:00
Joshua Clayton
6ee18cf1c9 Extract error printing to separate function 2016-05-01 06:20:47 -04:00
Joshua Clayton
8f5446a414 Move parsing response entirely to Parser 2016-05-01 05:40:30 -04:00