Skip to content

Commit

Permalink
v1.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
zeitlings committed Oct 20, 2024
1 parent 3294d53 commit a94b70e
Show file tree
Hide file tree
Showing 14 changed files with 75 additions and 16 deletions.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
</div>


Unified Search is an [Alfred](https://www.alfredapp.com/) workflow that provides a unified search experience across multiple web search engines and websites, currently supporting 129 web search instances and extensible through Alfred's internal [custom web search](https://www.alfredapp.com/help/features/web-search/#custom) feature.
Unified Search is an [Alfred](https://www.alfredapp.com/) workflow that provides a unified search experience across multiple web search engines and websites, currently supporting 131 web search instances and extensible through Alfred's internal [custom web search](https://www.alfredapp.com/help/features/web-search/#custom) feature.

## Usage

Expand Down Expand Up @@ -52,3 +52,15 @@ You can add specific web searches to the default options or remove them via the
- <kbd>⌘</kbd><kbd>↩</kbd> Add to / Remove from defaults
- <kbd>⌥</kbd><kbd>↩</kbd> Activate / Deactivate web search


## Plugin: Extra Pane

You can use *Unified Search* with [Alfred Extra Pane](https://github.com/mr-pennyworth/alfred-extra-pane).

Tap <kbd>⇥</kbd> while __in filter mode__ to elicit a preview, or prefix your search with `>` manually.


<!-- Unified Search Extra Pane Plugin Preview -->
<img src="assets/images/preview/plugin.png" width="600px" />

__Note:__ You can set the relevant [environment variable](https://www.alfredapp.com/help/workflows/advanced/variables/#environment) to `true` to always have the pane enabled.
36 changes: 28 additions & 8 deletions Unified Search/Unified Search/Models/Searches.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ extension WebSearches {
self.isAlfredWebsearch = isAlfredWebsearch
}

@inline(__always)
func matches(suffix: String) -> Bool {
let suffix: String = suffix.lowercased()
return shorthand?.lowercased() == suffix || name.lowercased() == suffix
}

func hash(into hasher: inout Hasher) {
hasher.combine(name)
hasher.combine(url)
Expand All @@ -61,12 +67,13 @@ extension WebSearches.WebSearch {

func alfredItem(query: String) -> Item? {
guard active else { return nil }
let arg: Argument = .string(url.replacing(inputPlaceholder, with: query))
let arg: String = url.replacing(inputPlaceholder, with: query)
return .with {
$0.arg = arg
$0.arg = .string(arg)
$0.title = name
$0.uid = name
if let isAlfredWebsearch, isAlfredWebsearch {
$0.title = name.replacing("{query}", with: "{input}") //+ " (active: \(active))"
$0.title = name.replacing("{query}", with: "{input}")
}
if let icon {
if let isAlfredWebsearch, isAlfredWebsearch {
Expand All @@ -75,14 +82,27 @@ extension WebSearches.WebSearch {
$0.icon = .init(path: "images/icons/\(icon).png")
}
}
$0.autocomplete = Workflow.filterBehaviour == .always
? "\(Search.queryFull) \(g_FilterSeperator) "
: "\(query) \(g_FilterSeperator) "

if Search.injectQuicklook {
$0.quicklookurl = arg
}

if !Search.queryHasFilterSeperator {
if Search.suffixIsExactMatch {
$0.autocomplete = "\(query) \(g_FilterSeperator) \(Search.suffix)"
} else {
$0.autocomplete = Workflow.filterBehaviour == .always
? "\(Search.queryFull) \(g_FilterSeperator) "
: "\(query) \(g_FilterSeperator) "
}
} else if !Search.injectQuicklook {
$0.autocomplete = "\(g_QuicklookHint) \(Search.queryFull) "
}

if let shorthand {
$0.shift = .init(arg: arg, subtitle: "Shorthand: \(shorthand)", icon: nil)
$0.shift = .init(arg: .string(arg), subtitle: "Shorthand: \(shorthand)", icon: nil)
}
$0.alt = .init(arg: arg, subtitle: url, icon: nil)
$0.alt = .init(arg: .string(arg), subtitle: url, icon: nil)
}
}

Expand Down
12 changes: 11 additions & 1 deletion Unified Search/Unified Search/Search+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation
extension Search {

static func getFilterHint(suffixMode queryHasFilterSeperator: Bool) -> String? {
let components: [String] = query.split(separator: g_FilterSeperator).map(\.trimmed)
let components: [String] = Self.query.split(separator: g_FilterSeperator).map(\.trimmed)
// If the separator is present, act on it regardless of set behaviour
let queryHasFilterSuffix: Bool = components.count > 1

Expand Down Expand Up @@ -38,6 +38,16 @@ extension Search {
return nil
}
}

/// Check if the query has the `g_QuicklookHint` prefix or `config_always_inject_quicklookurl` has been set to true to override.
/// If the quicklook hint is present, remove it from the query.
static func getQuicklookHint() -> Bool {
guard Self.query.hasPrefix(.init(g_QuicklookHint)) else {
return Workflow.injectQuicklook
}
Self.query = .init(Self.query.drop(while: { $0 == g_QuicklookHint || $0.isWhitespace }))
return true
}
}


Expand Down
2 changes: 1 addition & 1 deletion Unified Search/Unified Search/Utilities/FileHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ struct FileHandler {
if Workflow.includeCustomAlfredWebsearches {
let customAlfredSearches: [WebSearch] = getAlfredWebSearches()
if customAlfredSearches.isEmpty {
Workflow.log("Custom Alfred Web-Searches are included, but none were enabled. Enable at least one custom Alfred Websearch to include it in \(Workflow.Env.workflowName == "the workflow").")
Workflow.log("Custom Alfred Web-Searches are included, but none were enabled. Enable at least one custom Alfred Websearch to include it in \(Workflow.Env.workflowName ?? "the workflow").")
}
for customAlfredSearch in customAlfredSearches
where webSearches.firstIndex(where: { $0.name == customAlfredSearch.name }) == nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import Foundation

extension Workflow {

static let injectQuicklook: Bool = envvar("config_always_inject_quicklookurl") == "true"

static func envvar(_ key: String) -> String? {
Env.environment[key]
}
Expand Down
13 changes: 12 additions & 1 deletion Unified Search/Unified Search/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import Foundation

let g_FilterSeperator: String = "||"
let g_QuicklookHint: Character = ">"

struct Search {

Expand All @@ -16,20 +17,30 @@ struct Search {
/// Used for autocomplete where filter behaviour is `always` and only defaults are shown
static let queryFull: String = Workflow.userInput ?? ""
static var query: String = queryFull
static let queryHasFilterSeperator: Bool = query.firstRange(of: g_FilterSeperator) != nil
static var suffixIsExactMatch: Bool = false
static var suffix: String = ""
static var injectQuicklook: Bool = false
static private let fm: FileManager = .default

static func run() {
guard !query.trimmed.isEmpty else {
Workflow.info("Please enter text to search for.")
}
Self.probe()
let queryHasFilterSeperator: Bool = query.firstRange(of: g_FilterSeperator) != nil
Self.injectQuicklook = getQuicklookHint()
let suffix: String? = getFilterHint(suffixMode: queryHasFilterSeperator) // last query component
let suffixIsWildcard: Bool = suffix == "*"
let webSearches: [WebSearch] = FileHandler.getSearches()
guard webSearches.first(where: { $0.isDefault }) != nil else {
Workflow.info("At least one search must be configured as default.")
}
if !suffixIsWildcard, let suffix,
webSearches.first(where: { $0.matches(suffix: suffix) }) != nil
{
Self.suffixIsExactMatch = true
Self.suffix = suffix
}

var items: [Item] = []
let subtitle: String = "Search for '\(query)'"
Expand Down
12 changes: 8 additions & 4 deletions Unified Search/suffix web search.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -250,14 +250,16 @@
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CREATE_INFOPLIST_SECTION_IN_BINARY = YES;
CURRENT_PROJECT_VERSION = 1;
CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = U238XAT93R;
ENABLE_HARDENED_RUNTIME = YES;
GCC_OPTIMIZATION_LEVEL = 0;
INFOPLIST_FILE = "$(SRCROOT)/Unified Search/info.plist";
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.0.0;
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.zeitlings.unified-search";
PRODUCT_NAME = "Unified Search";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = Debug;
Expand All @@ -267,14 +269,16 @@
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CREATE_INFOPLIST_SECTION_IN_BINARY = YES;
CURRENT_PROJECT_VERSION = 1;
CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = U238XAT93R;
ENABLE_HARDENED_RUNTIME = YES;
GCC_OPTIMIZATION_LEVEL = z;
INFOPLIST_FILE = "$(SRCROOT)/Unified Search/info.plist";
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.0.0;
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.zeitlings.unified-search";
PRODUCT_NAME = "Unified Search";
SWIFT_OPTIMIZATION_LEVEL = "-Osize";
SWIFT_VERSION = 5.0;
};
name = Release;
Expand Down
Binary file not shown.
Binary file added assets/images/preview/plugin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed assets/workflow/images/preview/config1.png
Binary file not shown.
Binary file removed assets/workflow/images/preview/config2.png
Binary file not shown.
Binary file removed assets/workflow/images/preview/keyword1.png
Binary file not shown.
Binary file removed assets/workflow/images/preview/keyword2.png
Binary file not shown.
Binary file removed assets/workflow/images/preview/keyword3.png
Binary file not shown.

0 comments on commit a94b70e

Please sign in to comment.