Exemple #1
0
static bool do_attach() {
    anitomy::Anitomy anitomy;
    anitomy.options().parse_episode_title = false;
    anitomy.options().parse_file_extension = false;
    anitomy.options().parse_release_group = false;

    std::vector<std::wstring> videos;

    for (std::wstring line; std::getline(std::wcin, line, options.delimiter) && !line.empty();) {
        videos.emplace_back(line);
    }

    std::vector<std::pair<ExtractedInfo,std::wstring>> subs;

    for (std::wstring line; std::getline(std::wcin, line, options.delimiter) && !line.empty();) {
        if (!anitomy.Parse(wbasename(line))) {
            continue;
        }
        ExtractedInfo info(anitomy.elements());
        if (!info) {
            continue;
        }
        subs.emplace_back(std::move(info), line);
    }
    if (std::wcin) {
        std::cerr << "ERROR: extra data\n";
        return false;
    }

    std::sort(subs.begin(), subs.end());

    bool first = true;
    for (const auto &video : videos) {
        if (!first) {
            std::wcout << options.delimiter;
        }
        std::wcout << video << options.delimiter;
        first = false;

        if (!anitomy.Parse(wbasename(video))) {
            continue;
        }
        ExtractedInfo info(anitomy.elements());
        if (!info) {
            continue;
        }
        std::pair<ExtractedInfo,std::wstring> p(
            std::move(info),
            std::wstring() // empty string is always less or equal to anything
        );
        for (auto it = std::lower_bound(subs.begin(), subs.end(), p);
            it != subs.end() && it->first == p.first;
            ++it)
        {
            std::wcout << it->second << options.delimiter;
        }
    }

    return true;
}
Exemple #2
0
static bool do_sort() {
    anitomy::Anitomy anitomy;
    anitomy.options().parse_episode_title = false;
    anitomy.options().parse_file_extension = false;
    anitomy.options().parse_release_group = false;

    std::vector<std::pair<ExtractedInfo,std::wstring>> parsed;
    std::vector<std::wstring> unparseable;

    for (std::wstring line; std::getline(std::wcin, line, options.delimiter);) {
        if (!anitomy.Parse(wbasename(line))) {
            unparseable.emplace_back(line);
            continue;
        }
        parsed.emplace_back(ExtractedInfo(anitomy.elements()), line);
    }

    std::sort(parsed.begin(), parsed.end());

    for (const auto &line : unparseable) {
        std::wcout << line << options.delimiter;
    }
    for (const auto &p : parsed) {
        std::wcout << p.second << options.delimiter;
    }

    return true;
}
Exemple #3
0
/**
   See if the process described by \c proc matches the commandline \c
   cmd
*/
static bool match_pid(const wcstring &cmd,
                      const wchar_t *proc,
                      int flags,
                      size_t *offset)
{
    /* Test for a direct match. If the proc string is empty (e.g. the user tries to complete against %), then return an offset pointing at the base command. That ensures that you don't see a bunch of dumb paths when completing against all processes. */
    if (proc[0] != L'\0' && wcsncmp(cmd.c_str(), proc, wcslen(proc)) == 0)
    {
        if (offset)
            *offset = 0;
        return true;
    }

    /* Get the command to match against. We're only interested in the last path component. */
    const wcstring base_cmd = wbasename(cmd);

    bool result = string_prefixes_string(proc, base_cmd);
    if (result)
    {
        /* It's a match. Return the offset within the full command. */
        if (offset)
            *offset = cmd.size() - base_cmd.size();
    }
    return result;
}
/// See if the process described by \c proc matches the commandline \c cmd.
static bool match_pid(const wcstring &cmd, const wchar_t *proc) {
    // Don't wait for itself
    if (std::wcscmp(proc, L"wait") == 0) return false;

    // Get the command to match against. We're only interested in the last path component.
    const wcstring base_cmd = wbasename(cmd);
    return std::wcscmp(proc, base_cmd.c_str()) == 0;
}
Exemple #5
0
/* Tests whether the specified string cpath is the prefix of anything we could cd to. directories is a list of possible parent directories (typically either the working directory, or the cdpath). This does I/O!

   We expect the path to already be unescaped.
*/
bool is_potential_path(const wcstring &const_path, const wcstring_list_t &directories, path_flags_t flags, wcstring *out_path)
{
    ASSERT_IS_BACKGROUND_THREAD();
    
    const bool require_dir = !! (flags & PATH_REQUIRE_DIR);
    wcstring clean_path;
	int has_magic = 0;
	bool result = false;
    
    wcstring path(const_path);
    if (flags & PATH_EXPAND_TILDE)
        expand_tilde(path);    
    
    //	debug( 1, L"%ls -> %ls ->%ls", path, tilde, unescaped );
    
    for( size_t i=0; i < path.size(); i++)
    {
        wchar_t c = path.at(i);
        switch( c )
        {
            case PROCESS_EXPAND:
            case VARIABLE_EXPAND:
            case VARIABLE_EXPAND_SINGLE:
            case BRACKET_BEGIN:
            case BRACKET_END:
            case BRACKET_SEP:
            case ANY_CHAR:
            case ANY_STRING:
            case ANY_STRING_RECURSIVE:
            {
                has_magic = 1;
                break;		
            }
				
            case INTERNAL_SEPARATOR:
            {
                break;
            }
				
            default:
            {
                clean_path.push_back(c);
                break;
            }
				
        }
        
    }
    
    if( ! has_magic && ! clean_path.empty() )
    {
        /* Don't test the same path multiple times, which can happen if the path is absolute and the CDPATH contains multiple entries */
        std::set<wcstring> checked_paths;
        
        /* Keep a cache of which paths / filesystems are case sensitive */
        case_sensitivity_cache_t case_sensitivity_cache;
        
        for (size_t wd_idx = 0; wd_idx < directories.size() && ! result; wd_idx++) {
            const wcstring &wd = directories.at(wd_idx);
            
            const wcstring abs_path = apply_working_directory(clean_path, wd);
            
            /* Skip this if it's empty or we've already checked it */
            if (abs_path.empty() || checked_paths.count(abs_path))
                continue;
            checked_paths.insert(abs_path);
            
            /* If we end with a slash, then it must be a directory */
            bool must_be_full_dir = abs_path.at(abs_path.size()-1) == L'/';
            if (must_be_full_dir) 
            {
                struct stat buf;
                if (0 == wstat(abs_path, &buf) && S_ISDIR(buf.st_mode)) {
                    result = true;
                    /* Return the path suffix, not the whole absolute path */
                    if (out_path)
                        *out_path = clean_path;
                }
            }
            else
            {
                DIR *dir = NULL;
                
                /* We do not end with a slash; it does not have to be a directory */
                const wcstring dir_name = wdirname(abs_path);
                const wcstring base_name = wbasename(abs_path);
                if (dir_name == L"/" && base_name == L"/")
                {
                    result = true;
                    if (out_path)
                        *out_path = clean_path;
                }
                else if ((dir = wopendir(dir_name))) {
                    // We opened the dir_name; look for a string where the base name prefixes it
                    wcstring ent;
                    
                    // Check if we're case insensitive
                    bool case_insensitive = fs_is_case_insensitive(dir_name, dirfd(dir), case_sensitivity_cache);
                    
                    // Don't ask for the is_dir value unless we care, because it can cause extra filesystem acces */
                    bool is_dir = false;
                    while (wreaddir_resolving(dir, dir_name, ent, require_dir ? &is_dir : NULL))
                    {                    

                        /* Determine which function to call to check for prefixes */
                        bool (*prefix_func)(const wcstring &, const wcstring &);
                        if (case_insensitive) {
                            prefix_func = string_prefixes_string_case_insensitive;
                        } else {
                            prefix_func = string_prefixes_string;
                        }

                        if (prefix_func(base_name, ent) && (! require_dir || is_dir))
                        {
                            result = true;
                            if (out_path) {
                                /* We want to return the path in the same "form" as it was given. Take the given path, get its basename. Append that to the output if the basename actually prefixes the path (which it won't if the given path contains no slashes), and isn't a slash (so we don't duplicate slashes). Then append the directory entry. */
                                
                                out_path->clear();
                                const wcstring path_base = wdirname(const_path);
                                
                                
                                if (prefix_func(path_base, const_path)) {
                                    out_path->append(path_base);
                                    if (! string_suffixes_string(L"/", *out_path))
                                        out_path->push_back(L'/');
                                }
                                out_path->append(ent);
                                /* We actually do want a trailing / for directories, since it makes autosuggestion a bit nicer */
                                if (is_dir)
                                    out_path->push_back(L'/');
                            }
                            break;
                        }
                    }
                    closedir(dir);
                }
            }
        }
    }
    return result;
}